Karmada-Cluster 组件详解

Karmada Cluster 组件详解

目录


一、使用背景

1.1 为什么需要 Cluster 资源?

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

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

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                 map[string]string `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

工作原理

  1. 读取成员集群的 kubeconfig
  2. 提取集群 ID(优先从 ClusterProperty,否则使用 kube-system UID)
  3. 创建访问凭证(Secret)
  4. 在控制平面创建 Cluster 对象
  5. 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>

删除流程

  1. 从所有 ResourceBinding 和 ClusterResourceBinding 中移除该集群
  2. 删除该集群相关的所有 Work 对象
  3. 删除 ExecutionSpace 命名空间
  4. 删除 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: map[string]string{
                    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)
}

删除流程说明

  1. 检查依赖:确保没有 ResourceBinding/ClusterResourceBinding 引用该集群
  2. 清理资源:删除 ExecutionSpace 及其中的所有 Work 对象
  3. 移除 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)
    
    <-ctx.Done()
    return nil
}

健康检查逻辑

func (c *Controller) monitorClusterHealth(ctx context.Context) error {
    // 1. 列出所有集群
    clusterList := &clusterv1alpha1.ClusterList{}
    if err = c.Client.List(ctx, clusterList); err != nil {
        return err
    }
    
    // 2. 遍历每个集群检查健康状态
    for i := range clusterList.Items {
        cluster := &clusterList.Items[i]
        err = c.tryUpdateClusterHealth(ctx, cluster)
        if err != nil {
            klog.ErrorS(err, "Failed to update health", "cluster", cluster.Name)
            continue
        }
    }
    
    return nil
}

健康状态更新逻辑

func (c *Controller) tryUpdateClusterHealth(ctx context.Context, cluster *clusterv1alpha1.Cluster) error {
    // 1. 获取上次的健康状态
    clusterHealth := c.clusterHealthMap.getDeepCopy(cluster.Name)
    
    // 2. 获取当前 Ready 条件
    currentReadyCondition := meta.FindStatusCondition(cluster.Status.Conditions, 
        clusterv1alpha1.ClusterConditionReady)
    
    // 3. 对于 Pull 模式,检查 Lease 对象
    if cluster.Spec.SyncMode == clusterv1alpha1.Pull {
        observedLease := &coordinationv1.Lease{}
        err := c.Client.Get(ctx, 
            client.ObjectKey{Namespace: util.NamespaceClusterLease, Name: cluster.Name}, 
            observedLease)
        
        // 如果 Lease 更新了,说明 Agent 还在运行
        if err == nil && observedLease.Spec.RenewTime.After(clusterHealth.probeTimestamp.Time) {
            clusterHealth.probeTimestamp = metav1.Now()
        }
    }
    
    // 4. 检查是否超时
    gracePeriod := c.ClusterMonitorGracePeriod
    if currentReadyCondition == nil {
        gracePeriod = c.ClusterStartupGracePeriod  // 新集群给更长的优雅期
    }
    
    if metav1.Now().After(clusterHealth.probeTimestamp.Add(gracePeriod)) {
        // 超时未收到更新,标记为 Unknown
        // 更新 Cluster.Status.Conditions
        // ...
    }
    
    return nil
}

关键点

  • Pull 模式:通过 Lease 对象判断 Agent 是否存活
  • 超时检测:如果超过优雅期未收到状态更新,将集群标记为 Unknown
  • 状态缓存:使用 clusterHealthMap 缓存健康状态,避免频繁访问 API Server

4.3 Cluster Status Controller

Cluster Status Controller 负责收集和更新集群的状态信息,代码位于 pkg/controllers/status/cluster_status_controller.go

主要职责

  1. 连接测试:定期连接成员集群 API,检查是否可达
  2. 状态收集
    • Kubernetes 版本
    • API 资源列表(APIEnablements)
    • 节点摘要(总节点数、就绪节点数)
    • 资源摘要(可分配、已分配、等待分配的资源)
  3. 条件更新:更新 Cluster.Status.Conditions

核心流程

func (c *ClusterStatusController) syncClusterStatus(ctx context.Context, cluster *clusterv1alpha1.Cluster) error {
    // 1. 创建成员集群的客户端
    clusterClient, err := c.ClusterClientSetFunc(cluster.Name, c.Client, c.ClusterClientOption)
    if err != nil {
        return setStatusCollectionFailedCondition(ctx, c.Client, cluster, 
            fmt.Sprintf("failed to create a ClusterClient: %v", err))
    }
    
    // 2. 检查集群健康状态
    online, healthy := getClusterHealthStatus(clusterClient)
    observedReadyCondition := generateReadyCondition(online, healthy)
    
    // 3. 应用阈值调整(避免频繁状态切换)
    readyCondition := c.clusterConditionCache.thresholdAdjustedReadyCondition(
        cluster, &observedReadyCondition)
    
    // 4. 如果集群离线,直接更新状态并返回
    if !online && readyCondition.Status != metav1.ConditionTrue {
        return updateStatusCondition(ctx, c.Client, cluster, *readyCondition)
    }
    
    // 5. 收集详细状态信息
    if online && healthy && readyCondition.Status == metav1.ConditionTrue {
        // 收集 Kubernetes 版本
        kubernetesVersion, err := clusterClient.Discovery().ServerVersion()
        
        // 收集 API 资源列表
        apiEnablements, err := c.collectAPIEnablement(clusterClient)
        
        // 收集节点摘要
        nodeSummary, err := c.collectNodeSummary(clusterClient)
        
        // 收集资源摘要
        resourceSummary, err := c.collectResourceSummary(clusterClient, cluster)
        
        // 更新 Cluster.Status
        cluster.Status.KubernetesVersion = kubernetesVersion.GitVersion
        cluster.Status.APIEnablements = apiEnablements
        cluster.Status.NodeSummary = nodeSummary
        cluster.Status.ResourceSummary = resourceSummary
    }
    
    // 6. 更新 Ready 条件
    return updateStatusCondition(ctx, c.Client, cluster, *readyCondition)
}

4.4 关键设计模式

4.4.1 Finalizer 模式

Cluster 使用 Finalizer 确保删除时完成清理:

const ClusterControllerFinalizer = "karmada.io/cluster-controller"

func (c *Controller) ensureFinalizer(ctx context.Context, cluster *clusterv1alpha1.Cluster) (controllerruntime.Result, error) {
    if controllerutil.ContainsFinalizer(cluster, util.ClusterControllerFinalizer) {
        return controllerruntime.Result{}, nil
    }
    
    controllerutil.AddFinalizer(cluster, util.ClusterControllerFinalizer)
    return controllerruntime.Result{}, c.Client.Update(ctx, cluster)
}

4.4.2 索引优化

为了快速查询引用特定集群的 Binding,使用索引:

// 注册索引
indexregistry.RegisterResourceBindingIndexByFieldCluster(ctx, mgr)
indexregistry.RegisterClusterResourceBindingIndexByFieldCluster(ctx, mgr)

// 使用索引查询
rbList := &workv1alpha2.ResourceBindingList{}
err := c.List(ctx, rbList, client.MatchingFieldsSelector{
    Selector: fields.OneTermEqualSelector(
        indexregistry.ResourceBindingIndexByFieldCluster, 
        cluster.Name),
})

4.4.3 状态缓存

使用内存缓存集群健康状态,减少 API Server 压力:

type clusterHealthMap struct {
    sync.RWMutex
    clusterHealths map[string]*clusterHealthData
}

type clusterHealthData struct {
    probeTimestamp metav1.Time
    status         *clusterv1alpha1.ClusterStatus
    lease          *coordinationv1.Lease
}

五、总结

5.1 Cluster 的核心价值

  1. 统一抽象:将异构的 Kubernetes 集群统一抽象为 Cluster 对象
  2. 生命周期管理:完整的注册、监控、故障处理、删除流程
  3. 调度决策支持:提供集群属性、状态、污点等信息供调度器使用
  4. 状态可视化:实时展示集群的运行状态和资源使用情况

5.2 关键概念

概念 说明
ExecutionSpace 每个集群的执行空间(命名空间),存放该集群的 Work 对象
SyncMode Push(控制平面推送)或 Pull(成员集群拉取)
Taint 根据健康状态自动添加污点,影响调度决策
Finalizer 确保删除时完成资源清理
Conditions 集群条件状态(Ready、CompleteAPIEnablements)

5.3 与其他组件的关系

Cluster
  ├── 被 Scheduler 使用(集群选择)
  ├── 被 Binding Controller 使用(创建 Work 到对应 ExecutionSpace)
  ├── 被 Execution Controller 使用(连接成员集群 API)
  ├── 被 Status Controller 更新(状态同步)
  └── 被 Cluster Controller 管理(生命周期)

参考资源

  • 源码位置:
    • API 定义:pkg/apis/cluster/v1alpha1/types.go
    • Cluster Controller:pkg/controllers/cluster/cluster_controller.go
    • Cluster Status Controller:pkg/controllers/status/cluster_status_controller.go
  • 官方文档:https://karmada.io/docs/
  • 命令参考:
    • karmadactl join --help
    • karmadactl register --help
posted @ 2026-01-13 15:09  Mephostopheles  阅读(4)  评论(0)    收藏  举报