在裸金属上创建集群
本文档说明如何使用 bare-metal provider 在物理服务器上创建 Kubernetes 集群。该工作流仅支持 YAML——目前 bare-metal 集群还没有 Fleet Essentials UI。
前提条件
在创建集群之前,请确保满足以下所有前提条件。
1. 安装所需插件
在 global 集群上安装以下插件:
- Alauda Container Platform Kubeadm Provider
- Alauda Container Platform Bare Metal Infrastructure Provider(umbrella chart,同时安装 bare-metal manager 和
elemental-operator)
详情请参见 安装指南。
2. 导入 OS 镜像并确认 Image Catalog
在创建任何集群资源之前,请从 Alauda 技术支持获取匹配的 OS 镜像对,并将两个镜像都导入到目标平台 registry 中。仅导入一个镜像是不够的:
导入完成后,请使用目标平台 registry 中的镜像引用。不要将集群资源指向构建用 registry,也不要从另一个镜像引用派生出新的镜像引用,或替换为独立构建的镜像。继续之前,请在 registry 中或通过镜像导入结果确认这两个最终引用都存在。添加 image-catalog 条目或 SeedImage 引用不会导入对应镜像。
bare-metal provider chart 会附带一个 elemental-image-catalog ConfigMap,它将 Machine.spec.version 映射到用于(重新)配置节点的 elemental upgrade 镜像。你不需要单独创建此 ConfigMap——请确认目标 Kubernetes 版本已存在:
kubectl -n cpaas-system get configmap elemental-image-catalog -o yaml
所有用作 Machine.spec.version 的值(包括控制平面和 worker MachineDeployment 资源)都必须作为该 ConfigMap 中的 key 出现,并保留前导 v。请确认该 key 在目标平台 registry 中解析到导入的 base-image。provider 会在重新配置时,通过将条目中的 registry 部分替换为平台 registry 地址来解析镜像。如果缺少目标版本,则不会写入 reprovision plan,并且 BaremetalMachine 会一直处于 Failed / Reason=ImageCatalogMiss,直到添加该条目。
3. 网络连通性
- 每台物理主机都必须能够访问
global.platformUrl(elemental-system-agent 注册、plan secret 轮询)。
- 每台物理主机都必须能够从平台 registry(
global.registry.address)拉取镜像,供 elemental install(首次启动期间)和 elemental upgrade(每次重新配置期间)使用。
- 对于
Internal Self-built VIP,VIP 必须位于与控制平面节点 IP 相同的二层广播域中。vrid 在该域中必须唯一,网络必须允许 VRRP 和 gratuitous ARP 更新,并且节点镜像必须暴露 IPVS,且允许 Alive 将 net.ipv4.conf.all.arp_accept=1 和 net.ipv4.vs.conntrack=1 设置为启用。
- 对于
External LoadBalancer,请在创建集群之前先完成 listener 和控制平面后端的配置。请遵循 规划控制平面端点。
如果目标 VM 或物理主机在 live ISO 启动后未从 DHCP 获取地址,请在等待注册之前,从主机控制台手动配置网络。首先检查 NetworkManager 的连接名称,然后应用站点特定的地址、网关和 DNS 值:
nmcli connection show
nmcli connection modify "Wired connection 1" \
ipv4.method manual \
ipv4.addresses 192.168.254.73/24 \
ipv4.gateway 192.168.254.1 \
ipv4.dns 192.168.16.19 \
ipv4.ignore-auto-dns yes
nmcli connection up "Wired connection 1"
4. TPM 决策
请根据主机是否暴露真实硬件 TPM(/dev/tpm0)来设置 MachineRegistration.spec.config.elemental.registration.emulate-tpm,而不是根据主机是物理机还是虚拟机:
emulate-tpm: false(或省略该字段)——仅当主机具有可用的硬件 TPM 时使用,这样 elemental-register 才能将其用于 auth: tpm。
emulate-tpm: true 且 emulated-tpm-seed: -1——适用于任何没有硬件 TPM 的主机。这包括虚拟机以及未配备 TPM 模块的物理服务器(例如 Dell R620)。在此类主机上,如果 auth: tpm 与 emulate-tpm: false 组合使用,elemental-register 会因 TPM 验证失败而无法发送注册请求,因此 elemental-operator 会记录为 0 次注册 POST。
5. 公共 Registry 凭证(仅在稍后安装平台组件时需要)
创建 bare-metal 集群不需要 public-registry-credential。只有当新 workload cluster 上后续的平台组件需要从受凭证保护的公共 registry 拉取镜像时,才需要它。如果你的测试范围只到集群和节点 Ready,则可以忽略此前提条件。
6. 主机磁盘和启动准备
在启动 SeedImage ISO 之前,请先对每台主机上的每一块磁盘和虚拟磁盘(VD)进行分类。记录哪块设备是 OS 安装目标,以及哪些设备(如果有)必须保留应用数据:
- 清空选定的 OS 安装磁盘以及任何其他过时的启动磁盘,确保不存在可引导的旧操作系统。主机必须从 ISO 启动,而不是从磁盘上的旧 OS 启动。将
MachineRegistration.spec.config.elemental.install.device 设置为精确的 OS 磁盘。
- 不要清空你打算使用
Adopt 策略管理的数据磁盘。请单独备份它,记录其稳定 ID 和文件系统 UUID,并确保它不会被选作安装设备。
- 打算用于
InitializeIfBlank 的磁盘必须可丢弃且客观上为空白。即便如此,格式化仍然需要在主机注册后单独获得初始化批准;注册清单不会对其授权。
- 从所有磁盘中移除残留的 Elemental 分区标签——
COS_STATE、COS_PERSISTENT、COS_OEM、COS_RECOVERY——而不仅仅是目标安装磁盘。Elemental 会按标签解析分区(blkid -L COS_STATE);如果第二块磁盘上残留旧标签(例如来自之前的安装或遗留的 multipath 成员),它会解析到错误设备,导致 reprovision snapshotter 失败。
- 在同一块磁盘可能通过多条路径出现(multipath)的主机上,请确保这些路径中没有任何一条暴露仍带有
COS_* 标签的磁盘;任一路径上的残留标签都可能优先于目标安装磁盘被解析。应清理磁盘,而不是禁用 multipath——该镜像保留了它以支持网络附加存储启动。
- 在有多块磁盘的主机上,不要让
install.device 为空,也不要使用 /dev/sda 作为持久身份。请遵循 在多磁盘裸金属主机上选择固定系统磁盘,通过 WWN 复用一个 ISO,同时为每台主机选择其系统磁盘。
- 设置启动顺序,使主机优先从虚拟 CD / ISO 启动。
仅使用注册 inventory 报告的稳定存储标识。/dev/sdX、/dev/vdX、/dev/nvmeXnY 和 /dev/mapper/mpathX 这类 Linux 路径都是运行时路径,不能放入 MachineInventory.spec.storage。
集群创建工作流
使用 YAML 时,请先导入成对的 OS 镜像,然后按顺序执行五个必需的资源步骤,在加入 pool 之前还可选执行一个存储准备步骤。所有 Kubernetes 资源都必须应用在 cpaas-system 命名空间中。
WARNING
重要的命名空间要求
所有 bare-metal 资源都必须应用在 cpaas-system 命名空间中。provider 和 elemental-operator 只会对该命名空间中的对象进行调谐。
WARNING
Workload 集群命名
workload cluster-name 不能是 global。该名称保留给 global 集群使用,重复使用会导致 workload 集群的资源与 cpaas-system 中的 global 集群资源冲突。按照约定,CAPI Cluster 和 BaremetalCluster 应完全命名为 <cluster-name>,而其依赖资源(KubeadmControlPlane、KubeadmConfigTemplate、MachineDeployment、machine templates、pools、registrations)应以前缀 <cluster-name>- 命名。
解析占位符值
下面的示例清单使用 <placeholder> 语法表示环境相关的值:
步骤 1:构建 SeedImage 并注册主机
创建一个 MachineRegistration,用于描述注册 URL 和首次安装的 cloud-config,再创建一个指向匹配 ISO base image 的 SeedImage,让 elemental-operator 以该镜像为目标。
将 SeedImage.spec.baseImage 设置为导入的 base-image-iso 在目标平台 registry 中的最终引用。它必须与用于后续重新配置的 image catalog 中导入的 base-image 配对;不要自行更改 repository 名称或 tag 来构造 ISO 引用。
01-machineregistration-seedimage.yaml
apiVersion: elemental.cattle.io/v1beta1
kind: MachineRegistration
metadata:
name: <cluster-name>-registration
namespace: cpaas-system
labels:
app.kubernetes.io/part-of: cluster-api-provider-baremetal
spec:
# ${...} placeholders are expanded by elemental-register from SMBIOS data.
# System UUID is preferred over Serial Number because it is more reliable
# across virtualised test environments.
machineName: "<cluster-name>-${System Information/UUID}"
machineInventoryLabels:
app.kubernetes.io/part-of: cluster-api-provider-baremetal
pool.baremetal.alauda.io/eligible: "true"
elemental.cattle.io/serial-number: "${System Information/Serial Number}"
machineInventoryAnnotations:
elemental.cattle.io/machine-uuid: "${System Information/UUID}"
config:
elemental:
install:
device: <install-device>
eject-cd: true
reboot: true
snapshotter:
type: btrfs
maxSnaps: 4
registration:
# false only when the host has a real hardware TPM (/dev/tpm0). Set true
# (with emulated-tpm-seed: -1) on any host without one, including physical
# servers that ship without a TPM module.
emulate-tpm: false
---
apiVersion: elemental.cattle.io/v1beta1
kind: SeedImage
metadata:
name: <cluster-name>-registration-iso
namespace: cpaas-system
labels:
app.kubernetes.io/part-of: cluster-api-provider-baremetal
spec:
type: iso
baseImage: <base-image-iso> # Use the imported target-platform registry reference.
registrationRef:
apiVersion: elemental.cattle.io/v1beta1
kind: MachineRegistration
name: <cluster-name>-registration
namespace: cpaas-system
targetPlatform: linux/amd64
size: 20Gi
cleanupAfterMinutes: 120
不要将 /etc/resolv.conf 添加到 SeedImage.spec.cloud-config 中。保持 ISO 通用,仅在首次启动注册路径需要时,才在 MachineRegistration.spec.config.cloud-config 中放入站点特定的解析器配置。在已测试的 Global 部署流程中,ISO 不包含 resolver 文件;节点 DNS 之后通过 kubeadm bootstrap 数据进行配置。
install.device、install.eject-cd 和 install.reboot 都是有意设置的。如果省略目标磁盘,elemental install 可能会选到意外的设备。在多磁盘物理主机上,应使用 固定系统磁盘工作流,而不是会变化的 /dev/sdX 名称。如果 eject-cd 或 reboot 为 false,主机在首次安装后可能仍停留在 live 环境中,且永远无法成为 Cluster API 可用的 inventory。
应用清单并等待 SeedImage 构建完成:
kubectl apply -f 01-machineregistration-seedimage.yaml
kubectl -n cpaas-system get seedimage <cluster-name>-registration-iso -w
当 status.state 变为 Completed 时,获取下载 URL 和 ISO 校验和:
kubectl -n cpaas-system get seedimage <cluster-name>-registration-iso \
-o jsonpath='{.status.downloadURL}{"\n"}'
kubectl -n cpaas-system get seedimage <cluster-name>-registration-iso \
-o jsonpath='{.status.checksumURL}{"\n"}'
从该 ISO 启动每一台目标主机。elemental-register 会先运行(创建 MachineInventory 并上传 observedNetwork),然后 elemental install 将 OS 写入磁盘。安装完成后,主机将保持可用于 plan 执行的状态。如果 live ISO 环境没有 DHCP 地址,请按照 网络连通性 中的说明,在主机控制台上手动配置 NetworkManager,然后再等待 MachineInventory。
确认注册:
kubectl -n cpaas-system get machineinventories.elemental.cattle.io
你计划使用的每个 inventory 都必须:
- 显示
Ready=True。
- 具有非空的
status.plan.secretRef.name。
- 具有与主机预期 NIC 匹配的
spec.observedNetwork(仅当你希望安装时 IP 在重新配置后仍保持不变时需要)。
- 当需要受管理的数据盘时,运行支持 observer 的 OS 镜像,生成新的
status.observedStorage,并在分配到 pool 之前达到 status.storage.phase=Prepared。
记录准确的 MachineInventory 名称——下一步会按名称引用它们。
可选:准备受管数据磁盘
受管存储属于长期存在的 MachineInventory,而不是 CAPI Machine 或 BaremetalMachineTemplate。请在 inventory 尚未分配且加入生产 pool 之前进行配置。
按照 在裸金属主机上管理数据盘 执行以下操作:
- 验证
elemental-storage-observer.service 并检查 status.observedStorage。
- 为每个设备选择稳定 ID,并选择
Adopt 或 InitializeIfBlank。
- 使用匹配的
storagectl 二进制文件验证并原子性地补丁声明,以及在需要时补丁其初始化批准。
- 等待
StoragePrepared=True/AllRequiredVolumesPrepared 和 status.storage.phase=Prepared。
如果没有磁盘需要管理,请让 spec.storage 保持缺失,或设置 volumes: []。storage controller 会将该 inventory 收敛为 Unmanaged,并标记 StoragePrepared=True/NoManagedVolumes,同时不执行任何磁盘操作。
步骤 2:创建 MachineInventoryPool 资源
每个角色创建一个 pool。pool reconciler 会验证每个成员是否存在,计算容量计数器,并将 baremetal.alauda.io/pool=<pool-name> 注解写入 inventory。
02-machineinventorypool.yaml
apiVersion: infrastructure.cluster.x-k8s.io/v1beta1
kind: MachineInventoryPool
metadata:
name: <cluster-name>-control-plane-pool
namespace: cpaas-system
spec:
clusterName: <cluster-name>
machineInventories:
- name: <control-plane-inventory-1>
hostname: <control-plane-host-1> # Optional; falls back to the inventory name.
- name: <control-plane-inventory-2>
hostname: <control-plane-host-2>
- name: <control-plane-inventory-3>
hostname: <control-plane-host-3>
---
apiVersion: infrastructure.cluster.x-k8s.io/v1beta1
kind: MachineInventoryPool
metadata:
name: <cluster-name>-worker-pool
namespace: cpaas-system
spec:
clusterName: <cluster-name>
machineInventories:
- name: <worker-inventory-1>
hostname: <worker-host-1>
- name: <worker-inventory-2>
- name: <worker-inventory-3>
关键参数:
应用并验证:
kubectl apply -f 02-machineinventorypool.yaml
kubectl -n cpaas-system get machineinventorypools.infrastructure.cluster.x-k8s.io
健康的 pool 会报告 Ready=True、total = len(spec.machineInventories),以及 available = total - allocated - preparing - reprovisioning - unavailable。spec.machineInventories 中的 inventory 如果验证失败(缺失、缺少 plan secret、Ready=False,或存储未准备好),会增加 pool 的 unavailable 计数器,并在 MembersValid 条件中显现。非空的存储声明是一个分配门禁:在针对新的观测完成 Prepare 之前,该 inventory 对 CAPI 不可用(Available)。
控制平面 pool 的规模至少应达到 KubeadmControlPlane.spec.replicas。worker pool 的规模至少应达到 MachineDeployment.spec.replicas。对于滚动升级,pool 必须容纳完整的副本数——provider 使用的是同一 pool 上的先删后加语义,而不会同时执行两者。
步骤 3:创建控制平面集群资源
创建 BaremetalCluster(声明所选的控制平面端点模式)、控制平面 BaremetalMachineTemplate(指向控制平面 pool)、KubeadmControlPlane(副本数 + kubeadm 配置)以及 CAPI Cluster。
预 GA 的 Bare Metal API 在同一工作流中同时支持两种端点模式:
Internal:provider 部署 Alive,并调谐 VIP 和控制平面后端成员关系。
External:provider 跳过 Alive;load balancer 拥有者负责维护 listener、健康检查和后端成员关系。
由于 Bare Metal 尚未有更早的 GA 版本,因此不存在传统的 provider-version 选项卡。请在下面的清单中使用 <control-plane-load-balancer-type> 选择模式。
WARNING
使用 OS 镜像中内置的 Kubernetes 镜像
受支持的 bare-metal OS 镜像会将 kubeadm control-plane、CoreDNS 和 etcd 镜像预加载到 cloud.alauda.io/alauda 下。请在 KCP 配置中保留该 repository,并使用 OS 支持矩阵中的组件 tag。不要将其替换为 <registry-address>/tkestack:那样会生成与 OS 预加载镜像不匹配的镜像引用。OS 通过 containerd 配置其内置 pause 镜像;不要在 KCP kubelet 参数中添加 pod-infra-container-image。
TIP
完整配置参考
下面的示例使用的是最小化的 KubeadmControlPlane。如需生产环境建议采用的完整加固配置——包括 admission、audit、kubelet patch、encryption provider——请参见附录中的 完整 KubeadmControlPlane 配置。
03-cluster.yaml
apiVersion: infrastructure.cluster.x-k8s.io/v1beta1
kind: BaremetalCluster
metadata:
name: <cluster-name>
namespace: cpaas-system
spec:
controlPlaneLoadBalancer:
type: <control-plane-load-balancer-type>
host: <control-plane-vip>
port: <control-plane-port>
# Required only for Internal. Remove this field for External.
vrid: <vrid>
networkType: kube-ovn # Enables provider-managed Kube-OVN AppRelease reconciliation.
---
apiVersion: infrastructure.cluster.x-k8s.io/v1beta1
kind: BaremetalMachineTemplate
metadata:
name: <cluster-name>-control-plane-template
namespace: cpaas-system
spec:
template:
spec:
machineInventoryPoolRef:
name: <cluster-name>-control-plane-pool
---
apiVersion: controlplane.cluster.x-k8s.io/v1beta1
kind: KubeadmControlPlane
metadata:
name: <cluster-name>-control-plane
namespace: cpaas-system
spec:
replicas: 3
version: <kubernetes-version>
rolloutStrategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 0 # Bare-metal does not over-provision; replace one at a time.
machineTemplate:
nodeDrainTimeout: 5m
nodeVolumeDetachTimeout: 5m
infrastructureRef:
apiVersion: infrastructure.cluster.x-k8s.io/v1beta1
kind: BaremetalMachineTemplate
name: <cluster-name>-control-plane-template
kubeadmConfigSpec:
users:
- name: boot
sudo: ALL=(ALL) NOPASSWD:ALL
shell: /bin/bash
sshAuthorizedKeys:
- "<ssh-authorized-keys>"
clusterConfiguration:
imageRepository: cloud.alauda.io/alauda
dns:
imageTag: <dns-image-tag>
etcd:
local:
imageTag: <etcd-image-tag>
apiServer:
extraArgs:
profiling: "false"
tls-min-version: VersionTLS12
controllerManager:
extraArgs:
profiling: "false"
tls-min-version: VersionTLS12
scheduler:
extraArgs:
profiling: "false"
tls-min-version: VersionTLS12
initConfiguration:
nodeRegistration:
kubeletExtraArgs:
node-labels: "kube-ovn/role=master"
joinConfiguration:
nodeRegistration:
kubeletExtraArgs:
node-labels: "kube-ovn/role=master"
---
apiVersion: cluster.x-k8s.io/v1beta1
kind: Cluster
metadata:
name: <cluster-name>
namespace: cpaas-system
annotations:
capi.cpaas.io/resource-group-version: infrastructure.cluster.x-k8s.io/v1beta1
capi.cpaas.io/resource-kind: BaremetalCluster
cpaas.io/kube-ovn-join-cidr: <kube-ovn-join-cidr>
cpaas.io/kube-ovn-version: <kube-ovn-version>
cpaas.io/sentry-deploy-type: Baremetal
cpaas.io/alb-address-type: ClusterAddress
labels:
cluster-type: ProviderBaremetal
spec:
clusterNetwork:
pods:
cidrBlocks:
- <pods-cidr>
services:
cidrBlocks:
- <services-cidr>
controlPlaneRef:
apiVersion: controlplane.cluster.x-k8s.io/v1beta1
kind: KubeadmControlPlane
name: <cluster-name>-control-plane
infrastructureRef:
apiVersion: infrastructure.cluster.x-k8s.io/v1beta1
kind: BaremetalCluster
name: <cluster-name>
Cluster 注解。 bare-metal provider 在调谐期间依赖少量 Cluster 注解。操作员必须设置的权威注解如下:
BaremetalCluster 参数:
应用并观察:
kubectl apply -f 03-cluster.yaml
kubectl -n cpaas-system get clusters.cluster.x-k8s.io
kubectl -n cpaas-system get kubeadmcontrolplanes.controlplane.cluster.x-k8s.io
kubectl -n cpaas-system get baremetalmachines.infrastructure.cluster.x-k8s.io -w
每个新的控制平面 BaremetalMachine 都会从 Pending → Allocated → Reprovisioning → Running 逐步推进。请关注:
BaremetalMachine.status.machineInventoryRef.name —— 选中了哪个 inventory。
BaremetalMachine.status.planSecretRef.name —— 正在驱动哪个 plan secret。该 secret 带有 baremetal.alauda.io/plan.type=reprovision。
MachineInventory.status.plan.state —— 当主机完成 cloud-init clean、elemental upgrade、重启以及 kubeadm init/join 后,状态变为 Applied。
BaremetalCluster.status.conditions[EndpointReady] —— 当配置的控制平面端点可达时,该值为 true。
WARNING
bare-metal provider 不支持单节点控制平面。请至少配置三个控制平面副本(KubeadmControlPlane.spec.replicas: 3),以确保 etcd 保持法定人数。在 Internal 模式下,这些节点还会参与 Alive VIP 仲裁。
步骤 4:部署 worker 节点
在控制平面 Ready 之后,创建 worker BaremetalMachineTemplate、worker KubeadmConfigTemplate 和 MachineDeployment。完整的 worker YAML 和参数表见 Bare Metal 上管理节点 → 部署 worker 节点。
集群验证
使用 kubectl
# Cluster status
kubectl -n cpaas-system get cluster <cluster-name>
# Control plane progress
kubectl -n cpaas-system get kubeadmcontrolplane <cluster-name>-control-plane
# Per-machine state
kubectl -n cpaas-system get machines.cluster.x-k8s.io
kubectl -n cpaas-system get baremetalmachines.infrastructure.cluster.x-k8s.io
# Pool counters
kubectl -n cpaas-system get machineinventorypools.infrastructure.cluster.x-k8s.io
# Storage lifecycle for inventories that declare managed volumes
kubectl -n cpaas-system get machineinventories.elemental.cattle.io \
-o custom-columns='NAME:.metadata.name,PHASE:.status.storage.phase,PREPARED:.status.storage.conditions[?(@.type=="StoragePrepared")].status,ACTIVE:.status.storage.conditions[?(@.type=="StorageActive")].status'
# Workload cluster Nodes (use the workload kubeconfig)
kubectl get nodes -o wide
验证控制平面端点
确认所配置的模式和端点:
kubectl -n cpaas-system get baremetalcluster <cluster-name> \
-o jsonpath='{.spec.controlPlaneLoadBalancer.type}{" "}{.spec.controlPlaneEndpoint.host}{":"}{.spec.controlPlaneEndpoint.port}{"\n"}'
对于 Internal,请验证 Alive 和节点前提条件:
kubectl --kubeconfig <workload-kubeconfig> -n kube-system get pods -l app=alive -o wide
kubectl --kubeconfig <workload-kubeconfig> get --raw=/version
请在每个控制平面节点上运行以下命令,而不是在管理集群上运行:
sysctl net.ipv4.conf.all.arp_accept net.ipv4.vs.conntrack
对于 External,请根据 External LoadBalancer 合同 验证 load balancer 前端以及每个后端。确认 load balancer 拥有者已注册当前所有控制平面节点,并且每个后端上的 HTTPS /healthz 都返回 HTTP 200。
预期结果
成功创建的集群应显示:
Cluster.status.conditions[Ready]=True。
KubeadmControlPlane 的所有副本均为 Ready。
- 每个
BaremetalMachine.status.phase=Running 且 status.ready=true。
- 每个已使用的
MachineInventory.status.plan.state=Applied,并且其 plan secret 上带有 baremetal.alauda.io/plan.type=reprovision。
- 每个已使用且
spec.storage.volumes[] 非空的 inventory 都会报告 status.storage.phase=Active、StoragePrepared=True 和 StorageActive=True;对应的 BaremetalMachine 会报告 StorageReady=True/AllVolumesReady。
MachineInventoryPool.status 满足 available + allocated + preparing + reprovisioning + unavailable = total。
- Kubernetes 节点 Ready。
- 对于
Internal,Alive Pod Ready,且可通过 Self-built VIP 访问 API。
- 对于
External,load balancer 前端可访问,并且其后端列表与当前控制平面节点一致。
常见失败模式
关于 operator 侧完整状态机参考(每个 condition reason 和恢复动作),请参见 Provider Overview → clean / reprovision plans。
下一步
创建集群后:
附录
完整的 KubeadmControlPlane 配置
建议用于生产 bare-metal 集群的加固配置——包括 admission control、audit policy、kubelet patch、encryption provider 和 IPv6 绑定地址。请替换 解析占位符值 表中的占位符。
Kubernetes 1.35 kubelet settings
imagePullCredentialsVerificationPolicy: NeverVerify 仅从 Kubernetes 1.35 开始需要。在使用 Kubernetes 1.34 或更早版本创建集群时,请省略此参数。
apiVersion: controlplane.cluster.x-k8s.io/v1beta1
kind: KubeadmControlPlane
metadata:
name: <cluster-name>-control-plane
namespace: cpaas-system
spec:
replicas: 3
version: <kubernetes-version>
rolloutStrategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 0
machineTemplate:
nodeDrainTimeout: 5m
nodeVolumeDetachTimeout: 5m
infrastructureRef:
apiVersion: infrastructure.cluster.x-k8s.io/v1beta1
kind: BaremetalMachineTemplate
name: <cluster-name>-control-plane-template
kubeadmConfigSpec:
users:
- name: boot
sudo: ALL=(ALL) NOPASSWD:ALL
shell: /bin/bash
sshAuthorizedKeys:
- "<ssh-authorized-keys>"
files:
- path: /etc/kubernetes/admission/psa-config.yaml
owner: "root:root"
permissions: "0644"
content: |
apiVersion: apiserver.config.k8s.io/v1
kind: AdmissionConfiguration
plugins:
- name: PodSecurity
configuration:
apiVersion: pod-security.admission.config.k8s.io/v1
kind: PodSecurityConfiguration
defaults:
enforce: "privileged"
enforce-version: "latest"
audit: "baseline"
audit-version: "latest"
warn: "baseline"
warn-version: "latest"
exemptions:
usernames: []
runtimeClasses: []
namespaces:
- kube-system
- cpaas-system
- path: /etc/kubernetes/patches/kubeletconfiguration0+strategic.json
owner: "root:root"
permissions: "0644"
content: |
{
"apiVersion": "kubelet.config.k8s.io/v1beta1",
"kind": "KubeletConfiguration",
"imagePullCredentialsVerificationPolicy": "NeverVerify",
"protectKernelDefaults": true,
"tlsCertFile": "/etc/kubernetes/pki/kubelet.crt",
"tlsPrivateKeyFile": "/etc/kubernetes/pki/kubelet.key",
"streamingConnectionIdleTimeout": "5m",
"clientCAFile": "/etc/kubernetes/pki/ca.crt"
}
- path: /etc/kubernetes/audit/policy.yaml
owner: "root:root"
permissions: "0644"
content: |
apiVersion: audit.k8s.io/v1
kind: Policy
omitStages:
- "RequestReceived"
rules:
- level: None
users:
- system:kube-controller-manager
- system:kube-scheduler
- system:serviceaccount:kube-system:endpoint-controller
verbs: ["get", "update"]
namespaces: ["kube-system"]
resources:
- group: ""
resources: ["endpoints"]
- level: None
nonResourceURLs:
- /healthz*
- /version
- /swagger*
- level: None
resources:
- group: ""
resources: ["events"]
- level: None
verbs: ["get", "list", "watch"]
- level: None
resources:
- group: "coordination.k8s.io"
resources: ["leases"]
- level: None
resources:
- group: "authorization.k8s.io"
resources: ["subjectaccessreviews", "selfsubjectaccessreviews"]
- group: "authentication.k8s.io"
resources: ["tokenreviews"]
- level: Metadata
resources:
- group: ""
resources: ["secrets", "configmaps"]
- level: RequestResponse
resources:
- group: ""
- group: "apps"
- group: "rbac.authorization.k8s.io"
- group: "storage.k8s.io"
- group: "networking.k8s.io"
- level: Metadata
postKubeadmCommands:
- chmod 600 /var/lib/kubelet/config.yaml
clusterConfiguration:
imageRepository: cloud.alauda.io/alauda
dns:
imageTag: <dns-image-tag>
etcd:
local:
imageTag: <etcd-image-tag>
apiServer:
extraArgs:
audit-log-format: json
audit-log-maxage: "30"
audit-log-maxbackup: "10"
audit-log-maxsize: "200"
profiling: "false"
audit-log-mode: batch
audit-log-path: /etc/kubernetes/audit/audit.log
audit-policy-file: /etc/kubernetes/audit/policy.yaml
tls-cipher-suites: "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305,TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305,TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384"
admission-control-config-file: /etc/kubernetes/admission/psa-config.yaml
tls-min-version: VersionTLS12
kubelet-certificate-authority: /etc/kubernetes/pki/ca.crt
extraVolumes:
- name: vol-dir-0
hostPath: /etc/kubernetes
mountPath: /etc/kubernetes
pathType: Directory
controllerManager:
extraArgs:
bind-address: "::"
profiling: "false"
tls-min-version: VersionTLS12
scheduler:
extraArgs:
bind-address: "::"
tls-min-version: VersionTLS12
profiling: "false"
initConfiguration:
patches:
directory: /etc/kubernetes/patches
nodeRegistration:
kubeletExtraArgs:
node-labels: "kube-ovn/role=master"
joinConfiguration:
patches:
directory: /etc/kubernetes/patches
nodeRegistration:
kubeletExtraArgs:
node-labels: "kube-ovn/role=master"
worker bootstrap 是对称的——请参见 Bare Metal 上管理节点 → Bootstrap Template 中的 worker KubeadmConfigTemplate。