当集群数量从 3 个涨到 30 个,「怎么建集群」就从一次性任务变成了持续性问题:谁来保证所有集群的控制面版本一致?节点池扩容要不要人工点控制台?某个集群的 etcd 挂了怎么重建?Cluster API(CAPI)把这些操作变成声明式资源——用 Kubernetes 管理 Kubernetes,集群本身成为可 Git 化、可 Reconcile、可回滚的对象。本文覆盖 CAPI 的架构、资源模型、升级与扩缩流程,以及规模化与故障恢复的实践。
目录
- 1. Cluster API 架构与核心概念
- 2. Cluster 与 Machine 资源模型
- 3. 基础设施与引导提供者
- 4. 集群创建与升级流程
- 5. MachineDeployment 与滚动更新
- 6. 控制面自托管与托管拓扑
- 7. 多集群规模化与 GitOps
- 8. 故障恢复与集群删除
- 9. 生产最佳实践
1. Cluster API 架构与核心概念
1.1 用 Kubernetes 管理 Kubernetes
CAPI 的核心思想是把集群当作 Kubernetes 资源来管理。它运行在一个「管理集群(Management Cluster)」上,通过一组控制器(Provider)去创建、升级、删除「工作负载集群(Workload Cluster)」。
Management Cluster(管理集群)
├── CAPI 核心控制器(Cluster / Machine / MachineSet / MachineDeployment)
├── Bootstrap Provider(生成 cloud-init 等引导数据)
├── ControlPlane Provider(管理控制面,如 KubeadmControlPlane)
└── Infrastructure Provider(创建云主机 / 负载均衡 / 网络)
└── 创建并管理 Workload Cluster A / B / C ...
1.2 三种 Provider 的分工
| Provider 类型 | 职责 | 常见实现 |
|---|---|---|
| Infrastructure | 创建机器、网络、LB | AWS、Azure、vSphere、OpenStack、Metal3 |
| Bootstrap | 生成节点引导数据 | Kubeadm |
| ControlPlane | 管理控制面生命周期 | KubeadmControlPlane、TalosControlPlane |
职责分离带来可组合性:同一套 CAPI 核心可以同时管理公有云与裸金属集群,只需替换 Infrastructure Provider。
1.3 与管理集群的关系
管理集群本身通常是「自举」的:先用 clusterctl 把 CAPI 装到一个临时集群(如 kind 或 bootstrap 集群),再由 CAPI 创建第一个正式管理集群,最后把管理职责迁移过去。
clusterctl init --infrastructure aws
clusterctl generate cluster prod-1 --kubernetes-version v1.31.0 \
--control-plane-machine-count 3 --worker-machine-count 3 > prod-1.yaml
kubectl apply -f prod-1.yaml
clusterctl describe cluster prod-1 --show-conditions all
2. Cluster 与 Machine 资源模型
2.1 资源层级
Cluster 集群的顶层声明(控制面 Endpoint、网络)
├── KubeadmControlPlane 控制面(3 台机器 + etcd)
│ └── Machine x3 单台机器(绑定 InfraMachine + Bootstrap)
├── MachineDeployment 工作节点池(类似 Deployment)
│ └── MachineSet 一组同规格机器(类似 ReplicaSet)
│ └── Machine xN
└── ClusterResourceSet 集群初始化资源(CNI、CSI)
层级设计刻意对齐了工作负载 API:MachineDeployment ↔ Deployment、MachineSet ↔ ReplicaSet、Machine ↔ Pod。这降低了学习成本,也让滚动更新等语义可以复用。
2.2 Cluster 对象
apiVersion: cluster.x-k8s.io/v1beta1
kind: Cluster
metadata:
name: prod-1
spec:
clusterNetwork:
pods:
cidrBlocks: ["10.244.0.0/16"]
services:
cidrBlocks: ["10.96.0.0/12"]
controlPlaneRef:
apiVersion: controlplane.cluster.x-k8s.io/v1beta1
kind: KubeadmControlPlane
name: prod-1-control-plane
infrastructureRef:
apiVersion: infrastructure.cluster.x-k8s.io/v1beta2
kind: AWSCluster
name: prod-1
controlPlaneRef 与 infrastructureRef 是两个关键指针:前者指向控制面实现,后者指向基础设施实现。Cluster 本身不做事,它是协调中心。
2.3 Machine 与 OwnerReference 链
每台机器由 Machine 表示,它通过 infrastructureRef 与 bootstrap.dataSecretName 关联具体实现:
apiVersion: cluster.x-k8s.io/v1beta1
kind: Machine
metadata:
name: prod-1-md-0-abc12
spec:
clusterName: prod-1
version: v1.31.0
bootstrap:
dataSecretName: prod-1-md-0-abc12-bootstrap-data
infrastructureRef:
kind: AWSMachine
name: prod-1-md-0-abc12
整条链靠 OwnerReference 级联:删除 Cluster 会级联删除所有 Machine、MachineSet、MachineDeployment 与云资源。这是 CAPI 删除集群时的核心机制,也是删除事故的常见来源。
3. 基础设施与引导提供者
3.1 Infrastructure Provider 做什么
以 AWS 为例,AWSCluster 描述网络与负载均衡,AWSMachine 描述单台 EC2 实例:
apiVersion: infrastructure.cluster.x-k8s.io/v1beta2
kind: AWSMachineTemplate
metadata:
name: prod-1-md-0
spec:
template:
spec:
instanceType: m6i.xlarge
iamInstanceProfile: nodes.cluster-api-provider-aws.sigs.k8s.io
sshKeyName: prod-key
rootVolume: {size: 100, type: gp3}
Instance 规格变更必须新建模板(Immutable),这是 CAPI 的通用约定:MachineTemplate 不可变,变更意味着滚动替换。
3.2 Bootstrap Provider 做什么
Kubeadm Bootstrap Provider 生成 cloud-init 数据并写入 Secret,节点启动时读取并执行 kubeadm join。可用 kubectl get secret <machine>-bootstrap-data -o jsonpath='{.data.value}' | base64 -d 查看,其中含证书与 join 配置,注意敏感。
3.3 Provider 版本兼容矩阵
CAPI 核心版本 <-> Provider 版本 <-> Kubernetes 版本
例如:CAPI v1.8 支持 K8s 1.28~1.31,CAPA v2.6 对应 CAPI v1.8
升级顺序必须是先升 Provider,再升核心,否则 CRD 字段可能不匹配。
4. 集群创建与升级流程
4.1 创建流程时序
1. 应用 Cluster + AWSCluster
2. Infrastructure Provider 创建 VPC / 子网 / LB / 安全组
3. Cluster 获得 controlPlaneEndpoint
4. KubeadmControlPlane 创建第一台控制面机器,Bootstrap 生成 cloud-init
5. 其余控制面节点加入,etcd 组成集群
6. MachineDeployment 创建 Worker 节点并 join,ClusterResourceSet 下发 CNI/CSI
7. Cluster 状态置为 Ready
4.2 状态与条件观察
clusterctl describe cluster prod-1 --show-conditions all
kubectl get cluster,machine,kubeadmcontrolplane,machinedeployment -n default
CAPI 的 conditions 非常详尽,排查时优先看条件而非事件:
| 条件 | 含义 |
|---|---|
| InfrastructureReady | 基础设施就绪 |
| ControlPlaneReady | 控制面就绪 |
| NodeHealthy | 节点健康 |
4.3 升级控制面
升级只需修改 version 字段,KubeadmControlPlane 会按「滚动 + etcd 保护」策略逐台替换:
kubectl patch kubeadmcontrolplane prod-1-control-plane --type merge \
-p '{"spec":{"version":"v1.31.1"}}'
升级规则:一次只能升一个次版本(1.30 → 1.31 可以,1.29 → 1.31 不行),且必须控制面先于工作节点。KCP 会保证 etcd 成员始终为奇数且不丢失 quorum。
4.4 升级工作节点
修改 MachineDeployment 模板中的 version 字段即可触发节点滚动替换,做法与控制面一致。
5. MachineDeployment 与滚动更新
5.1 滚动策略
apiVersion: cluster.x-k8s.io/v1beta1
kind: MachineDeployment
metadata:
name: prod-1-md-0
spec:
replicas: 6
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 1
maxUnavailable: 0
selector:
matchLabels:
cluster.x-k8s.io/cluster-name: prod-1
pool: md-0
template:
spec:
clusterName: prod-1
version: v1.31.1
infrastructureRef:
kind: AWSMachineTemplate
name: prod-1-md-0
maxSurge: 1 + maxUnavailable: 0 是最保守也最安全的组合:先起新机器、等 Ready、再删旧机器,全程不降容量。
5.2 节点排空与优雅下线
滚动更新前 CAPI 会调用 kubectl drain。要让有状态工作负载优雅迁移,必须为业务 Pod 配置 PodDisruptionBudget(如 minAvailable: 2)。没有 PDB,drain 会强行驱逐,可能造成短暂不可用。
5.3 节点池的常见操作
| 操作 | 做法 |
|---|---|
| 扩容 | 修改 MachineDeployment 的 replicas |
| 换机型 | 新建 MachineTemplate,更新引用,触发滚动 |
| 换镜像 | 修改 MachineDeployment 模板的 image 字段 |
| 打散到多可用区 | 模板加 topologySpreadConstraints 或故障域字段 |
6. 控制面自托管与托管拓扑
6.1 三种拓扑
| 拓扑 | 描述 | 适用 |
|---|---|---|
| Standalone | 管理集群与工作负载集群完全分离 | 生产推荐 |
| Pivot | 自举期间从临时集群迁移到正式管理集群 | 初始化阶段 |
6.2 自举与 Pivot
自举的标准做法是 Pivot:先在临时集群创建管理集群,再把 CAPI 组件与所有 CR 迁移过去。
# 1. 用临时集群创建管理集群(含 CAPI 组件)
clusterctl init --infrastructure aws
# 2. 迁移 CAPI 组件与 CR 到目标管理集群
clusterctl move --to-kubeconfig=mgmt.kubeconfig
clusterctl move 会暂停所有对象、迁移 Secret 与 CR、再恢复,过程中新旧集群都不能操作被迁移对象。
6.3 托管控制面
部分 Provider 支持「托管控制面」(如 EKS、AKS 托管模式),此时 controlPlaneRef 指向托管实现,控制面机器不由 CAPI 管理,但工作节点仍由 MachineDeployment 管理。
7. 多集群规模化与 GitOps
7.1 用 Fleet 管理集群集合
当管理集群要管理上百个工作负载集群时,逐一手写 YAML 不可行。做法是用 Git 存放集群清单,用 Flux/Argo CD 同步到管理集群:
gitops-repo/
├── clusters/prod-1/{cluster.yaml,kcp.yaml,md-0.yaml}
├── clusters/prod-2/...
└── fleets/prod-clusterset.yaml # 批量定义共同属性
7.2 ClusterClass 与模板化
ClusterClass 把「一个集群由哪些组件构成」抽象成可复用模板,避免复制粘贴:
apiVersion: cluster.x-k8s.io/v1beta1
kind: ClusterClass
metadata:
name: aws-standard
spec:
infrastructure:
ref: {kind: AWSClusterTemplate}
controlPlane:
ref: {kind: KubeadmControlPlaneTemplate}
workers:
machineDeployments:
- class: default-worker
template:
bootstrap:
ref: {kind: KubeadmConfigTemplate}
使用 ClusterClass 后,创建一个集群只需引用类名与少量参数:
kind: Cluster
spec:
topology:
class: aws-standard
version: v1.31.0
controlPlane:
replicas: 3
workers:
machineDeployments:
- {class: default-worker, name: md-0, replicas: 6}
托管拓扑(Managed Topology)会持续 Reconcile:改 Cluster 的 topology 字段,CAPI 自动推导出 KCP 与 MD 的变更,无需手工维护下层对象。
7.3 规模化注意事项
□ 管理集群自身也要高可用(3 控制面 + etcd 备份)
□ 单个管理集群的纳管规模有上限(控制器并发与 etcd 压力)
□ 分批升级 Provider,避免一次影响全部集群
□ 为每个工作负载集群配置独立命名空间与 RBAC
8. 故障恢复与集群删除
8.1 控制面节点故障
KCP 会自动检测并替换不健康的控制面机器,触发条件是节点 NotReady 或 Machine 的 NodeHealthy 为 False。可用 kubectl get machines -l cluster.x-k8s.io/control-plane="" 与 kubectl describe machine 查看条件。替换控制面机器时 etcd 成员会先移除再加入,期间 quorum 不能丢,因此控制面副本数必须为奇数且 ≥ 3。
8.2 误删恢复
CAPI 的资源链是级联删除的,删除 Cluster 会连带删除云资源。防误删手段:
□ Cluster 加注解 cluster.x-k8s.io/paused 或删除保护 webhook
□ GitOps 仓库加保护分支与审批
□ 云侧开启资源删除保护(如 AWS DeletionProtection)
□ 定期备份管理集群的 etcd
若已误删,只要云资源还在,可用 clusterctl 重新导入;若云资源已删,只能重建。
8.3 删除流程与阻塞排查
删除顺序:MachineDeployment -> MachineSet -> Machine -> 云主机 -> 网络 -> Cluster
常见阻塞:云资源被手动挂载的卷 / 安全组依赖占用;finalizer 未清除
不要手工删除 finalizer,那会留下孤儿云资源;应先定位是哪个 Provider 卡住。
9. 生产最佳实践
9.1 落地 Checklist
□ 管理集群独立部署,3 控制面 + etcd 定期备份
□ 使用 ClusterClass 模板化,禁止复制粘贴 YAML
□ 集群清单纳入 Git,用 Flux/Argo CD 同步
□ 控制面副本数为奇数且 >= 3
□ 滚动更新用 maxSurge=1 + maxUnavailable=0
□ 所有有状态工作负载配置 PDB
□ 升级顺序:Provider 先于核心,控制面先于工作节点
□ 一次只升一个次版本,关键集群开启删除保护
□ 用 clusterctl describe 做例行巡检
9.2 常见坑与对策
| 坑 | 现象 | 对策 |
|---|---|---|
| 升级顺序错误 | CRD 字段不匹配、控制器报错 | Provider 先于核心升级 |
| 跨次版本升级 | KCP 拒绝或集群异常 | 一次只升一个次版本 |
| 缺 PDB | drain 强行驱逐导致中断 | 有状态负载配置 PDB |
| MachineTemplate 就地改 | 变更不生效 | 新建模板并更新引用 |
| 误删 Cluster | 云资源被级联删除 | 删除保护 + GitOps 审批 |
| 手工清 finalizer | 留下孤儿云资源 | 定位卡住的 Provider 再处理 |
| 单管理集群纳管过多 | 控制器延迟升高 | 分片管理,拆分管理集群 |
小结
Cluster API 的价值不在于「能建集群」,而在于把集群生命周期变成可版本控制、可 Reconcile、可回滚的声明式资源:Cluster 描述拓扑,Machine 描述机器,Provider 负责落地,OwnerReference 负责级联。落地的关键有三点——用 ClusterClass 消除模板复制、用 GitOps 让集群清单可审计、用保守的滚动策略与 PDB 保证变更不降容量。同时必须清醒认识到级联删除的威力:一次误删可能带走整套云资源,因此删除保护与备份不是可选项。记住:集群即资源,管理集群同样需要被当作生产系统来运维。
继续阅读
探索更多技术文章
浏览归档,发现更多关于系统设计、工具链和工程实践的内容。