使用 Admiral 进行多集群 Istio 配置和服务发现

自动配置 Istio,使其部署(集群)作为一个单一网格工作。

2020年1月5日 | 作者:Anil Attuluri - Intuit,Jason Webb - Intuit

在 Intuit,我们阅读了博文 用于隔离和边界保护的多网格部署,并立即与其中提到的某些问题产生了关联。我们意识到,即使我们希望配置一个单一的多集群网格,而不是博文中描述的多网格联合体,但在我们的环境中也存在相同的不统一命名问题。这篇博文解释了我们如何使用 Admiral(GitHub 中 istio-ecosystem 下的一个开源项目)解决了这些问题。

背景

使用 Istio,我们意识到多集群的配置很复杂,并且难以随着时间的推移进行维护。因此,出于可扩展性和其他操作原因,我们选择了 具有复制控制平面的多集群 Istio 服务网格 中描述的模型。遵循此模型,在广泛采用 Istio 服务网格之前,我们必须解决以下关键要求

我们拥有 160 多个 Kubernetes 集群,所有集群都具有全局唯一的命名空间名称。在此配置中,我们可以将相同的服务工作负载部署在不同区域中,并在具有不同名称的命名空间中运行。因此,遵循 多集群版本路由 中提到的路由策略,示例名称 foo.namespace.global 不会跨集群工作。我们需要一个全局唯一且可发现的服务 DNS,它可以解析多个集群中的服务实例,每个实例都使用其自己的唯一 Kubernetes FQDN 运行/可寻址。例如,如果 foo 在两个具有不同名称的 Kubernetes 集群中运行,则 foo.global 应解析为 foo.uswest2.svc.cluster.localfoo.useast2.svc.cluster.local。此外,我们的服务需要具有不同解析和全局路由属性的其他 DNS 名称。例如,foo.global 应首先在本地解析,然后使用拓扑路由路由到远程实例,而 foo-west.globalfoo-east.global(用于测试的名称)应始终解析到各自的区域。

上下文配置

经过进一步调查,很明显配置需要是上下文相关的:每个集群都需要一个专门针对其世界观的配置。

例如,我们有一个由订单和报表使用的支付服务。支付服务在 us-east(集群 3)和 us-west(集群 2)中具有高可用性/灾难恢复部署。支付服务在每个区域中以不同的名称部署在命名空间中。订单服务部署在与 us-west 中的支付服务不同的集群(集群 1)中。报表服务部署在与 us-west 中的支付服务相同的集群(集群 2)中。

Example of calling a workload in Istio multicluster
使用 Istio 进行跨集群工作负载通信

下面是集群 1 和集群 2 中支付服务的 Istio ServiceEntry yaml,它说明了其他服务使用支付服务所需的上下文配置

集群 1 服务条目

apiVersion: networking.istio.io/v1alpha3
kind: ServiceEntry
metadata:
  name: payments.global-se
spec:
  addresses:
  - 240.0.0.10
  endpoints:
  - address: ef394f...us-east-2.elb.amazonaws.com
    locality: us-east-2
    ports:
      http: 15443
  - address: ad38bc...us-west-2.elb.amazonaws.com
    locality: us-west-2
    ports:
      http: 15443
  hosts:
  - payments.global
  location: MESH_INTERNAL
  ports:
  - name: http
    number: 80
    protocol: http
  resolution: DNS

集群 2 服务条目

apiVersion: networking.istio.io/v1alpha3
kind: ServiceEntry
metadata:
  name: payments.global-se
spec:
  addresses:
  - 240.0.0.10
  endpoints:
  - address: ef39xf...us-east-2.elb.amazonaws.com
    locality: us-east-2
    ports:
      http: 15443
  - address: payments.default.svc.cluster.local
    locality: us-west-2
    ports:
      http: 80
  hosts:
  - payments.global
  location: MESH_INTERNAL
  ports:
  - name: http
    number: 80
    protocol: http
  resolution: DNS

从集群 2 中报表服务的角度来看,支付服务的 ServiceEntry(Istio CRD)将设置指向本地 Kubernetes FQDN 的 us-west 位置和指向集群 3 的 istio-ingressgateway(负载均衡器)的 us-east 位置。从集群 1 中订单服务的角度来看,支付服务的 ServiceEntry 将设置指向集群 2 的 istio-ingressgatewayus-west 位置和指向集群 3 的 istio-ingressgatewayus-east 位置。

但是,还有更多复杂性:如果支付服务希望在 us-west 进行计划维护时将流量转移到 us-east 区域,该怎么办?这将要求支付服务更改其所有客户端集群中的 Istio 配置。如果没有自动化,这几乎是不可能的。

Admiral 来救援:Admiral 就是自动化

Admiral 是 Istio 控制平面的控制器。

Example of calling a workload in Istio multicluster with Admiral
使用 Istio 和 Admiral 进行跨集群工作负载通信

Admiral 基于唯一的服务标识符自动配置跨多个集群的 Istio 网格,使其作为一个单一网格工作,该标识符将运行在多个集群上的工作负载与服务相关联。它还提供跨集群的 Istio 配置的自动供应和同步。这减轻了开发人员和网格运营人员的负担,有助于扩展到多个集群。

Admiral CRD

全局流量路由

使用 Admiral 的全局流量策略 CRD,支付服务可以更新区域流量权重,Admiral 会更新使用支付服务的所有集群中的 Istio 配置。

apiVersion: admiral.io/v1alpha1
kind: GlobalTrafficPolicy
metadata:
  name: payments-gtp
spec:
  selector:
    identity: payments
  policy:
  - dns: default.payments.global
    lbType: 1
    target:
    - region: us-west-2/*
      weight: 10
    - region: us-east-2/*
      weight: 90

在上面的示例中,90% 的支付服务流量被路由到 us-east 区域。此全局流量配置会自动转换为 Istio 配置,并上下文映射到 Kubernetes 集群,以便为支付服务的客户端在网格内启用多集群全局路由。

此全局流量路由功能依赖于 Istio 1.5 或更高版本中可用的每个服务的 Istio 位置负载均衡。

依赖关系

Admiral 的 Dependency CRD 允许我们根据服务标识符指定服务的依赖关系。这优化了 Admiral 生成的配置的交付,仅交付到服务依赖客户端所在的必要集群(而不是写入所有集群)。Admiral 还配置和/或更新客户端工作负载命名空间中的 Sidecar Istio CRD,以将 Istio 配置限制在其依赖项。我们使用在其他地方记录的服务到服务授权信息来生成此 dependency 记录供 Admiral 使用。

orders 服务的 dependency 示例

apiVersion: admiral.io/v1alpha1
kind: Dependency
metadata:
  name: dependency
  namespace: admiral
spec:
  source: orders
  identityLabel: identity
  destinations:
  - payments

Dependency 是可选的,服务的依赖关系缺失将导致该服务的 Istio 配置被推送到所有集群。

总结

Admiral 提供了新的全局流量路由和唯一服务命名功能,以解决 具有复制控制平面的多集群部署 中描述的 Istio 模型带来的一些挑战。它消除了在集群之间进行手动配置同步的需要,并为每个集群生成上下文配置。这使得操作由许多 Kubernetes 集群组成的服务网格成为可能。

我们认为 Istio/服务网格社区将受益于这种方法,因此我们 开源了 Admiral,并期待您的反馈和支持!

分享此文章