云上Kubernetes集群跨可用区高可用网络拓扑设计:从零理解为何与如何做

很多人在云上部署K8s集群只用一个可用区,一旦机房故障整个集群就挂了。本文面向初学者,用通俗语言解释可用区、高可用、跨AZ网络拓扑的核心概念,并给出实用的设计原则和注意事项,帮你搭建真正高可用的集群。

云上Kubernetes集群跨可用区高可用网络拓扑设计:从零理解为何与如何做
封面图:ZuCDN · ZuCDN 原创

一个真实的问题:单可用区集群有多脆弱?

配置前的检查

关于Multi-AZ,最值得先弄清楚的是配置边界和排错顺序。假设你把Kubernetes集群的所有节点(控制面和Worker)都放在同一个数据中心机房,也就是同一个可用区(Availability Zone,简称AZ)。某天这个机房因为光缆被挖断、电力波动或者冷却系统故障而整体下线,你的整个集群——包括API Server、调度器、所有应用Pod——全部不可用。更糟的是,即使数据有备份,恢复集群到另一个机房也需要重建网络、重新调度,可能需要几小时甚至更久。

这就是单可用区部署的致命弱点:单一故障域。在云上,可用区是物理隔离的数据中心单元,每个AZ拥有独立的电力、冷却和网络,AZ之间通过低延迟光纤连接。因此,要想让集群扛得住AZ级别的灾难,就必须把节点和关键组件分散到多个可用区,也就是跨可用区(Multi-AZ)部署

核心概念:可用区与跨可用区高可用怎么理解?

配置前的检查

想象一下你经营一家连锁奶茶店。如果只有一个店铺,一次火灾就让生意全停。但如果你在城市的东、西、南三个方向各开一家店,其中任何一家出问题,顾客可以转向其他店。这里的“店铺”就是可用区,“连锁店系统”就是跨可用区集群。

在云上,可用区(AZ)是一组物理上隔离的数据中心,通常一个地域(Region)包含多个AZ,比如阿里云华北2(北京)可用区A、B、C,AWS us-east-1有6个AZ。每个AZ内部网络延迟极低(<1ms),AZ之间延迟通常在2~5ms,带宽充足但跨AZ流量会产生额外的网络费用(按GB计费)。

高可用(High Availability)的目标是让系统在部分组件失效时仍能正常服务。对于Kubernetes集群,高可用意味着:控制面(Control Plane)的etcd、API Server、Controller Manager、Scheduler至少有2个副本分布在不同的AZ;工作节点(Worker Nodes)也分散部署,并且通过调度规则让应用Pod分布在多个AZ上。

为什么要跨可用区设计Kubernetes网络拓扑?与Multi-AZ

配置前的检查

K8s网络是集群通信的血管,跨AZ的网络拓扑设计直接决定了集群的可用性和性能。设计核心目标有三个:

  • 控制面高可用:etcd集群跨AZ部署,保证Leader故障时能快速选举新Leader;API Server负载均衡到多个AZ的实例,避免单点。
  • 工作负载高可用:通过PodAntiAffinity将同一Deployment的Pod分布在多个AZ上,确保一个AZ宕机时其他AZ的Pod仍能处理流量。
  • 网络通信不因AZ故障受阻:Service的Cluster IP、Ingress控制器、DNS(CoreDNS)等组件也需要多AZ部署,避免单AZ失效导致服务发现或流量入口中断。

跨AZ网络拓扑的关键设计要素

1. 控制面节点的AZ分布

如果你的云厂商支持托管K8s(如阿里云ACK、AWS EKS、GKE),控制面由云厂商负责高可用,通常自动分布在3个AZ上。如果是自建集群,务必在至少3个AZ中各部署一台控制面节点,并使用外部负载均衡器(如SLB、NLB)将流量分发到这些节点。etcd成员也要跨AZ分布,推荐奇数个成员(3或5),这样少数AZ故障时etcd仍然可用。

2. Worker节点的AZ分布与Pod调度

创建工作节点组时,在每个AZ中创建数量相同的节点(比如每个AZ 3台,共9台)。然后利用PodAntiAffinity规则,让Pod尽量散布到不同AZ:

affinity:
  podAntiAffinity:
    preferredDuringSchedulingIgnoredDuringExecution:
    - weight: 100
      podAffinityTerm:
        labelSelector:
          matchExpressions:
          - key: app
            operator: In
            values:
            - my-app
        topologyKey: topology.kubernetes.io/zone

topology.kubernetes.io/zone是节点自动带有的标签,表示节点所在的AZ。通过这个规则,K8s会尽量把Pod调度到不同AZ的节点上。

3. 网络插件(CNI)的跨AZ通信

常见的CNI如Calico、Flannel、Cilium都支持跨AZ通信,底层依赖云厂商的VPC网络。每个节点上的Pod IP通常从节点所在的VPC子网中分配。跨AZ的Pod通信会经过云厂商的底层路由器,延迟略高但带宽充足。你需要确保:

  • 每个AZ中至少有一个节点子网(/24或更大),不同AZ的子网CIDR不重叠。
  • 节点安全组允许来自其他AZ子网的Pod CIDR流量(通常是全部内网允许)。
  • 如果使用Calico的IPIP或VXLAN模式,注意隧道封装会增加CPU消耗和延迟;在云VPC环境下,建议使用Direct Routing模式(如Calico的“云原生”模式或Cilium的eBPF直接路由),避免二次封装。

4. Service与Ingress的跨AZ负载均衡

Service(ClusterIP类型)通过kube-proxy在节点上做DNAT,天然可以在任何节点上接收流量并转发到后端Pod,即使Pod在其他AZ。但为了最优路径,建议使Service的externalTrafficPolicy: Local,这样外部流量只会到达有健康Pod的节点,避免跨AZ的SNAT和额外跳转。不过这会带来流量不均衡的问题,需要结合云厂商的负载均衡器使用。

对于Ingress,推荐在每个AZ部署一个Ingress Controller的Pod(通过PodAntiAffinity或节点亲和性),并在前面挂载云厂商的SLB/ALB(负载均衡器)。SLB/ALB通常支持跨AZ分发流量,并且可以配置健康检查,只把流量发给健康的Ingress Pod。

5. CoreDNS与集群关键组件的多AZ部署

CoreDNS负责服务发现,如果所有CoreDNS Pod都在同一个AZ,该AZ故障时整个集群域名解析中断。将CoreDNS的副本数设置为至少等于AZ数量(比如3),并添加topologySpreadConstraints让Pod均匀分布在各个AZ上:

topologySpreadConstraints:
- maxSkew: 1
  topologyKey: topology.kubernetes.io/zone
  whenUnsatisfiable: DoNotSchedule
  labelSelector:
    matchLabels:
      k8s-app: kube-dns

跨AZ部署的隐藏成本与权衡与Multi-AZ

我的处理经验

理想很丰满,实际运维时需要面对几个现实问题:

  • 跨AZ流量费用:云厂商对流出节点的流量收费,同AZ内免费,跨AZ按量计费(通常0.1~0.2元/GB)。如果应用Pod之间频繁跨AZ通信,账单可能激增。解决方案:对延迟不敏感且流量大的批处理任务尽量调度到同AZ,通过节点亲和性控制。
  • 延迟增加:同AZ延迟1ms以内,跨AZ可能2~5ms。对于Redis、数据库等高QPS的中间件,每增加2ms可能导致P99延迟明显上升。这类中间件建议同AZ部署主节点,跨AZ部署从节点做灾备。
  • 网络带宽不对称:部分云厂商的AZ间带宽有限制,大流量场景需要提前测试。

因此,并非所有工作负载都需要跨AZ。对于非关键应用或测试环境,单AZ足够。但对于生产级的核心业务,尤其是需要SLA保障的服务,跨AZ是必需品。

总结:从零到一搭建跨AZ K8s集群的最佳实践

容易忽略的细节

如果你刚开始规划集群,可以按以下步骤走:

  1. 选择一个云地域,至少启用3个可用区(如果云厂商提供,有些只提供2个)。
  2. 创建VPC,并在每个AZ中创建至少一个子网(用于节点)和一个额外的Pod子网(如果CNI需要)。
  3. 部署托管K8s集群(推荐),或者自建控制面并跨AZ分布。
  4. 创建节点组,每个AZ节点数量相同,并确保节点带有正确的topology.kubernetes.io/zone标签。
  5. 安装CNI时选择直接路由模式(如Calico VXLAN on cloud routing 或 Cilium native routing),避免过度封装。
  6. 为所有有状态工作负载(数据库、缓存)单独设计跨AZ策略:主从跨AZ或同AZ主+跨AZ备份。
  7. 使用PodTopologySpreadConstraints和PodAntiAffinity控制Pod分布。
  8. 监控跨AZ流量成本和延迟,设置告警。

跨AZ高可用不是免费午餐,但它是应对AZ级灾难最有效的手段。理解背后的网络拓扑设计,才能避免“跨AZ了但根本没用好”的尴尬。按这个顺序复查,Multi-AZ遇到异常时也更容易定位。

延伸阅读