# Istio 1.0 的实战测试

原文：[Battle Testing Istio 1.0](https://medium.com/vescloud/battle-testing-istio-1-0-a0248ce68403)

原作者：[Jakub Pavlík](https://medium.com/@pupapaik)

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

本文结构：

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

## 安装和环境

Istio 构建在[微服务架构](https://medium.com/microservices-in-practice/microservices-layered-architecture-88a7fc38d3f1)基础之上，其中的应用网络由多个服务构成：

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

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1746317121859/2fc6099f-f10c-4657-a893-54941aa6bd97.png align="center")

更多细节可移步浏览[官方文档](https://istio.io/docs/zh/concepts/what-is-istio/overview/#architecture)。

安装过程比较方便。支持不同的环境（例如 Docker），但是 Kubernetes 是最适合我们需要的。

安装方法支持列表：

* **预渲染的 YAML**：这种方式适合预制环境（演示、评估以及 PoC 等）；这是因为其中的参数调整非常困难。YAML 文件可以进行模板化处理，但是其中有超过 3700 行代码，需要较大投入才能完成定制。
    
* **Helm**：这种方式是参数化的，比较适合真实世界中的部署活动。正式的环境部署应该需要这样的定制能力。
    

本文只是一次评估，因此使用了第一种方式。

**用静态 YAML 部署的 Istio 1.0**：

```bash
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](https://twitter.com/sebgoa) 在 [Twitter](https://medium.com/vescloud/battle-testing-istio-1-0-a0248ce68403) 中说的：如果你觉得 Kubernetes 很难，来看看（理解和维护）Istio 和他的 43 个 API 对象吧。

运维的复杂性，在未来可以用 Galley 对服务和客户端的配置管理来进行简化。Galley 是 1.0 中新引入的组件，在 Istio 中，承担配置的导入、处理和分发任务。这一组件的主要目标是应对现有的配置方面的挑战，例如检测、组件之间的复用、配置错误和验证等问题。这样就可以提供更好的运维体验，同时降低对 Istio 各组件深入理解的需求。Galley 负责把其它 Istio 组件和从底层平台获取用户配置的细节中隔离开来。它其中包含了 Kubernetes 的 CRD 监听器，用来收集配置；还有一个网格配置协议（Mesh Config Protocol-MCP）服务器用于配置分发；以及一个用于验证的 Webhook，使用 [Kubernetes API Server](https://github.com/istio/istio/tree/master/galley) 对配置进行前置检查。

Galley 在 Istio 1.0 中可以禁用，并且在 AWS EKS 中必须和 Sidecar 的自动注入一起禁用，这是因为 EKS 不支持启用准入控制器，例如这里要用到的修改和验证 Webhook。加入 [Google Group](https://groups.google.com/forum/#!forum/istio-dev) 阅读 [Galley 概要设计文档](https://docs.google.com/document/d/1477BlHU0leWA4IKFRwnbNl5MZngf5m2K-JsBIo6dxJE/edit#) 可以获得更多信息。

### 管理 Ingress Gateway

在 [v1alpha3](https://istio.io/docs/reference/config/istio.networking.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 同步信息，并提供一个状态概览：

```bash
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 集群，第二个实例出现了如下问题：

```bash
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 开始支持单控制平面下的多集群部署。[博客](https://medium.com/ibm-cloud/multi-cluster-support-for-service-mesh-with-ibm-cloud-private-d7d791f9b778)中提供了 0.8 中运行多集群 Istio 的详细介绍。Google 还在上一次 KubeCon 上做了一次演示（[视频](https://youtu.be/bLJL53UIcqI?t=14m9s)）。1.0 版本中加入了为数众多的安全和性能方面的改进，其中包括远程集群的 Sidecar 自动注入能力。这方面可以参考[详细设计文档](https://docs.google.com/document/d/1cOxPnTpnVWKR0m7a6PYJ-0NSTZ-e2J1IULnfojz7OZ4/edit#)。

不幸的是这一功能在我们的生产环境上也是有问题的，现列举如下：

* 集群间的 Pod 网络需要打通——这超出了 Istio 的能力范围，应该由 VPN 来完成这一任务。目前有提案使用 [Zero VPN](https://docs.google.com/document/d/1QLMeycCoj6fbBKoOLiaDCc09Fbi89s5VoBW-eAxKwVs/edit#heading=h.qex63c29z2to) 来解决这一问题。
    
* 远端集群需要能够解析 Pilot、Policy、Telemetry 以及 StatsD 端点——目前远程集群会使用控制面集群的 Pod IP，而 Pod IP 是可能因为 Pod 重启或者 Node 崩溃而发生变化的，这就需要重新部署 Istio。目前已经有 [PR](https://github.com/istio/istio/pull/6210) 在尝试解决这个问题：部署额外的 Istio Ingress Gateway 来负责对 Istio Pilot、Policy 以及 Telemetry 端点的访问。
    
* Istio 的配置和状态是保存在“主”集群上的，一旦主集群发生了故障，就会出现跨集群的瓶颈。
    
* Github 上还跟踪了其它 [Issue](https://github.com/istio/istio/issues/4822)。
    

## 结论

Istio 是第一个[生产就绪的版本](https://preliminary.istio.io/about/notes/1.0/)，多数核心组件都已稳定，我们对其稳定性基本满意，运维方面还存在一些问题，在生产环境中的应用很有挑战性。

* 因为新的操作可能会对既有工作负载造成影响，动态环境中的运维活动颇具危险性。
    
* 必须监控的一些内容：配置变更，Sidecar 日志，Mixer 中的 Kubernetes 适配器。
    
* 部分 Kubernetes 特性并未完整集成，例如 Pod 检测、Headless 服务。
    

迄今为止，Istio 获得了巨大成就。如果是对系统缺乏深入理解的用户，要在生产环境中操作 Kubernetes 还是有一定难度的。我们认为，Istio 1.0 的完成度是合乎要求的，目前的用户多数都要归为超级用户的类别。短期之内，需要托管的 Istio 产品来满足消费市场的需要。还需要持续关注性能、伸缩以及策略处理方面的进展。
