同名 Service 能跨集群访问,是否就算完成多集群

不能。真正的两集群须分别证明服务发现看到了远端 endpoints、东西向网络能穿越边界、工作负载身份在预期信任关系下通过、故障切换确实由可用的远端实例处理,以及业务数据是否有独立同步/去重方案。第 31 篇的两个 namespace 即使互访,也不是两个 Kubernetes 控制平面与两个故障域。本篇先以 sidecar 双 primary、双网络为待测拓扑;不能把得到的 sidecar 结果直接外推 ambient 多集群。

两个不同 kube-system UID 的集群:各自 Istiod 发现与 east-west gateway 联通,业务账本仍各自独立

令 A 集群运行 frontend → orders 和 inventory-v1,B 集群运行相同 Service 名的 inventory-v2,两边各用固定请求 ID 返回真实版本。每侧的 Istiod 不是数据面业务转发节点;请求跨网络时要核对其实际经过的东西向网关、接收端代理及目标 Pod。控制面知道某个远端 IP,不代表路由必然经过正确网关或 TLS 身份被接受。若两套集群各自创建了合成库存账本,即使远端请求成功,账本数据依然不会自动同步;把跨集群 200 当作事务一致性会把副作用风险掩盖掉。

四层配置与五层证据

先冻结 Kubernetes、Istio 与 CNI 兼容版本、网络拓扑、实际镜像 digest 和信任根的公开标识,审查东西向网关暴露范围、跨集群 endpoint 导出范围及恢复策略。安装配置、Kubernetes Service 资源、控制器发现/配置下发、sidecar 当前 endpoint、真实跨网关请求路径、目标库存响应和账本须各留证据;单独拿一张 proxy-status ACK 截图不证明成功。若信任根不同,策略究竟要求共享根、跨域别名还是拒绝,必须按选定发布版本和实际握手验证;不提交私钥或 token。

阶段 请求来源与后端条件 应保存的区分证据
正常本地 A 的 v1 健康 A 端配置、命中的 v1 应用记录和连接
远端请求 按明确规则选 B 的 v2 A/B 两侧代理与东西向网关、B 应用版本
本地端点撤离 A 的 v1 变为 not ready EndpointSlice 变化、A 代理 EDS、失败/切换窗口
隔离网络或错误信任 仅对实验东西向路径注入 拒绝位置、客户端非零退出、恢复后重新收敛

本地故障切换不等于只有远端可用;其他路由/重试、缓存连接与本地残留端点会影响观察。比较新建连接和已有连接,保留故障发生时刻与每次请求 ID;网络故障只针对隔离的合成实验链路,不中断宿主或其他任务节点。不同集群可见服务不等于业务事务有全局原子性,重复的 POST /reserve 用各集群账本分别核验,并把不一致记为应用层缺口。

双 context 安全入口与正反实验

从 examples/service-mesh/ 只读运行:

1
SM_CONTEXT_A=service-mesh-lab-a SM_CONTEXT_B=service-mesh-lab-b SM_NAMESPACE=service-mesh-lab bash scripts/check-32.sh

脚本只接受明确的两个实验 context 和合成 namespace,先检查 kubectl 可用及 context 存在,再要求两个 kube-system UID 不同,最后分别只读节点、Service、EndpointSlice 和 Pod。**UID 不同只是排除同一集群冒充双集群的前置检查,不是跨网通信证据。**通过后再做 A 本地成功、A 显式请求 B、撤离 A 的 v1、阻断只属于实验网关的链路、恢复等对照。预期拒绝/切换未发生时,断言必须非零;保存每次完整命令、退出码、响应、证书公开元数据、代理实际资源和后端账本。

尚未建立双集群、东西向网关或共享信任配置。本篇多集群发现、网络、身份、切换、恢复与业务一致性实验均 NOT_RUN。第 00 篇进程模拟两个库存版本不是多集群。

用两个普通 sidecar 集群复现远端恢复

本章采用 Istio 1.27.0 多主、不同网络的 sidecar 模式;E07 的 ambient HBONE gateway 配置不用于这里。两个明确的实验 context 为 service-mesh-lab-a、service-mesh-lab-b,脚本还要求 kube-system UID 不同。需要两个 API server 互通、可达的东西向网关地址、共同根下的集群中间 CA。CA 生成步骤可复用 E07 的实验 PKI,控制面安装与网关则使用本章文件。

1
SM_CONTEXT_A=service-mesh-lab-a SM_CONTEXT_B=service-mesh-lab-b ISTIO_DIR=/absolute/path/istio-1.27.0 SM_EVIDENCE_DIR=evidence/32/install bash mainline/32/install.sh

cluster.yaml.in 设置 meshID=mesh32、cluster1/cluster2 和 network1/network2,采用 minimal sidecar profile。脚本从固定发行包运行 gen-eastwest-gateway.sh 并应用 expose-services.yaml,随后双向创建 remote secret。这里的东西向 gateway 为 sidecar 跨网络服务转发;不能换成 E07 的 15008 HBONE Gateway 就假设协议相容。

remote secret 让控制面读取对端服务发现,不是请求数据隧道。东西向入口可达解决数据通路,也不自动建立 API 访问权限。先检查网关外部地址、对端 API 访问、远端端点出现在代理配置,再部署业务;LoadBalancer 地址 Pending 时应先给实验环境提供可路由实现,不能填一个虚构 IP。

1
2
3
kubectl --context service-mesh-lab-a -n istio-system get svc istio-eastwestgateway -o wide
kubectl --context service-mesh-lab-b -n istio-system get svc istio-eastwestgateway -o wide
node scripts/render-kubernetes.mjs evidence/32/apps.yaml service-mesh-demo:lab

把相同应用镜像载入两个集群的全部节点后,分别创建 namespace、启用 sidecar 注入并应用 apps.yaml。该生成器使用 imagePullPolicy Never;远端节点没载入镜像会 ImagePullBackOff,这不是网格故障。以下两条为 A 的操作,B 用对应 context 重复:

1
2
3
kubectl --context service-mesh-lab-a create namespace service-mesh-lab
kubectl --context service-mesh-lab-a label namespace service-mesh-lab istio-injection=enabled
kubectl --context service-mesh-lab-a apply -f evidence/32/apps.yaml -f mainline/26/policy.yaml -f mainline/26/probes.yaml

为让返回版本能辨别位置,A 仅保留 inventory-v1,B 仅保留 inventory-v2;两集群的 inventory Service 定义和 selector 保持一致。首次验证要保存实际远端 endpoint/网关地址,不能仅凭看到 v2 就忽略部署标签是否正确。

1
2
3
4
5
kubectl --context service-mesh-lab-a -n service-mesh-lab scale deployment inventory-v2 --replicas=0
kubectl --context service-mesh-lab-b -n service-mesh-lab scale deployment inventory-v1 --replicas=0
kubectl --context service-mesh-lab-a -n service-mesh-lab wait --for=condition=Ready pod/mesh-probe --timeout=120s
istioctl --context service-mesh-lab-a proxy-config endpoints pod/mesh-probe -n service-mesh-lab
kubectl --context service-mesh-lab-a -n service-mesh-lab exec mesh-probe -c curl -- curl -sv -H 'x-request-id: cross-cluster-normal' 'http://inventory:8080/quote?sku=paper'

正常路径连续请求保存版本分布,但不要求未配置 locality 策略时必定优先本地。故障实验先把 A 的 inventory-v1 缩零,在 Service 更新和代理收敛后,A 请求应由 B 的 v2 处理;再将 B 的 v2 缩零检查无可用上游;恢复 B 后验证新连接恢复,最后恢复 A。每阶段保存 EndpointSlice、代理 endpoints、响应 ID 与两边应用日志,按时间区分控制面发现延迟和数据路径连接失败。

清理先恢复被缩容的 Deployment,再删除本轮创建的业务 namespace;删除 remote secret 前依据 istio/multiCluster 标签确认本轮集群标识,不要删除其他网格连接。若两个集群专用于本实验,最后才销毁各自 kind 集群。当前双集群操作为 NOT_RUN。原则是分开验证发现、跨网络转发和故障后的新请求;固定版东西向网关生成脚本 可核对本章实际配置来源。

练习与参考解答

  1. 在两个 namespace 创建 inventory Service,再使两个 Pod 返回 v1/v2,能称作多集群对照吗?参考解答:不能。先用两个互不相同的集群标识和独立 API、网络/控制面边界证明拓扑,分别核对实际请求路径经东西向网关、源/目标工作负载身份;同集群隔离只测试 namespace 范围。
  2. A 的 v1 不可用后 A 的读请求成功命中 B 的 v2,能认定合成预留账本的数据一致了吗?参考解答:不能。访问路径切换只说明读请求到达远端;检查 A/B 两本账的相同 operation_id、顺序、冲突及重复执行,然后决定应用事务与同步策略。改变条件为 B 延迟或网络分区时,还需观察客户端超时后两边是否已各自执行。

官方参考与系列导航

系列导航:11 连接与负载均衡 → 31 多租户 → 32 多集群(本文)→ 33 性能对照。