16.4.7 跨集群服务发现与多集群网络

跨集群服务发现与多集群网络#

跨集群场景常见于多数据中心、混合云与多地域部署,需要解决服务发现、网络互通、流量治理与统一可观测问题。目标是在不牺牲隔离性的前提下,实现跨集群的服务访问与容灾切换。

1. 原理与架构草图#

文章图片

2. 需求与挑战(要点)#

  • 服务发现一致性:跨集群解析同一服务名或全局服务名。
  • 网络互通与隔离:Pod/Service网段可达且可控。
  • 流量治理:就近访问、主备切换与灰度比例。
  • 可观测性:跨集群链路指标与日志统一。

3. 典型实现模式与示例#

模式A:DNS级别多集群发现(简化版)
- 思路:ExternalDNS/全局DNS将服务域名解析到多集群入口。
- 优点:简单;缺点:健康检查与细粒度治理有限。

模式B:Kubernetes MCS(标准化)
- 思路:ServiceExport/ServiceImport 同步跨集群服务与DNS。
- 需要:MCS控制器与多集群DNS插件支持。

模式C:网关+服务网格
- 思路:东西向网关暴露服务,网格提供mTLS与治理策略。
- 适合:复杂流量治理与多活。

4. Kubernetes MCS 安装与示例#

以下示例使用 MCS API CRD + CoreDNS 插件 的典型流程(以两集群为例,A/B 均需操作)。

4.1 安装 MCS API CRD(两集群)

# 安装 MCS API CRD(Cluster A / Cluster B 都执行)
kubectl apply -f https://github.com/kubernetes-sigs/mcs-api/releases/download/v0.1.0/mcs-crds.yaml

# 解释:
# - ServiceExport/ServiceImport CRD 供控制器与DNS插件使用

4.2 部署示例服务(Cluster A)

# 文件:svc-a.yaml
apiVersion: v1
kind: Namespace
metadata:
  name: demo
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: echo-a
  namespace: demo
spec:
  replicas: 2
  selector:
    matchLabels:
      app: echo-a
  template:
    metadata:
      labels:
        app: echo-a
    spec:
      containers:
      - name: echo
        image: hashicorp/http-echo:0.2.3
        args: ["-text=hello-from-cluster-a"]
        ports:
        - containerPort: 5678
---
apiVersion: v1
kind: Service
metadata:
  name: echo
  namespace: demo
spec:
  selector:
    app: echo-a
  ports:
  - port: 80
    targetPort: 5678
kubectl apply -f svc-a.yaml
kubectl -n demo get svc,po -l app=echo-a

4.3 导出服务(Cluster A)

# 文件:export-echo.yaml
apiVersion: multicluster.x-k8s.io/v1alpha1
kind: ServiceExport
metadata:
  name: echo
  namespace: demo
kubectl apply -f export-echo.yaml

# 解释:
# - 将 demo/echo 标记为可跨集群发现

4.4 导入服务与解析(Cluster B)

这里假设已经有 MCS 控制器与DNS插件运行(如 Kubefed/MCS-controller 实现)。

# 验证 ServiceImport(由控制器自动创建)
kubectl -n demo get serviceimport echo -o yaml

# 在 Cluster B 中解析全局服务名(示例格式)
kubectl -n demo run dns-test --rm -it --image=busybox:1.36 --restart=Never -- \
  nslookup echo.demo.svc.clusterset.local

预期效果
- echo.demo.svc.clusterset.local 返回 Cluster A 的地址列表。
- Cluster B 访问 curl http://echo.demo.svc.clusterset.local 返回 hello-from-cluster-a

5. 多集群网络互通示例(CNI 互通 + 网段规划)#

5.1 网段规划检查

# 检查 Cluster A/B 的 Pod/Service CIDR
kubectl cluster-info dump | grep -m 1 -E "clusterCIDR|serviceCIDR"

# 解释:
# - Pod/Service 网段不能冲突,否则跨集群路由不稳定

5.2 互通验证(双向)

# Cluster A 中访问 Cluster B 的 Pod IP(假设已互通)
kubectl -n demo run ping-test --rm -it --image=busybox:1.36 --restart=Never -- \
  ping -c 3 <cluster-b-pod-ip>

# 解释:
# - 能 ping 通说明底层网络可达

6. 关键命令与效果说明#

# 查看跨集群导出/导入状态
kubectl get serviceexport -A
kubectl get serviceimport -A

# 查看 CoreDNS 配置是否包含 clusterset.local
kubectl -n kube-system get configmap coredns -o yaml

7. 常见故障排查#

1) 解析成功但访问失败
- 检查网段冲突、路由是否可达、NetworkPolicy/安全组限制。

# 网络连通性测试
kubectl -n demo run net-test --rm -it --image=alpine:3.19 --restart=Never -- \
  sh -c "apk add --no-cache curl; curl -m 3 http://echo.demo.svc.clusterset.local"

2) 解析不到 clusterset.local
- 检查 CoreDNS 配置与 MCS 控制器状态。

kubectl -n kube-system logs deploy/coredns --tail=200
kubectl -n <mcs-namespace> logs deploy/mcs-controller --tail=200

3) 流量未按策略分配
- DNS TTL 过长或网关权重未刷新。

# 查看 DNS 记录 TTL
kubectl -n kube-system logs deploy/coredns | grep -i ttl

8. 练习(动手验证)#

1) 在 Cluster A 导出 demo/echo,在 Cluster B 解析并访问。
2) 修改 Cluster A 部署为 replicas=0,验证 Cluster B 访问失败并观察 DNS 缓存行为。
3) 将服务暴露到网关(Cluster A),在 Cluster B 通过网关域名访问并对比延迟。
4) 规划不同 Pod/Service CIDR(如 10.10.0.0/16 与 10.20.0.0/16),验证互通与冲突差异。

本节重点在于理解跨集群服务发现的模式与网络互通的核心原则,结合实际业务需求选择合适的实现路径,确保可靠性与可治理性。