|Index|SUSE Telco Cloud Documentación|Aprovisionamiento de red dirigido totalmente automatizado|Aprovisionamiento de clúster descendente con aprovisionamiento de red dirigido (multinodo)
Se aplica a SUSE Telco Cloud 3.7

53 Aprovisionamiento de clúster descendente con aprovisionamiento de red dirigido (multinodo)

Esta sección describe el flujo de trabajo utilizado para automatizar el aprovisionamiento de un clúster descendente multinodo utilizando aprovisionamiento de red dirigida y MetalLB como estrategia de equilibrador de carga. Esta es la forma más sencilla de automatizar el aprovisionamiento de un clúster descendente. El siguiente diagrama muestra el flujo de trabajo utilizado para automatizar el aprovisionamiento de un clúster descendente multinodo utilizando aprovisionamiento de red dirigida y MetalLB.

Requisitos

Flujo de trabajo

El siguiente diagrama muestra el flujo de trabajo utilizado para automatizar el aprovisionamiento de un clúster descendente multinodo utilizando aprovisionamiento de red dirigida:

atip automate multinode1
  1. Inscribid los tres hosts de equipo sin sistema operativo para que estén disponibles para el proceso de aprovisionamiento.

  2. Aprovisionad los tres hosts de equipo sin sistema operativo para instalar y configurar el sistema operativo y el clúster de Kubernetes utilizando MetalLB.

Inscribid los hosts de equipo sin sistema operativo

El primer paso es inscribir los tres hosts de equipo sin sistema operativo en el clúster de gestión para que estén disponibles para ser aprovisionados. Para ello, debéis crear los siguientes archivos (bmh-example-node1.yaml, bmh-example-node2.yaml y bmh-example-node3.yaml) en el clúster de gestión, para especificar las credenciales de BMC que se utilizarán y el objeto BaremetalHost que se inscribirá en el clúster de gestión.

Nota
Nota
  • Solo debéis reemplazar los valores entre $\{…​\} por los valores reales.

  • Os guiaremos a través del proceso para un solo host. Los mismos pasos se aplican a los otros dos nodos.

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

Dónde:

  • ${BMC_NODE1_USERNAME} — El nombre de usuario para la BMC del primer host bare-metal.

  • ${BMC_NODE1_PASSWORD} — La contraseña para la BMC del primer host bare-metal.

  • ${BMC_NODE1_MAC} — La dirección MAC del primer host bare-metal que se debe utilizar.

  • ${BMC_NODE1_ADDRESS} — La URL para el BMC del primer host bare-metal (por ejemplo, redfish-virtualmedia://192.168.200.75/redfish/v1/Systems/1/). La parte del host de la URL puede ser una dirección IP (v4 o v6) o un nombre de dominio, donde la infraestructura existente lo permita. Para obtener más información sobre las diferentes opciones disponibles según su proveedor de hardware, consulte el siguiente enlace.

Nota
Nota
  • Si no se ha especificado ninguna configuración de red para el host, ya sea en el momento de la creación de la imagen o a través de la definición BareMetalHost, se utilizará un mecanismo de autoconfiguración (DHCP, DHCPv6, SLAAC). Para obtener más detalles o configuraciones complejas, consulte el Capítulo 54, Configuración de red avanzada.

  • Los clústeres IPv6 de pila única requieren un clúster de gestión de pila dual.

  • La arquitectura debe ser x86_64 o aarch64, dependiendo de la arquitectura del equipo sin sistema operativo que se va a inscribir.

  • Todos los servidores modernos vienen con un BMC capaz de manejar pila dual; sin embargo, la compatibilidad con IPv6 (y posiblemente la opción de usar nombres de host para la capacidad VirtualMedia) debe verificarse antes de su uso en producción en un entorno de pila dual.

Una vez creado el archivo, se debe ejecutar el siguiente comando en el clúster de gestión para comenzar a inscribir los equipos sin sistema operativo en el clúster de gestión:

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

Los nuevos objetos de equipo sin sistema operativo se inscriben, cambiando su estado de registro a inspección y disponible. Los cambios se pueden comprobar utilizando el siguiente comando:

$ kubectl get bmh -o wide
Nota
Nota

El objeto BaremetalHost está en el estado registering hasta que se validan las credenciales BMC. Una vez validadas las credenciales, el objeto BaremetalHost cambia su estado a inspecting, y este paso podría llevar algún tiempo dependiendo del hardware (hasta 20 minutos). Durante la fase de inspección, se recupera la información del hardware y se actualiza el objeto de Kubernetes. Compruebe la información utilizando el siguiente comando: kubectl get bmh -o yaml.

Paso de aprovisionamiento

Una vez que los tres equipos sin sistema operativo están inscritos y disponibles, el siguiente paso es aprovisionar los equipos sin sistema operativo para instalar y configurar el sistema operativo y el clúster de Kubernetes, creando un equilibrador de carga para gestionarlos. Para ello, se debe crear el siguiente archivo (capi-provisioning-example.yaml) en el clúster de gestión con la siguiente información (el `capi-provisioning-example.yaml se puede generar uniendo los siguientes bloques).

Nota
Nota
  • Solo se deben reemplazar los valores entre $\{…​\} con los valores reales.

  • La dirección VIP es una dirección IP reservada que no está asignada a ningún nodo y se utiliza para configurar el equilibrador de carga. En un clúster de pila dual, se pueden especificar tanto una IPv4 como una IPv6, pero en los siguientes ejemplos se dará prioridad a la dirección IPv4.

A continuación se muestra la definición del clúster, donde la red del clúster se puede configurar utilizando los bloques pods y services. Además, contiene las referencias a los objetos del plano de control y de la infraestructura (utilizando el proveedor Metal3) que se van a utilizar.

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
Nota
Nota
  • Son posibles tanto despliegues de pila única como de pila dual; elimine los CIDR IPv6 y las direcciones VIP IPv6 (en las secciones siguientes) para un clúster solo IPv4.

  • Añadir la etiqueta cluster-api.cattle.io/rancher-auto-import: "true" a los objetos cluster.x-k8s.io importará el clúster a Rancher (creando un objeto clusters.management.cattle.io correspondiente). Consulte la documentación de Cluster API para obtener más información.

El objeto Metal3Cluster especifica el punto de conexión del plano de control que utiliza la dirección VIP ya reservada (reemplazando el ${EDGE_VIP_ADDRESS_IPV4}) que se va a configurar y el indicador cloudProviderEnabled establecido en false porque se utilizan los tres nodos sin sistema operativo.

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

El objeto RKE2ControlPlane especifica la configuración del plano de control que se va a utilizar, y el objeto Metal3MachineTemplate especifica la imagen del plano de control que se va a utilizar.

  • Una anotación de exclusión del equilibrador de carga que informa a los equilibradores de carga externos como MetalLB de que un nodo va a ser vaciado durante las operaciones de ciclo de vida, como la actualización de versión de los clústeres en sentido descendente. Para obtener información, consulte: Sección 60.1, “Exclusión del equilibrador de carga”

  • El número de réplicas que se van a utilizar (en este caso, tres).

  • El modo de anuncio que debe utilizar el equilibrador de carga (address utiliza la implementación L2), así como la dirección que se va a utilizar (reemplazando el ${EDGE_VIP_ADDRESS} con la dirección VIP).

  • El serverConfig con el complemento CNI que se va a utilizar (en este caso, Cilium), y la(s) dirección(es) y nombre(s) VIP adicionales que se incluirán en tlsSan.

  • El bloque agentConfig contiene el Ignition formato que se debe utilizar y el additionalUserData que se debe utilizar para configurar el RKE2 nodo con información como:

    • El servicio systemd denominado rke2-preinstall.service para reemplazar automáticamente PROVIDERID y node-name durante el proceso de aprovisionamiento utilizando la información de Ironic además de añadir la etiqueta metal3.io/uuid a los objetos Node con el UUID BareMetalHost.

    • El bloque storage que contiene los manifiestos necesarios para instalar los charts de Helm MetalLB y endpoint-copier-operator.

    • El archivo de recurso personalizado metalLB que incluye el IPaddressPool y el L2Advertisement utilizados para exponer externamente el servidor de API para este clúster de descarga a través de la dirección VIP configurada (reemplazando ${EDGE_VIP_ADDRESS_IPV4} con esa dirección VIP seleccionada).

    • El archivo endpoint-svc.yaml que se va a utilizar para configurar el servicio kubernetes-vip para que sea expuesto por MetalLB a través de la dirección VIP configurada.

    • El archivo rke2-traefik-config.yaml que proporciona la configuración de ampliación para el RKE2 gráfico de Helm rke2-traefik integrado.

    • El archivo metallb-traefik-cr.yaml que contiene los manifiestos de instancia de recursos personalizados MetalLB (IPAddressPool y L2Advertisement) necesarios para exponer externamente el servicio Ingress a través de las IPs virtuales ${INGRESS_IPV4} y ${INGRESS_IPV6}.

  • El último bloque de información contiene la versión de Kubernetes que se debe utilizar. El ${RKE2_VERSION} es la versión de RKE2 que se debe utilizar reemplazando este valor (por ejemplo, v1.36.3+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"
              # Note we use _ as a delimiter for sed here because the providerid includes / characters
              ExecStart=/bin/sh -c "sed -i \"s_PROVIDERID_$(jq -r .providerid /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
        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: 307.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: 307.0.3+up0.16.1
                    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
                      spec:
                        type: LoadBalancer
                        externalTrafficPolicy: Local
                        allocateLoadBalancerNodePorts: false
            mode: 0644
            user:
              name: root
            group:
              name: root
            mode: 0644
            user:
              name: root
            group:
              name: root
          - path: /var/lib/rancher/rke2/server/manifests/metallb-traefik-cr.yaml
            overwrite: true
            contents:
              inline: |
                apiVersion: metallb.io/v1beta1
                kind: IPAddressPool
                metadata:
                  name: ingress-ippool
                  namespace: metallb-system
                spec:
                  addresses:
                    - ${INGRESS_IPV4}/32
                    - ${INGRESS_IPV6}/128
                  serviceAllocation:
                    priority: 100
                    serviceSelectors:
                    - matchExpressions:
                      - {key: app.kubernetes.io/name, operator: In, values: [rke2-traefik]} # assign to rke2-traefik LB svc
                ---
                apiVersion: metallb.io/v1beta1
                kind: L2Advertisement
                metadata:
                  name: ingress-l2-adv
                  namespace: metallb-system
                spec:
                  ipAddressPools:
                    - ingress-ippool
            mode: 0644
            user:
              name: root
            group:
              name: root
    kubelet:
      extraArgs:
      - provider-id=metal3://PROVIDERID
    nodeName: "Node-multinode-cluster"

El objeto Metal3MachineTemplate especifica la siguiente información:

  • El dataTemplate que se va a utilizar como referencia para la plantilla.

  • El hostSelector que se debe utilizar coincidiendo con la etiqueta creada durante el proceso de inscripción.

  • El image que se debe utilizar como referencia a la imagen generada mediante EIB en la sección (Capítulo 50, Preparar la imagen del clúster descendente para escenarios conectados) anterior, y checksum y checksumType que se deben utilizar para validar la imagen.

apiVersion: infrastructure.cluster.x-k8s.io/v1beta2
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
        diskFormat: raw
        url: http://imagecache.local:8080/eibimage-output-telco.raw

El objeto Metal3DataTemplate especifica el metaData para el clúster en sentido descendente.

apiVersion: infrastructure.cluster.x-k8s.io/v1beta2
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

Los siguientes archivos yaml son un ejemplo de configuración para los nodos trabajadores.

A 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}

El objeto RKE2ConfigTemplate especifica la plantilla de configuración que se debe utilizar para los nodos trabajadores de clústeres multinodo.

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://PROVIDERID
        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"
                  # Note we use _ as a delimiter for sed here because the providerid includes / characters
                  ExecStart=/bin/sh -c "sed -i \"s_PROVIDERID_$(jq -r .providerid /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

El objeto Metal3MachineTemplate contiene referencias a dataTemplate, hostSelector y image para los nodos trabajadores:

apiVersion: infrastructure.cluster.x-k8s.io/v1beta2
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
        diskFormat: raw
        url: http://imagecache.local:8080/eibimage-slmicro-rt-telco.raw

El objeto Metal3DataTemplate especifica la metaData para el clúster descendente para los nodos trabajadores:

apiVersion: infrastructure.cluster.x-k8s.io/v1beta2
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

Una vez creado el archivo uniendo los bloques anteriores, ejecute el siguiente comando en el clúster de gestión para comenzar a aprovisionar los tres nuevos hosts como equipos sin sistema operativo:

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