Istio 1.0 的实战测试
原作者:Jakub Pavlík
最近 Istio 成功发布了 1.0,并宣称生产就绪。我们的 SRE 团队对 Istio 1.0 生产状态进行了全面分析,最后提出了我们的建议。
本文结构:
- 安装和环境。
- 要点和建议。
安装和环境
Istio 构建在微服务架构基础之上,其中的应用网络由多个服务构成:
- Sidecar:接收来自 Pilot 的配置信息,以代理服务器的身份处理入站和出站流量。
- Pilot:管理代理服务器,并和 Kubernetes 进行交互。
- Mixer:接收来自代理服务器的指标,实施访问控制、配额管理等功能。
- Citadel:为服务和用户提供认证和鉴权、管理凭据和 RBAC。
更多细节可移步浏览官方文档。
安装过程比较方便。支持不同的环境(例如 Docker),但是 Kubernetes 是最适合我们需要的。
安装方法支持列表:
- 预渲染的 YAML:这种方式适合预制环境(演示、评估以及 PoC 等);这是因为其中的参数调整非常困难。YAML 文件可以进行模板化处理,但是其中有超过 3700 行代码,需要较大投入才能完成定制。
- Helm:这种方式是参数化的,比较适合真实世界中的部署活动。正式的环境部署应该需要这样的定制能力。
本文只是一次评估,因此使用了第一种方式。
用静态 YAML 部署的 Istio 1.0:
NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE
deploy/grafana 1 1 1 1 20h
deploy/istio-citadel 1 1 1 1 20h
deploy/istio-egressgateway 1 1 1 1 20h
deploy/istio-galley 1 1 1 1 20h
deploy/istio-ingressgateway 1 1 1 1 20h
deploy/istio-pilot 1 1 1 1 20h
deploy/istio-policy 1 1 1 1 20h
deploy/istio-sidecar-injector 1 1 1 1 20h
deploy/istio-statsd-prom-bridge 1 1 1 1 20h
deploy/istio-telemetry 1 1 1 1 20h
deploy/istio-tracing 1 1 1 1 20h
deploy/prometheus 1 1 1 1 20h
deploy/servicegraph 1 1 1 1 20h
NAME REFERENCE TARGETS MINPODS MAXPODS REPLICAS AGE
hpa/istio-egressgateway Deployment/istio-egressgateway <unknown> / 55% 1 5 1 20h
hpa/istio-ingressgateway Deployment/istio-ingressgateway <unknown> / 55% 1 5 1 20h
NAME DESIRED SUCCESSFUL AGE
jobs/istio-cleanup-secrets 1 1 20h
jobs/istio-grafana-post-install 1 1 20h
jobs/istio-mixer-post-install-1.0 1 1 20h
NAME READY STATUS RESTARTS AGE
po/grafana-67b5df5b97-d685n 1/1 Running 0 20h
po/istio-citadel-65df4cf668-xspff 1/1 Running 0 20h
po/istio-egressgateway-6678667b46-pmfmx 1/1 Running 0 20h
po/istio-galley-7c64c8c948-8npwp 1/1 Running 27 20h
po/istio-ingressgateway-6dfd7fc84-w6snd 1/1 Running 0 3h
po/istio-pilot-6cc9f4f7c6-552h4 2/2 Running 0 20h
po/istio-policy-5476f99674-sqn7h 2/2 Running 0 20h
po/istio-sidecar-injector-5f47598cd7-8qlq6 1/1 Running 0 20h
po/istio-statsd-prom-bridge-5d44ddb7cf-lrc8t 1/1 Running 0 20h
po/istio-telemetry-654bfd8487-bmdwv 2/2 Running 0 20h
po/istio-tracing-5fbd79cc-pnq5n 1/1 Running 0 20h
po/prometheus-7b6f8b9996-t4t92 1/1 Running 0 20h
po/servicegraph-7d7ccc9b7f-b86c4 1/1 Running 0 20h
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
svc/grafana ClusterIP 10.0.18.159 <none> 3000/TCP 20h
svc/istio-citadel ClusterIP 10.0.228.1 <none> 8060/TCP,9093/TCP 20h
svc/istio-egressgateway ClusterIP 10.0.217.249 <none> 80/TCP,443/TCP 20h
svc/istio-galley ClusterIP 10.0.131.153 <none> 443/TCP,9093/TCP 20h
svc/istio-ingressgateway LoadBalancer 10.0.72.147 13.66.222.246 80:31380/TCP,443:31390/TCP,31400:31400/TCP,15011:30223/TCP,8060:31415/TCP 20h
svc/istio-pilot ClusterIP 10.0.67.90 <none> 15010/TCP,15011/TCP,8080/TCP,9093/TCP 20h
svc/istio-policy ClusterIP 10.0.135.115 <none> 9091/TCP,15004/TCP,9093/TCP 20h
svc/istio-sidecar-injector ClusterIP 10.0.158.161 <none> 443/TCP 20h
svc/istio-statsd-prom-bridge ClusterIP 10.0.17.41 <none> 9102/TCP,9125/UDP 20h
svc/istio-telemetry ClusterIP 10.0.139.187 <none> 9091/TCP,15004/TCP,9093/TCP,42422/TCP 20h
svc/jaeger-agent ClusterIP None <none> 5775/UDP,6831/UDP,6832/UDP 20h
svc/jaeger-collector ClusterIP 10.0.172.142 <none> 14267/TCP,14268/TCP 20h
svc/jaeger-query ClusterIP 10.0.51.47 <none> 16686/TCP 20h
svc/prometheus ClusterIP 10.0.156.162 <none> 9090/TCP 20h
svc/servicegraph ClusterIP 10.0.163.81 <none> 8088/TCP 20h
svc/tracing ClusterIP 10.0.111.218 <none> 80/TCP 20h
svc/zipkin ClusterIP 10.0.89.198 <none> 9411/TCP 20h
要点和建议
操作复杂度
Istio 的功能集随着每次发布逐步增长,运维需求也自然是水涨船高。要运维 Istio,不仅要有对 Istio 组件和配置的基本理解,还需要对 Kubernetes 有深入的认识。Istio 1.0 中包含了 51 个 CRD,比 0.8 版本又多出了 8 个。
正如 Sebastein Goasguen 在 Twitter 中说的:如果你觉得 Kubernetes 很难,来看看(理解和维护)Istio 和他的 43 个 API 对象吧。
运维的复杂性,在未来可以用 Galley 对服务和客户端的配置管理来进行简化。Galley 是 1.0 中新引入的组件,在 Istio 中,承担配置的导入、处理和分发任务。这一组件的主要目标是应对现有的配置方面的挑战,例如检测、组件之间的复用、配置错误和验证等问题。这样就可以提供更好的运维体验,同时降低对 Istio 各组件深入理解的需求。Galley 负责把其它 Istio 组件和从底层平台获取用户配置的细节中隔离开来。它其中包含了 Kubernetes 的 CRD 监听器,用来收集配置;还有一个网格配置协议(Mesh Config Protocol-MCP)服务器用于配置分发;以及一个用于验证的 Webhook,使用 Kubernetes API Server 对配置进行前置检查。
Galley 在 Istio 1.0 中可以禁用,并且在 AWS EKS 中必须和 Sidecar 的自动注入一起禁用,这是因为 EKS 不支持启用准入控制器,例如这里要用到的修改和验证 Webhook。加入 Google Group 阅读 Galley 概要设计文档 可以获得更多信息。
管理 Ingress Gateway
在 v1alpha3 中, Istio Gateway 和 VirtualService 一起,替换了 Kubernetes 的原生 Ingress。相对于 Kubernetes 的原生 Ingress,这一组合提供了更多高级配置。然而这些资源只是定义,真正的流量管理是由 Ingress Gateway 完成的。
Ingress Gateway 是一个 Istio proxy(Envoy),它会根据 Gateway 和 VirtualService 定义响应网格外发来的入站流量。缺省的安装只包含一个 ingressgateway
pod 并且只使用 LoadBalancer 服务申请了一个公共 IP。要注意下面的限制:
- 多个服务无法同时监听同一个外部端口,例如网格外只能开放一个 3306 端口。
VirtualService
的路径不可重叠。如果有多个独立团队使用 Istio 的话可能会出现问题。
这两个限制都可以通过部署多个 ingressgateway
pod 来监听多个公共 IP 的方式来解决。遗憾的是,对多个 ingressgateway
实例的管理不太简单,需要自行定义合适的选择器。
配置验证和同步
可以使用标准的 kubectl
命令配置 Istio,也可以选择使用原生的 istioctl
工具。两种方法会得到同样的结果——在 Kubernetes 中创建 CRD。
注意:只有
istioctl
会在把定义文件发送给 Kubernetes API Server 之前对 CRD 进行验证。
Kubernetes 中部署的 Istio Webhook 会进行第二次验证,但是他只会对配置的结构进行验证,功能验证目前还没有实现。因为只做语义验证不做功能验证,上面提到的路径叠加问题会很容易遇到。
Istio 1.0 在 istioctl
命令中加入很多状态和健康状态方面的改进。istioctl proxy-status
命令会获取 Pilot 和 Envoy 之间最新发送和接收的 xDS 同步信息,并提供一个状态概览:
istioctl proxy-status
PROXY CDS LDS EDS RDS PILOT VERSION
details-v1-7bcdcc4fd6-9p7sr.default SYNCED SYNCED SYNCED (100%) SYNCED istio-pilot-6cc9f4f7c6-552h4 1.0.0
istio-egressgateway-6678667b46-pmfmx.istio-system SYNCED SYNCED SYNCED (100%) NOT SENT istio-pilot-6cc9f4f7c6-552h4 1.0.0
istio-ingressgateway-6dfd7fc84-w6snd.istio-system SYNCED SYNCED SYNCED (100%) SYNCED istio-pilot-6cc9f4f7c6-552h4 1.0.0
kad-5f89bf94fc-b48z2.kad SYNCED SYNCED SYNCED (100%) SYNCED istio-pilot-6cc9f4f7c6-552h4 1.0.0
productpage-v1-8584c875d8-9mlbr.default SYNCED SYNCED SYNCED (100%) SYNCED istio-pilot-6cc9f4f7c6-552h4 1.0.0
ratings-v1-54cf9dc8f8-hthzx.default SYNCED SYNCED SYNCED (100%) SYNCED istio-pilot-6cc9f4f7c6-552h4 1.0.0
reviews-v1-59cbdd7959-2ng8m.default SYNCED SYNCED SYNCED (100%) SYNCED istio-pilot-6cc9f4f7c6-552h4 1.0.0
reviews-v2-dccb4cfc9-rp6rx.default SYNCED SYNCED SYNCED (100%) SYNCED istio-pilot-6cc9f4f7c6-552h4 1.0.0
reviews-v3-5465dc97bc-k9rdb.default SYNCED SYNCED SYNCED (100%) SYNCED istio-pilot-6cc9f4f7c6-552h4 1.0.0
StatefulSet 和 Headless 服务的支持
Headless 服务是没有 IP 的,服务中的各个实例通常会用点对点的形式进行访问,因此在服务网格中,这种服务是个难于应对的问题。要给这种服务配置 mTLS 认证,流量的检测和处理都可能遇到问题。
Kubernetes StatefulSet 经常和 Headless 服务一同使用。在服务实例之间进行通信时,我们也发现了问题。我们用 StatefulSet 运行 Cassandra 集群,第二个实例出现了如下问题:
INFO 13:44:05 Handshaking version with cassandra-0.cassandra.sre.svc.cluster.local/10.244.4.33
INFO 13:44:05 Cannot handshake version with cassandra-0.cassandra.sre.svc.cluster.local/10.244.4.33
要解决这个问题,要把 Cassandra 移出网格,或者修改 mTLS 认证策略。这一问题在目前正在跟踪之中。
https://github.com/istio/istio/issues/5005
https://github.com/istio/istio/pull/6885
https://github.com/istio/istio/issues/1277
Pod 检测
Kubernetes 会进行 Pod 检测,查看 Pod 的存活和就绪状态。检测方法有多种实现方式,TCP 和 HTTP 是最常见的。当 Kubelet 能够通过 HTTP 请求或者 TCP 连接访问到 Pod,就会判定 Pod 检测成功。当服务间的 mTLS 启用时,Kubelet 却并非网格的一部分,因此就无法访问 Pod 了。
要解决这一问题:
- 推荐方案是为服务检测准备单独的端口,并在这一端口上禁用认证功能。
- 禁止 Pod 检测也是一个可选方案。
- 在 Pod 内部使用 exec 检测,代替 Kubelet 完成这一任务。然而我们不推荐这种方式,这种检测不够全面,可能会有隐藏问题存在,例如 CNI。
多集群鸿沟
Istio 从 0.8 开始支持单控制平面下的多集群部署。博客中提供了 0.8 中运行多集群 Istio 的详细介绍。Google 还在上一次 KubeCon 上做了一次演示(视频)。1.0 版本中加入了为数众多的安全和性能方面的改进,其中包括远程集群的 Sidecar 自动注入能力。这方面可以参考详细设计文档。
不幸的是这一功能在我们的生产环境上也是有问题的,现列举如下:
- 集群间的 Pod 网络需要打通——这超出了 Istio 的能力范围,应该由 VPN 来完成这一任务。目前有提案使用 Zero VPN 来解决这一问题。
- 远端集群需要能够解析 Pilot、Policy、Telemetry 以及 StatsD 端点——目前远程集群会使用控制面集群的 Pod IP,而 Pod IP 是可能因为 Pod 重启或者 Node 崩溃而发生变化的,这就需要重新部署 Istio。目前已经有 PR 在尝试解决这个问题:部署额外的 Istio Ingress Gateway 来负责对 Istio Pilot、Policy 以及 Telemetry 端点的访问。
- Istio 的配置和状态是保存在“主”集群上的,一旦主集群发生了故障,就会出现跨集群的瓶颈。
- Github 上还跟踪了其它 Issue。
结论
Istio 是第一个生产就绪的版本,多数核心组件都已稳定,我们对其稳定性基本满意,运维方面还存在一些问题,在生产环境中的应用很有挑战性。
- 因为新的操作可能会对既有工作负载造成影响,动态环境中的运维活动颇具危险性。
- 必须监控的一些内容:配置变更,Sidecar 日志,Mixer 中的 Kubernetes 适配器。
- 部分 Kubernetes 特性并未完整集成,例如 Pod 检测、Headless 服务。
迄今为止,Istio 获得了巨大成就。如果是对系统缺乏深入理解的用户,要在生产环境中操作 Kubernetes 还是有一定难度的。我们认为,Istio 1.0 的完成度是合乎要求的,目前的用户多数都要归为超级用户的类别。短期之内,需要托管的 Istio 产品来满足消费市场的需要。还需要持续关注性能、伸缩以及策略处理方面的进展。