一、istio是什么
Istio 何以得名
Istio 是由 Google、IBM、Lyft 等共同开源的 Service Mesh(服务网格)框架,旨在解决大量微服务的发现、连接、管理、监控以及安全等问题。Istio 对应用是透明的,不需要改动任何服务代码就可以实现透明的服务治理。仅举几例:
- 流量管理 :超时,重试,负载均衡,
- 安全性: 最终用户身份验证和授权,
- 可观察性: 跟踪,监控和记录。

Istio(ISS-tee-oh)是由 Tetrate 创始人 Varun Talwar 和谷歌首席工程师 Louis Ryan 在 2017 年命名的,当时他们都在谷歌工作。
Istio 在希腊语中是 “sail” 的意思,它(ιστίο)延用了 Kubernetes(在希腊语中是飞行员或舵手的意思)建立的希腊航海主题。Istio 和它的表亲 Istos(ιστός)(意思是桅杆、网)都来自古希腊词根 Istimi(ἵστημι),意思是 “to make stand”。
Istio 并不是首字母缩写,但如果一定要说它代表着什么,也许会是 “I Secure, Then I Observe”(我保护,我观察),或者 “I’m Sexy To Infrastructure Operators.”(我对基础设施运营商富有吸引力)。
istio版本演化
Istio 0.1——开启 Service Mesh 的新纪元
2017 年 5 月 24 日,Google、IBM 和 Lyft 发布了 Istio 0.1。
在用户将应用部署到 Kubernetes 上之后,如何管理容器之间的流量及确保应用的安全性,就成了突出问题,Service Mesh 的出现就是为了解决这一问题。在 Istio 开源之前,市场上只有创业公司 Buoyant 一家的 Service Mesh 产品 Linkerd,2017 年正值 Kubernetes 赢得容器编排之战,云原生社区中急需找到新的增长点,Service Mesh 开始抬头,Istio 的推出更使得该领域急剧升温。
Istio 基于 Envoy 构建,在开源之初就确立的链接、保护、控制和观测”微服务”的使命。(注意,“微服务”后来在 Istio 的官网描述中被改成了服务,)该版本只支持 Kubernetes 环境,并计划在接下来的几个月添加诸如虚拟机和 Cloud Foundry 等环境的支持。计划每三个月发布一个大版本。
该版本发布时仅一个命令行工具 istioctl,但是它的意义是划时代的,它确立了 Service Mesh 的 sidecar 模式,即在应用容器 pod 中注入一个 proxy 来管理服务间通信,再通过控制平面统一管控这些 sidecar,后续的所有声称为 Service Mesh 的产品都应用了该模式。
Istio 0.8——1.0 的前奏
2018 年 6 月 1 日,Istio 0.8 发布,API 级别的变更,堪称 1.0。
该版本带来了重大的 API 级别的变更,新引进了 v1alpha3 路由 API,该 API 不向前兼容!确立了沿用至今的 Gateway(新引入,不在支持 ingress、egress 代理)、VirtualService(取代了原先的 RouteRule)、DestinationRule(取代了 DestinationPolicy)、ServiceEntry(取代了 EgressRule) 等资源类型。重命名了安全模块,以前的 Istio-Auth 或者 Istio-CA 现在被统称为 Citadel。
Istio 1.1——企业就绪
2019 年 3 月 19 日,Istio 1.1 发布,API 更加稳定,支持多 Kubernetes 集群。
距离 1.0 版本发布已经过去快 7 个月了,虽然越来越多的公司在生产中使用 Istio,但是一些大型公司在尝试使用 Istio 的过程中,遇到了一些瓶颈。此版本主要是优化性能,新增配置管理组件 Galley,新增了 sidecar 资源,可以更精细地控制附加到命名空间中工作负载的 sidecar 代理的行为。使用 RedHat 开发的 Kiali 替换了 Istio 原先使用的 ServiceGraph 插件。
Istio 1.5——拥抱变化,回归单体
2020 年 3 月 6 日,Istio 1.5 发布,有史以来最重大的一次变革。
Istio 1.5 是一个具有重大变革的版本。长久以来,面对社区对 Istio 的性能和易用性的诟病,Istio 团队终于正视自身的问题,在当前版本中彻底推翻了原有控制平面的架构,完成了重建。
架构调整
主要包括重建了控制平面,将原有的多个组件(Galley、Citadel、Pilot)整合为一个单体结构 istiod;同时废弃了被诟病已久的 Mixer 组件。还对是否向后兼容的部分也做了说明,如果你要从 1.4.x 版本升级到 1.5 必须知道这些变化。
Istio 1.8——用户至上的选择
2020 年 11 月 18 日,Istio 1.8 发布,顺应用户呼声,对虚拟机的支持更进一步。
这是 Istio 在 2020 年发布的最后一个版本,按照 Istio 社区在今年初设定的目标继续推进,该版本主要有以下更新:
- 支持使用 Helm 3 进行安装和升级
- 正式移除了 Mixer
- 新增了 Istio DNS proxy,透明地拦截应用程序的 DNS 查询,实现智能应答
- 新增了 WorkloadGroup 以简化对虚拟机的引入
WorkloadGroup是一个新的 API 对象,旨在与虚拟机等非 Kubernetes 工作负载一起使用,模仿现有的用于 Kubernetes 工作负载的 sidecar 注入和部署规范模型来引导 Istio 代理。
istio架构
Istio 从逻辑上可以分为数据平面和控制平面:
- 数据平面主要由一系列的智能代理(默认为 Envoy)组成,管理微服务之间的网络通信
- 控制平面负责管理和配置代理来路由流量,并配置 Mixer 以进行策略部署和遥测数据收集
- Istio 是可定制可扩展的,组件是可拔插的
Istio 架构可以如下图所示
它主要由以下组件构成:
Envoy:Lyft 开源的高性能代理,用于调解服务网格中所有服务的入站和出站流量。它支持动态服务发现、负载均衡、TLS 终止、HTTP/2 和 gPRC 代理、熔断、健康检查、故障注入和性能测量等丰富的功能。Envoy 以 sidecar 的方式部署注入到相关的服务 Pod 中,从而无需重新构建或重写代码。
Mixer:负责访问控制、执行策略并从 Envoy 代理中收集遥测数据。
Pilot:动态管理 Envoy 实例的生命周期,提供服务发现、智能路由和弹性流量管理(如超时、重试)等功能。它将流量管理策略转化为 Envoy 数据平面配置,并传播到 sidecar 中。Pilot 将服务发现机制抽象为符合 Envoy 数据平面 API 的标准格式,以便支持在多种环境下运行并保持流量管理的相同操作接口。
Citadel 通过内置身份和凭证管理提供服务间和最终用户的身份认证。支持基于角色的访问控制、基于服务标识的策略执行等。
二、istio安装
istiod安装
下载tar包
curl -L https://istio.io/downloadIstio | ISTIO_VERSION=1.8.1 TARGET_ARCH=x86_64 sh -
转到 Istio 包目录,将 istioctl 客户端加入搜索路径(Linux or macOS)
cd istio-1.8.1export PATH=$PWD/bin:$PATH
开始部署 ```shell [root@liaoxb-nroow6grda6k-master-0 istio-1.8.1]# istioctl install This will install the Istio default profile with [“Istio core” “Istiod” “Ingress gateways”] components into the cluster. Proceed? (y/N) y Detected that your cluster does not support third party JWT authentication. Falling back to less secure first party JWT. See https://istio.io/v1.8/docs/ops/best-practices/security/#configure-third-party-service-account-tokens for details. ✔ Istio core installed ✔ Istiod installed ✔ Ingress gateways installed ✔ Installation complete
[root@liaoxb-nroow6grda6k-master-0 istio-1.8.1]# ki get po NAME READY STATUS RESTARTS AGE istio-ingressgateway-557c6797b5-2kl79 1/1 Running 0 58s istiod-bdcf67975-qqdjf 1/1 Running 0 62s
[root@liaoxb-nroow6grda6k-master-0 istio-1.8.1]# ki get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
istio-ingressgateway LoadBalancer 10.254.163.47 172.33.0.77 15021:30326/TCP,80:30613/TCP,443:31216/TCP,15012:31104/TCP,15443:32506/TCP 2m53s
istiod ClusterIP 10.254.196.236
<a name="SkhA2"></a>## 插件安装**部署 **[Kiali](https://istio.io/latest/zh/docs/ops/integrations/kiali/)** 仪表板、 以及 **[Prometheus](https://istio.io/latest/zh/docs/ops/integrations/prometheus/)**、 **[Grafana](https://istio.io/latest/zh/docs/ops/integrations/grafana)**、 还有 **[Jaeger](https://istio.io/latest/zh/docs/ops/integrations/jaeger/)```shell[root@liaoxb-nroow6grda6k-master-0 istio-1.8.1]# kubectl apply -f samples/addonsserviceaccount/grafana createdconfigmap/grafana createdservice/grafana createddeployment.apps/grafana createdconfigmap/istio-grafana-dashboards createdconfigmap/istio-services-grafana-dashboards createddeployment.apps/jaeger createdservice/tracing createdservice/zipkin createdservice/jaeger-collector createdcustomresourcedefinition.apiextensions.k8s.io/monitoringdashboards.monitoring.kiali.io createdserviceaccount/kiali createdconfigmap/kiali createdclusterrole.rbac.authorization.k8s.io/kiali-viewer createdclusterrole.rbac.authorization.k8s.io/kiali createdclusterrolebinding.rbac.authorization.k8s.io/kiali createdservice/kiali createddeployment.apps/kiali createdmonitoringdashboard.monitoring.kiali.io/envoy createdmonitoringdashboard.monitoring.kiali.io/go createdmonitoringdashboard.monitoring.kiali.io/kiali createdmonitoringdashboard.monitoring.kiali.io/micrometer-1.0.6-jvm-pool createdmonitoringdashboard.monitoring.kiali.io/micrometer-1.0.6-jvm createdmonitoringdashboard.monitoring.kiali.io/micrometer-1.1-jvm createdmonitoringdashboard.monitoring.kiali.io/microprofile-1.1 createdmonitoringdashboard.monitoring.kiali.io/microprofile-x.y createdmonitoringdashboard.monitoring.kiali.io/nodejs createdmonitoringdashboard.monitoring.kiali.io/quarkus createdmonitoringdashboard.monitoring.kiali.io/springboot-jvm-pool createdmonitoringdashboard.monitoring.kiali.io/springboot-jvm createdmonitoringdashboard.monitoring.kiali.io/springboot-tomcat createdmonitoringdashboard.monitoring.kiali.io/thorntail createdmonitoringdashboard.monitoring.kiali.io/tomcat createdmonitoringdashboard.monitoring.kiali.io/vertx-client createdmonitoringdashboard.monitoring.kiali.io/vertx-eventbus createdmonitoringdashboard.monitoring.kiali.io/vertx-jvm createdmonitoringdashboard.monitoring.kiali.io/vertx-pool createdmonitoringdashboard.monitoring.kiali.io/vertx-server createdserviceaccount/prometheus createdconfigmap/prometheus createdclusterrole.rbac.authorization.k8s.io/prometheus createdclusterrolebinding.rbac.authorization.k8s.io/prometheus createdservice/prometheus createddeployment.apps/prometheus created[root@liaoxb-nroow6grda6k-master-0 istio-1.8.1]# kubectl rollout status deployment/kiali -n istio-systemWaiting for deployment "kiali" rollout to finish: 0 of 1 updated replicas are available...deployment "kiali" successfully rolled out[root@liaoxb-nroow6grda6k-master-0 istio-1.8.1]# ki get deployNAME READY UP-TO-DATE AVAILABLE AGEgrafana 1/1 1 1 3m43sistio-ingressgateway 1/1 1 1 10mistiod 1/1 1 1 10mjaeger 1/1 1 1 3m43skiali 1/1 1 1 3m43sprometheus 1/1 1 1 3m42s[root@liaoxb-nroow6grda6k-master-0 istio-1.8.1]# ki get svcNAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGEgrafana ClusterIP 10.254.57.192 <none> 3000/TCP 3m50sistio-ingressgateway LoadBalancer 10.254.163.47 172.33.0.77 15021:30326/TCP,80:30613/TCP,443:31216/TCP,15012:31104/TCP,15443:32506/TCP 10mistiod ClusterIP 10.254.196.236 <none> 15010/TCP,15012/TCP,443/TCP,15014/TCP 10mjaeger-collector ClusterIP 10.254.69.79 <none> 14268/TCP,14250/TCP 3m50skiali ClusterIP 10.254.53.124 <none> 20001/TCP,9090/TCP 3m50sprometheus ClusterIP 10.254.113.29 <none> 9090/TCP 3m49stracing ClusterIP 10.254.244.177 <none> 80/TCP 3m50szipkin ClusterIP 10.254.182.18 <none> 9411/TCP 3m50s
NodePort方式访问Kiali
apiVersion: v1kind: Servicemetadata:name: my-kialilabels:app: kialiversion: v1.26.0spec:type: NodePortports:- port: 20001targetPort: 20001protocol: TCPname: httpselector:app: kialiversion: v1.26.0
三、示例应用
Bookinfo介绍
这个应用模仿在线书店的一个分类,显示一本书的信息。 页面上会显示一本书的描述,书籍的细节(ISBN、页数等),以及关于这本书的一些评论。
Bookinfo 应用中的几个微服务是由不同的语言编写的。 这些服务对 Istio 并无依赖,但是构成了一个有代表性的服务网格的例子:它由多个服务、多个语言构成,并且 reviews 服务具有多个版本。
部署应用
要在 Istio 中运行这一应用,无需对应用自身做出任何改变。 您只要简单的在 Istio 环境中对服务进行配置和运行,具体一点说就是把 Envoy sidecar 注入到每个服务的pod中。
[root@liaoxb-3twn5oh27qof-master-0 istio-1.6.8]# kubectl label namespace default istio-injection=enablednamespace/default labeled[root@liaoxb-3twn5oh27qof-master-0 istio-1.6.8]# kubectl apply -f samples/bookinfo/platform/kube/bookinfo.yamlservice/details createdserviceaccount/bookinfo-details createddeployment.apps/details-v1 createdservice/ratings createdserviceaccount/bookinfo-ratings createddeployment.apps/ratings-v1 createdservice/reviews createdserviceaccount/bookinfo-reviews createddeployment.apps/reviews-v1 createddeployment.apps/reviews-v2 createddeployment.apps/reviews-v3 createdservice/productpage createdserviceaccount/bookinfo-productpage createddeployment.apps/productpage-v1 created
访问应用
集群内访问
pod ip直接访问
[escore@liaoxb-3twn5oh27qof-master-0 ~]$ kubectl get po -owide |grep productpageproductpage-v1-64794f5db4-4tlwz 2/2 Running 0 4d17h 10.253.2.55 liaoxb-3twn5oh27qof-worker-0 <none> <none>[escore@liaoxb-3twn5oh27qof-master-0 ~]$ curl -s 10.253.2.55:9080/productpage |grep -o "<title>.*</title>"<title>Simple Bookstore App</title>
在ratings容器内访问
[escore@liaoxb-3twn5oh27qof-master-0 ~]$ kubectl exec "$(kubectl get pod -l app=ratings -o jsonpath='{.items[0].metadata.name}')" -c ratings -- curl -s productpage:9080/productpage | grep -o "<title>.*</title>"<title>Simple Bookstore App</title>
clusterip访问

外部访问
- ingress访问
```shell
为应用定义 Ingress 网关
[root@liaoxb-p5ozyw7joz6h-master-0 istio-1.6.8]# kubectl apply -f samples/bookinfo/networking/bookinfo-gateway.yaml gateway.networking.istio.io/bookinfo-gateway created virtualservice.networking.istio.io/bookinfo created
为访问网关设置两个变量:INGRESS_HOST 和 INGRESS_PORT
[root@liaoxb-p5ozyw7joz6h-master-0 istio-1.6.8]# export INGRESS_HOST=$(kubectl -n istio-system get service istio-ingressgateway -o jsonpath=’{.status.loadBalancer.ingress[0].ip}’) [root@liaoxb-p5ozyw7joz6h-master-0 istio-1.6.8]# export INGRESS_PORT=$(kubectl -n istio-system get service istio-ingressgateway -o jsonpath=’{.spec.ports[?(@.name==”http2”)].port}’) [root@liaoxb-p5ozyw7joz6h-master-0 istio-1.6.8]# export SECURE_INGRESS_PORT=$(kubectl -n istio-system get service istio-ingressgateway -o jsonpath=’{.spec.ports[?(@.name==”https”)].port}’) [root@liaoxb-p5ozyw7joz6h-master-0 istio-1.6.8]# echo $INGRESS_HOST 172.33.0.44 [root@liaoxb-p5ozyw7joz6h-master-0 istio-1.6.8]# echo $INGRESS_PORT 80 [root@liaoxb-p5ozyw7joz6h-master-0 istio-1.6.8]# echo $SECURE_INGRESS_PORT 443
设置 GATEWAY_URL
[root@liaoxb-p5ozyw7joz6h-master-0 istio-1.6.8]# export GATEWAY_URL=$INGRESS_HOST:$INGRESS_PORT [root@liaoxb-p5ozyw7joz6h-master-0 istio-1.6.8]# echo “$GATEWAY_URL” 172.33.0.44:80
运行下面命令,验证 Bookinfo 是否已经实现了外部访问```shell$ echo "http://$GATEWAY_URL/productpage"
浏览器访问Bookinfo 应用的产品页面
NodePort方式访问
apiVersion: v1kind: Servicemetadata:name: my-prolabels:app: productpageversion: v1spec:type: NodePortports:- port: 9080targetPort: 9080protocol: TCPname: httpselector:app: productpageversion: v1
四、Sidecar模式
Sidecar 模式的优势
通过抽象出与功能相关的共同基础设施(监控、可观测性、超时重试、熔断),降低了微服务代码的复杂度。
- 不再需要编写相同的第三方组件配置文件和代码,所以能够降低微服务架构中的代码重复度。
- 降低应用程序代码和底层平台的耦合度。
Sidecar 注入过程
了解 Istio 为数据平面自动注入 Sidecar 的详细过程
向 Pod 中注入 Istio Sidecar 的两种方法:
- 使用 istioctl 手动注入
- 启用 Pod 所属命名空间的 Istio sidecar 注入器自动注入。
手动注入直接修改配置,如 Deployment,并将代理配置注入其中。
当 Pod 所属命名空间启用自动注入后,自动注入器会使用准入控制器在创建 Pod 时自动注入代理配置。
如果您不确定使用哪一种方法,建议使用自动注入。

自动注入 Sidecar
1、一个命名空间中设置了 istio-injection=enabled 标签,且 Injection webhook 被启用后,任何新的 Pod 都有将在创建时自动添加 Sidecar。
kubectl label namespace default istio-injection=enabled
2、在该命名空间下,新部署应用或者重启pod,此时istio会给pod成功注入sidecar配置,主要包括:
- Init 容器 istio-init:用于给 Sidecar 容器即 Envoy 代理做初始化,设置 iptables 端口转发
- Envoy sidecar 容器 istio-proxy:运行 Envoy 代理
Istio 和 sidecar 配置保存在 istio 和 istio-sidecar-injector 这两个 ConfigMap 中,其中包含了 Go template,所谓自动 sidecar 注入就是将生成 Pod 配置从应用 YAML 文件期间转移到 mutable webhook中。
Sidecar 注入与流量劫持详解
查看应用pod的yaml配置(以productpage为例)
spec:containers:- image: docker.io/istio/examples-bookinfo-productpage-v1:1.16.2imagePullPolicy: IfNotPresentname: productpageports:- containerPort: 9080protocol: TCPresources: {}terminationMessagePath: /dev/termination-logterminationMessagePolicy: FilevolumeMounts:- mountPath: /tmpname: tmp- mountPath: /var/run/secrets/kubernetes.io/serviceaccountname: bookinfo-productpage-token-csg4freadOnly: true- args:- proxy- sidecar- --domain- $(POD_NAMESPACE).svc.cluster.local- --serviceCluster- productpage.$(POD_NAMESPACE)- --proxyLogLevel=warning- --proxyComponentLogLevel=misc:error- --concurrency- "2"env:- name: JWT_POLICYvalue: first-party-jwt- name: PILOT_CERT_PROVIDERvalue: istiod- name: CA_ADDRvalue: istiod.istio-system.svc:15012- name: POD_NAMEvalueFrom:fieldRef:apiVersion: v1fieldPath: metadata.name- name: POD_NAMESPACEvalueFrom:fieldRef:apiVersion: v1fieldPath: metadata.namespace- name: INSTANCE_IPvalueFrom:fieldRef:apiVersion: v1fieldPath: status.podIP- name: SERVICE_ACCOUNTvalueFrom:fieldRef:apiVersion: v1fieldPath: spec.serviceAccountName- name: HOST_IPvalueFrom:fieldRef:apiVersion: v1fieldPath: status.hostIP- name: CANONICAL_SERVICEvalueFrom:fieldRef:apiVersion: v1fieldPath: metadata.labels['service.istio.io/canonical-name']- name: CANONICAL_REVISIONvalueFrom:fieldRef:apiVersion: v1fieldPath: metadata.labels['service.istio.io/canonical-revision']- name: PROXY_CONFIGvalue: |{"proxyMetadata":{"DNS_AGENT":""}}- name: ISTIO_META_POD_PORTSvalue: |-[{"containerPort":9080,"protocol":"TCP"}]- name: ISTIO_META_APP_CONTAINERSvalue: productpage- name: ISTIO_META_CLUSTER_IDvalue: Kubernetes- name: ISTIO_META_INTERCEPTION_MODEvalue: REDIRECT- name: ISTIO_META_WORKLOAD_NAMEvalue: productpage-v1- name: ISTIO_META_OWNERvalue: kubernetes://apis/apps/v1/namespaces/default/deployments/productpage-v1- name: ISTIO_META_MESH_IDvalue: cluster.local- name: TRUST_DOMAINvalue: cluster.local- name: DNS_AGENTimage: docker.io/istio/proxyv2:1.8.1imagePullPolicy: Alwaysname: istio-proxyports:- containerPort: 15090name: http-envoy-promprotocol: TCPreadinessProbe:failureThreshold: 30httpGet:path: /healthz/readyport: 15021scheme: HTTPinitialDelaySeconds: 1periodSeconds: 2successThreshold: 1timeoutSeconds: 3resources:limits:cpu: "2"memory: 1Girequests:cpu: 100mmemory: 128MisecurityContext:allowPrivilegeEscalation: falsecapabilities:drop:- ALLprivileged: falsereadOnlyRootFilesystem: truerunAsGroup: 1337runAsNonRoot: truerunAsUser: 1337terminationMessagePath: /dev/termination-logterminationMessagePolicy: FilevolumeMounts:- mountPath: /var/run/secrets/istioname: istiod-ca-cert- mountPath: /var/lib/istio/dataname: istio-data- mountPath: /etc/istio/proxyname: istio-envoy- mountPath: /etc/istio/podname: istio-podinfo- mountPath: /var/run/secrets/kubernetes.io/serviceaccountname: bookinfo-productpage-token-csg4freadOnly: truednsPolicy: ClusterFirstenableServiceLinks: trueinitContainers:- args:- istio-iptables- -p- "15001"- -z- "15006"- -u- "1337"- -m- REDIRECT- -i- '*'- -x- ""- -b- '*'- -d- 15090,15021,15020env:- name: DNS_AGENTimage: docker.io/istio/proxyv2:1.8.1imagePullPolicy: Alwaysname: istio-initresources:limits:cpu: "2"memory: 1Girequests:cpu: 100mmemory: 128MisecurityContext:allowPrivilegeEscalation: falsecapabilities:add:- NET_ADMIN- NET_RAWdrop:- ALLprivileged: falsereadOnlyRootFilesystem: falserunAsGroup: 0runAsNonRoot: falserunAsUser: 0terminationMessagePath: /dev/termination-logterminationMessagePolicy: FilevolumeMounts:- mountPath: /var/run/secrets/kubernetes.io/serviceaccountname: bookinfo-productpage-token-csg4freadOnly: truenodeName: liaoxb-nroow6grda6k-worker-0priority: 0restartPolicy: AlwaysschedulerName: default-schedulersecurityContext: {}serviceAccount: bookinfo-productpageserviceAccountName: bookinfo-productpageterminationGracePeriodSeconds: 30tolerations:- effect: NoExecutekey: node.kubernetes.io/not-readyoperator: ExiststolerationSeconds: 300- effect: NoExecutekey: node.kubernetes.io/unreachableoperator: ExiststolerationSeconds: 300volumes:- emptyDir: {}name: tmp- name: bookinfo-productpage-token-csg4fsecret:defaultMode: 420secretName: bookinfo-productpage-token-csg4f- emptyDir:medium: Memoryname: istio-envoy- emptyDir: {}name: istio-data- downwardAPI:defaultMode: 420items:- fieldRef:apiVersion: v1fieldPath: metadata.labelspath: labels- fieldRef:apiVersion: v1fieldPath: metadata.annotationspath: annotationsname: istio-podinfo- configMap:defaultMode: 420name: istio-ca-root-certname: istiod-ca-cert
Init 容器启动命令解析
Istio 在 Pod 中注入的 Init 容器名为 istio-init,参考 istio-init 容器的启动参数,得到完整的启动命令如下:
istio-iptables -p 15001 -z 15006 -u 1337 -m REDIRECT -i '*' -x "" -b '*' -d "15090,15021,15020"
该容器存在的意义就是让 Envoy 代理可以拦截所有的进出 Pod 的流量,即将入站流量重定向到 Sidecar,再拦截应用容器的出站流量经过 Sidecar 处理后再出站。
$ istio-iptables.sh -p PORT -u UID -g GID [-m mode] [-b ports] [-d ports] [-i CIDR] [-x CIDR] [-h]-p: 指定重定向所有 TCP 流量的 Envoy 端口(默认为 $ENVOY_PORT = 15001)-u: 指定未应用重定向的用户的 UID。通常,这是代理容器的 UID(默认为 $ENVOY_USER 的 uid,istio_proxy 的 uid 或 1337)-g: 指定未应用重定向的用户的 GID。(与 -u param 相同的默认值)-m: 指定入站连接重定向到 Envoy 的模式,“REDIRECT” 或 “TPROXY”(默认为 $ISTIO_INBOUND_INTERCEPTION_MODE)-b: 逗号分隔的入站端口列表,其流量将重定向到 Envoy(可选)。使用通配符 “*” 表示重定向所有端口。为空时表示禁用所有入站重定向(默认为 $ISTIO_INBOUND_PORTS)-d: 指定要从重定向到 Envoy 中排除(可选)的入站端口列表,以逗号格式分隔。使用通配符“*” 表示重定向所有入站流量(默认为 $ISTIO_LOCAL_EXCLUDE_PORTS)-i: 指定重定向到 Envoy(可选)的 IP 地址范围,以逗号分隔的 CIDR 格式列表。使用通配符 “*” 表示重定向所有出站流量。空列表将禁用所有出站重定向(默认为 $ISTIO_SERVICE_CIDR)-x: 指定将从重定向中排除的 IP 地址范围,以逗号分隔的 CIDR 格式列表。使用通配符 “*” 表示重定向所有出站流量(默认为 $ISTIO_SERVICE_EXCLUDE_CIDR)。环境变量位于 $ISTIO_SIDECAR_CONFIG(默认在:/var/lib/istio/envoy/sidecar.env)
这条启动命令的作用是:
- 将应用容器的所有TCP流量都重定向转发到 Envoy 的 15001 端口。
- 使用 istio-proxy 用户身份运行, UID 为 1337,即 Envoy 所处的用户空间,这也是 istio-proxy容器默认使用的用户,见 YAML 配置中的 runAsUser 字段。
- 使用默认的 REDIRECT 模式来重定向流量。
因为 Init 容器初始化完毕后就会自动终止,因为我们无法登陆到容器中查看 iptables 信息,但是 Init 容器初始化结果会保留到应用容器和 Sidecar 容器中。
istio-proxy 容器启动命令解析
为了查看 iptables 配置,我们需要登陆到 Sidecar 容器中使用 root 用户来查看,因为 kubectl 无法使用特权模式来远程操作 docker 容器,所以我们需要登陆到 productpage Pod 所在的主机上使用 docker命令登陆容器中查看。
查看 iptables 配置,列出 NAT(网络地址转换)表的所有规则,因为在 Init 容器启动的时候选择给 istio-iptables.sh 传递的参数中指定将入站流量重定向到 Envoy 的模式为 “REDIRECT”,因此在 iptables 中将只有 NAT 表的规格配置。iptables 命令的详细用法请参考 iptables,规则配置请参考 iptables 规则配置。
检查下该容器的 Dockerfile 看看 ENTRYPOINT 是什么以确定启动时执行的命令。
再参考 istio-proxy 容器的启动参数,得到完整的启动命令如下:
/usr/local/bin/pilot-agent proxy sidecar --domain $(POD_NAMESPACE).svc.cluster.local --serviceCluster productpage.$(POD_NAMESPACE) --proxyLogLevel=warning /usr/local/bin/pilot-agent proxy sidecar --domain $(POD_NAMESPACE).svc.cluster.local --serviceCluster productpage.$(POD_NAMESPACE) --proxyLogLevel=warning --proxyComponentLogLevel=misc:error --concurrency "2"
对照 bookinfo 示例的 productpage 的查看建立的连接。在 productpage-v1-745ffc55b7-2l2lw Pod 的 istio-proxy 容器中使用 root 用户查看打开的端口。
$ lsof -iCOMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAMEenvoy 11 istio-proxy 9u IPv4 73951 0t0 TCP localhost:15000 (LISTEN) # Envoy admin 端口envoy 11 istio-proxy 17u IPv4 74320 0t0 TCP productpage-v1-745ffc55b7-2l2lw:46862->istio-pilot.istio-system.svc.cluster.local:15010 (ESTABLISHED) # 15010:istio-pilot 的 grcp-xds 端口envoy 11 istio-proxy 18u IPv4 73986 0t0 UDP productpage-v1-745ffc55b7-2l2lw:44332->istio-statsd-prom-bridge.istio-system.svc.cluster.local:9125 # 给 Promethues 发送 metric 的端口envoy 11 istio-proxy 52u IPv4 74599 0t0 TCP *:15001 (LISTEN) # Envoy 的监听端口envoy 11 istio-proxy 53u IPv4 74600 0t0 UDP productpage-v1-745ffc55b7-2l2lw:48011->istio-statsd-prom-bridge.istio-system.svc.cluster.local:9125 # 给 Promethues 发送 metric 端口envoy 11 istio-proxy 54u IPv4 338551 0t0 TCP productpage-v1-745ffc55b7-2l2lw:15001->172.17.8.102:52670 (ESTABLISHED) # 52670:Ingress gateway 端口envoy 11 istio-proxy 55u IPv4 338364 0t0 TCP productpage-v1-745ffc55b7-2l2lw:44046->172.33.78.9:9091 (ESTABLISHED) # 9091:istio-telemetry 服务的 grpc-mixer 端口envoy 11 istio-proxy 56u IPv4 338473 0t0 TCP productpage-v1-745ffc55b7-2l2lw:47210->zipkin.istio-system.svc.cluster.local:9411 (ESTABLISHED) # 9411: zipkin 端口envoy 11 istio-proxy 58u IPv4 338383 0t0 TCP productpage-v1-745ffc55b7-2l2lw:41564->172.33.84.8:9080 (ESTABLISHED) # 9080:details-v1 的 http 端口envoy 11 istio-proxy 59u IPv4 338390 0t0 TCP productpage-v1-745ffc55b7-2l2lw:54410->172.33.78.5:9080 (ESTABLISHED) # 9080:reivews-v2 的 http 端口envoy 11 istio-proxy 60u IPv4 338411 0t0 TCP productpage-v1-745ffc55b7-2l2lw:35200->172.33.84.5:9091 (ESTABLISHED) # 9091:istio-telemetry 服务的 grpc-mixer 端口envoy 11 istio-proxy 62u IPv4 338497 0t0 TCP productpage-v1-745ffc55b7-2l2lw:34402->172.33.84.9:9080 (ESTABLISHED) # reviews-v1 的 http 端口envoy 11 istio-proxy 63u IPv4 338525 0t0 TCP productpage-v1-745ffc55b7-2l2lw:50592->172.33.71.5:9080 (ESTABLISHED) # reviews-v3 的 http 端口
从输出级过上可以验证 Sidecar 是如何接管流量和与 istio-pilot 通信,及向 Mixer 做遥测数据汇聚的。感兴趣的读者可以再去看看其他几个服务的 istio-proxy 容器中的 iptables 和端口信息。
四、istio怎么用
流量管理
虚拟服务(Virtual Service)和目标规则(Destination Rule) 是 Istio 流量路由功能的关键拼图。
虚拟服务
虚拟服务配置如何在服务网格内将请求路由到服务,这基于 Istio 和平台提供的基本的连通性和服务发现能力。
虚拟服务同时提供了丰富的方式,为发送至这些工作负载的流量指定不同的路由规则。典型的应用场景是A/B测试、金丝雀部署。
客户端将虚拟服务视为一个单一实体,将请求发送至虚拟服务主机(hosts字段),然后 Envoy 根据虚拟服务规则(http字段)把流量路由到不同的版本。
示例:
配置基于服务不同版本的流量百分比路由规则,把请求路由分发到reviews服务的不同版本v1、v3。
kind: VirtualServiceapiVersion: networking.istio.io/v1alpha3metadata:name: reviewsnamespace: defaultselfLink: >-/apis/networking.istio.io/v1alpha3/namespaces/default/virtualservices/reviewsuid: 202e6401-a3ae-407e-a1ce-4bbb67d41228resourceVersion: '121162'generation: 1creationTimestamp: '2021-06-23T07:57:05Z'labels:kiali_wizard: request_routingspec:hosts:- reviews # hosts 字段实际上不必是 Istio 服务注册的一部分,可以是 IP 地址、DNS 名称,或者依赖于平台的一个简称http: # 也可以用 tcp 和 tls 片段为 TCP 和未终止的 TLS 流量设置路由规则- route:- destination:host: reviews.default.svc.cluster.local # destination 的 host 必须是存在于 Istio 服务注册中心的实际目标地址subset: v1weight: 10- destination:host: reviews.default.svc.cluster.localsubset: v2weight: 0- destination:host: reviews.default.svc.cluster.localsubset: v3weight: 90
请求流量数据展示:
目标规则
与虚拟服务一样,目标规则也是 Istio 流量路由功能的关键部分。您可以将虚拟服务视为将流量如何路由到给定目标地址,然后使用目标规则来配置该目标的流量。
kind: DestinationRuleapiVersion: networking.istio.io/v1alpha3metadata:name: reviewsnamespace: defaultselfLink: >-/apis/networking.istio.io/v1alpha3/namespaces/default/destinationrules/reviewsuid: 7644311c-d363-48b1-80eb-221c2462f4c6resourceVersion: '121161'generation: 1creationTimestamp: '2021-06-23T07:57:05Z'labels:kiali_wizard: request_routingspec:host: reviews.default.svc.cluster.localsubsets:- labels:version: v1name: v1- labels:version: v2name: v2- labels:version: v3name: v3
超时和重试
超时是 Envoy 代理等待来自给定服务的答复的时间量,以确保服务不会因为等待答复而无限期的挂起,并在可预测的时间范围内调用成功或失败。
apiVersion: networking.istio.io/v1alpha3kind: VirtualServicemetadata:name: ratingsspec:hosts:- ratingshttp:- route:- destination:host: ratingssubset: v1timeout: 10s
重试设置指定如果初始调用失败,Envoy 代理尝试连接服务的最大次数。通过确保调用不会因为临时过载的服务或网络等问题而永久失败,重试可以提高服务可用性和应用程序的性能。重试之间的间隔(25ms+)是可变的,并由 Istio 自动确定,从而防止被调用服务被请求淹没。HTTP 请求的默认重试行为是在返回错误之前重试两次。
apiVersion: networking.istio.io/v1alpha3kind: VirtualServicemetadata:name: ratingsspec:hosts:- ratingshttp:- route:- destination:host: ratingssubset: v1retries: # 初始调用失败后最多重试 3 次来连接到服务子集,每个重试都有 2 秒的超时attempts: 3perTryTimeout: 2s
故障注入
- 延迟:延迟是时间故障。它们模拟增加的网络延迟或一个超载的上游服务。
- 终止:终止是崩溃失败。他们模仿上游服务的失败。终止通常以 HTTP 错误码或 TCP 连接失败的形式出现。
apiVersion: networking.istio.io/v1alpha3kind: VirtualServicemetadata:name: ratingsspec:hosts:- ratingshttp:- fault:delay:percentage:value: 10 # 10分之1的访问rating服务请求,配置了5s延迟fixedDelay: 5sroute:- destination:host: ratingssubset: v1
