|Index|SUSE Telco Cloud 文档|全自动定向网络配置|使用定向网络置备(多节点)进行下游集群置备
Applies to SUSE Telco Cloud 3.6

52 使用定向网络置备(多节点)进行下游集群置备

本节介绍了用于通过定向网络置备和`MetalLB`作为负载均衡器策略来自动置备多节点下游集群的工作流程。 这是自动化置备下游集群的最简单方法。下图显示了用于通过定向网络置备和`MetalLB`来自动置备多节点下游集群的工作流程。

要求

工作流程

下图显示了用于通过定向网络置备来自动置备多节点下游集群的工作流程:

atip automate multinode1
  1. 注册这三台裸机主机,使其可用于置备。

  2. 置备这三台裸机主机,以使用`MetalLB`安装和配置操作系统及 Kubernetes 集群。

注册裸机主机

第一步是在管理集群中注册这三台裸机主机,使其可供置备。 为此,必须在管理集群中创建以下文件(bmh-example-node1.yamlbmh-example-node2.yamlbmh-example-node3.yaml),以指定要使用的`BMC`凭据以及要在管理集群中注册的`BaremetalHost`对象。

Note
Note
  • 仅需将`$\{…​\}`之间的值替换为实际值。

  • 我们将引导您完成仅针对一台主机的流程。同样的步骤适用于另外两个节点。

apiVersion: v1
kind: Secret
metadata:
  name: node1-example-credentials
type: Opaque
data:
  username: ${BMC_NODE1_USERNAME}
  password: ${BMC_NODE1_PASSWORD}
---
apiVersion: metal3.io/v1alpha1
kind: BareMetalHost
metadata:
  name: node1-example
  labels:
    cluster-role: control-plane
spec:
  architecture: x86_64
  online: true
  bootMACAddress: ${BMC_NODE1_MAC}
  bmc:
    address: ${BMC_NODE1_ADDRESS}
    disableCertificateVerification: true
    credentialsName: node1-example-credentials

其中:

  • ${BMC_NODE1_USERNAME} — 第一台裸机主机 BMC 的用户名。

  • ${BMC_NODE1_PASSWORD} — 第一台裸机主机 BMC 的密码。

  • ${BMC_NODE1_MAC} — 要使用的第一台裸机主机的 MAC 地址。

  • ${BMC_NODE1_ADDRESS} — 第一台裸机主机 BMC 的 URL(例如,redfish-virtualmedia://192.168.200.75/redfish/v1/Systems/1/)。在现有基础设施允许的情况下,URL 的主机部分可以是 IP 地址(v4 或 v6)或域名。要了解有关根据您的硬件提供商可用的不同选项的更多信息,请查看以下 链接

Note
Note
  • 如果未指定主机的网络配置(无论是在镜像构建时还是通过`BareMetalHost`定义),则将使用自动配置机制(DHCP、DHCPv6、SLAAC)。有关更多详细信息或复杂配置,请查看Chapter 53, 高级网络配置

  • 单栈 IPv6 集群处于技术预览状态,尚未正式支持。

  • 架构必须是`x86_64`或`aarch64`,具体取决于要注册的裸机主机的架构。

  • 所有现代服务器都配备了支持双栈的 BMC,但在生产环境中使用双栈环境之前,应验证 IPv6 支持(以及可能使用主机名进行 VirtualMedia 功能的选项)。

文件创建后,必须在管理集群中执行以下命令,以开始将裸机主机注册到管理集群中:

$ kubectl apply -f bmh-example-node1.yaml
$ kubectl apply -f bmh-example-node2.yaml
$ kubectl apply -f bmh-example-node3.yaml

新的裸机主机对象已注册,其状态从 registering(注册中)变为 inspecting(检查中)和 available(可用)。可以使用以下命令检查更改:

$ kubectl get bmh -o wide
Note
Note

在验证`BMC`凭据之前,BaremetalHost`对象处于`registering`状态。凭据验证完成后,`BaremetalHost`对象的状态将更改为`inspecting,根据硬件的不同,此步骤可能需要一些时间(最长 20 分钟)。在检查阶段,将检索硬件信息并更新 Kubernetes 对象。使用以下命令检查信息:kubectl get bmh -o yaml

置备步骤

一旦三个裸机主机注册并可用,下一步就是置备裸机主机,以安装和配置操作系统及 Kubernetes 集群,并创建一个负载均衡器来管理它们。 为此,必须在管理集群中创建以下文件 (capi-provisioning-example.yaml),并包含以下信息(`capi-provisioning-example.yaml 可以通过合并以下代码块生成)。

Note
Note
  • 只有 $\{…​\} 内的值必须替换为实际值。

  • VIP 地址是一个预留的 IP 地址,未分配给任何节点,用于配置负载均衡器。在双栈集群中,可以同时指定 IPv4 和 IPv6 地址,但在以下示例中,将优先使用 IPv4 地址。

以下是集群定义,其中可以使用 podsservices 块来配置集群网络。此外,它还包含要使用的控制平面和基础设施(使用 Metal3 提供程序)对象的引用。

apiVersion: cluster.x-k8s.io/v1beta2
kind: Cluster
metadata:
  name: multinode-cluster
  namespace: default
  labels:
    cluster-api.cattle.io/rancher-auto-import: "true"
spec:
  clusterNetwork:
    pods:
      cidrBlocks:
        - 192.168.0.0/18
        - fd00:1234:4321::/48
    services:
      cidrBlocks:
        - 10.96.0.0/12
        - fd00:5678:8765:4321::/112
  controlPlaneRef:
    apiGroup: controlplane.cluster.x-k8s.io
    kind: RKE2ControlPlane
    name: multinode-cluster
  infrastructureRef:
    apiGroup: infrastructure.cluster.x-k8s.io
    kind: Metal3Cluster
    name: multinode-cluster
Note
Note
  • 单栈和双栈部署均可行;对于仅使用 IPv4 的集群,请删除 IPv6 CIDR 和 IPv6 VIP 地址(在后续章节中)。

  • 将标签 cluster-api.cattle.io/rancher-auto-import: "true" 添加到 cluster.x-k8s.io 对象中会将集群导入 Rancher(通过创建相应的 clusters.management.cattle.io 对象)。 有关更多信息,请参阅 Cluster API 文档

Metal3Cluster 对象指定了控制平面端点,该端点使用已预留的 VIP 地址(替换 ${EDGE_VIP_ADDRESS_IPV4})进行配置,并使用 noCloudProvider,因为使用了三个裸机节点。

apiVersion: infrastructure.cluster.x-k8s.io/v1beta1
kind: Metal3Cluster
metadata:
  name: multinode-cluster
  namespace: default
spec:
  controlPlaneEndpoint:
    host: ${EDGE_VIP_ADDRESS_IPV4}
    port: 6443
  noCloudProvider: true

RKE2ControlPlane 对象指定要使用的控制平面配置,Metal3MachineTemplate 对象指定要使用的控制平面镜像。

  • 一种负载均衡器排除注解,用于通知 MetalLB 等外部负载均衡器,在下游集群升级等生命周期操作期间,节点将被排空。有关详细信息,请参见:Section 59.1, “负载均衡器排除”

  • 要使用的副本数量(在本例中为三个)。

  • 负载均衡器要使用的通告模式(address 使用 L2 实现),以及要使用的地址(将 ${EDGE_VIP_ADDRESS} 替换为 VIP 地址)。

  • 要使用的带有 CNI 插件的 serverConfig(在本例中为 Cilium),以及要在 tlsSan 下列出的额外 VIP 地址和名称。

  • agentConfig 块包含用于配置 RKE2 节点的信息,例如要使用的 Ignition 格式和 additionalUserData

    • 名为 rke2-preinstall.service 的 systemd 服务,用于在置备过程中使用 Ironic 信息自动替换 BAREMETALHOST_UUIDnode-name,并为具有 BareMetalHost UUID 的节点对象添加 metal3.io/uuid 标签。

    • 名为 rke2-traefik-deployment.service 的 systemd 服务用于在 /etc/rancher/rke2/config.yaml 文件中将 RKE2 的 ingress-controller 配置服务器选项设置为 traefik

    • 包含用于安装 MetalLBendpoint-copier-operator 的 Helm chart 的 storage 块。

    • 包含要使用的 IPaddressPoolL2AdvertisementmetalLB 自定义资源文件(将 ${EDGE_VIP_ADDRESS_IPV4} 替换为 VIP 地址)。

    • 用于配置 kubernetes-vip 服务的 endpoint-svc.yaml 文件,该服务由 MetalLB 用于管理 VIP 地址。

  • 最后一部分信息包含要使用的 Kubernetes 版本。${RKE2_VERSION} 是要使用的 RKE2 版本,用于替换此值(例如 v1.35.4+rke2r1)。

apiVersion: controlplane.cluster.x-k8s.io/v1beta2
kind: RKE2ControlPlane
metadata:
  name: multinode-cluster
  namespace: default
  annotations: {
    rke2.controlplane.cluster.x-k8s.io/load-balancer-exclusion: "true"
  }
spec:
  infrastructureRef:
    apiGroup: infrastructure.cluster.x-k8s.io
    kind: Metal3MachineTemplate
    name: multinode-cluster-controlplane
  replicas: 3
  version: ${RKE2_VERSION}
  rolloutStrategy:
    type: "RollingUpdate"
    rollingUpdate:
      maxSurge: 0
  registrationMethod: "control-plane-endpoint"
  registrationAddress: ${EDGE_VIP_ADDRESS}
  serverConfig:
    cni: cilium
    tlsSan:
      - ${EDGE_VIP_ADDRESS_IPV4}
      - ${EDGE_VIP_ADDRESS_IPV6}
      - https://${EDGE_VIP_ADDRESS_IPV4}.sslip.io
      - https://${EDGE_VIP_ADDRESS_IPV6}.sslip.io
  agentConfig:
    format: ignition
    additionalUserData:
      config: |
        variant: fcos
        version: 1.4.0
        systemd:
          units:
          - name: rke2-preinstall.service
            enabled: true
            contents: |
              [Unit]
              Description=rke2-preinstall
              Wants=network-online.target
              Before=rke2-install.service
              ConditionPathExists=!/run/cluster-api/bootstrap-success.complete
              [Service]
              Type=oneshot
              User=root
              ExecStartPre=/bin/sh -c "mount -L config-2 /mnt"
              ExecStart=/bin/sh -c "sed -i \"s/BAREMETALHOST_UUID/$(jq -r .uuid /mnt/openstack/latest/meta_data.json)/\" /etc/rancher/rke2/config.yaml"
              ExecStart=/bin/sh -c "echo \"node-name: $(jq -r .name /mnt/openstack/latest/meta_data.json)\" >> /etc/rancher/rke2/config.yaml"
              ExecStart=/bin/sh -c "echo \"node-label:\" >> /etc/rancher/rke2/config.yaml"
              ExecStart=/bin/sh -c "echo \"  - metal3.io/uuid=$(jq -r .uuid /mnt/openstack/latest/meta_data.json)\" >> /etc/rancher/rke2/config.yaml"
              ExecStartPost=/bin/sh -c "umount /mnt"
              [Install]
              WantedBy=multi-user.target
          # rke2-traefik-deployment.service unit to be removed once "traefik" being the default ingress controller (starting with RKE2 v1.36)
          - name: rke2-traefik-deployment.service
            enabled: true
            contents: |
              [Unit]
              Description=rke2-traefik-deployment
              Wants=rke2-preinstall.service
              Before=rke2-install.service
              ConditionPathExists=!/run/cluster-api/bootstrap-success.complete
              [Service]
              Type=oneshot
              User=root
              ExecStart=/bin/sh -c "echo \"ingress-controller: traefik\" >> /etc/rancher/rke2/config.yaml"
              [Install]
              WantedBy=multi-user.target
        storage:
          directories:
          - path: /var/lib/rancher/rke2/server/manifests
            overwrite: true
          files:
            # https://docs.rke2.io/networking/multus_sriov#using-multus-with-cilium
            - path: /var/lib/rancher/rke2/server/manifests/rke2-cilium-config.yaml
              overwrite: true
              contents:
                inline: |
                  apiVersion: helm.cattle.io/v1
                  kind: HelmChartConfig
                  metadata:
                    name: rke2-cilium
                    namespace: kube-system
                  spec:
                    valuesContent: |-
                      cni:
                        exclusive: false
              mode: 0644
              user:
                name: root
              group:
                name: root
            - path: /var/lib/rancher/rke2/server/manifests/endpoint-copier-operator.yaml
              overwrite: true
              contents:
                inline: |
                  apiVersion: helm.cattle.io/v1
                  kind: HelmChart
                  metadata:
                    name: endpoint-copier-operator
                    namespace: kube-system
                  spec:
                    chart: oci://registry.suse.com/edge/charts/endpoint-copier-operator
                    targetNamespace: endpoint-copier-operator
                    version: 306.0.1+up0.3.0
                    createNamespace: true
            - path: /var/lib/rancher/rke2/server/manifests/metallb.yaml
              overwrite: true
              contents:
                inline: |
                  apiVersion: helm.cattle.io/v1
                  kind: HelmChart
                  metadata:
                    name: metallb
                    namespace: kube-system
                  spec:
                    chart: oci://registry.suse.com/edge/charts/metallb
                    targetNamespace: metallb-system
                    version: 306.0.2+up0.15.3
                    createNamespace: true

            - path: /var/lib/rancher/rke2/server/manifests/metallb-cr.yaml
              overwrite: true
              contents:
                inline: |
                  apiVersion: metallb.io/v1beta1
                  kind: IPAddressPool
                  metadata:
                    name: kubernetes-vip-ip-pool
                    namespace: metallb-system
                  spec:
                    addresses:
                      - ${EDGE_VIP_ADDRESS_IPV4}/32
                      - ${EDGE_VIP_ADDRESS_IPV6}/128
                    serviceAllocation:
                      priority: 100
                      namespaces:
                        - default
                      serviceSelectors:
                        - matchExpressions:
                          - {key: "serviceType", operator: In, values: [kubernetes-vip]}
                  ---
                  apiVersion: metallb.io/v1beta1
                  kind: L2Advertisement
                  metadata:
                    name: ip-pool-l2-adv
                    namespace: metallb-system
                  spec:
                    ipAddressPools:
                      - kubernetes-vip-ip-pool
            - path: /var/lib/rancher/rke2/server/manifests/endpoint-svc.yaml
              overwrite: true
              contents:
                inline: |
                  apiVersion: v1
                  kind: Service
                  metadata:
                    name: kubernetes-vip
                    namespace: default
                    labels:
                      serviceType: kubernetes-vip
                  spec:
                    ipFamilyPolicy: PreferDualStack
                    ports:
                    - name: rke2-api
                      port: 9345
                      protocol: TCP
                      targetPort: 9345
                    - name: k8s-api
                      port: 6443
                      protocol: TCP
                      targetPort: 6443
                    type: LoadBalancer
          - path: /var/lib/rancher/rke2/server/manifests/rke2-traefik-config.yaml
            overwrite: true
            contents:
              inline: |
                apiVersion: helm.cattle.io/v1
                kind: HelmChartConfig
                metadata:
                  name: rke2-traefik
                  namespace: kube-system
                spec:
                  valuesContent: |-
                    ingressClass:
                      isDefaultClass: true
                    ports:
                      web:
                        hostPort: null    # disallow hostPort
                        exposedPort: 80
                      websecure:
                        hostPort: null    # disallow hostPort
                        exposedPort: 443
                    service:
                      enabled: true
                      type: LoadBalancer
                      spec:
                        externalTrafficPolicy: Local
                        allocateLoadBalancerNodePorts: false  # k8s GA from 1.24; supported by MetalLB
            mode: 0644
            user:
              name: root
            group:
              name: root
    kubelet:
      extraArgs:
      - provider-id=metal3://BAREMETALHOST_UUID
    nodeName: "Node-multinode-cluster"

Metal3MachineTemplate 对象指定以下信息:

  • 用作模板引用的 dataTemplate

  • 与注册过程中创建的标签相匹配的 hostSelector

  • 用作对上一 节 (Chapter 49, 为连接场景准备下游集群镜像) 中使用 EIB 生成的镜像的引用的 image,以及用于验证镜像的 checksumchecksumType

apiVersion: infrastructure.cluster.x-k8s.io/v1beta1
kind: Metal3MachineTemplate
metadata:
  name: multinode-cluster-controlplane
  namespace: default
spec:
  template:
    spec:
      dataTemplate:
        name: multinode-cluster-controlplane-template
      hostSelector:
        matchLabels:
          cluster-role: control-plane
      image:
        checksum: http://imagecache.local:8080/eibimage-output-telco.raw.sha256
        checksumType: sha256
        format: raw
        url: http://imagecache.local:8080/eibimage-output-telco.raw

Metal3DataTemplate 对象指定了下游集群的 metaData

apiVersion: infrastructure.cluster.x-k8s.io/v1beta1
kind: Metal3DataTemplate
metadata:
  name: multinode-cluster-controlplane-template
  namespace: default
spec:
  clusterName: multinode-cluster
  metaData:
    objectNames:
    - key: name
      object: machine
    - key: local-hostname
      object: machine
    - key: local_hostname
      object: machine

以下 yaml 文件是工作节点的配置示例。

一个 MachineDeployment

apiVersion: cluster.x-k8s.io/v1beta2
kind: MachineDeployment
metadata:
  labels:
    cluster.x-k8s.io/cluster-name: multinode-cluster
    nodepool: nodepool-0
  name: multinode-cluster-workers
  namespace: default
spec:
  clusterName: multinode-cluster
  replicas: 3
  selector:
    matchLabels:
      cluster.x-k8s.io/cluster-name: multinode-cluster
      nodepool: nodepool-0
  template:
    metadata:
      labels:
        cluster.x-k8s.io/cluster-name: multinode-cluster
        nodepool: nodepool-0
    spec:
      bootstrap:
        configRef:
          apiGroup: bootstrap.cluster.x-k8s.io
          kind: RKE2ConfigTemplate
          name: multinode-cluster-workers
      clusterName: multinode-cluster
      infrastructureRef:
        apiGroup: infrastructure.cluster.x-k8s.io
        kind: Metal3MachineTemplate
        name: multinode-cluster-workers
      deletion:
        nodeDrainTimeoutSeconds: 0
      version: ${RKE2_VERSION}

RKE2ConfigTemplate 对象指定了用于多节点集群工作节点配置的模板。

apiVersion: bootstrap.cluster.x-k8s.io/v1beta2
kind: RKE2ConfigTemplate
metadata:
  name: multinode-cluster-workers
  namespace: default
spec:
  template:
    spec:
      agentConfig:
        format: ignition
        kubelet:
          extraArgs:
          - provider-id=metal3://BAREMETALHOST_UUID
        nodeName: "Node-multinode-cluster-worker"
        additionalUserData:
          config: |
            variant: fcos
            version: 1.4.0
            systemd:
              units:
              - name: rke2-preinstall.service
                enabled: true
                contents: |
                  [Unit]
                  Description=rke2-preinstall
                  Wants=network-online.target
                  Before=rke2-install.service
                  ConditionPathExists=!/run/cluster-api/bootstrap-success.complete
                  [Service]
                  Type=oneshot
                  User=root
                  ExecStartPre=/bin/sh -c "mount -L config-2 /mnt"
                  ExecStart=/bin/sh -c "sed -i \"s/BAREMETALHOST_UUID/$(jq -r .uuid /mnt/openstack/latest/meta_data.json)/\" /etc/rancher/rke2/config.yaml"
                  ExecStart=/bin/sh -c "echo \"node-name: $(jq -r .name /mnt/openstack/latest/meta_data.json)\" >> /etc/rancher/rke2/config.yaml"
                  ExecStart=/bin/sh -c "echo \"node-label:\" >> /etc/rancher/rke2/config.yaml"
                  ExecStart=/bin/sh -c "echo \"  - metal3.io/uuid=$(jq -r .uuid /mnt/openstack/latest/meta_data.json)\" >> /etc/rancher/rke2/config.yaml"
                  ExecStartPost=/bin/sh -c "umount /mnt"
                  [Install]
                  WantedBy=multi-user.target

Metal3MachineTemplate 对象包含工作节点的 dataTemplatehostSelectorimage 的引用:

apiVersion: infrastructure.cluster.x-k8s.io/v1beta1
kind: Metal3MachineTemplate
metadata:
  name: multinode-cluster-workers
  namespace: default
spec:
  template:
    spec:
      dataTemplate:
        name: multinode-cluster-workers-template
      hostSelector:
        matchLabels:
          cluster-role: worker
      image:
        checksum: http://imagecache.local:8080/eibimage-slmicro-rt-telco.raw.sha256
        checksumType: sha256
        format: raw
        url: http://imagecache.local:8080/eibimage-slmicro-rt-telco.raw

Metal3DataTemplate 对象指定了工作节点下游集群的 metaData

apiVersion: infrastructure.cluster.x-k8s.io/v1beta1
kind: Metal3DataTemplate
metadata:
  name: multinode-cluster-workers-template
  namespace: default
spec:
  clusterName: multinode-cluster
  metaData:
    objectNames:
    - key: name
      object: machine
    - key: local-hostname
      object: machine
    - key: local_hostname
      object: machine

文件通过合并上述各块内容创建完成后,在管理集群中运行以下命令,开始配置新的三台裸机主机:

$ kubectl apply -f capi-provisioning-example.yaml