Istio 1.0 的实战测试

原文:Battle Testing Istio 1.0

原作者:Jakub Pavlík

最近 Istio 成功发布了 1.0,并宣称生产就绪。我们的 SRE 团队对 Istio 1.0 生产状态进行了全面分析,最后提出了我们的建议。

本文结构:

  • 安装和环境。
  • 要点和建议。

安装和环境

Istio 构建在微服务架构基础之上,其中的应用网络由多个服务构成:

  • Sidecar:接收来自 Pilot 的配置信息,以代理服务器的身份处理入站和出站流量。
  • Pilot:管理代理服务器,并和 Kubernetes 进行交互。
  • Mixer:接收来自代理服务器的指标,实施访问控制、配额管理等功能。
  • Citadel:为服务和用户提供认证和鉴权、管理凭据和 RBAC。

Istio Architecture

更多细节可移步浏览官方文档

安装过程比较方便。支持不同的环境(例如 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 GoasguenTwitter 中说的:如果你觉得 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 产品来满足消费市场的需要。还需要持续关注性能、伸缩以及策略处理方面的进展。

Avatar
崔秀龙

简单,是大师的责任;我们凡夫俗子,能做到清楚就很不容易了。

comments powered by Disqus
下一页
上一页

相关