饮墨

子安饮墨馀三斗,留与卿儿作赋来

Karmada 多集群管理实战:让 Kubernetes 跨集群调度不再痛苦

痛点:单集群到多集群的管理困境

当业务规模增长到一定阶段,单个 Kubernetes 集群已无法满足需求——你可能面对以下场景:

  • 多区域容灾:业务部署在 2~3 个可用区/Region,需要故障自动切换
  • 混合云架构:部分业务在公有云(AWS/GCP),部分在私有数据中心
  • 资源隔离:不同团队或不同环境(生产/预发/测试)用独立集群,但需要统一管理
  • 单集群瓶颈:节点超 5000、Pod 超 15 万时,etcd 和 API Server 压力剧增

传统做法是在每个集群上分别 kubectl apply,配合自研脚本同步配置。这带来的问题是:配置漂移、故障切换慢、缺乏全局视图。

Karmada(Kubernetes Armada)正是 CNCF 孵化的多集群编排引擎,解决的就是这个问题。

方案:Karmada 核心架构

Karmada 采用 Push 模式 + 资源模板(Resource Template)+ 调度策略(Propagation Policy) 三层抽象:

┌──────────────────────────────────────────────┐
│              Karmada Control Plane            │
│  ┌─────────┐  ┌──────────────┐  ┌────────┐  │
│  │ API Svr │  │  Controller  │  │Scheduler│  │
│  └────┬────┘  └──────┬───────┘  └───┬────┘  │
│       │               │              │        │
│  ┌────┴───────────────┴──────────────┴────┐  │
│  │         Karmada etcd (独立)            │  │
│  └────────────────────────────────────────┘  │
└──────────────────────────────────────────────┘
        │              │              │
   ┌────▼────┐   ┌────▼────┐   ┌────▼────┐
   │ Cluster1 │   │ Cluster2 │   │ Cluster3 │
   │  (AWS)   │   │  (GCP)   │   │ (On-Prem)│
   └──────────┘   └──────────┘   └──────────┘

核心概念:

概念 作用
Resource Template 标准 K8s 资源(Deployment/Service 等),提交到 Karmada API
PropagationPolicy 定义资源分发到哪些集群、副本如何分配
OverridePolicy 针对不同集群做差异化配置(如镜像仓库地址)
ResourceBinding 调度结果,记录资源到集群的映射

关键优势:应用定义和调度策略解耦——你不需要修改现有 YAML,只需追加 Policy 即可实现多集群分发。

实操步骤

Step 1:安装 Karmada 控制面

使用 karmadactl 一键初始化(生产环境建议独立 etcd + HA 部署):

# 安装 karmadactl CLI
curl -sL https://raw.githubusercontent.com/karmada-io/karmada/master/hack/install-cli.sh | bash

# 在管理集群上初始化 Karmada 控制面
karmadactl init --karmada-apiserver-replicas 3 \
  --etcd-replicas 3 \
  --karmada-data /var/lib/karmada

# 查看安装结果
kubectl get pods -n karmada-system

输出示例:

NAME                                        READY   STATUS    RESTARTS
karmada-apiserver-0                         1/1     Running   0
karmada-controller-manager-xxx              1/1     Running   0
karmada-scheduler-xxx                       1/1     Running   0
karmada-etcd-0                              1/1     Running   0

Step 2:注册成员集群

将已有的 K8s 集群加入 Karmada:

# Push 模式注册(Karmada 主动推送,适合网络可达场景)
karmadactl join cluster-aws \
  --kubeconfig=/root/.kube/aws-config \
  --cluster-kubeconfig=/root/.kube/aws-config

karmadactl join cluster-gcp \
  --kubeconfig=/root/.kube/gcp-config \
  --cluster-kubeconfig=/root/.kube/gcp-config

# 查看已注册集群
karmadactl get clusters

输出:

NAME          VERSION   MODE   READY   AGE
cluster-aws   v1.30.2   Push   True    2m
cluster-gcp   v1.29.4   Push   True    1m

Step 3:部署应用 + 分发策略

# nginx-deploy.yaml — 标准 Deployment,无需任何修改
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-ha
  namespace: production
spec:
  replicas: 6
  selector:
    matchLabels:
      app: nginx-ha
  template:
    metadata:
      labels:
        app: nginx-ha
    spec:
      containers:
      - name: nginx
        image: nginx:1.27-alpine
        resources:
          requests:
            cpu: 100m
            memory: 128Mi
---
# propagation-policy.yaml — 调度策略:副本按权重分配到两个集群
apiVersion: policy.karmada.io/v1alpha1
kind: PropagationPolicy
metadata:
  name: nginx-ha-policy
  namespace: production
spec:
  resourceSelectors:
    - apiVersion: apps/v1
      kind: Deployment
      name: nginx-ha
  placement:
    clusterAffinity:
      clusterNames:
        - cluster-aws
        - cluster-gcp
    replicaScheduling:
      replicaDivisionPreference: Weighted
      replicaSchedulingType: Divided
      weightPreference:
        staticWeightList:
          - targetCluster:
              clusterNames:
                - cluster-aws
            weight: 2
          - targetCluster:
              clusterNames:
                - cluster-gcp
            weight: 1
# 提交到 Karmada 控制面
kubectl apply -f nginx-deploy.yaml --context karmada-apiserver
kubectl apply -f propagation-policy.yaml --context karmada-apiserver

# 查看分发状态
karmadactl get deployment nginx-ha -n production

结果:cluster-aws 分配 4 副本,cluster-gcp 分配 2 副本(按 2:1 权重)。

Step 4:差异化配置(OverridePolicy)

不同集群使用不同镜像仓库:

apiVersion: policy.karmada.io/v1alpha1
kind: OverridePolicy
metadata:
  name: nginx-image-override
  namespace: production
spec:
  targetCluster:
    clusterNames:
      - cluster-gcp
  overrideRules:
    - overriders:
        imageOverrider:
          - component: Registry
            operator: replace
            value: gcr.io/my-project

这样 cluster-gcp 的 Pod 自动拉取 gcr.io/my-project/nginx:1.27-alpine,无需维护两份 Deployment。

避坑指南

1. 控制面与成员集群网络不通

现象karmadactl join 成功但 cluster 状态一直 NotReady

排查

# 检查 karmada-agent 日志(Pull 模式)或 controller 日志
kubectl logs -n karmada-system deployment/karmada-controller-manager | grep "cluster-aws"

解法:跨区域/跨云场景建议用 Pull 模式——在成员集群部署 karmada-agent,由 agent 主动拉取资源,无需控制面能访问成员集群 API。

2. 资源冲突:已有同名资源

现象PropagationPolicy 生效后报 AlreadyExists

解法:设置 conflictResolution: Overwrite 让 Karmada 接管已有资源:

spec:
  conflictResolution: Overwrite

生产环境建议先用 Abort(默认)观察,确认无误后再改为 Overwrite

3. 故障转移不生效

现象:成员集群宕机但副本未迁移。

解法:需要显式开启 Failover 调度:

spec:
  placement:
    spreadConstraints:
      - maxGroups: 2
        minGroups: 1
    replicaScheduling:
      replicaSchedulingType: Divided
  failover:
    application:
      decisionConditions:
        tolerationSeconds: 60
      purgeMode: Graciously

tolerationSeconds: 60 表示集群不可达 60 秒后触发迁移,避免网络抖动误触发。

总结

维度 建议
规模 2~3 集群起步即可引入 Karmada,门槛低于 Cluster API
网络 跨云用 Pull 模式,同 VPC 用 Push 模式
调度 先 Duplicated(全量复制)跑通,再切 Divided(副本拆分)
故障转移 生产必须配置 Failover + 合理 tolerationSeconds
与 GitOps 结合 ArgoCD 管理 Karmada 控制面的资源,形成 GitOps → Karmada → 成员集群 三级流水线

Karmada 不是"另一个平台",而是在现有 K8s 之上加了一层轻量编排。你的 Deployment/Service YAML 不用改一行,只需追加 Policy 文件——这是它相比 KubeFed(已废弃)和自研方案最大的优势。

您还没有登录,请登录后发表评论。