Karmada-API Server 组件详解

Karmada API Server 组件详解

目录


一、使用背景

1.1 为什么需要 Karmada API Server?

Karmada API Server 是 Karmada 控制平面的核心组件,它充当整个多集群系统的统一 API 入口数据存储层

核心作用

  1. 统一的 API 入口

    • 提供 Kubernetes 原生 API 接口
    • 支持所有 Kubernetes 资源类型(Deployment、Service、ConfigMap 等)
    • 提供 Karmada 自定义资源 API(Cluster、PropagationPolicy、ResourceBinding、Work 等)
  2. 数据存储中心

    • 所有 Karmada 资源对象都存储在 API Server 背后的 etcd 中
    • Controller Manager、Scheduler 等组件都通过 API Server 访问数据
    • 提供资源的 CRUD 操作和 Watch 机制
  3. 多集群协调基础

    • 存储资源模板(Resource Template)
    • 存储传播策略(PropagationPolicy)
    • 存储绑定关系(ResourceBinding)
    • 存储工作负载(Work)

1.2 与其他组件的关系

                    ┌─────────────────┐
                    │   kubectl /     │
                    │   karmadactl    │
                    └────────┬────────┘
                             │
                    ┌────────▼────────┐
                    │ Karmada API     │ ◄─── 统一入口
                    │ Server          │
                    │ (kube-apiserver)│
                    └────────┬────────┘
                             │
            ┌────────────────┼────────────────┐
            │                │                │
    ┌───────▼──────┐ ┌───────▼──────┐ ┌───────▼──────┐
    │ Controller   │ │   Scheduler  │ │    Webhook   │
    │ Manager      │ │              │ │              │
    └──────────────┘ └──────────────┘ └──────────────┘
            │                │                │
            └────────────────┼────────────────┘
                             │
                    ┌────────▼────────┐
                    │      etcd       │ ◄─── 存储后端
                    │  (数据存储)     │
                    └─────────────────┘

1.3 为什么使用 kube-apiserver?

Karmada 直接使用 Kubernetes 的 kube-apiserver 作为其 API Server,而不是重新开发,原因如下:

  1. 成熟稳定:kube-apiserver 是 Kubernetes 的核心组件,经过大规模生产验证
  2. API 兼容性:天然支持 Kubernetes 原生 API,无需转换
  3. 丰富的功能
    • RBAC 认证授权
    • Admission Webhooks
    • API Versioning
    • Watch 机制
    • 资源验证
  4. 维护成本低:跟随 Kubernetes 社区更新,减少维护负担

二、架构设计

2.1 组件架构

Karmada API Server 包含两个主要组件:

1. Karmada API Server(主 API Server)

  • 实现:直接使用 kube-apiserver 二进制
  • 端口:5443(不同于标准 Kubernetes 的 6443)
  • 作用:提供所有 Kubernetes 原生 API 和 Karmada CRD API

2. Karmada Aggregated API Server(聚合 API Server)

  • 实现:Karmada 自定义实现(cmd/aggregated-apiserver/
  • 作用:扩展 API,提供额外的资源端点
  • 注册方式:通过 Kubernetes 的 APIService 机制聚合到主 API Server

2.2 API 分组

核心 API 组

  1. Kubernetes 原生 API

    • /api/v1 - Core API(Pod、Service、ConfigMap 等)
    • /apis/apps/v1 - Apps API(Deployment、StatefulSet 等)
    • /apis/networking.k8s.io/v1 - Networking API(Ingress 等)
    • 所有标准的 Kubernetes API 组
  2. Karmada 自定义 API

    • /apis/cluster.karmada.io/v1alpha1 - Cluster 资源
    • /apis/work.karmada.io/v1alpha1 / /apis/work.karmada.io/v1alpha2 - Work、ResourceBinding
    • /apis/policy.karmada.io/v1alpha1 - PropagationPolicy、OverridePolicy
    • /apis/autoscaling.karmada.io/v1alpha1 - FederatedHPA
    • /apis/search.karmada.io/v1alpha1 - Search API(通过 Aggregated API Server)
    • /apis/config.karmada.io/v1alpha1 - ResourceInterpreter 配置

2.3 存储架构

Karmada API Server
    │
    ├── etcd(存储后端)
    │   ├── 资源模板(Deployment、Service 等)
    │   ├── Cluster 对象
    │   ├── PropagationPolicy
    │   ├── ResourceBinding
    │   └── Work 对象
    │
    └── 支持的操作
        ├── GET(查询)
        ├── POST(创建)
        ├── PUT(更新)
        ├── PATCH(部分更新)
        ├── DELETE(删除)
        └── WATCH(监听变更)

三、使用方式

3.1 访问 Karmada API Server

获取 kubeconfig

Karmada 安装后会自动生成 kubeconfig 文件,通常位于:

# 使用 karmadactl init 安装后
export KUBECONFIG="$HOME/.kube/karmada.config"

# 切换到 karmada-apiserver context
kubectl config use-context karmada-apiserver

验证连接

# 检查 API Server 是否可达
kubectl cluster-info

# 查看所有 API 资源
kubectl api-resources

# 查看 Karmada 自定义资源
kubectl api-resources | grep karmada

3.2 基本操作示例

创建资源

# 创建 Deployment(资源模板)
kubectl create deployment nginx --image=nginx

# 创建 PropagationPolicy
kubectl apply -f - <<EOF
apiVersion: policy.karmada.io/v1alpha1
kind: PropagationPolicy
metadata:
  name: nginx-propagation
spec:
  resourceSelectors:
    - apiVersion: apps/v1
      kind: Deployment
      name: nginx
  placement:
    clusterAffinity:
      clusterNames:
        - member1
        - member2
EOF

查询资源

# 查看所有集群
kubectl get clusters

# 查看 ResourceBinding
kubectl get resourcebindings

# 查看 Work 对象
kubectl get works -A

# 查看 PropagationPolicy
kubectl get propagationpolicies

监听资源变化

# Watch ResourceBinding 变化
kubectl get resourcebindings -w

# Watch 特定集群状态
kubectl get cluster member1 -w

3.3 直接调用 REST API

使用 curl

# 获取访问令牌(从 kubeconfig 中提取)
TOKEN=$(kubectl config view --raw -o jsonpath='{.users[0].user.token}')

# 调用 API
curl -k -H "Authorization: Bearer $TOKEN" \
  https://<api-server-address>:5443/apis/cluster.karmada.io/v1alpha1/clusters

# 查看 API 版本
curl -k -H "Authorization: Bearer $TOKEN" \
  https://<api-server-address>:5443/api/v1

使用 kubectl proxy

# 启动本地代理
kubectl proxy --port=8080

# 通过代理访问
curl http://localhost:8080/apis/cluster.karmada.io/v1alpha1/clusters
curl http://localhost:8080/apis/work.karmada.io/v1alpha2/resourcebindings

3.4 配置和部署

使用 karmadactl 部署

# 初始化 Karmada(会自动部署 API Server)
karmadactl init --kubeconfig ~/.kube/config

# 自定义配置
karmadactl init \
  --kubeconfig ~/.kube/config \
  --karmada-apiserver-image registry.k8s.io/kube-apiserver:v1.28.0 \
  --etcd-image k8s.gcr.io/etcd:3.5.9-0

使用 Helm 部署

# values.yaml
apiServer:
  image:
    registry: registry.k8s.io
    repository: kube-apiserver
    tag: v1.28.0
  replicas: 1
  serviceType: ClusterIP
  serviceSubnet: 10.96.0.0/12
  extraArgs:
    max-requests-inflight: 1500
    max-mutating-requests-inflight: 500
helm install karmada ./charts/karmada -f values.yaml

使用 Karmada Operator 部署

apiVersion: operator.karmada.io/v1alpha1
kind: Karmada
metadata:
  name: karmada
spec:
  components:
    karmadaAPIServer:
      image: registry.k8s.io/kube-apiserver:v1.28.0
      replicas: 1
      serviceType: ClusterIP
      serviceSubnet: "10.96.0.0/12"

3.5 常见配置选项

性能调优

extraArgs:
  # 并发请求限制
  max-requests-inflight: 1500          # 只读请求
  max-mutating-requests-inflight: 500  # 变更请求
  
  # 连接池
  storage-media-type: application/vnd.kubernetes.protobuf
  
  # 日志级别
  v: 4

安全配置

extraArgs:
  # TLS 配置
  tls-min-version: VersionTLS13
  
  # 授权模式
  authorization-mode: Node,RBAC
  
  # 准入控制
  enable-admission-plugins: NodeRestriction
  disable-admission-plugins: StorageObjectInUseProtection,ServiceAccount

四、源码原理

4.1 部署清单生成

Karmada API Server 的部署清单通过模板生成,代码位于 operator/pkg/controlplane/apiserver/manifests.go

核心配置

const KarmadaApiserverDeployment = `
apiVersion: apps/v1
kind: Deployment
metadata:
  name: {{ .DeploymentName }}
  namespace: {{ .Namespace }}
spec:
  replicas: {{ .Replicas }}
  template:
    spec:
      containers:
      - name: kube-apiserver
        image: {{ .Image }}
        command:
        - kube-apiserver
        - --allow-privileged=true
        - --authorization-mode=Node,RBAC
        - --client-ca-file=/etc/karmada/pki/ca.crt
        - --enable-bootstrap-token-auth=true
        - --etcd-servers=https://etcd-client.karmada-system.svc.cluster.local:2379
        - --bind-address=0.0.0.0
        - --secure-port=5443
        - --service-cluster-ip-range={{ .ServiceSubnet }}
        - --tls-cert-file=/etc/karmada/pki/apiserver.crt
        - --tls-private-key-file=/etc/karmada/pki/apiserver.key
        ...
`

关键启动参数说明

参数 说明
--secure-port=5443 HTTPS 端口(区别于标准 Kubernetes 的 6443)
--etcd-servers etcd 服务器地址
--service-cluster-ip-range Service ClusterIP 范围
--authorization-mode=Node,RBAC 授权模式
--enable-bootstrap-token-auth 启用 Bootstrap Token 认证
--client-ca-file 客户端 CA 证书
--tls-cert-file / --tls-private-key-file TLS 证书

4.2 部署逻辑

代码位置:operator/pkg/controlplane/apiserver/apiserver.go

func EnsureKarmadaAPIServer(
    client clientset.Interface, 
    cfg *operatorv1alpha1.KarmadaComponents, 
    name, namespace string, 
    featureGates map[string]bool,
) error {
    // Step 1: 安装 API Server Deployment
    if err := installKarmadaAPIServer(
        client, cfg.KarmadaAPIServer, cfg.Etcd, 
        name, namespace, featureGates,
    ); err != nil {
        return fmt.Errorf("failed to install karmada apiserver, err: %w", err)
    }

    // Step 2: 创建 Service
    return createKarmadaAPIServerService(
        client, cfg.KarmadaAPIServer, name, namespace,
    )
}

installKarmadaAPIServer 流程

func installKarmadaAPIServer(...) error {
    // 1. 解析 Deployment 模板
    apiserverDeploymentBytes, err := util.ParseTemplate(
        KarmadaApiserverDeployment, 
        templateData,
    )
    
    // 2. 解码为 Deployment 对象
    apiserverDeployment := &appsv1.Deployment{}
    kuberuntime.DecodeInto(..., apiserverDeploymentBytes, apiserverDeployment)
    
    // 3. 配置 etcd 客户端凭证
    err = etcd.ConfigureClientCredentials(
        apiserverDeployment, etcdCfg, name, namespace,
    )
    
    // 4. 应用额外配置(Annotations、Labels、Args 等)
    patcher.NewPatcher().
        WithAnnotations(cfg.Annotations).
        WithLabels(cfg.Labels).
        WithExtraArgs(cfg.ExtraArgs).
        WithExtraVolumeMounts(cfg.ExtraVolumeMounts).
        ForDeployment(apiserverDeployment)
    
    // 5. 创建或更新 Deployment
    apiserverDeployment, err = apiclient.CreateOrUpdateDeployment(
        client, apiserverDeployment,
    )
    
    // 6. 创建 PodDisruptionBudget
    return pdb.EnsurePodDisruptionBudget(...)
}

4.3 CRD 注册

Karmada 的自定义资源通过 CRD(CustomResourceDefinition)注册到 API Server。

CRD 安装流程

代码位置:pkg/karmadactl/cmdinit/karmada/deploy.go

func InitKarmadaResources(dir, caBase64, systemNamespace string) error {
    // 1. 创建系统命名空间
    cmdutil.CreateOrUpdateNamespace(clientSet, ...)
    
    // 2. 安装 CRDs
    basesCRDsFiles := utils.ListFiles(dir + "/crds/bases")
    for _, v := range basesCRDsFiles {
        createCRDs(crdClient, v)
    }
    
    // 3. 创建 Webhook 配置
    createOrUpdateMutatingWebhookConfiguration(...)
    createOrUpdateValidatingWebhookConfiguration(...)
    
    // 4. 初始化 Aggregated API Service
    initAggregatedAPIService(...)
    
    return nil
}

主要 CRD 类型

CRD 类型 API Group 用途
Cluster cluster.karmada.io/v1alpha1 成员集群定义
ResourceBinding work.karmada.io/v1alpha2 资源绑定关系
ClusterResourceBinding work.karmada.io/v1alpha2 集群级资源绑定
Work work.karmada.io/v1alpha1 工作负载
PropagationPolicy policy.karmada.io/v1alpha1 传播策略
ClusterPropagationPolicy policy.karmada.io/v1alpha1 集群级传播策略
OverridePolicy policy.karmada.io/v1alpha1 覆盖策略
FederatedHPA autoscaling.karmada.io/v1alpha1 多集群 HPA

4.4 Aggregated API Server

Karmada 使用 Kubernetes 的 API Aggregation 机制扩展 API。

APIService 注册

代码位置:operator/pkg/karmadaresource/apiservice/manifest.go

apiVersion: apiregistration.k8s.io/v1
kind: APIService
metadata:
  name: v1alpha1.cluster.karmada.io
spec:
  group: cluster.karmada.io
  version: v1alpha1
  service:
    name: karmada-aggregated-apiserver
    namespace: karmada-system
  caBundle: <CA证书>
  groupPriorityMinimum: 2000
  versionPriority: 10

工作原理

客户端请求
    │
    ├─> /apis/cluster.karmada.io/v1alpha1/clusters
    │
    ▼
Karmada API Server (kube-apiserver)
    │
    ├─> 检查 APIService
    │   └─> 发现 cluster.karmada.io 由聚合服务器处理
    │
    ▼
转发到 Aggregated API Server
    │
    └─> karmada-aggregated-apiserver:443

Aggregated API Server 实现

代码位置:cmd/aggregated-apiserver/app/aggregated-apiserver.go

func Run(ctx context.Context, opts *options.Options) error {
    // 1. 加载配置
    config, err := NewConfig(opts)
    
    // 2. 创建服务器
    server, err := config.Complete().New()
    
    // 3. 安装 API
    server.GenericAPIServer.InstallAPIGroup(&apiGroupInfo)
    
    // 4. 启动服务器
    return server.GenericAPIServer.PrepareRun().RunWithContext(ctx)
}

4.5 认证和授权

认证方式

Karmada API Server 支持多种认证方式:

  1. TLS 客户端证书认证

    --client-ca-file=/etc/karmada/pki/ca.crt
    
  2. Bootstrap Token 认证

    --enable-bootstrap-token-auth=true
    

    用于 Pull 模式的集群注册

  3. ServiceAccount Token 认证

    --service-account-key-file=/etc/karmada/pki/karmada.key
    

授权模式

--authorization-mode=Node,RBAC
  • Node:节点授权器,用于 kubelet 访问
  • RBAC:基于角色的访问控制(Role-Based Access Control)

4.6 etcd 集成

连接配置

--etcd-servers=https://etcd-client.karmada-system.svc.cluster.local:2379
--etcd-cafile=/etc/karmada/pki/etcd-client/ca.crt
--etcd-certfile=/etc/karmada/pki/etcd-client/tls.crt
--etcd-keyfile=/etc/karmada/pki/etcd-client/tls.key

存储路径

Karmada 的资源在 etcd 中的存储路径遵循 Kubernetes 的标准格式:

/registry/{api-group}/{resource}/{namespace}/{name}

例如:

  • /registry/cluster.karmada.io/clusters/member1
  • /registry/work.karmada.io/resourcebindings/default/nginx-deployment
  • /registry/policy.karmada.io/propagationpolicies/default/nginx-propagation

4.7 Watch 机制

API Server 的 Watch 机制是 Controller 的基础,所有 Controller 都依赖它监听资源变化。

工作原理

Controller Manager
    │
    ├─> Watch ResourceBinding
    │   └─> GET /apis/work.karmada.io/v1alpha2/resourcebindings?watch=true
    │
    ├─> Watch PropagationPolicy
    │   └─> GET /apis/policy.karmada.io/v1alpha1/propagationpolicies?watch=true
    │
    └─> Watch Cluster
        └─> GET /apis/cluster.karmada.io/v1alpha1/clusters?watch=true

API Server
    │
    └─> etcd Watch
        └─> 监听 etcd 中的资源变化
            └─> 通过 HTTP Stream 推送给客户端

客户端示例

// Controller 中使用 Informer 监听资源
informer := factory.InformerFor(
    &workv1alpha2.ResourceBinding{},
    func(client versioned.Interface, resyncPeriod time.Duration) cache.SharedIndexInformer {
        return workinformers.NewResourceBindingInformer(
            client, namespace, resyncPeriod, cache.Indexers{},
        )
    },
)

informer.AddEventHandler(cache.ResourceEventHandlerFuncs{
    AddFunc:    func(obj interface{}) { /* 处理新增 */ },
    UpdateFunc: func(oldObj, newObj interface{}) { /* 处理更新 */ },
    DeleteFunc: func(obj interface{}) { /* 处理删除 */ },
})

五、总结

5.1 关键设计决策

决策 理由
使用 kube-apiserver 而非自研 成熟稳定,维护成本低
端口使用 5443 而非 6443 避免与标准 Kubernetes 冲突
集成 Aggregated API Server 扩展 API 功能,保持架构灵活
支持多种认证方式 适应不同部署场景(Push/Pull 模式)

5.2 与其他组件的关系

用户/工具
    │
    └─> kubectl / karmadactl
            │
            ▼
    Karmada API Server
            │
    ┌───────┼───────┐
    │       │       │
    ▼       ▼       ▼
Controller Scheduler Webhook
Manager
    │       │       │
    └───────┼───────┘
            │
            ▼
        etcd

调试命令

# 查看 API Server 日志
kubectl logs -n karmada-system -l app=karmada-apiserver

# 检查 API Server 健康状态
kubectl get --raw /readyz

# 查看 API Server 指标
kubectl top pod -n karmada-system -l app=karmada-apiserver

# 测试 API Server 连接
kubectl get --raw /version

参考资源

posted @ 2026-01-13 15:22  Mephostopheles  阅读(2)  评论(0)    收藏  举报