在多区域多可用区的场景下部署 Kubernetes,首先要理解一个关键点:可用区(AZ)之间通常具备低延迟、高带宽的专用网络,而区域(Region)之间则是完全隔离的数据中心,网络延迟普遍在几十毫秒以上。因此,把 etcd 集群直接跨区域部署往往会因为写延迟过高导致集群不稳定,甚至频繁触发选举。一个更稳妥的做法是,让每个区域拥有独立的控制平面和 etcd 集群,上层通过联邦或统一入口来管理多个区域的工作负载。下面这张架构图展示了典型的跨区域控制面与数据面分离模式。

控制平面与 etcd 的高可用设计
在单个区域内,控制平面高可用的标准做法是部署三节点 etcd 集群,配合多个 API Server 实例和负载均衡器。但一旦涉及多个区域,直接把 etcd 节点分布到不同区域会带来两个致命问题:第一,etcd 采用 Raft 共识协议,写入需要多数节点确认,跨区域的高延迟会让每一次写操作都变得极其缓慢;第二,区域间网络抖动会导致频繁的领导者选举,严重时整个 etcd 集群会失去 quorum。因此,正确的模式是为每个区域建立独立的 etcd 集群,区域之间不共享 etcd 存储。
控制平面可以有两种跨区域扩展策略。第一种是“单主多从”模式:一个区域作为主控制平面,其余区域部署只读的 API Server 转发层,所有变更操作回源到主区域。这种方式实现简单,但对主区域的网络依赖很强。第二种是“联邦控制平面”模式,使用 Karmada 或 Kubernetes Federation v2 等项目,在每个区域运行完整的集群,上层通过联邦 API 统一分发资源。第二种方式复杂度更高,但容灾能力更强,适合对可用性要求苛刻的生产系统。
下面是一个使用 kubeadm 初始化单区域控制平面时,配置 etcd 高可用的关键片段。注意 etcd 的证书和节点配置必须严格一致:
apiVersion: kubeadm.k8s.io/v1beta3
kind: ClusterConfiguration
etcd:
local:
dataDir: /var/lib/etcd
extraArgs:
listen-client-urls: "https://127.0.0.1:2379"
advertise-client-urls: "https://127.0.0.1:2379"
listen-peer-urls: "https://10.0.0.1:2380"
initial-advertise-peer-urls: "https://10.0.0.1:2380"
initial-cluster: "cp1=https://10.0.0.1:2380,cp2=https://10.0.0.2:2380,cp3=https://10.0.0.3:2380"
initial-cluster-state: "new"
在多区域设计中,我们推荐每个区域的控制平面节点使用独立的证书和 CA,避免跨区域证书泄露风险。同时,kube-apiserver 的 --etcd-servers 参数必须指向本区域内的 etcd 端点,绝不能配置成跨区域地址。如果使用云厂商托管服务,例如 AWS EKS 的跨可用区模式,控制平面会自动分布在多个 AZ 内,但区域之间仍然是独立的集群,需要额外通过 VPC Peering 或 Transit Gateway 打通网络。
工作负载调度与跨区网络方案
多可用区部署中,Pod 的调度策略直接决定故障转移的效率。Kubernetes 原生提供了拓扑分布约束(Topology Spread Constraints)和 Pod 反亲和性(PodAntiAffinity),可以把同一 Deployment 的副本均匀分散到不同的可用区。例如,下面的 YAML 强制要求副本必须分布在至少两个可用区,并且单个可用区内的副本数不超过总数的一半:
apiVersion: apps/v1
kind: Deployment
metadata:
name: web-app
spec:
replicas: 4
selector:
matchLabels:
app: web
template:
metadata:
labels:
app: web
spec:
topologySpreadConstraints:
- maxSkew: 1
topologyKey: topology.kubernetes.io/zone
whenUnsatisfiable: DoNotSchedule
labelSelector:
matchLabels:
app: web
containers:
- name: nginx
image: nginx:1.25
ports:
- containerPort: 80
当区域数量增多时,单纯依赖调度约束还不够,因为每个区域都是独立集群,无法跨集群调度。此时推荐使用 Karmada 或 Federation v2 的“副本调度策略”。Karmada 允许你定义一个 PropagationPolicy,将 Deployment 按权重分发到不同区域的成员集群,并支持故障时的自动重调度。下面是 Karmada 的 PropagationPolicy 示例:
apiVersion: policy.karmada.io/v1alpha1
kind: PropagationPolicy
metadata:
name: web-app-policy
spec:
resourceSelectors:
- apiVersion: apps/v1
kind: Deployment
name: web-app
placement:
clusterAffinity:
clusterNames:
- cluster-zone-a
- cluster-zone-b
- cluster-zone-c
replicaScheduling:
replicaDivisionPreference: Weighted
replicaSchedulingType: Divided
weightPreference:
staticWeightList:
- targetCluster:
clusterNames: [cluster-zone-a]
weight: 3
- targetCluster:
clusterNames: [cluster-zone-b]
weight: 2
- targetCluster:
clusterNames: [cluster-zone-c]
weight: 1
网络层面,跨区域 Pod 通信通常依赖云厂商的 VPC Peering、Transit Gateway 或者专线。如果使用 Calico 或 Cilium 作为 CNI,需要额外配置跨区域路由。在非云环境下,可以使用 WireGuard 或 IPsec 隧道打通每个区域的 Pod CIDR,但要注意 MTU 和延迟。另一个常见做法是采用服务网格(如 Istio)的多集群模式,通过东西向网关在区域之间转发流量,但会增加运维复杂度。因此,在生产环境中,建议优先使用云厂商提供的托管网络能力,避免自建跨区域隧道。
Service 暴露也需要考虑区域感知。普通的 ClusterIP Service 只在本区域集群内有效,跨区域访问需要借助 Ingress 或多集群 Service API。Kubernetes 社区正在推进 Multi-Cluster Service API(MCS),它允许定义一个 ServiceImport 资源,让其他区域的集群发现并访问该服务。对于入口流量,可以使用全局负载均衡器(如 AWS Global Accelerator、GCP External HTTP(S) Load Balancing)根据用户地理位置或健康检查结果路由到最近的区域集群。
存储与数据复制策略
有状态应用在多区域部署中最难处理。如果 Pod 使用本地存储或单区域持久卷,一旦区域故障,数据将无法访问。常见的方案有两种:存储层异步复制和应用层数据同步。存储层复制依赖 CSI 驱动提供的跨区域卷复制能力,例如 AWS EBS 的跨区域快照复制、Ceph RBD 的异地备份。但存储复制通常只能做到接近实时的异步复制,RPO 可能达到分钟级,无法满足强一致性要求。
对于需要强一致性的场景,建议采用应用层多主或主从复制。例如,使用 Vitess 管理跨区域 MySQL 集群,使用 Cassandra 或 CockroachDB 这种原生支持多区域部署的数据库。Kubernetes 本身不负责数据复制,你需要通过 StatefulSet 配合 Operator(如 Postgres Operator、Redis Operator)来实现跨区域数据同步。下面是一个使用 Rook 部署跨区域 Ceph 集群的思路,不过更推荐使用托管数据库服务,因为跨区域存储集群的运维成本非常高。
如果确实需要在 Kubernetes 中管理跨区域存储,可以考虑使用 OpenEBS 或 Longhorn 的备份功能,定期将卷快照复制到另一个区域的 S3 兼容存储。恢复时通过 Velero 这样的备份恢复工具重建应用。Velero 支持跨集群恢复,可以在区域故障时快速在备用区域拉起工作负载。以下是一个 Velero 备份存储位置配置示例:
apiVersion: velero.io/v1
kind: BackupStorageLocation
metadata:
name: cross-region-backup
namespace: velero
spec:
provider: aws
objectStorage:
bucket: velero-backup-eu-west-1
prefix: k8s
config:
region: eu-west-1
s3ForcePathStyle: "false"
基于 Cluster API 的声明式集群管理
手动在多区域创建和维护多个 Kubernetes 集群非常繁琐,推荐使用 Cluster API(CAPI)来声明式地管理基础设施。CAPI 允许你用 YAML 描述每个区域的集群配置,包括控制平面节点、工作节点、网络和存储。配合 ClusterClass,可以定义一套可复用的集群模板,在不同区域快速创建同构集群。下面是一个使用 AWS 作为 provider 的 Cluster API 示例,展示如何声明一个跨三个可用区的集群:
apiVersion: cluster.x-k8s.io/v1beta1
kind: Cluster
metadata:
name: multi-az-cluster
namespace: default
spec:
clusterNetwork:
pods:
cidrBlocks: ["10.244.0.0/16"]
services:
cidrBlocks: ["10.96.0.0/12"]
topology:
class: aws-quickstart
version: v1.27.0
controlPlane:
replicas: 3
workers:
machineDeployments:
- name: md-zone-a
class: default-worker
replicas: 2
failureDomain: us-east-1a
- name: md-zone-b
class: default-worker
replicas: 2
failureDomain: us-east-1b
- name: md-zone-c
class: default-worker
replicas: 2
failureDomain: us-east-1c
CAPI 的强大之处在于它可以与 ClusterClass 结合,通过 failureDomain 字段自动将控制平面节点分散到不同可用区,同时使用 MachineHealthCheck 自动替换故障节点。对于跨区域场景,你需要为每个区域创建独立的 Cluster 资源,然后通过 Karmada 或其他联邦工具将它们纳入统一管理。CAPI 还支持 ClusterResourceSet,可以自动在每个新集群中安装 CNI、CSI 和监控组件,大大减少重复操作。
最后需要强调,多区域多可用区部署不是银弹。它带来容灾能力的同时,也引入了更高的网络延迟、数据一致性风险和运维复杂度。在开始设计之前,务必明确业务对 RPO 和 RTO 的具体要求,再决定采用单集群多可用区、多集群联邦还是完全隔离的备份恢复方案。不要为了架构而架构,适合的才是最好的。
Kubernetes多区域部署高可用架构修改时间:2026-08-25 00:17:03