Cluster API 与声明式集群生命周期管理

系统讲解 Cluster API 的声明式集群管理:Management/Workload 集群架构、Cluster 与 Machine 资源模型、基础设施与引导提供者、集群创建与升级流程、MachineDeployment 滚动更新、托管拓扑、多集群 GitOps 规模化,以及故障恢复与集群删除的生产实践。

当集群数量从 3 个涨到 30 个,「怎么建集群」就从一次性任务变成了持续性问题:谁来保证所有集群的控制面版本一致?节点池扩容要不要人工点控制台?某个集群的 etcd 挂了怎么重建?Cluster API(CAPI)把这些操作变成声明式资源——用 Kubernetes 管理 Kubernetes,集群本身成为可 Git 化、可 Reconcile、可回滚的对象。本文覆盖 CAPI 的架构、资源模型、升级与扩缩流程,以及规模化与故障恢复的实践。


目录


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创建机器、网络、LBAWS、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 拒绝或集群异常一次只升一个次版本
缺 PDBdrain 强行驱逐导致中断有状态负载配置 PDB
MachineTemplate 就地改变更不生效新建模板并更新引用
误删 Cluster云资源被级联删除删除保护 + GitOps 审批
手工清 finalizer留下孤儿云资源定位卡住的 Provider 再处理
单管理集群纳管过多控制器延迟升高分片管理,拆分管理集群

小结

Cluster API 的价值不在于「能建集群」,而在于把集群生命周期变成可版本控制、可 Reconcile、可回滚的声明式资源:Cluster 描述拓扑,Machine 描述机器,Provider 负责落地,OwnerReference 负责级联。落地的关键有三点——用 ClusterClass 消除模板复制、用 GitOps 让集群清单可审计、用保守的滚动策略与 PDB 保证变更不降容量。同时必须清醒认识到级联删除的威力:一次误删可能带走整套云资源,因此删除保护与备份不是可选项。记住:集群即资源,管理集群同样需要被当作生产系统来运维。

继续阅读

探索更多技术文章

浏览归档,发现更多关于系统设计、工具链和工程实践的内容。

全部文章 返回首页

「云原生」更多文章

  1. 调度均衡:Descheduler 与资源碎片整理
  2. 运行时安全:Falco/Tetragon 与 eBPF 检测实战
  3. 拓扑感知路由:topologySpread、本地流量与流量亲和