在 Huawei Cloud Stack 上创建集群

本文档提供了使用 Cluster API 在 Huawei Cloud Stack 平台上创建 Kubernetes 集群的完整说明。

前提条件

在创建集群之前,请确保满足以下所有前提条件:

1. 安装所需插件

global 集群上安装以下插件:

  • Alauda Container Platform Kubeadm Provider
  • Alauda Container Platform HCS Infrastructure Provider

有关详细安装说明,请参阅 Installation Guide

2. 准备 HCS 基础设施输入

在编写本文档中的任何 YAML 之前,请先准备所有 HCS 相关输入:

  • HCS 凭证 Secret 值
  • provider 可识别的计算值,例如 imageNameflavorNameavailabilityZone
  • 集群网络清单,包括集群使用的子网和可用 IP 范围
  • 控制平面 ELB 地址规划,包括 vipAddressvipSubnetName 以及固定的 L4 和 L7 IP
  • 控制平面和工作节点的静态 IP 池规划

完整清单、来源信息和约束请参阅 Infrastructure Resources for Huawei Cloud Stack

集群创建概览

从整体上看,您将在 global 集群中创建以下 Cluster API 资源,以便为功能完整的 Kubernetes 集群提供基础设施并完成引导。

在本页编写任何 YAML 之前,请先完成 Infrastructure Resources for Huawei Cloud Stack 中的准备清单。该清单涵盖了 provider 期望的值、这些值的获取方式,以及在填充清单之前必须提前规划的值。

WARNING

重要的命名空间要求

为了确保与 作为业务集群正确集成,所有资源都必须部署在 cpaas-system 命名空间中。在其他命名空间中部署资源可能会导致集成问题。

集群创建流程按以下顺序进行:

  1. 配置 HCS 认证(Secret)
  2. 创建机器配置池(HCSMachineConfigPool)
  3. 配置机器模板(HCSMachineTemplate)
  4. 配置 KubeadmControlPlane
  5. 配置 HCSCluster
  6. 创建 Cluster

控制平面配置

控制平面负责管理集群状态、调度以及 Kubernetes API。本节展示如何配置高可用控制平面。

WARNING

配置参数指南

在配置资源时,请谨慎修改参数:

  • 仅替换用 <> 括起来的值,并将其改为与您的环境对应的值
  • 保留所有其他参数,因为它们代表经过优化或必需的配置
  • 修改非占位符参数可能会导致集群不稳定或集成问题

配置 HCS 认证

HCS 认证信息存储在 Secret 资源中。

apiVersion: v1
kind: Secret
metadata:
  name: <credential-secret-name>
  namespace: cpaas-system
type: Opaque
data:
  accessKey: <base64-encoded-access-key>
  secretKey: <base64-encoded-secret-key>
  projectID: <base64-encoded-project-id>
  region: <base64-encoded-region>
  externalGlobalDomain: <base64-encoded-domain>
参数描述
.data.accessKey来自 My Settings > Access Keys 的 HCS access key ID(base64 编码)
.data.secretKey来自 My Settings > Access Keys 的 HCS secret access key(base64 编码)
.data.projectID来自 My Settings > Resource Spaces 的 Resource Space ID(base64 编码)
.data.regionprovider 使用的 HCS region API 值(base64 编码)。租户管理员无法从 HCS UI 中获取此值;请从 HCS 管理员处获取
.data.externalGlobalDomainprovider 使用的 HCS 平台访问域名(base64 编码)

您可以复用现有的 HCS 凭证 Secret。其名称不需要与集群名称一致,但 HCSCluster.spec.identityRef.name 必须引用该 Secret。

配置机器配置池

HCSMachineConfigPool 用于定义 VM 的预配置主机名和静态 IP 地址。

WARNING

池大小要求

该配置池至少必须包含与您计划部署的控制平面节点数量相同的条目。

networks[] 中的每个条目使用一个子网选择器。对于新清单,请设置 subnetNamesubnetId 其一,但不要同时设置二者。现有清单可以保留已弃用的 subenetName 字段;如果在更新该清单时同时新增 subnetName,其值必须与 subenetName 完全一致。不要在 subenetNamesubnetNamesubnetId 之间提供冲突值。

如果在机器配置池中使用 subnetName,请在 HCSCluster.spec.network.subnets 中包含相同的子网名称。

对于初始集群创建流程,仅通过名称列出现有子网即可,因为控制器会在集群变为 Ready 之前解析子网元数据。如果后续要向已处于 Ready 状态的 HCSCluster 中新增另一个子网,不要只追加 name。请使用完整的子网对象补丁更新父级 HCSCluster.spec.network.subnets 条目,以便后续机器或 ELB 操作可以复用已解析的子网元数据。

apiVersion: infrastructure.cluster.x-k8s.io/v1beta1
kind: HCSMachineConfigPool
metadata:
  name: <cluster-name>
  namespace: cpaas-system
spec:
  configs:
    - hostname: master-1
      networks:
        - subnetName: <subnet-name>
          ipAddress: 192.168.1.11
    - hostname: master-2
      networks:
        - subnetName: <subnet-name>
          ipAddress: 192.168.1.12
    - hostname: master-3
      networks:
        - subnetName: <subnet-name>
          ipAddress: 192.168.1.13
参数类型必填描述
.spec.configs[]array非空的机器配置列表
.spec.configs[].hostnamestringVM 主机名。请使用小写字母、数字、连字符(-)或点号(.);该值必须以小写字母或数字开头和结尾,且长度不得超过 253 个字符
.spec.configs[].networks[]arrayVM 的非空网络配置列表
.spec.configs[].networks[].subnetNamestring否*新清单推荐使用的子网名称字段
.spec.configs[].networks[].subnetIdstring否*子网 ID。当子网名称有歧义时,请使用此字段代替 subnetName
.spec.configs[].networks[].ipAddressstringVM 的静态 IP 地址

*对于新清单,请设置 subnetNamesubnetId 其一。现有清单可以继续使用 subenetName,并且只有在两个字段使用相同值时才可以新增 subnetName。不要提供冲突的子网选择器值。

注意: CRD schema 将 subnetNamesubenetNamesubnetId 列为可选字段,但不会表达它们允许的组合关系。编写清单时,请遵循上面的 provider 级规则。

注意: 若要为一个节点挂载多个 NIC,请添加多个 networks[] 条目。provider 仅使用这些条目来挂载 NIC,并分配子网选择器和静态 IP。它不支持声明每个 NIC 的角色、默认网关、静态路由或每个 NIC 的 DNS 设置。

配置机器模板

HCSMachineTemplate 用于定义控制平面节点的 VM 规格。

WARNING

存储要求

建议为控制平面节点配置以下数据盘挂载点:

  • /var/lib/etcd - etcd 数据(10GB+)
  • /var/lib/kubelet - kubelet 数据(100GB+)
  • /var/lib/containerd - container runtime 数据(100GB+)
  • /var/cpaas - 平台数据和日志(40GB+)
apiVersion: infrastructure.cluster.x-k8s.io/v1beta1
kind: HCSMachineTemplate
metadata:
  name: <cluster-name>-control-plane
  namespace: cpaas-system
spec:
  template:
    spec:
      imageName: <vm-image-name>
      flavorName: <instance-flavor>
      availabilityZone: <availability-zone>
      rootVolume:
        type: SSD
        size: 100
      configPoolRef:
        name: <cluster-name>
      dataVolumes:
        - size: 10
          type: SSD
          mountPath: /var/lib/etcd
          format: xfs
        - size: 100
          type: SSD
          mountPath: /var/lib/kubelet
          format: xfs
        - size: 100
          type: SSD
          mountPath: /var/lib/containerd
          format: xfs
        - size: 40
          type: SSD
          mountPath: /var/cpaas
          format: xfs
参数类型必填描述
.spec.template.spec.imageNamestringHCS 镜像名称,例如 microos-4.2.1-new
.spec.template.spec.flavorNamestringprovider 可识别的 HCS API 值,与 Flavor.Name 匹配。不要使用租户 UI 中的显示名称
.spec.template.spec.availabilityZonestringprovider 可识别的 HCS API 值,与 ZoneName 匹配。不要使用租户 UI 中的显示名称
.spec.template.spec.rootVolume.typestring卷类型(SSDSATA
.spec.template.spec.rootVolume.sizeint系统盘大小,单位为 GB
.spec.template.spec.configPoolRef.namestring引用的 HCSMachineConfigPool 名称
.spec.template.spec.dataVolumes[]array数据卷配置
.spec.template.spec.dataVolumes[].sizeint是*数据盘大小,单位为 GB
.spec.template.spec.dataVolumes[].typestring是*卷类型
.spec.template.spec.dataVolumes[].mountPathstring是*挂载路径
.spec.template.spec.dataVolumes[].formatstring是*文件系统格式(xfsext4

*当指定 dataVolumes 时为必填。

注意: 不要在 HCSMachineTemplate 清单中设置运行时身份字段,例如 providerIDserverId。provider 会在创建 HCS 实例时分配这些值。

注意: 租户管理员无法从 HCS UI 中获取 provider 可识别的 flavorNameavailabilityZone 值。在应用清单之前,请从 HCS 管理员处获取准确值。

配置 KubeadmControlPlane

KubeadmControlPlane 用于定义 Kubernetes 控制平面配置。

apiVersion: controlplane.cluster.x-k8s.io/v1beta1
kind: KubeadmControlPlane
metadata:
  name: <cluster-name>
  namespace: cpaas-system
spec:
  replicas: 3
  version: <kubernetes-version>
  rolloutStrategy:
    type: RollingUpdate
    rollingUpdate:
      maxSurge: 0
  kubeadmConfigSpec:
    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",
            "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/encryption-provider.conf
        owner: root:root
        permissions: "0600"
        content: |
          apiVersion: apiserver.config.k8s.io/v1
          kind: EncryptionConfiguration
          resources:
          - resources:
            - secrets
            providers:
            - aescbc:
                keys:
                - name: key1
                  secret: bootstrap-placeholder
      - path: /etc/kubernetes/audit/policy.yaml
        owner: root:root
        permissions: "0644"
        content: |
          apiVersion: audit.k8s.io/v1
          kind: Policy
          rules:
          - level: Metadata
    clusterConfiguration:
      imageRepository: <image-repository>
      dns:
        imageTag: <dns-image-tag>
      etcd:
        local:
          imageTag: <etcd-image-tag>
      apiServer:
        extraArgs:
          audit-log-format: json
          audit-log-mode: batch
          audit-log-path: /etc/kubernetes/audit/audit.log
          audit-policy-file: /etc/kubernetes/audit/policy.yaml
          admission-control-config-file: /etc/kubernetes/admission/psa-config.yaml
          encryption-provider-config: /etc/kubernetes/encryption-provider.conf
          kubelet-certificate-authority: /etc/kubernetes/pki/ca.crt
          profiling: "false"
          tls-min-version: VersionTLS12
        extraVolumes:
          - name: vol-dir-0
            hostPath: /etc/kubernetes
            mountPath: /etc/kubernetes
            pathType: Directory
      controllerManager:
        extraArgs:
          bind-address: "::"
          flex-volume-plugin-dir: "/opt/libexec/kubernetes/kubelet-plugins/volume/exec/"
          profiling: "false"
          tls-min-version: VersionTLS12
      scheduler:
        extraArgs:
          bind-address: "::"
          profiling: "false"
          tls-min-version: VersionTLS12
    postKubeadmCommands:
      - chmod 600 /var/lib/kubelet/config.yaml
    initConfiguration:
      patches:
        directory: /etc/kubernetes/patches
      nodeRegistration:
        kubeletExtraArgs:
          node-labels: "kube-ovn/role=master"
          protect-kernel-defaults: "true"
          volume-plugin-dir: "/opt/libexec/kubernetes/kubelet-plugins/volume/exec/"
    joinConfiguration:
      patches:
        directory: /etc/kubernetes/patches
      nodeRegistration:
        kubeletExtraArgs:
          node-labels: "kube-ovn/role=master"
          volume-plugin-dir: "/opt/libexec/kubernetes/kubelet-plugins/volume/exec/"
  machineTemplate:
    nodeDrainTimeout: 1m
    nodeDeletionTimeout: 5m
    infrastructureRef:
      apiVersion: infrastructure.cluster.x-k8s.io/v1beta1
      kind: HCSMachineTemplate
      name: <cluster-name>-control-plane

HCS controller 在解析 cloud-init 数据时也会注入文件。它会为控制平面机器写入 /etc/kubernetes/pki/kubelet.crt/etc/kubernetes/pki/kubelet.key/etc/kubernetes/encryption-provider.conf。对于第一台控制平面机器,controller 会生成 encryption provider 配置。在控制平面初始化后,它会尝试复用现有的 kube-apiserver encryption provider 配置。如果您在 /etc/kubernetes/encryption-provider.conf 中包含了一个 bootstrap 文件,请将其视为占位内容,因为 controller 生成或同步的文件具有优先级。

注意: 请将 apiServer.extraArgsapiServer.extraVolumes 配合配置。如果没有挂载该卷,kube-apiserver 将无法读取 /etc/kubernetes 下写入的文件。

注意: 上面的 rolloutStrategy.rollingUpdate.maxSurge: 0 示例适用于具有静态 IP 的高可用控制平面。对于至少包含三个副本的固定规模控制平面池,请保留此设置,以便替换操作按先缩容后扩容的顺序进行。如果您创建的是单控制平面 HCS 集群(spec.replicas: 1),请不要将 rolloutStrategy 块复制到创建清单中。KubeadmControlPlane 校验会拒绝单副本使用这种缩容式滚动更新配置。

注意: HCS 也支持通过设置 spec.replicas: 1 并在引用的 HCSMachineConfigPool 中准备一条控制平面配置项来创建单控制平面集群。请将其视为仅用于创建的拓扑,并在该创建清单中不要设置 rollout strategy。本文档中的升级流程不支持单控制平面 HCS 集群。

仅对 OS Support Matrix 中明确列出的组件版本使用该文档,例如受支持的 MicroOS 镜像所对应的 coredns 和 etcd 镜像标签。它并不是所有 HCS 清单值的完整来源。在应用此 YAML 之前,还应使用已批准的发布基线来确定 imageRepository、DNS 镜像仓库、Kube-OVN 版本、Kube-OVN join CIDR、Pod CIDR 和 Service CIDR 等值。

配置 HCSCluster

HCSCluster 资源用于定义 HCS 基础设施配置。

HCS provider 会在 HCS 平台上为 Kubernetes API server 创建一个 Elastic Load Balance (ELB)。该 ELB 必须保持 Hybrid Load Balancing 处于启用状态,以便集群节点也能通过 ELB 地址访问 API server。

对于本文档所述的 HCS 流程,请提供 vipAddresselbVirsubnetL4IpselbVirsubnetL7Ips。每个 elbVirsubnetL4Ips[].ipselbVirsubnetL7Ips[].ips 条目都必须包含两个 IP。

如果设置了 vipDomainName,请配置 HCS Cloud DNS Private Zones,使该域名解析到 vipAddress

在引用任何子网之前,请先在 spec.network.subnets 中列出集群使用的每一个子网。vipSubnetNameelbVirsubnetL4Ips[].subnetNameelbVirsubnetL7Ips[].subnetName 以及 HCSMachineConfigPool 使用的 subnetName 值,都必须存在于 spec.network.subnets 中。

对于初始集群创建流程,controller 可以通过 name 解析现有子网元数据。对于已存在的 Ready 集群,请追加完整的子网对象,而不是只写 name。对于控制平面 ELB 将使用的任何子网,都要包含 id,并包含 neutronSubnetId。同时也要在子网清单中保留 cidrgatewayIpprimaryDNSsecondaryDNS

集群创建完成后,不要禁用 provider 创建的 ELB 上的 Hybrid Load Balancing。集群依赖该 ELB 模式,以便节点能够通过 ELB 地址访问 API server。

apiVersion: infrastructure.cluster.x-k8s.io/v1beta1
kind: HCSCluster
metadata:
  name: <cluster-name>
  namespace: cpaas-system
spec:
  controlPlaneLoadBalancer:
    vipAddress: <control-plane-vip-address>
    vipSubnetName: <vip-subnet-name>
    vipDomainName: <control-plane-vip-domain-name>
    elbVirsubnetL4Ips:
      - subnetName: <subnet-name>
        ips:
          - <l4-ip-1>
          - <l4-ip-2>
    elbVirsubnetL7Ips:
      - subnetName: <subnet-name>
        ips:
          - <l7-ip-1>
          - <l7-ip-2>
  networkType: kube-ovn
  network:
    vpc:
      name: <vpc-name>
    subnets:
      - name: <subnet-name>
    securityGroup:
      name: <security-group-name>
  identityRef:
    name: <credential-secret-name>
参数类型必填描述
.spec.networkTypestring网络类型,目前支持 kube-ovn
.spec.network.vpc.namestringVPC 名称
.spec.network.subnets[].namestring集群子网清单中的子网名称。集群清单中其他位置引用到的每个子网都必须出现在此列表中
.spec.network.subnets[].idstring建议子网 ID。对于已存在的 Ready 集群,在后续追加子网时请包含此值,以便机器创建安全复用子网清单
.spec.network.subnets[].neutronSubnetIdstringELB 子网建议填写Neutron 子网 ID。对于控制平面 ELB 使用的任何子网都应包含此值
.spec.network.subnets[].cidrstring建议保留在集群子网清单中的子网 CIDR
.spec.network.subnets[].gatewayIpstring建议保留在集群子网清单中的子网网关
.spec.network.subnets[].primaryDNSstring建议保留在集群子网清单中的主 DNS
.spec.network.subnets[].secondaryDNSstring建议保留在集群子网清单中的辅 DNS
.spec.network.securityGroup.namestring安全组名称
.spec.identityRef.namestringHCSCluster 引用的非空凭证 Secret 名称;该值不需要与集群名称一致
.spec.controlPlaneLoadBalancerobjectprovider 创建的控制平面 ELB 的 ELB 设置
.spec.controlPlaneLoadBalancer.vipAddressstring控制平面 ELB 的固定 VIP
.spec.controlPlaneLoadBalancer.vipSubnetNamestring包含 ELB VIP 的子网名称。该子网也必须出现在 .spec.network.subnets
.spec.controlPlaneLoadBalancer.vipDomainNamestringVIP 的域名。配置 HCS Cloud DNS Private Zones 使其解析到 vipAddress
.spec.controlPlaneLoadBalancer.elbVirsubnetL4Ips[]array用于 Hybrid Load Balancing 的 L4 虚拟子网 IP 组
.spec.controlPlaneLoadBalancer.elbVirsubnetL4Ips[].subnetNamestringL4 虚拟子网 IP 的子网名称。该子网也必须出现在 .spec.network.subnets
.spec.controlPlaneLoadBalancer.elbVirsubnetL4Ips[].ips[]string两个固定的 L4 虚拟子网 IP
.spec.controlPlaneLoadBalancer.elbVirsubnetL7Ips[]array用于 Hybrid Load Balancing 的 L7 虚拟子网 IP 组
.spec.controlPlaneLoadBalancer.elbVirsubnetL7Ips[].subnetNamestringL7 虚拟子网 IP 的子网名称。该子网也必须出现在 .spec.network.subnets
.spec.controlPlaneLoadBalancer.elbVirsubnetL7Ips[].ips[]string两个固定的 L7 虚拟子网 IP

创建清单中不要包含 spec.controlPlaneEndpoint。在 HCS 创建流程中,controller 会在创建 HCSCluster 后,基于 spec.controlPlaneLoadBalancer 推导并填充该字段。不要手动设置 controlPlaneEndpoint,也不要添加空的 controlPlaneEndpoint 对象。如果清单中显式包含 controlPlaneEndpoint,则必须同时包含 hostport

配置 Cluster

Cluster API 中的 Cluster 资源用于声明集群,并引用控制平面和基础设施资源。

apiVersion: cluster.x-k8s.io/v1beta1
kind: Cluster
metadata:
  name: <cluster-name>
  namespace: cpaas-system
  annotations:
    cpaas.io/sentry-deploy-type: Baremetal
    cpaas.io/alb-address-type: ClusterAddress
    capi.cpaas.io/resource-group-version: infrastructure.cluster.x-k8s.io/v1beta1
    capi.cpaas.io/resource-kind: HCSCluster
    cpaas.io/kube-ovn-join-cidr: <kube-ovn-join-cidr>
    cpaas.io/kube-ovn-version: <kube-ovn-version>
  labels:
    cluster-type: HCS
spec:
  clusterNetwork:
    pods:
      cidrBlocks:
        - <pods-cidr>
    services:
      cidrBlocks:
        - <services-cidr>
  controlPlaneRef:
    apiVersion: controlplane.cluster.x-k8s.io/v1beta1
    kind: KubeadmControlPlane
    name: <cluster-name>
  infrastructureRef:
    apiVersion: infrastructure.cluster.x-k8s.io/v1beta1
    kind: HCSCluster
    name: <cluster-name>
注解描述
cpaas.io/sentry-deploy-type部署类型,设为 Baremetal
cpaas.io/alb-address-typeALB 地址类型,设为 ClusterAddress
capi.cpaas.io/resource-group-version资源组版本
capi.cpaas.io/resource-kind资源类型,设为 HCSCluster
cpaas.io/kube-ovn-join-cidrKube-OVN join 子网 CIDR
cpaas.io/kube-ovn-versionKube-OVN 版本

集群验证

部署完所有集群资源后,请验证集群是否已成功创建。

使用 kubectl

# 检查集群状态
kubectl get cluster -n cpaas-system <cluster-name>

# 验证控制平面节点
kubectl get kubeadmcontrolplane -n cpaas-system <cluster-name>

# 检查机器状态
kubectl get machines -n cpaas-system

# 验证集群部署状态
kubectl get clustermodule <cluster-name> -o jsonpath='{.status.base.deployStatus}'

预期结果

成功创建的集群应显示:

  • 集群状态:RunningProvisioned
  • 所有控制平面机器:Running
  • Kubernetes 节点:Ready
  • Cluster Module 状态:Completed

添加工作节点

有关向集群添加工作节点的说明,请参阅 Managing Nodes

升级集群

有关升级集群组件的说明,请参阅 Upgrading Clusters