迁移多网络网格
多网络网格中的每个集群都有自己的网络和东西向网关,跨集群流量会经过这些网关。本文档列出了迁移单集群网格的每个阶段新增的内容;此处未提及的所有内容都相同。
请先确认拓扑,参见确定网络拓扑。
下面的大多数代码块都作用于一个集群,并将其指定为 ${CTX}。请在第一个代码块之前设置它,并且每次切换到下一个集群时再次设置,参见一次指定一个集群:
目录
每个阶段新增的内容阶段 0:记录并探测每个集群阶段 1:面向多集群网格的 Kiali阶段 2:每个集群一个控制平面部署 Mesh v2 东西向网关阶段 3 和阶段 4:逐个迁移集群阶段 5:逐个停用集群阶段 6:完成每个集群将追踪报告保留在每个集群内验证迁移后每个阶段新增的内容
阶段 0:记录并探测每个集群
针对每个集群运行为迁移做准备,并将 --context 设置为该集群;为每个集群保留一组变量。每个集群的网格标识都不同,必须分别记录:
每个集群上的 meshID 都相同;network 和 clusterName 不同。Mesh v2 必须为每个集群复现这三个值。
扩展设置流量探测中的流量探测,以覆盖跨集群路径:为每个集群提供一个网格内探测,该探测调用一个由两个集群中的工作负载共同支持的服务,即跨集群探测中指定的服务。两个方向都要进行探测,因为一个集群上的迁移步骤会改变另一个集群能够访问的内容。
在任何内容发生变化之前,使用针对每个集群运行的阶段 3 和阶段 4 的端点检查记录该路径解析到的内容:另一个集群的端点,以及这些端点上的 rq_success,构成后续阶段进行比较的基线。将这些记录与迁移笔记放在一起,而不要放在 BACKUP_DIR 中,因为每个集群上的该目录都不同。
请与记录的内容进行比较,而不是与平均分配进行比较:网格的流量策略决定分配方式,加权本地性分配、本地性故障转移,以及两者都没有的网格,其表现都不同。端点是始终能够提供信息的部分——无论流量是否使用它们,它们都存在,因此,即使本地性策略让每次调用都留在自己的集群中,端点仍能显示跨集群路径是否已编程。
阶段 1:面向多集群网格的 Kiali
Kiali 从一个存储中读取每个集群的指标,并需要对每个集群具有读取权限。请遵循在多集群网格中安装 Kiali,而不是单集群说明:Kiali server 在网格中的一个集群上运行,其他每个集群都会获得一个 Kiali 资源,该资源只生成远程集群资源。
它的先决条件正是迁移后的网格通常需要添加的内容:
- 各集群向同一个监控存储报告。
kubectl --context "${CTX}" get feature monitoring -o jsonpath='{.spec.accessInfo.database.address}'在网格的每个集群上都返回相同的地址。 - 每个集群都安装 Kiali Operator,包括不运行 Kiali server 的集群。
- 每个集群上都存在
PodMonitor,并按照创建指标资源中的说明进行限制;ServiceMonitor会在阶段 5中跟进。 - 网格范围的
Telemetry资源在每个运行控制平面的集群上都携带mesh_id标签覆盖。Kiali 根据该标签过滤网格的指标,因此报告mesh_id="unknown"的代理对它不可见。迁移中的网格无需在此处添加任何内容:每个集群的 Mesh v1 资源都携带该标签,并配置两代代理;阶段 5会在每个集群上将其替换为同样携带该标签的asm-default。现在创建asm-default不会改变任何内容,参见创建指标资源。
Kiali 会在其日志中报告发现的内容:每个集群对应一行 Discovered cluster,每行都包含 Accessible=true。
阶段 2:每个集群一个控制平面
按照安装 Mesh v2 控制平面中的说明,在每个集群上创建 IstioCNI 和 Istio 资源,并使用为该集群记录的值:
其他内容均不变:每个控制平面都会加载其所在集群的 cacerts secret,并且两个中间证书都由同一个根证书签名,因此工作负载在跨集群和跨代际的情况下仍会相互信任。
远程 secret 会被重复使用。验证每个 Mesh v2 控制平面都能看到另一个集群:
每个控制平面都会列出另一个集群,其状态为 synced。
部署 Mesh v2 东西向网关
跨集群流量会通过其所在集群的东西向网关到达工作负载。Mesh v2 代理会将流量发送到控制平面提供的网关地址,因此每个集群都需要一个 Mesh v2 东西向网关,然后才能迁移工作负载。
Mesh v1 东西向网关会继续并行运行:两代网关都会终止相同的基于 SNI 的透传,并且每个代理都会使用其自身控制平面播发的网关。
读取当前网关
记录 service 和 Gateway 资源的选择器,以及网络标签。Mesh v2 部署会携带这些选择器的并集,与南北向网关完全相同。
部署 Mesh v2 东西向网关
topology.istio.io/network使此 pod 成为其网络的东西向网关。没有该标签,控制平面就不会向另一个集群播发此网关。ISTIO_META_REQUESTED_NETWORK_VIEW将网关获得的端点限制为其自身网络中的端点,这与 Mesh v1 网关配置的值相同。没有该配置,网关还会获知另一个集群的端点,并将从那里到达的流量直接发回,参见部分跨集群请求失败并返回 503。- 现有的
Service会通过app和istio选择新的 pod,因此向另一个集群发布的网关地址不会发生变化。 - 由于网格保留 Mesh v1 的注入策略,因此需要
sidecar.istio.io/inject: "true"。
检查网关是否已编程
第一个数字统计该 pod 在 15443 端口上终止的 SNI 匹配项数量,每个网格跨集群发布的 service 和端口对应一个匹配项——在小型网格中通常有几十个;如果网关未按此方式编程,则为 0。随后,service 端点中会同时包含 Mesh v1 和 Mesh v2 网关 pod。
最后一个命令会列出网关将网格 service 解析到的端点。这些端点必须全部是其所在集群的 pod 地址。其中如果有一个地址的端口为 15443,则表示该地址是另一个集群的东西向网关,这意味着缺少网络视图,请求可能会被反弹回来。
阶段 3 和阶段 4:逐个迁移集群
按照单集群网格中的说明,迁移一个集群的工作负载和网关,然后转到下一个集群。探针会报告跨集群路径是否持续提供流量。每个命名空间迁移后,在两个集群上检查它是否仍已编程——一个集群上的迁移步骤会改变另一个集群所能到达的内容:
另一个集群的端点是其东西向网关在 15443 端口上的地址,并且处于正常状态。探针运行期间,其 rq_success 会持续增长,增长比例与阶段 0中记录的比例相同;如果本地计数器持续增长而另一个计数器停止,则表示调用不再离开该集群。如果端点是另一个集群的原始 pod 地址,则表示该控制平面的 network 值不正确。除标头外完全没有输出,则表示 TARGET_SERVICE 不是 service 的完全限定名称,请参见跨集群探针。
阶段 5:逐个停用集群
在 global 集群上执行一次以下步骤:删除网格中每个集群的 ServiceMesh 资源,以及将这些资源连接在一起的 ServiceMeshGroup。在准备迁移中设置的 CLUSTER_NAMES 和 MESH_GROUP 会将此次删除限制在此网格内。只有当平台上不再有其他 Mesh v1 网格时,才会卸载该插件。
每个网格集群上的步骤与单集群网格中的步骤相同,但有一项额外操作。东西向网关 service 属于 Mesh v1 控制平面资源——并非通过 owner reference,而是通过 operator 标签关联——因此会随该资源一起删除。请先在每个集群上将其解除关联:
其余标签仍必须包含 app、istio 和 topology.istio.io/network:Mesh v2 网关 pod 就是通过这些标签选择的。删除 Mesh v1 控制平面资源后,会移除 Mesh v1 网关 pod,同时保留 service、其地址以及后端的 Mesh v2 pod。
阶段 6:完成每个集群
- 证书。对每个集群重复移交证书颁发机构,使用同一个根证书为每个中间证书签名,并在其 subject 中使用集群名称。当集群持有来自不同中间证书的证书时,跨集群 mutual TLS 仍可正常工作,因为根证书未发生变化。
- 修订标签和宽限期。对于每个集群,按照单集群网格中的方式执行。
- 追踪。整个网格使用一个索引系列:在每个集群上使用相同的索引前缀运行安装,以便在一个位置组装跨集群的追踪。作用于 Elasticsearch 的步骤——生命周期策略、索引初始化以及附加现有 Mesh v1 索引——针对整个网格运行一次,而不是每个集群运行一次。随后,每个集群保留自己的 collector 和自己的 Jaeger 实例,并且每个实例都提供整个网格的追踪。
将追踪报告保留在每个集群内
每个集群运行自己的 collector,且二者都使用相同的 service 名称 otel-collector.jaeger-system.svc.cluster.local 对外发布。若不做处理,控制平面会将它们合并为一组端点,每个 proxy 都会在两个端点之间对其 span 导出进行负载均衡。collector 没有 sidecar,因此没有网络身份,其端点不会被重写为东西向网关地址:proxy 会收到远程 collector 的原始 pod 地址,而该地址属于另一个网络,无法访问。两个端点都被报告为 HEALTHY——没有任何组件检查它们——因此,发送到远程端点的每次导出都会无声无息地丢失。追踪消失的程度取决于导出的分布方式:追踪看起来不完整,有些追踪会完全丢失。
将网格指向新的 collector会将 collector service 声明为仅限集群本地,从而丢弃另一个集群的端点。在每个运行控制平面的集群上执行此操作,然后检查是否只剩下一个端点:
一个端点,位于本地集群中。这样,跨集群的追踪就会包含两侧的 span。
此设置会通过控制平面传播——Operator 会重新渲染网格配置,istiod 会重新加载该配置并将其推送到每个 proxy——因此,与修补操作同时运行的检查仍会列出两个 collector。等待几秒后再次运行。
此条目仅影响该主机。应用 service 的跨集群负载均衡以及它们使用的东西向网关路径均不变。
验证
istioctl --context "${CTX}" remote-clusters --revision "${V2_REVISION}"在每个集群上报告synced。- 每个集群的跨集群端点都是另一个集群的东西向网关,运行正常,并且其
rq_success按照阶段 0 中记录的比例增长。 - 依赖拓扑的流量策略——例如本地性负载均衡和异常点检测——其行为与迁移前一致。它们是 Istio 资源,不会因迁移而改变。
- Kiali 显示每个集群的工作负载,跨集群的追踪包含两侧的 span。span 会将其生成所在的集群作为
istio.cluster_id携带,这正是读取跨集群调用追踪时所依据的信息。 - 每个集群上的东西向网关 service 保留其地址,其端点是 Mesh v2 网关 pod。
迁移后
Kiali 的流量图是整个已迁移网格的视图,而上述检查只涵盖探针调用的 service。打开 Traffic Graph,选择网格的命名空间,并启用 Display > Cluster Boxes:工作负载会按集群分组,每个跨集群调用都是框之间的一条边。确认边会在两个方向上绘制,并且没有任何 service 丢失其流量中跨集群的那一半,参见在多集群网格中安装 Kiali 的验证。
如果端点检查通过,但图中没有绘制连接两个集群的边,通常问题出在 Kiali,而不是网格:它从一个存储中读取两个集群的指标,并按 mesh_id 进行筛选;指标缺失或标记为 mesh_id="unknown" 的集群对它不可见,参见阶段 1:用于多集群网格的 Kiali。