使用 Admiral 进行多集群 Istio 配置和服务发现
自动配置 Istio,使其部署(集群)作为一个单一网格工作。
在 Intuit,我们阅读了博文 用于隔离和边界保护的多网格部署,并立即与其中提到的某些问题产生了关联。我们意识到,即使我们希望配置一个单一的多集群网格,而不是博文中描述的多网格联合体,但在我们的环境中也存在相同的不统一命名问题。这篇博文解释了我们如何使用 Admiral(GitHub 中 istio-ecosystem
下的一个开源项目)解决了这些问题。
背景
使用 Istio,我们意识到多集群的配置很复杂,并且难以随着时间的推移进行维护。因此,出于可扩展性和其他操作原因,我们选择了 具有复制控制平面的多集群 Istio 服务网格 中描述的模型。遵循此模型,在广泛采用 Istio 服务网格之前,我们必须解决以下关键要求
- 创建与命名空间分离的服务 DNS 条目,如 多网格部署的功能 中所述。
- 跨多个集群的服务发现。
- 支持主动-主动和高可用性/灾难恢复部署。我们还必须在跨离散集群的全局唯一命名空间中部署的服务中支持这些至关重要的弹性模式。
我们拥有 160 多个 Kubernetes 集群,所有集群都具有全局唯一的命名空间名称。在此配置中,我们可以将相同的服务工作负载部署在不同区域中,并在具有不同名称的命名空间中运行。因此,遵循 多集群版本路由 中提到的路由策略,示例名称 foo.namespace.global
不会跨集群工作。我们需要一个全局唯一且可发现的服务 DNS,它可以解析多个集群中的服务实例,每个实例都使用其自己的唯一 Kubernetes FQDN 运行/可寻址。例如,如果 foo
在两个具有不同名称的 Kubernetes 集群中运行,则 foo.global
应解析为 foo.uswest2.svc.cluster.local
和 foo.useast2.svc.cluster.local
。此外,我们的服务需要具有不同解析和全局路由属性的其他 DNS 名称。例如,foo.global
应首先在本地解析,然后使用拓扑路由路由到远程实例,而 foo-west.global
和 foo-east.global
(用于测试的名称)应始终解析到各自的区域。
上下文配置
经过进一步调查,很明显配置需要是上下文相关的:每个集群都需要一个专门针对其世界观的配置。
例如,我们有一个由订单和报表使用的支付服务。支付服务在 us-east
(集群 3)和 us-west
(集群 2)中具有高可用性/灾难恢复部署。支付服务在每个区域中以不同的名称部署在命名空间中。订单服务部署在与 us-west
中的支付服务不同的集群(集群 1)中。报表服务部署在与 us-west
中的支付服务相同的集群(集群 2)中。
下面是集群 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-ingressgateway
的 us-west
位置和指向集群 3 的 istio-ingressgateway
的 us-east
位置。
但是,还有更多复杂性:如果支付服务希望在 us-west
进行计划维护时将流量转移到 us-east
区域,该怎么办?这将要求支付服务更改其所有客户端集群中的 Istio 配置。如果没有自动化,这几乎是不可能的。
Admiral 来救援:Admiral 就是自动化
Admiral 是 Istio 控制平面的控制器。
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,并期待您的反馈和支持!