华尔街见闻基于istio的服务网格实践

距离2017 年的见闻技术架构调整接近 2 年,随着业务线的发展,见闻技术部的项目数量、项目架构类型、基础设施规模、服务变动频率都在不断地增加,带给 SRE 的挑战是如何能更快地助力于开发人员更快更稳定地部署服务,保障线上服务的稳定。前端

咱们的后端开发团队仍然以 Golang 为主,不一样业务线的技术选型不尽相同,同时存在 Python,Java 服务,这就须要 SRE 提供更易接入的微服务基础组件,常见的方案就是为每种语言提供适配的微服务基础组件,但痛点是基础组件更新维护的成本较高。git

为了解决痛点,咱们将目光放到服务网格,它能利用基础设施下沉解决多语言基础库依赖问题,不一样的语言不须要再引入各类不一样的服务发现、监控等依赖库,只需简单的配置并运行在给定的环境下,就能享有以上功能,同时网络做为最重要的通讯组件,能够基于它实现不少复杂的功能,譬如根据不一样可用区进行的智能路由、服务熔断降级等。github

为此,咱们调研了一些服务网格方案,包括IstioLinkerd,基于咱们的当前的后端架构特色:golang

  • 服务通讯协议主要基于 gRPC、HTTP
  • 基于 Kubernetes 的 Docker 部署
  • 拥抱开源,使用了 Prometheus、Grafana 做为监控,Zipkin 做为链路追踪等

对比下来,Istio 拥有更多活跃的开源贡献者,迭代速度快,以及 Istio 架构可行性讨论,咱们选择 Istio 做为实践方案。docker

架构

Service Mesh

这张图介绍了见闻典型的服务网格架构,左半图介绍了一个用户请求是如何处理,右半图介绍运维系统是如何监控服务,若无特殊说明,服务都是部署在腾讯云托管 Kubernetes。数据库

组件一览

  • Go(1.11) 后端语言。
  • Docker(17.12.1-ce) 容器技术。
  • Kubernetes(1.10.5,托管于腾讯云容器平台) 容器编排工具。
  • Istio(1.0.0) 服务网格开源方案,支持与 Kubernetes 集成。
    • Ingress, Proxy(Istio 1.0.0) 服务流量转发、智能代理,基于Envoy实现,Istio 二次开发Proxy
    • Pilot Discovery(Istio 1.0.5) 负责服务发现,经过监听 Kubernetes 中ServicePod等资源维护服务映射表。
    • Mixer Policy(Istio 1.0.5) 管理服务之间访问权限,提供 gRPC 形式的 Check 接口。
    • Mixer Telemetry(Istio 1.0.5) 负责接收服务指标数据,提供 gRPC 形式的 Report 接口。
    • Citadel 负责管理代理证书。
  • Dashboard 基于Kubernetes Dashboard二次开发的Istio Dashboard,负责管理 Istio 服务发布,配置变动等。
  • Grafana 负责监控数据可视化。
  • Prometheus 时序数据库,经常使用于监控系统。
  • Jaeger 负责服务链路追踪,组件包括 collector、Jaeger UI。
  • Cassandra 分布式 NoSQL 数据库,用于 Jaeger 指标数据存储。

用户请求分析

  1. 咱们先从用户请求端开始,用户的请求经过 Tencent 4 层 LB 转发到基于 Envoy 的 Istio Ingress,Ingress 根据配置将请求路由到 Service A 所在的 Pod
  2. Service A 所在 Pod 接收 Ingress 请求
    • 访问 Service A 的请求会先到达 Proxy 再由它转发到 Service A 进程
    • Service A 向 Service B 发出的请求被 iptables 路由到 Proxy(下文会提到 iptables 的初始化)
    • Proxy 进程发起对 Service B 所在 Pod 的请求
      • Proxy 进程同步请求 Mixer Policy 服务,检查是否容许访问 Service B,检查经过,开始请求
      • Proxy 进程记录请求的指标(QPS,Latency,Status Code 分布等),异步并批量上报到 Mixer Telemetry 服务,这里是客户端指标
  3. Service B 所在 Pod 接收请求
    • Service B Proxy 接收请求并路由到 Service B 所在进程
      • Proxy 进程记录请求的指标(QPS,Latency,Status Code 分布等),异步并批量上报到 Mixer Telemetry 服务,这里是服务端指标
    • Service B 进程处理完请求并返回
  4. 数据原路返回到用户端

以上的流程能够观察到,服务之间通讯彻底依靠 Proxy 进程完成,Proxy 进程接管同一个 Pod 中服务的出入流量,完成请求的路由。apache

架构可行性

经过架构图以及以上流程,咱们拆分出如下关键组件,观察其性能、可用性、拓展性。后端

  1. Istio Ingress 高性能,可拓展 Istio Ingress 用来处理用户入流量,使用 Envoy 实现,转发性能高。挂载在负载均衡后,经过增长实例实现可拓展。api

  2. Istio Proxy 随应用部署,轻微性能损耗,可随应用数量拓展 Istio Proxy 以Sidecar形式随应用一块儿部署,增长 2 次流量转发,存在性能损耗。 性能: 4 核 8G 服务器,上面运行 Proxy 服务和 API 服务,API 服务只返回 ok 字样。(此测试只测试极限 QPS) 单独测试 API 服务的 QPS 在 59k+,平均延时在 1.68ms,CPU 占用 4 核。 经过代理访问的 QPS7k+,平均延时 14.97ms,代理 CPU 占用 2 核,API 服务 CPU 占用 2 核。 CPU 消耗以及转发消耗下降了 QPS,增长了延时,经过增长机器核数并增长服务部署数量缓解该问题,通过测试环境测试,延时能够接受。 可用性:基于 Envoy,咱们认为 Envoy 的可用性高于应用。依赖 Pilot Discovery 进行服务路由,可用性受 Pilot Discovery 影响。 拓展性:Sidecar 形式,随应用数拓展缓存

  3. Istio Policy 服务可拓展,但同步调用存在风险 Istio Policy 须要在服务调用前访问,是同步请求,会增长服务调用延时,经过拓展服务数量增长处理能力。属于可选服务,见闻生产未使用该组件。 性能: 未测试 可用性:若开启 Policy,必须保证 Policy 高可用,不然正常服务将不可用 拓展性:增长实例数量进行拓展

  4. Istio Telemetry 监控收集服务 性能: 从监控上观察 Report 5000qps,使用 25 核,响应时间 p99 在 72ms。异步调用不影响应用的响应时间。 可用性:Telemetry 不影响服务可用性 拓展性:增长实例数量进行拓展

  5. Pilot Discovery 性能: 服务发现组件 1.0.5 版本通过监控观察,300 个 Service,1000 个 Pod,服务变动次数 1 天 100 次,平均 CPU 消耗在 0.01 核,内存占用在 1G 之内。 可用性: 在服务更新时须要保证可用,不然新建立的 Pod 没法获取最新路由规则,对于已运行 Pod 因为 Proxy 存在路由缓存不受 Pilot Discovery 关闭的影响。 拓展性:增长实例数量能够增长处理量。

能够看到各个组件的可用性、拓展性都有相应的策略达到保障,咱们认为 Istio 是具备可实施性的。

Istio 流量控制背后

Pilot Discovery: Istio 的交通大脑

Pilot Discovery 负责 Istio 服务发现,支持在 Kubernetes 里部署,它读取 K8S 资源配置,并生成 Proxy 可用的路由表。如下面的 Service A 服务为例,介绍 Istio 如何进行精细路由。

Pilot Discovery生成配置

  1. Discovery 与对应 K8S 集群的 API server 相连,拉取全量资源信息,并使用 Watch 方法对增量变动进行同步。
  2. 根据 Service A 的配置,生成对应 Service A 的路由配置,经过 gRPC 形式的 ADS 接口提供给 Proxy。
  3. Proxy 同步到最新配置,热更新后配置生效。

要知道若是在 Istio 访问一个服务,必须得声明 K8S Service

Istio 经过 K8S CRD拓展 K8S 已有的服务访问能力,咱们列举网络相关经常使用的配置:

  • Gateway 控制 Istio Ingress 的路由转发及 TLS 证书绑定。
  • VirtualService 服务流量控制,实现如 A/B 测试、错误注入、服务保护等。
  • DestinationRule 用于目标服务的版本管理,根据 Pod 的 Label 区分目标服务的版本,联合 VirtualService 进行流量控制。

如下举个例子介绍如何利用它们配置一样大小流量到服务的不一样版本,

# serviceA.yaml
kind: Service
apiVersion: v1
metadata:
 name: serviceA
 labels:
 app: serviceA
spec:
 ports:
 - name: http-8080
 protocol: TCP
 port: 8080
 targetPort: 8080
 selector:
 app: serviceA
 type: ClusterIP

# virtualServiceA.yaml
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
 name: serviceA
spec:
 hosts:
 - serviceA
 http:
 - route:
 - destination:
 host: serviceA
 subset: v1
 - route:
 - destination:
 host: serviceA
 subset: v2
---
# destinationRule
apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
 name: serviceA
spec:
 host: serviceA
 subsets:
 - labels:
 version: v1
 name: v1
 - labels:
 version: v2
 name: v2
复制代码

以上实现了 Istio 服务调用 serviceA 时,会随机地 50%几率到 serviceA 的 v1 版本,50%几率到 serviceA 的 v2 版本。

能够看到,VirtualService 经过 hosts 关联 serviceA,在 http 区域有两个 route,分别是 subset v1, subset v2,v1,v2 依赖 DestinationRule 来定义,一样用 host 来标注该 DestinationRule 控制哪一个 host 的访问,以及经过 pod label 中 version 来划分不一样版本。

流量控制方面,Istio 有至关丰富的功能支持,同时也带来了至关的复杂度,建议用户根据平常的使用频率在后台实现相应的前端控制台,利用自动化来完成流量控制。

Proxy 工做机制

  1. 自动注入 在 K8S 1.9 以后的版本,Istio 利用 K8S 提供的MutatingAdmissionWebhook在 K8S 建立 Pod 前回调 Istio 提供的 istio-sidecar-injector 动态修改 Pod 配置,添加以 Sidecar 形式运行的 Proxy。这里开启自动注入有两个维度,一是 namespace,namespace 须要添加istio-injection : enabled标签,这样实现该 namespace 下的全部 Pod 自动注入 Proxy;二是 deployment 能够设置 annotation 关闭自动注入。 若是 K8S 版本不够,能够利用命令行工具修改 Deployment 的配置。
  2. 接管 Pod 流量 Service A 所在 Pod 至少运行 Service A 应用容器以及用于代理的 Envoy 容器,建立 Pod 时 proxy-init 命令负责获取 Pod 监听的端口和具体协议,以此初始化网络,利用 iptables 将容器网络出入流量都转发到 Proxy 监听的 localhost 端口。 若 Service A 的 Pod 声明 servicePort 为 8080:HTTP,最终 Proxy 将会接收 8080 端口的 Pod 入流量和所有的 Pod 出流量。
  3. 服务发现 Proxy 基于 Envoy,与 Pilot Discovery 链接,动态同步 Kubernetes 集群中全部的服务信息:服务与 Pod IP、端口之间的映射表,经过路由信息实现智能路由,从而使服务发现从业务代码中剥离。
  4. 链路追踪 Proxy 支持设置 Zipkin URL,异步上报链路追踪数据。
  5. 服务质量监控 Proxy 将属性包上报给 Telemetry 服务,Telemetry 根据用户的配置生成指标数据并由 Prometheus 收集。

适配 Istio

咱们目前的服务部署在腾讯云托管 Kubernetes,节点使用 16 核 32G 的网络加强型机器,全部的后端服务都以 Docker 部署,K8S 集群外部署高可用 ETCD 支持集群内服务发现,数据库以 MySQL、Cassandra、MongoDB 为主,消息队列采用 Kafka、NSQ。在应用 Istio 的过程当中,咱们对基础库进行了修改,删减了 Istio 已提供的功能并完成了对 Istio 的适配。

前情提要

见闻旧后端服务架构,全部 Golang 服务以打包成 Docker 镜像,以"gRPC"协议通讯。

old-infrastructure

去"框架"

见闻 Golang 后端使用go-micro 框架,一个支持多插件的 Golang 微服务框架,做者将组件分红 transport,server,client,registry,codec 等,经过组合不一样类型的组件很是灵活地配置微服务技术栈。对于有定制需求的微服务架构,是值得推荐的选择。

通讯协议做为服务互通的基石,Istio 对 gRPC 和 HTTP 很是友好,根据协议 Istio 能解析 HTTP 头中的信息,支持提取指标以供分析。go-micro 只是利用 HTTP 和 gRPC 做为通讯协议,可是协议的解析逻辑是协议无关的,因此能够说它只是用了这些通讯协议的外壳,传输的报文内容是"micro 方言",这就致使了 Golang 暴露的服务没法被其它语言其它框架调用。为了将协议能在多语言中彻底统一,也为了更好地使用 Istio 的监控统计功能,这个时候咱们开始对 go-micro 的存留有一些新的思考,咱们是否还须要 go-micro?通过近 2 年的生产实践,咱们是否是能够更精简咱们的框架?

通过这些思考事后,咱们的决定是去 go-micro 框架,拥抱更轻量级的基础框架,这个框架只要支持:

  • gRPC 纯原生便可
  • Istio 支持 Istio 的基础功能,譬如一些 HTTP header 转发等
  • 改动尽可能小 咱们已经存在上百个 Golang 项目,避免改动 Golang 项目代码,将改动放到基础库为佳

go-micro 经过定义自制 protobuf 插件的方式在 stub 代码中集成框架功能,通过对逻辑的梳理,咱们决定复写 protobuf 插件,生成兼容 micro 的 stub 代码,经过对 micro 接口的向后兼容,开发人员不须要修改代码,只须要在 CI 阶段运行 protoc 即时生成新版代码。

详情可见再见,micro

运维流程

右半图描述运维人员如何利用运维后台运维 Kubernetes 集群,Istio 的运维必须有自动化的工具来减小人工配置带来的错误,见闻的旧运维后台基于腾讯云容器平台暴露的开放 API,在引入 Istio 后,功能依赖于更细节的 label 以及 CRD(Custom Resource Definition),因而得依托更细粒度的 Kubernetes API,新的后台须要能完成基本的 Kubernetes 运维,并且结合 Istio 的实际进行平常更新,通过选型,见闻基于 Kubernetes Dashboard 二次开发了 Istio 部分的一些功能(APP 部署、更新,Istio 配置更新等),利用 Istio Dashboard 实现 APP 建立、部署接口,并由此重构原有的运维后台。

最终,SRE 提供两个后台,精细控制的 Istio Dashboard;提供给开发人员平常更新使用的简化版后台。

服务发布

平常最重要、最高频的功能,服务版本变动。

服务建立

服务建立包括对老服务的改造,一个 K8S 服务要通过一些配置上的更新才能成为 Istio APP。一个 Kubernetes 服务须要知足如下要求来得到 Istio 的功能支持:

  • Service资源声明服务监听的端口号以及协议 这里的服务端口声明中 name 字段值须要以协议名为起始值,譬如 grpc、http、tcp、udp 等,istio 识别前缀,用于初始化 Proxy,譬如grpc-svchttp-svc,不正确的端口命名会引发 Proxy 的异常行为,以及监控服务没法捕获该协议下的指标。

  • 服务探活接口 每一个后端服务提供一个 HTTP 探活接口,这样服务启动时,不至于让其它服务访问到未就绪的状态。 对于 HTTP 探活接口的定义包括 Proxy 以及 APP 是否初始化完成,见闻的实践是在基础镜像中打入一个探活程序:

    1. 检测 Proxy 是否初始化 经过 Proxy 的配置同步时间与 Pilot Discovery 的配置更新时间对比,相同时认为其就绪。
    2. APP 自定义接口 APP 能够在指定端口提供就绪 API。
    # serviceA.yaml
    kind: Service
    apiVersion: v1
    metadata:
     name: serviceA
     namespace: default
     labels:
     app: serviceA
    spec:
     ports:
     - name: grpc
     protocol: TCP
     port: 10088
     targetPort: 10088
     selector:
     app: serviceA
     type: ClusterIP
    复制代码
  • Deployment 资源要求

    1. 有必要的两个 label:app 和 version,明肯定义流量控制中的目标服务。 能够看例子中 deployment 的 app 为 serviceA,version 为 v1。
    2. 声明对外服务的端口,要求 Proxy 对指定端口入流量的接管。 例子中 ports 声明了 10088 端口。
    # deploymentA.yaml
    kind: Deployment
    apiVersion: extensions/v1beta1
    metadata:
     name: serviceA-v1
     labels:
     app: serviceA
     version: v1
    spec:
     replicas: 1
     selector:
     matchLabels:
     app: serviceA
     version: v1
     template:
     metadata:
     labels:
     app: serviceA
     version: v1
     spec:
     containers:
     - name: serviceA
     image: "some-image"
     ports:
     - containerPort: 10088
     protocol: TCP
     resources:
     requests:
     cpu: 1000m
     livenessProbe:
     httpGet:
     path: /health
     port: 54321
     scheme: HTTP
     initialDelaySeconds: 1
     timeoutSeconds: 2
     periodSeconds: 5
     successThreshold: 1
     failureThreshold: 3
     terminationMessagePath: /dev/termination-log
     terminationMessagePolicy: File
     imagePullPolicy: Always
     securityContext:
     privileged: false
     restartPolicy: Always
     terminationGracePeriodSeconds: 30
     dnsPolicy: ClusterFirst
    复制代码

符合以上要求,服务能正确接入 Istio 系统并得到服务发现和监控的能力。

服务更新

Istio 提供流量控制,给运维带来方便的 A/B 测试,用于根据指定规则迁移流量。 见闻的服务更新依靠 Istio 流量迁移功能,发布服务的新版本,并将流量经过 Istio 规则迁移到新版本,实际细节以下:

  1. 更新流量控制将流量指向已有版本 如下实例利用 VirtualService 将 ServiceA 的服务流量所有指向已存在的 v1 版本
    # virtualService
    apiVersion: networking.istio.io/v1alpha3
    kind: VirtualService
    metadata:
     name: serviceA
    spec:
     hosts:
     - serviceA
     http:
     - route:
     - destination:
     host: serviceA
     subset: v1
    ---
    # destinationRule
    apiVersion: networking.istio.io/v1alpha3
    kind: DestinationRule
    metadata:
     name: serviceA
    spec:
     host: serviceA
     subsets:
     - labels:
     version: v1
     name: v1
    复制代码
  2. 部署新版本的 Deployment 查找符合 app label 的 deployment,运维人员基于该 deployment 建立 v2 版本的 deployment,并向 destinationRule 中增长 v2 版本。 yaml # destinationRule apiVersion: networking.istio.io/v1alpha3 kind: DestinationRule metadata: name: serviceA spec: host: serviceA subsets: - labels: version: v1 name: v1 - labels: version: v2 name: v2
  3. 更新流量控制将流量指向新版本 如下实例利用 VirtualService 将 ServiceA 的服务流量所有指向 v2 版本 yaml # virtualService apiVersion: networking.istio.io/v1alpha3 kind: VirtualService metadata: name: serviceA spec: hosts: - serviceA http: - route: - destination: host: serviceA subset: v2
  4. 下线 v1 版本的 deployment,删除 DestinationRule 中的 v1

使用Istio Dashboard来实现上述流程

canary-deployment

Ingress 配置

为何使用 Istio Ingress 做为新的 Ingress 方案?

过去咱们使用腾讯云托管的 Kubernetes Ingress,为了对 Ingress 流量控制而引入 Istio Ingress。咱们以前提到 Istio Ingress 是基于 Envoy,它读取 Istio 控制的配置进行路由,与其它内部服务同样方便地接入 Istio 全部功能。

除了 VirtualService 和 DestinationRule,Istio 定义了 Gateway 来控制实例支持的 Host 和证书。具体的流程是:

  1. 建立 Istio Ingress 提供的 Deployment 和 Service 建立 Deployment ingressgateway 时,以 ConfigMap 的形式挂载 Ingress 须要的证书。
  2. 配置 Gateway 配置 Ingress 接收具体域名(如 wallstreetcn.com)的流量,以及对应的 TLS 证书位置,这里的证书路径已经挂在到 Ingress 的 Deployment 上。如下是一个典型的 Gateway 配置。
apiVersion: networking.istio.io/v1alpha3
kind: Gateway
metadata:
 name: wallstreetcn-com
 namespace: istio-system
spec:
 selector:
 istio: ingressgateway
 servers:
 - hosts:
 - wallstreetcn.com
 port:
 name: http
 number: 80
 protocol: HTTP
 - hosts:
 - wallstreetcn.com
 port:
 name: https
 number: 443
 protocol: HTTPS
 tls:
 mode: SIMPLE
 privateKey: /etc/istio/ingressgateway-certs/tls.key
 serverCertificate: /etc/istio/ingressgateway-certs/tls.crt
复制代码

配置完成后,再配合 VirtualService 的路由控制,控制 Ingress 的反向代理到 default 命名空间下的 gateway 服务 80 端口,以下所示:

apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
 name: wallstreetcn-com
 namespace: istio-system
spec:
 gateways:
 - wallstreetcn-com
 hosts:
 - wallstreetcn.com
 http:
 - route:
 - destination:
 host: gateway.default.svc.cluster.local
 port:
 number: 80
复制代码

监控指标

Istio 支持 Prometheus 拉取集群指标,并提供 Grafana 看板展现。这里建议初期使用 Istio 自带的 Grafana 看板配置,而且注意 Kubernetes 主机的类型划分,Prometheus 服务适合放在内存型机器。能够与 Dashboard 集成,在发布服务过程当中即时查看指标。

服务质量

Istio 自带一些默认的 Grafana 面板,统计全部能够被访问的 HTTP/gRPC 服务的返回码以及延时状况。

对于返回码,认为 5xx 为错误,并在面板上使用label_join((sum(rate(istio_requests_total{reporter="destination", response_code!~"5.*"}[1m])) by (destination_workload, destination_workload_namespace) / sum(rate(istio_requests_total{reporter="destination"}[1m])) by (destination_workload, destination_workload_namespace)), "destination_workload_var", ".", "destination_workload", "destination_workload_namespace")计算服务错误率。

对于延时状况采用histogram_quantile获取多维度 p50、p90、p9五、p99 的延时分布。

istio-mesh

链路追踪

以前提到 Proxy 由 Envoy 实现,Envoy 支持设置 Zipkin 上报 API,Proxy 在收发请求时将链路指标上报到 Zipkin,为了实现链路追踪,Proxy 在流量转发中解析协议中的 HTTP 或 gRPC 请求头,找出其中的追踪头,组装成指标。 因此应用端须要在收到调用方请求时解析出请求头,并持续携带该请求头向后传递。 因为见闻在 Ingress 以后映射一个 HTTP gateway,请求从 Ingress 转发到 HTTP gateway,再发送到后续的 gRPC 服务,因此 HTTP gateway 有段代码生成 gRPC 请求头。

import (
  "github.com/labstack/echo"
  gmeta "google.golang.org/grpc/metadata"
)

// Create a gRPC context from Echo.
func NewContextFromEcho(ec echo.Context) context.Context {
  md := gmeta.MD{}
  for _, header := range []string{
    "x-request-id",
    "x-b3-traceid",
    "x-b3-spanid",
    "x-b3-parentspanid",
    "x-b3-sampled",
    "x-b3-flags",
    "x-ot-span-context",
  } {
    md.Set(header, ec.Request().Header.Get(header))
  }

  md.Set("x-b3-parentspanid", ec.Request().Header.Get("x-b3-spanid"))
  return gmeta.NewOutgoingContext(context.Background(), md)
}
复制代码

在后续的 gRPC 服务调用中使用该 Context,至于 gRPC 服务之间的调用,咱们发现会自动将 context 传递到下一个服务,因此没有作相似处理。

这里追踪的数据若是全量捕获将会是很是大的,而且对于监控来讲也没必要要,因此能够设置抽样率,Istio 提供 ConfigMap 中设置抽样率,通常来讲设置成 1%便可。

实践中的宝贵经验

在 Istio 实践过程当中,有哪些须要注意的问题。

  1. API server 的强依赖,单点故障 Istio 对 Kubernetes 的 API 有很强的依赖,诸如流量控制(Kubernetes 资源)、集群监控(Prometheues 经过 Kubernetes 服务发现查找 Pod)、服务权限控制(Mixer Policy)。因此须要保障 API server 的高可用,咱们曾遇到 Policy 组件疯狂请求 Kubernetes API server 使 API server 没法服务,从而致使服务发现等服务没法更新配置。 _ 为避免这种请求,建议使用者了解与 API server 直接通讯组件的原理,并尽可能减小直接通讯的组件数量,增长必要的 Rate limit。 _ 尽可能将与 API server 通讯的服务置于能够随时关闭的环境,这是考虑若是部署在同一 Kubernetes 集群,若是 API server 挂掉,没法关闭这些有问题的服务,致使死锁(又想恢复 API server,又要依靠 API server 关闭服务)

  2. 服务配置的自动化 服务配置是 Istio 部署后的重头戏,避免使用手动方式更改配置,使用代码更新配置,将经常使用的几个配置更新操做作到运维后台,相信手动必定会犯错的事实。

  3. 关于 Pilot Discovery Pilot Discovery 1.0.0 版本有很大的性能问题,1.0.4 有很大的性能提高,但引入了一个新 bug,因此请使用 1.0.5 及以上的版本,该版本在见闻的平均 CPU 负载从 10 核降到了 0.5 核,大大下降了 Proxy 同步配置的延时。

  4. 关于 Mixer Policy 1.0.0 这个组件曾致使 API server 负载太高(很高的 list pods 请求),因此咱们暂时束之高阁,慎用。

  5. 性能调优 在使用 Proxy、Telemetry 时,默认它们会打印访问日志,咱们选择在生产上关闭该日志。 时刻观察 Istio 社区的最新版本,查看新版本各个组件的性能优化以及 bug 修复状况,将 Istio 当作高度模块化的系统,单独升级某些组件。上面就提到咱们在 Istio1.0 的基础上使用了 1.0.5 版本的 Policy、Telemetry、Pilot Discovery 等组件。

  6. 服务平滑更新和关闭 Istio 依靠 Proxy 来帮助 APP 进行路由,考虑几种状况会出现意外的状态: _ APP 启动先于 Proxy,并开始调用其它服务,这时 Proxy 还没有初始化完毕,APP 调用失败。 _ Service B 关闭时,调用者 Service A 的 Proxy 还没有同步更新 Service A 关闭的状态,向 Service B 发送请求,调用失败。

第一种状况要求 APP 有重试机制,能适当重试请求,避免启动时的 Proxy 初始化与 APP 初始化的时差。 第二种状况,一种是服务更新时,咱们使用新建新服务,再切流量;一种是服务异常退出,这种状况是在客户端重试机制。但愿使用 Istio 的开发人员有更好的解决方案。

下一步计划

见闻 Istio 化已于去年 10 月份完成并上线,咱们的线上集群中 Istio 和非 Istio 的 APP 混合部署,上千的 Pod 数量曾对不够健壮的服务发现组件形成巨大的压力,在这期间曾遇到 Istio 的一些惊喜,并不断总结经验,但愿给以后使用 Istio 的同窗一些借鉴。以后的过程当中,SRE 的目标依然是保障线上服务的健壮性。

  1. Istio Dashboard 优化 APP 部署流程,考虑自动部署的功能,经过服务指标自动完成灰度发布和流量迁移。
  2. Prometheus Prometheus 的高可用、可拓展方案的探索。
相关文章
相关标签/搜索