巨耗 发表于 2026-1-13 15:50:00

Karmada-Cluster 组件详解

Karmada Cluster 组件详解

目录


[*]一、使用背景
[*]二、Cluster API 定义
[*]三、使用方式
[*]四、源码原理
[*]五、总结
一、使用背景

1.1 为什么需要 Cluster 资源?

在 Karmada 多集群管理系统中,Cluster 是代表成员集群的核心资源对象。它的主要作用是:

[*]集群注册与发现:将 Kubernetes 集群注册到 Karmada 控制平面
[*]集群生命周期管理:管理集群的加入、健康检查、故障处理、删除等
[*]集群属性定义:记录集群的地理位置(Region/Zone)、云提供商、资源模型等信息
[*]调度决策依据:为 Scheduler 提供集群信息,用于资源分发决策
[*]状态同步:收集和展示成员集群的实时状态(节点、资源等)
1.2 在多集群架构中的位置

Karmada 控制平面
    │
    ├── Cluster (成员集群1) ──┐
    ├── Cluster (成员集群2) ──┼──> ResourceBinding ──> Work ──> 实际资源
    └── Cluster (成员集群3) ──┘Cluster 是 Karmada 与成员集群之间的桥梁,所有资源分发都必须基于已注册的 Cluster。
二、Cluster API 定义

2.1 基本结构

Cluster 是一个集群级(ClusterScope)的 CRD 资源,定义在 pkg/apis/cluster/v1alpha1/types.go:
// Cluster represents the desired state and status of a member cluster.
type Cluster struct {
    metav1.TypeMeta   `json:",inline"`
    metav1.ObjectMeta `json:"metadata,omitempty"`
   
    // Spec 定义了集群的期望状态(配置信息)
    Spec ClusterSpec `json:"spec"`
   
    // Status 表示集群的实际状态(运行时信息)
    Status ClusterStatus `json:"status,omitempty"`
}2.2 ClusterSpec - 期望配置

ClusterSpec 定义了集群的配置信息:
核心字段

type ClusterSpec struct {
    // ID: 集群唯一标识符
    // 1. 优先从 ClusterProperty API 获取
    // 2. 否则使用 kube-system namespace 的 UID
    ID string `json:"id,omitempty"`
   
    // SyncMode: 同步模式(Push 或 Pull)
    // - Push: 控制平面主动推送资源到成员集群
    // - Pull: 成员集群的 Agent 主动拉取资源
    SyncMode ClusterSyncMode `json:"syncMode"`
   
    // APIEndpoint: 成员集群的 API 地址
    APIEndpoint string `json:"apiEndpoint,omitempty"`
   
    // SecretRef: 访问成员集群的凭证(包含 token 和 caBundle)
    SecretRef *LocalSecretReference `json:"secretRef,omitempty"`
   
    // ImpersonatorSecretRef: Impersonator 的凭证(用于 Pull 模式)
    ImpersonatorSecretRef *LocalSecretReference `json:"impersonatorSecretRef,omitempty"`
   
    // 连接配置
    InsecureSkipTLSVerification bool   `json:"insecureSkipTLSVerification,omitempty"`
    ProxyURL                  string `json:"proxyURL,omitempty"`
    ProxyHeader               mapstring `json:"proxyHeader,omitempty"`
   
    // 集群属性(用于调度)
    Provider string   `json:"provider,omitempty"`   // 云提供商(如 aws, alibaba)
    Region   string   `json:"region,omitempty"`   // 区域
    Zones    []string `json:"zones,omitempty"`      // 可用区列表
   
    // Taints: 集群污点(用于调度决策)
    Taints []corev1.Taint `json:"taints,omitempty"`
   
    // ResourceModels: 资源模型(用于资源估算和调度)
    ResourceModels []ResourceModel `json:"resourceModels,omitempty"`
}SyncMode 详解

const (
    // Push 模式:控制平面主动推送
    // - 控制器在控制平面运行,直接连接成员集群 API
    // - 适合网络可达的场景
    Push ClusterSyncMode = "Push"
   
    // Pull 模式:成员集群主动拉取
    // - Agent 在成员集群运行,拉取控制平面的资源
    // - 适合网络受限或安全隔离的场景
    Pull ClusterSyncMode = "Pull"
)2.3 ClusterStatus - 运行时状态

ClusterStatus 记录了集群的实时状态:
type ClusterStatus struct {
    // KubernetesVersion: Kubernetes 版本
    KubernetesVersion string `json:"kubernetesVersion,omitempty"`
   
    // APIEnablements: 集群支持的 API 资源列表
    APIEnablements []APIEnablement `json:"apiEnablements,omitempty"`
   
    // Conditions: 集群条件状态
    Conditions []metav1.Condition `json:"conditions,omitempty"`
   
    // NodeSummary: 节点摘要
    NodeSummary *NodeSummary `json:"nodeSummary,omitempty"`
   
    // ResourceSummary: 资源摘要(可分配、已分配、等待分配)
    ResourceSummary *ResourceSummary `json:"resourceSummary,omitempty"`
   
    // RemedyActions: 需要执行的修复操作
    RemedyActions []string `json:"remedyActions,omitempty"`
}Conditions 类型

const (
    // ClusterConditionReady: 集群是否就绪
    ClusterConditionReady = "Ready"
   
    // ClusterConditionCompleteAPIEnablements: API 启用是否完整
    ClusterConditionCompleteAPIEnablements = "CompleteAPIEnablements"
)ResourceSummary 结构

type ResourceSummary struct {
    // Allocatable: 可分配资源总量(所有节点的总和)
    Allocatable corev1.ResourceList `json:"allocatable,omitempty"`
   
    // Allocating: 等待调度的资源(Pending Pods)
    Allocating corev1.ResourceList `json:"allocating,omitempty"`
   
    // Allocated: 已分配的资源(已调度的 Pods)
    Allocated corev1.ResourceList `json:"allocated,omitempty"`
   
    // AllocatableModelings: 资源模型统计
    AllocatableModelings []AllocatableModeling `json:"allocatableModelings,omitempty"`
}三、使用方式

3.1 注册集群(Push 模式)

使用 karmadactl join 命令注册集群:
# 基本用法
karmadactl join CLUSTER_NAME \
--cluster-kubeconfig=<成员集群的 kubeconfig> \
--kubeconfig=<Karmada 控制平面的 kubeconfig>

# 完整示例
karmadactl join member1 \
--cluster-kubeconfig=$HOME/.kube/member1.config \
--cluster-namespace=karmada-cluster \
--cluster-provider=aliyun \
--cluster-region=cn-hangzhou \
--cluster-zones=cn-hangzhou-a,cn-hangzhou-b \
--kubeconfig=$HOME/.kube/karmada.config工作原理:

[*]读取成员集群的 kubeconfig
[*]提取集群 ID(优先从 ClusterProperty,否则使用 kube-system UID)
[*]创建访问凭证(Secret)
[*]在控制平面创建 Cluster 对象
[*]Cluster Controller 检测到新集群,创建 ExecutionSpace(命名空间)
3.2 注册集群(Pull 模式)

Pull 模式需要成员集群主动注册:
# Step 1: 在控制平面创建 bootstrap token
karmadactl token create --print-register-command \
--kubeconfig=<Karmada 控制平面的 kubeconfig>

# 输出示例:
# karmadactl register 172.18.0.5:5443 \
#   --token t8xfio.640u9gp9obc72v5d \
#   --discovery-token-ca-cert-hash sha256:9cfa542ff48f43793d1816b1dd0a78ad574e349d8f6e005e6e32e8ab528e4244

# Step 2: 在成员集群执行注册命令(指定成员集群的 kubeconfig)
karmadactl register 172.18.0.5:5443 \
--token t8xfio.640u9gp9obc72v5d \
--discovery-token-ca-cert-hash sha256:9cfa542ff48f43793d1816b1dd0a78ad574e349d8f6e005e6e32e8ab528e4244 \
--kubeconfig=<成员集群的 kubeconfig>Pull 模式特点:

[*]成员集群主动连接控制平面
[*]需要在成员集群部署 karmada-agent
[*]适合网络隔离场景
3.3 查看集群

# 列出所有集群
kubectl get clusters

# 查看集群详细信息
kubectl get cluster <cluster-name> -o yaml

# 查看集群状态
kubectl describe cluster <cluster-name>3.4 删除集群

# 删除集群(会触发优雅删除流程)
kubectl delete cluster <cluster-name>删除流程:

[*]从所有 ResourceBinding 和 ClusterResourceBinding 中移除该集群
[*]删除该集群相关的所有 Work 对象
[*]删除 ExecutionSpace 命名空间
[*]删除 Cluster 对象
3.5 手动创建 Cluster(YAML)

也可以直接通过 YAML 创建:
apiVersion: cluster.karmada.io/v1alpha1
kind: Cluster
metadata:
name: member1
spec:
syncMode: Push
apiEndpoint: https://member1-api.example.com:6443
secretRef:
    namespace: karmada-cluster
    name: member1
provider: aliyun
region: cn-hangzhou
zones:
    - cn-hangzhou-a
    - cn-hangzhou-b
taints: []# 可以添加污点来阻止调度四、源码原理

4.1 Cluster Controller 架构

Cluster Controller 负责管理 Cluster 资源的生命周期,代码位于 pkg/controllers/cluster/cluster_controller.go。
核心结构

type Controller struct {
    client.Client                  // Kubernetes 客户端
    EventRecorder record.EventRecorder
   
    // 健康检查配置
    ClusterMonitorPeriod      time.Duration// 监控周期(默认 5s)
    ClusterMonitorGracePeriod time.Duration// 优雅期(默认 40s)
    ClusterStartupGracePeriod time.Duration// 启动优雅期(默认 1min)
    CleanupCheckInterval      time.Duration// 清理检查间隔(10s)
   
    // 集群健康状态缓存
    clusterHealthMap *clusterHealthMap
   
    RateLimiterOptions ratelimiterflag.Options
}4.2 核心工作流程

4.2.1 Reconcile 主流程

func (c *Controller) Reconcile(ctx context.Context, req controllerruntime.Request) (controllerruntime.Result, error) {
    // 1. 获取 Cluster 对象
    cluster := &clusterv1alpha1.Cluster{}
    if err := c.Client.Get(ctx, req.NamespacedName, cluster); err != nil {
      if apierrors.IsNotFound(err) {
            return controllerruntime.Result{}, nil
      }
      return controllerruntime.Result{}, err
    }
   
    // 2. 判断是否为删除操作
    if !cluster.DeletionTimestamp.IsZero() {
      return c.removeCluster(ctx, cluster)
    }
   
    // 3. 同步集群(创建/更新)
    return c.syncCluster(ctx, cluster)
}4.2.2 syncCluster - 集群同步

func (c *Controller) syncCluster(ctx context.Context, cluster *clusterv1alpha1.Cluster) (controllerruntime.Result, error) {
    // Step 1: 创建 ExecutionSpace(执行空间)
    // ExecutionSpace 是一个命名空间,格式为: karmada-es-{cluster-name}
    // 用于存放该集群相关的 Work 对象
    err := c.createExecutionSpace(ctx, cluster)
    if err != nil {
      c.EventRecorder.Event(cluster, corev1.EventTypeWarning,
            events.EventReasonCreateExecutionSpaceFailed, err.Error())
      return controllerruntime.Result{}, err
    }
   
    // Step 2: 根据集群条件添加污点
    // - Ready=False: 添加 NotReady taint
    // - Ready=Unknown: 添加 Unreachable taint
    // - Ready=True: 移除所有调度相关的污点
    err = c.taintClusterByCondition(ctx, cluster)
    if err != nil {
      return controllerruntime.Result{}, err
    }
   
    // Step 3: 确保 Finalizer 存在
    // Finalizer 用于在删除时执行清理逻辑
    return c.ensureFinalizer(ctx, cluster)
}关键点:

[*]ExecutionSpace:每个集群都有一个独立的命名空间,用于隔离该集群的 Work 对象
[*]Taint 机制:根据集群健康状态自动添加污点,调度器会据此决策是否调度到该集群
4.2.3 createExecutionSpace - 创建执行空间

func (c *Controller) createExecutionSpace(ctx context.Context, cluster *clusterv1alpha1.Cluster) error {
    // 生成执行空间名称:karmada-es-{cluster-name}
    executionSpaceName := names.GenerateExecutionSpaceName(cluster.Name)
   
    executionSpaceObj := &corev1.Namespace{}
    err := c.Client.Get(ctx, types.NamespacedName{Name: executionSpaceName}, executionSpaceObj)
    if err != nil {
      if !apierrors.IsNotFound(err) {
            return err
      }
      
      // 创建新的执行空间
      executionSpace := &corev1.Namespace{
            ObjectMeta: metav1.ObjectMeta{
                Name: executionSpaceName,
                Labels: mapstring{
                  util.KarmadaSystemLabel: util.KarmadaSystemLabelValue,
                },
            },
      }
      err = c.Client.Create(ctx, executionSpace)
      if err != nil {
            return err
      }
      klog.V(2).InfoS("Created execution space", "cluster", cluster.Name, "namespace", executionSpaceName)
    }
   
    return nil
}执行空间的作用:

[*]隔离不同集群的 Work 对象
[*]便于管理和查询特定集群的工作负载
[*]支持 RBAC 权限隔离
4.2.4 taintClusterByCondition - 污点管理

func (c *Controller) taintClusterByCondition(ctx context.Context, cluster *clusterv1alpha1.Cluster) error {
    currentReadyCondition := meta.FindStatusCondition(cluster.Status.Conditions,
      clusterv1alpha1.ClusterConditionReady)
   
    if currentReadyCondition != nil {
      switch currentReadyCondition.Status {
      case metav1.ConditionFalse:
            // 集群不健康,添加 NotReady 污点
            err = c.updateClusterTaints(ctx,
                []*corev1.Taint{NotReadyTaintTemplateForSched},
                []*corev1.Taint{UnreachableTaintTemplateForSched},
                cluster)
      case metav1.ConditionUnknown:
            // 集群不可达,添加 Unreachable 污点
            err = c.updateClusterTaints(ctx,
                []*corev1.Taint{UnreachableTaintTemplateForSched},
                []*corev1.Taint{NotReadyTaintTemplateForSched},
                cluster)
      case metav1.ConditionTrue:
            // 集群健康,移除所有调度污点
            err = c.updateClusterTaints(ctx,
                nil,
                []*corev1.Taint{NotReadyTaintTemplateForSched, UnreachableTaintTemplateForSched},
                cluster)
      }
    }
    return err
}污点定义:
var (
    // UnreachableTaintTemplateForSched: 集群不可达时的污点
    UnreachableTaintTemplateForSched = &corev1.Taint{
      Key:    clusterv1alpha1.TaintClusterUnreachable,// "cluster.karmada.io/unreachable"
      Effect: corev1.TaintEffectNoSchedule,
    }
   
    // NotReadyTaintTemplateForSched: 集群不健康时的污点
    NotReadyTaintTemplateForSched = &corev1.Taint{
      Key:    clusterv1alpha1.TaintClusterNotReady,// "cluster.karmada.io/not-ready"
      Effect: corev1.TaintEffectNoSchedule,
    }
)4.2.5 removeCluster - 集群删除

func (c *Controller) removeCluster(ctx context.Context, cluster *clusterv1alpha1.Cluster) (controllerruntime.Result, error) {
    // Step 1: 删除 ExecutionSpace
    if err := c.removeExecutionSpace(ctx, cluster); err != nil {
      klog.ErrorS(err, "Failed to remove execution space", "cluster", cluster.Name)
      return controllerruntime.Result{}, err
    }
   
    // Step 2: 检查 ExecutionSpace 是否已删除
    if exist, err := c.ExecutionSpaceExistForCluster(ctx, cluster.Name); err != nil {
      return controllerruntime.Result{}, err
    } else if exist {
      // 如果还存在,等待下次重试
      return controllerruntime.Result{RequeueAfter: c.CleanupCheckInterval}, nil
    }
   
    // Step 3: 从健康状态缓存中删除
    c.clusterHealthMap.delete(cluster.Name)
   
    // Step 4: 检查集群是否已从所有 Binding 中移除
    if done, err := c.isTargetClusterRemoved(ctx, cluster); err != nil {
      return controllerruntime.Result{}, err
    } else if !done {
      // 如果还有 Binding 引用该集群,等待下次重试
      return controllerruntime.Result{RequeueAfter: c.CleanupCheckInterval}, nil
    }
   
    // Step 5: 移除 Finalizer,允许 Cluster 对象被删除
    return c.removeFinalizer(ctx, cluster)
}删除流程说明:

[*]检查依赖:确保没有 ResourceBinding/ClusterResourceBinding 引用该集群
[*]清理资源:删除 ExecutionSpace 及其中的所有 Work 对象
[*]移除 Finalizer:允许 Kubernetes 真正删除 Cluster 对象
4.2.6 monitorClusterHealth - 健康监控

Cluster Controller 启动一个后台 goroutine 定期监控集群健康状态:
func (c *Controller) Start(ctx context.Context) error {    klog.InfoS("Starting cluster health monitor")      // 启动周期性健康检查    go wait.UntilWithContext(ctx, func(ctx context.Context) {      if err := c.monitorClusterHealth(ctx); err != nil {            klog.ErrorS(err, "Error monitoring cluster health")      }    }, c.ClusterMonitorPeriod)

窖咎 发表于 2026-1-15 08:58:32

收藏一下   不知道什么时候能用到

澹台忆然 发表于 2026-1-17 07:08:15

分享、互助 让互联网精神温暖你我

伯斌 发表于 2026-1-17 20:17:05

用心讨论,共获提升!

柄利 发表于 2026-1-18 06:30:38

前排留名,哈哈哈

裴涛 发表于 2026-1-19 10:40:23

谢谢楼主提供!

玛凶 发表于 2026-1-20 01:00:27

很好很强大我过来先占个楼 待编辑

兑谓 发表于 2026-1-21 13:00:20

这个有用。

膏包 发表于 2026-1-27 02:32:21

收藏一下   不知道什么时候能用到

东门芳洲 发表于 2026-1-27 06:33:06

分享、互助 让互联网精神温暖你我

玻倌瞽 发表于 2026-1-27 21:03:03

谢谢楼主提供!

余思洁 发表于 2026-1-28 07:25:33

懂技术并乐意极积无私分享的人越来越少。珍惜

命煦砌 发表于 2026-1-31 08:59:07

感谢分享

颜清华 发表于 2026-2-9 00:11:02

热心回复!

庾芷秋 发表于 2026-2-9 12:07:40

谢谢分享,辛苦了

靳夏萱 发表于 2026-2-9 22:04:13

谢谢分享,试用一下

尤晓兰 发表于 2026-2-10 11:58:08

热心回复!

党新苗 发表于 2026-2-10 13:18:47

感谢分享

邹语彤 发表于 2026-2-10 16:31:08

热心回复!

孟清妍 发表于 2026-2-11 15:50:26

热心回复!
页: [1] 2
查看完整版本: Karmada-Cluster 组件详解