Istio入门
Istio 在逻辑上分为数据平面和控制平面。
数据平面,由一组高性能的智能代理(基于 Envoy 改进的 istio-proxy)组成,它们控制和协调了被代理服务的所有网络通信,同时也负责收集和上报相关的监控数据。
控制平面,负责制定应用策略来控制网络流量的路由。
Istio 由多个组件组成,核心组件及其作用为如下:
Ingressgateway,控制外部流量访问 Istio 内部的服务。
Egressgateway,控制 Istio 内部访问外部服务的流量。
Pilot,负责管理服务网格内部的服务和流量策略。它将服务信息和流量控制的高级路由规则在运行时传播给 Proxy,并将特定平台的服务发现机制抽象为 Proxy 可使用的标准格式。
Citadel,提供身份认证和凭证管理。
Galley,负责验证、提取、处理和分发配置。
Proxy,作为服务代理,调节所有 Service Mesh 单元的入口和出口流量。
这其中 Proxy 属于数据平面,以 Sidecar 的方式与应用程序一同部署到 Pod 中,而 Pilot、Citadel 和 Galley 属于控制平面。
除此之外,Istio 中还提供一些额外的插件,如 grafana、istio-tracing、kiali 和 prometheus,用于进行可视化的数据查看、流量监控和链路追踪等。
Pilot:Istio 控制面中最核心的模块,负责运行时配置下发,具体来说,就是和 Envoy 之间基于 xDS 协议进行的各种 Envoy 配置信息的推送,包括服务发现、路由发现、集群发现、监听器发现等。
Citadel:负责证书的分发和轮换,使 Sidecar 代理两端实现双向 TLS 认证、访问授权等。
Galley:配置信息的格式和正确性校验,将配置信息提供给 Pilot 使用。
Istio 通过 Galley 模块管理配置,Pilot 模块解析配置为 xDS 协议格式,通过 gRPC 和 Envoy 进行通信,以便完成配置和节点信息更新,pilot-agent 作为 Envoy 守护模块,保证 Envoy 的正常运行和平滑重启。
本地业务服务 productpage 通过 iptables 劫持的方式和本地 Envoy 进行通信,Envoy 完成服务发现后将请求转发到 ProductDetail 服务的所在 Pod,同样通过 iptables 劫持的方式将请求转发到本地的业务服务 ProductDetail。
实例服务原理解析
apiVersion: v1 kind: Service metadata: name: productpage labels: app: productpage service: productpage spec: ports: - port: 9080 name: http selector: app: productpage
首先定义了一个 Service 类型的资源,而 Service 是 Kubernetes 抽象出来的服务概念,一组 Pod 的集合便是 Kubernetes 的 Service。Pod 是有生命周期的,Pod 的 IP 在不同的生命周期内发生变化,但抽象出来的 Service 名称是不会变化的。
这样就可以通过服务名访问这些后端 IP,而不用感知后端 Pod IP 的变化。
然后在 Metadata 中定义了这一组 Service 的 label ,通过 selector 指定响应的标签,就可以访问带有这组标签定义的 Pod 集合。另外这组配置还指定了服务端口为 9080,服务的协议为 HTTP ,这些信息将用于 Sidecar 的代理转发。
接下来,通过 Deployment 控制 Pod 的生命周期,定义了 Pod 的副本数量。下面的示例中,定义一个 replicas 为 1,也就是 Pod 的副本数量为 1,因为是测试环境,所以没有设置更多的副本数量保障服务的 SLA 。
当然一些常规的镜像拉取地址和拉取方式也做了定义:
apiVersion: apps/v1 kind: Deployment metadata: name: productpage-v1 labels: app: productpage version: v1 spec: replicas: 1 selector: matchLabels: app: productpage version: v1 template: metadata: labels: app: productpage version: v1 spec: serviceAccountName: bookinfo-productpage containers: - name: productpage image: docker.io/istio/examples-bookinfo-productpage-v1:1.16.2 imagePullPolicy: IfNotPresent ports: - containerPort: 9080 volumeMounts: - name: tmp mountPath: /tmp volumes: - name: tmp emptyDir: {}
另外在 Kubernetes 的 Service 里面并没有版本的概念,如果想进行染色或者金丝雀发布,就需要借助 Istio 的能力。通过上述命令可以看到,在 Deployment 类型中定义了 Version V1 的 lable,这个 lable 最终会转化成不同的服务名,比如 productpage-v1 的方式,下发到 Sidecar 中, Sidecar 根据这个服务名称进行服务发现,以实现不同版本号访问的方法。
下一步,用到了 Ingress 模式。定义一组网关类型的资源, Istio 通过 Gateway 将服务发布成外部可访问的服务,通过 80 端口将服务通过 Ingress 网关转发到特定的服务上。
apiVersion: networking.istio.io/v1alpha3 kind: Gateway metadata: name: bookinfo-gateway spec: selector: istio: ingressgateway # use istio default controller servers: - port: number: 80 name: http protocol: HTTP hosts: - "*"
在这里,Gateway 资源类型,需要配合 VirtualService 类型的资源一起使用。那么,定义匹配到的 URI 具体路由到哪个服务呢?
在这个程序中可以看到匹配到 /productpage 路径的服务,而在 route 中定义了 destination 的 host 将会是路由的服务名。
apiVersion: networking.istio.io/v1alpha3 kind: VirtualService metadata: name: bookinfo spec: hosts: - "*" gateways: - bookinfo-gateway http: - match: - uri: exact: /productpage - uri: prefix: /static - uri: exact: /login - uri: exact: /logout - uri: prefix: /api/v1/products route: - destination: host: productpage port: number: 9080