documentation.suse.com / Documentação do SUSE Edge / Guias de início rápido / Implantações automatizadas de BMC com Metal3

1 Implantações automatizadas de BMC com Metal3

Metal3 é um projeto da CNCF que oferece recursos de gerenciamento de infraestrutura bare metal para Kubernetes.

O Metal3 inclui recursos nativos do Kubernetes para gerenciar o ciclo de vida de servidores bare metal que suportam gerenciamento com protocolos fora da banda, como o Redfish.

Ele também conta com suporte a Cluster API (CAPI), que permite gerenciar os recursos da infraestrutura de vários provedores por meio de APIs amplamente adotadas e independentes de fornecedor.

1.1 Por que usar este método

Este método é útil em cenários com hardware de destino que permite o gerenciamento fora da banda e quando se deseja um fluxo de gerenciamento de infraestrutura automatizado.

O cluster de gerenciamento é configurado para oferecer APIs declarativas que permitem o gerenciamento de inventário e de estado dos servidores bare metal do cluster downstream, incluindo inspeção automatizada, limpeza e provisionamento/desprovisionamento.

1.2 Arquitetura de alto nível

início rápido da arquitetura do metal3

1.3 Pré-requisitos

Há algumas restrições específicas relacionadas ao hardware e à rede de servidor do cluster downstream:

  • Cluster de gerenciamento

    • É preciso ter conectividade de rede com a API de gerenciamento/BMC do servidor de destino

    • É preciso ter conectividade com a rede do plano de controle do servidor de destino

    • Para clusters de gerenciamento de vários nós, é necessário um endereço IP reservado adicional

  • Hosts para serem controlados

    • É preciso ter suporte a gerenciamento fora da banda pelas interfaces do Redfish, iDRAC ou iLO

    • É preciso ter suporte à implantação por mídia virtual (não há suporte a PXE no momento)

    • É preciso ter conectividade de rede com o cluster de gerenciamento para acessar as APIs de provisionamento do Metal3

Algumas ferramentas são necessárias e podem ser instaladas no cluster de gerenciamento ou em um host que possa acessá-lo.

Faça download do arquivo de imagem de sistema operacional SL-Micro.x86_64-6.1-Base-GM.raw pelo SUSE Customer Center ou pela página de download da SUSE.

1.3.1 Configurar o cluster de gerenciamento

As etapas básicas de instalação de um cluster de gerenciamento e uso do Metal3 são:

  1. Instalar um cluster de gerenciamento RKE2

  2. Instalar o Rancher

  3. Instalar um provedor de armazenamento (opcional)

  4. Instalar as dependências do Metal3

  5. Instalar as dependências da CAPI pelo Rancher Turtles

  6. Criar uma imagem do sistema operacional SLEMicro para hosts do cluster downstream

  7. Registrar CRs de BareMetalHost para definir o inventário de bare metal

  8. Criar um cluster downstream definindo recursos da CAPI

Este guia considera que já existe um cluster RKE2 e que o Rancher (incluindo o cert-manager) foi instalado, por exemplo, usando o Edge Image Builder (Capítulo 11, Edge Image Builder).

Dica
Dica

Estas etapas também podem ser totalmente automatizadas conforme descrito na documentação do cluster de gerenciamento (Capítulo 40, Configurando o cluster de gerenciamento).

1.3.2 Instalando as dependências do Metal3

O cert-manager deve ser instalado e executado caso não tenha sido junto com a instalação do Rancher.

É necessário instalar um provedor de armazenamento persistente. O SUSE Storage é recomendado, mas também é possível usar o local-path-provisioner em ambientes de desenvolvimento/PoC. A instrução abaixo considera que StorageClass foi marcada como padrão; do contrário, será necessária uma configuração adicional para o gráfico do Metal3.

Um IP adicional é necessário, que pode ser gerenciado por MetalLB para fornecer um endpoint consistente aos serviços de gerenciamento do Metal3. Esse IP deve fazer parte da sub-rede do plano de controle e ser reservado para configuração estática (e não fazer parte de um pool DHCP).

Dica
Dica

Se o cluster de gerenciamento é um nó único, é possível evitar o requisito de IP flutuante adicional gerenciado por MetalLB. Consulte a Seção 1.6.1, “Configuração de nó único”.

  1. Vamos instalar primeiro o MetalLB:

    helm install \
      metallb oci://registry.suse.com/edge/charts/metallb \
      --namespace metallb-system \
      --create-namespace
  2. Na sequência, definimos um IPAddressPool e L2Advertisement usando o IP reservado, especificado abaixo como STATIC_IRONIC_IP:

    export STATIC_IRONIC_IP=<STATIC_IRONIC_IP>
    
    cat <<-EOF | kubectl apply -f -
    apiVersion: metallb.io/v1beta1
    kind: IPAddressPool
    metadata:
      name: ironic-ip-pool
      namespace: metallb-system
    spec:
      addresses:
      - ${STATIC_IRONIC_IP}/32
      serviceAllocation:
        priority: 100
        serviceSelectors:
        - matchExpressions:
          - {key: app.kubernetes.io/name, operator: In, values: [metal3-ironic]}
    EOF
    cat <<-EOF | kubectl apply -f -
    apiVersion: metallb.io/v1beta1
    kind: L2Advertisement
    metadata:
      name: ironic-ip-pool-l2-adv
      namespace: metallb-system
    spec:
      ipAddressPools:
      - ironic-ip-pool
    EOF
  3. Agora é possível instalar o Metal3:

    helm install \
      metal3 oci://registry.suse.com/edge/charts/metal3 \
      --namespace metal3-system \
      --create-namespace \
      --set global.ironicIP="$STATIC_IRONIC_IP"
  4. A execução do contêiner init pode levar cerca de dois minutos nesta implantação, portanto, garanta que todos os pods estejam em execução antes de continuar:

    kubectl get pods -n metal3-system
    NAME                                                    READY   STATUS    RESTARTS   AGE
    baremetal-operator-controller-manager-85756794b-fz98d   2/2     Running   0          15m
    metal3-metal3-ironic-677bc5c8cc-55shd                   4/4     Running   0          15m
    metal3-metal3-mariadb-7c7d6fdbd8-64c7l                  1/1     Running   0          15m
Atenção
Atenção

Não avance para as etapas seguintes até que todos os pods no namespace metal3-system estejam em execução.

1.3.3 Instalando as dependências de API do cluster

As dependências de API do cluster são gerenciadas pelo gráfico Helm do Rancher Turtles:

cat > values.yaml <<EOF
rancherTurtles:
  features:
    embedded-capi:
      disabled: true
    rancher-webhook:
      cleanup: true
EOF

helm install \
  rancher-turtles oci://registry.suse.com/edge/charts/rancher-turtles \
  --namespace rancher-turtles-system \
  --create-namespace \
  -f values.yaml

Após algum tempo, os pods do controlador deverão estar em execução nos namespaces capi-system, capm3-system, rke2-bootstrap-system e rke2-control-plane-system.

1.3.4 Preparar a imagem do cluster downstream

O Kiwi (Capítulo 28, Criando imagens atualizadas do SUSE Linux Micro com o Kiwi) e o Edge Image Builder (Capítulo 11, Edge Image Builder) são usados para preparar a imagem base do SLEMicro modificado que foi provisionado nos hosts do cluster downstream.

Neste guia, abordamos a configuração mínima necessária para implantar o cluster downstream.

1.3.4.1 Configuração da imagem

Nota
Nota

Primeiro siga o Capítulo 28, Criando imagens atualizadas do SUSE Linux Micro com o Kiwi para gerar uma imagem nova como a primeira etapa necessária para criar clusters.

Ao executar o Edge Image Builder, um diretório é montado com base no host, portanto, é necessário criar uma estrutura de diretórios para armazenar os arquivos de configuração usados para definir a imagem de destino.

├── downstream-cluster-config.yaml
├── base-images/
│   └ SL-Micro.x86_64-6.1-Base-GM.raw
├── network/
|   └ configure-network.sh
└── custom/
    └ scripts/
        └ 01-fix-growfs.sh
1.3.4.1.1 Arquivo de definição da imagem do cluster downstream

O downstream-cluster-config.yaml é o arquivo de configuração principal para a imagem do cluster downstream. Veja a seguir um exemplo mínimo de implantação por meio do Metal3:

apiVersion: 1.2
image:
  imageType: raw
  arch: x86_64
  baseImage: SL-Micro.x86_64-6.1-Base-GM.raw
  outputImageName: SLE-Micro-eib-output.raw
operatingSystem:
  time:
    timezone: Europe/London
    ntp:
      forceWait: true
      pools:
        - 2.suse.pool.ntp.org
      servers:
        - 10.0.0.1
        - 10.0.0.2
  kernelArgs:
    - ignition.platform.id=openstack
    - net.ifnames=1
  systemd:
    disable:
      - rebootmgr
      - transactional-update.timer
      - transactional-update-cleanup.timer
  users:
    - username: root
      encryptedPassword: $ROOT_PASSWORD
      sshKeys:
      - $USERKEY1
  packages:
    packageList:
      - jq
  sccRegistrationCode: $SCC_REGISTRATION_CODE

Em que $SCC_REGISTRATION_CODE é o código de registro copiado do SUSE Customer Center, e a lista de pacotes contém o jq, que é obrigatório.

$ROOT_PASSWORD é a senha criptografada do usuário root, que pode ser útil para teste/depuração. É possível gerá-la com o comando openssl passwd -6 PASSWORD.

Para os ambientes de produção, a recomendação é usar as chaves SSH que podem ser adicionadas ao bloco de usuários substituindo a $USERKEY1 pelas chaves SSH reais.

Nota
Nota

O net.ifnames=1 habilita a Nomenclatura de interface de rede previsível.

Isso corresponde à configuração padrão do gráfico do Metal3, mas a configuração deve corresponder ao valor predictableNicNames do gráfico.

Veja também que o ignition.platform.id=openstack é obrigatório. Sem esse argumento, a configuração do SUSE Linux Micro pelo ignition vai falhar no fluxo automatizado do Metal3.

A seção time é opcional, mas sua configuração é altamente recomendada para evitar possíveis problemas com certificados e divergência de relógio. O valor usado neste exemplo é somente para fins ilustrativos. Ajuste-o de acordo com seus requisitos específicos.

1.3.4.1.2 Script growfs

Atualmente, é necessário um script personalizado (custom/scripts/01-fix-growfs.sh) para expandir o sistema de arquivos de acordo com o tamanho do disco na primeira inicialização após o provisionamento. O script 01-fix-growfs.sh contém as seguintes informações:

#!/bin/bash
growfs() {
  mnt="$1"
  dev="$(findmnt --fstab --target ${mnt} --evaluate --real --output SOURCE --noheadings)"
  # /dev/sda3 -> /dev/sda, /dev/nvme0n1p3 -> /dev/nvme0n1
  parent_dev="/dev/$(lsblk --nodeps -rno PKNAME "${dev}")"
  # Last number in the device name: /dev/nvme0n1p42 -> 42
  partnum="$(echo "${dev}" | sed 's/^.*[^0-9]\([0-9]\+\)$/\1/')"
  ret=0
  growpart "$parent_dev" "$partnum" || ret=$?
  [ $ret -eq 0 ] || [ $ret -eq 1 ] || exit 1
  /usr/lib/systemd/systemd-growfs "$mnt"
}
growfs /
Nota
Nota

Adicione seus próprios scripts personalizados para execução durante o processo de provisionamento usando a mesma abordagem. Para obter mais informações, consulte o Capítulo 3, Clusters independentes com o Edge Image Builder.

1.3.4.2 Criação de imagem

Depois que a estrutura de diretórios for preparada de acordo com as seções anteriores, execute o seguinte comando para criar a imagem:

podman run --rm --privileged -it -v $PWD:/eib \
 registry.suse.com/edge/3.3/edge-image-builder:1.2.1 \
 build --definition-file downstream-cluster-config.yaml

Ele cria o arquivo de imagem de saída chamado SLE-Micro-eib-output.raw, com base na definição descrita acima.

Depois disso, a imagem de saída deverá estar disponível em um servidor web, ou o contêiner de servidor de mídia habilitado pelo gráfico do Metal3 (Nota) ou um outro servidor acessível localmente. Nos exemplos a seguir, chamamos esse servidor de imagecache.local:8080.

Nota
Nota

Na implantação de imagens EIB em clusters downstream, é necessário também incluir a soma sha256 da imagem no objeto Metal3MachineTemplate. É possível gerá-la com este comando:

sha256sum <image_file> > <image_file>.sha256
# On this example:
sha256sum SLE-Micro-eib-output.raw > SLE-Micro-eib-output.raw.sha256

1.3.5 Adicionando o inventário de BareMetalHost

Para registrar servidores bare metal para implantação automatizada, é necessário criar dois recursos: um segredo com as credenciais de acesso ao BMC e um recurso BareMetalHost do Metal3 com a definição da conexão com o BMC e outros detalhes:

apiVersion: v1
kind: Secret
metadata:
  name: controlplane-0-credentials
type: Opaque
data:
  username: YWRtaW4=
  password: cGFzc3dvcmQ=
---
apiVersion: metal3.io/v1alpha1
kind: BareMetalHost
metadata:
  name: controlplane-0
  labels:
    cluster-role: control-plane
spec:
  online: true
  bootMACAddress: "00:f3:65:8a:a3:b0"
  bmc:
    address: redfish-virtualmedia://192.168.125.1:8000/redfish/v1/Systems/68bd0fb6-d124-4d17-a904-cdf33efe83ab
    disableCertificateVerification: true
    credentialsName: controlplane-0-credentials

Observe o seguinte:

  • O nome de usuário/senha do segredo deve ser codificado com base64. Observe que ele não deve incluir novas linhas à direita (por exemplo, usar echo -n, não apenas echo!)

  • É possível definir o rótulo cluster-role agora ou mais tarde, durante a criação do cluster. No exemplo abaixo, esperamos control-plane ou worker

  • bootMACAddress deve ser um MAC válido correspondente à NIC de plano de controle do host

  • O endereço bmc é a conexão com a API de gerenciamento de BMC. As seguintes opções são suportadas:

    • redfish-virtualmedia://<ENDEREÇO IP>/redfish/v1/Systems/<ID DO SISTEMA>: mídia virtual Redfish, por exemplo, SuperMicro

    • idrac-virtualmedia://<ENDEREÇO IP>/redfish/v1/Systems/System.Embedded.1: iDRAC da Dell

  • Consulte os documentos da API upstream para obter mais detalhes sobre a API BareMetalHost

1.3.5.1 Configurando IPs estáticos

O exemplo do BareMetalHost acima considera que o DHCP configura a rede do plano de controle, mas nos cenários em que a configuração manual é necessária, como no caso dos IPs estáticos, é possível definir uma configuração adicional, conforme descrito abaixo.

1.3.5.1.1 Script adicional para configuração de rede estática

Ao criar a imagem base com o Edge Image Builder, na pasta network, crie o arquivo configure-network.sh a seguir.

Esse procedimento consome os dados da unidade de configuração na primeira inicialização e configura a rede do host usando a ferramenta NM Configurator.

#!/bin/bash

set -eux

# Attempt to statically configure a NIC in the case where we find a network_data.json
# In a configuration drive

CONFIG_DRIVE=$(blkid --label config-2 || true)
if [ -z "${CONFIG_DRIVE}" ]; then
  echo "No config-2 device found, skipping network configuration"
  exit 0
fi

mount -o ro $CONFIG_DRIVE /mnt

NETWORK_DATA_FILE="/mnt/openstack/latest/network_data.json"

if [ ! -f "${NETWORK_DATA_FILE}" ]; then
  umount /mnt
  echo "No network_data.json found, skipping network configuration"
  exit 0
fi

DESIRED_HOSTNAME=$(cat /mnt/openstack/latest/meta_data.json | tr ',{}' '\n' | grep '\"metal3-name\"' | sed 's/.*\"metal3-name\": \"\(.*\)\"/\1/')
echo "${DESIRED_HOSTNAME}" > /etc/hostname

mkdir -p /tmp/nmc/{desired,generated}
cp ${NETWORK_DATA_FILE} /tmp/nmc/desired/_all.yaml
umount /mnt

./nmc generate --config-dir /tmp/nmc/desired --output-dir /tmp/nmc/generated
./nmc apply --config-dir /tmp/nmc/generated
1.3.5.1.2 Segredo adicional com a configuração de rede do host

É possível definir um segredo adicional com os dados no formato nmstate suportado pela ferramenta NM Configurator (Capítulo 12, Rede de borda) para cada host.

Depois disso, o segredo será referenciado no recurso BareMetalHost pelo campo de especificação preprovisioningNetworkDataName.

apiVersion: v1
kind: Secret
metadata:
  name: controlplane-0-networkdata
type: Opaque
stringData:
  networkData: |
    interfaces:
    - name: enp1s0
      type: ethernet
      state: up
      mac-address: "00:f3:65:8a:a3:b0"
      ipv4:
        address:
        - ip:  192.168.125.200
          prefix-length: 24
        enabled: true
        dhcp: false
    dns-resolver:
      config:
        server:
        - 192.168.125.1
    routes:
      config:
      - destination: 0.0.0.0/0
        next-hop-address: 192.168.125.1
        next-hop-interface: enp1s0
---
apiVersion: metal3.io/v1alpha1
kind: BareMetalHost
metadata:
  name: controlplane-0
  labels:
    cluster-role: control-plane
spec:
  preprovisioningNetworkDataName: controlplane-0-networkdata
# Remaining content as in previous example
Nota
Nota

Em algumas situações, é possível omitir o endereço MAC. Consulte a Seção 12.5.8, “Configurações unificadas de nós” para obter mais detalhes.

1.3.5.2 Preparação do BareMetalHost

Depois de criar o recurso BareMetalHost e os segredos associados conforme descrito acima, será acionado um fluxo de trabalho de preparação do host:

  • Uma imagem de disco RAM será iniciada depois de conectar a mídia virtual ao BMC do host de destino

  • O disco RAM inspeciona os detalhes do hardware e prepara o host para provisionamento (por exemplo, limpando os discos de dados anteriores)

  • Ao término desse processo, os detalhes do hardware no campo status.hardware do BareMetalHost serão atualizados e poderão ser verificados

Esse processo pode levar bastante tempo, mas quando for concluído, você verá que o estado do BareMetalHost deve mudar para available:

% kubectl get baremetalhost
NAME             STATE       CONSUMER   ONLINE   ERROR   AGE
controlplane-0   available              true             9m44s
worker-0         available              true             9m44s

1.3.6 Criando clusters downstream

Agora criamos os recursos de Cluster API que definem o cluster downstream e os recursos de Machine que provisionam e, depois, iniciam os recursos do BareMetalHost para formar um cluster RKE2.

1.3.7 Implantação do plano de controle

Para implantar o plano de controle, definimos um manifesto YAML semelhante ao mostrado abaixo, que contém os seguintes recursos:

  • O recurso Cluster define o nome do cluster, as redes e o tipo de provedor de plano de controle/infraestrutura (neste caso, RKE2/Metal3)

  • Metal3Cluster define o endpoint do plano de controle (IP do host para nó único, endpoint LoadBalancer para vários nós; neste exemplo, foi considerado o nó único)

  • RKE2ControlPlane define a versão RKE2 e a configuração adicional necessária durante a inicialização do cluster

  • Metal3MachineTemplate define a imagem do sistema operacional que será aplicada aos recursos do BareMetalHost, e hostSelector define quais BareMetalHosts serão consumidos

  • Metal3DataTemplate define o metaData adicional que será passado para o BareMetalHost (veja que o networkData não é suportado na solução Edge)

Nota
Nota

Para simplificar, este exemplo considera um plano de controle de nó único em que o BareMetalHost está configurado com o IP 192.168.125.200. Para ver exemplos mais avançados de vários nós, consulte o Capítulo 42, Provisionamento de rede direcionado totalmente automatizado.

apiVersion: cluster.x-k8s.io/v1beta1
kind: Cluster
metadata:
  name: sample-cluster
  namespace: default
spec:
  clusterNetwork:
    pods:
      cidrBlocks:
        - 192.168.0.0/18
    services:
      cidrBlocks:
        - 10.96.0.0/12
  controlPlaneRef:
    apiVersion: controlplane.cluster.x-k8s.io/v1beta1
    kind: RKE2ControlPlane
    name: sample-cluster
  infrastructureRef:
    apiVersion: infrastructure.cluster.x-k8s.io/v1beta1
    kind: Metal3Cluster
    name: sample-cluster
---
apiVersion: infrastructure.cluster.x-k8s.io/v1beta1
kind: Metal3Cluster
metadata:
  name: sample-cluster
  namespace: default
spec:
  controlPlaneEndpoint:
    host: 192.168.125.200
    port: 6443
  noCloudProvider: true
---
apiVersion: controlplane.cluster.x-k8s.io/v1beta1
kind: RKE2ControlPlane
metadata:
  name: sample-cluster
  namespace: default
spec:
  infrastructureRef:
    apiVersion: infrastructure.cluster.x-k8s.io/v1beta1
    kind: Metal3MachineTemplate
    name: sample-cluster-controlplane
  replicas: 1
  version: v1.32.4+rke2r1
  rolloutStrategy:
    type: "RollingUpdate"
    rollingUpdate:
      maxSurge: 0
  agentConfig:
    format: ignition
    kubelet:
      extraArgs:
        - provider-id=metal3://BAREMETALHOST_UUID
    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"
                ExecStartPost=/bin/sh -c "umount /mnt"
                [Install]
                WantedBy=multi-user.target
---
apiVersion: infrastructure.cluster.x-k8s.io/v1beta1
kind: Metal3MachineTemplate
metadata:
  name: sample-cluster-controlplane
  namespace: default
spec:
  template:
    spec:
      dataTemplate:
        name: sample-cluster-controlplane-template
      hostSelector:
        matchLabels:
          cluster-role: control-plane
      image:
        checksum: http://imagecache.local:8080/SLE-Micro-eib-output.raw.sha256
        checksumType: sha256
        format: raw
        url: http://imagecache.local:8080/SLE-Micro-eib-output.raw
---
apiVersion: infrastructure.cluster.x-k8s.io/v1beta1
kind: Metal3DataTemplate
metadata:
  name: sample-cluster-controlplane-template
  namespace: default
spec:
  clusterName: sample-cluster
  metaData:
    objectNames:
      - key: name
        object: machine
      - key: local-hostname
        object: machine
      - key: local_hostname
        object: machine

Depois de adaptado ao seu ambiente, aplique o exemplo usando o kubectl e monitore o status do cluster por meio do clusterctl.

% kubectl apply -f rke2-control-plane.yaml

# Wait for the cluster to be provisioned
% clusterctl describe cluster sample-cluster
NAME                                                    READY  SEVERITY  REASON  SINCE  MESSAGE
Cluster/sample-cluster                                  True                     22m
├─ClusterInfrastructure - Metal3Cluster/sample-cluster  True                     27m
├─ControlPlane - RKE2ControlPlane/sample-cluster        True                     22m
│ └─Machine/sample-cluster-chflc                        True                     23m

1.3.8 Implantação de worker/computação

De maneira semelhante à implantação do plano de controle, definimos um manifesto YAML que contém os seguintes recursos:

  • MachineDeployment define o número de réplicas (hosts) e o provedor de inicialização/infraestrutura (neste caso, RKE2/Metal3)

  • RKE2ConfigTemplate descreve a versão RKE2 e a configuração da primeira inicialização para inicializar o host do agente

  • Metal3MachineTemplate define a imagem do sistema operacional que será aplicada aos recursos do BareMetalHost, e o seletor de host define quais BareMetalHosts serão consumidos

  • Metal3DataTemplate define os metadados adicionais que serão passados para o BareMetalHost (veja que o networkData não é suportado atualmente)

apiVersion: cluster.x-k8s.io/v1beta1
kind: MachineDeployment
metadata:
  labels:
    cluster.x-k8s.io/cluster-name: sample-cluster
  name: sample-cluster
  namespace: default
spec:
  clusterName: sample-cluster
  replicas: 1
  selector:
    matchLabels:
      cluster.x-k8s.io/cluster-name: sample-cluster
  template:
    metadata:
      labels:
        cluster.x-k8s.io/cluster-name: sample-cluster
    spec:
      bootstrap:
        configRef:
          apiVersion: bootstrap.cluster.x-k8s.io/v1alpha1
          kind: RKE2ConfigTemplate
          name: sample-cluster-workers
      clusterName: sample-cluster
      infrastructureRef:
        apiVersion: infrastructure.cluster.x-k8s.io/v1beta1
        kind: Metal3MachineTemplate
        name: sample-cluster-workers
      nodeDrainTimeout: 0s
      version: v1.32.4+rke2r1
---
apiVersion: bootstrap.cluster.x-k8s.io/v1alpha1
kind: RKE2ConfigTemplate
metadata:
  name: sample-cluster-workers
  namespace: default
spec:
  template:
    spec:
      agentConfig:
        format: ignition
        version: v1.32.4+rke2r1
        kubelet:
          extraArgs:
            - provider-id=metal3://BAREMETALHOST_UUID
        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"
                    ExecStartPost=/bin/sh -c "umount /mnt"
                    [Install]
                    WantedBy=multi-user.target
---
apiVersion: infrastructure.cluster.x-k8s.io/v1beta1
kind: Metal3MachineTemplate
metadata:
  name: sample-cluster-workers
  namespace: default
spec:
  template:
    spec:
      dataTemplate:
        name: sample-cluster-workers-template
      hostSelector:
        matchLabels:
          cluster-role: worker
      image:
        checksum: http://imagecache.local:8080/SLE-Micro-eib-output.raw.sha256
        checksumType: sha256
        format: raw
        url: http://imagecache.local:8080/SLE-Micro-eib-output.raw
---
apiVersion: infrastructure.cluster.x-k8s.io/v1beta1
kind: Metal3DataTemplate
metadata:
  name: sample-cluster-workers-template
  namespace: default
spec:
  clusterName: sample-cluster
  metaData:
    objectNames:
      - key: name
        object: machine
      - key: local-hostname
        object: machine
      - key: local_hostname
        object: machine

Quando o exemplo acima for copiado e adaptado ao seu ambiente, ele poderá ser aplicado usando o kubectl e, depois, o status do cluster poderá ser monitorado com o clusterctl

% kubectl apply -f rke2-agent.yaml

# Wait for the worker nodes to be provisioned
% clusterctl describe cluster sample-cluster
NAME                                                    READY  SEVERITY  REASON  SINCE  MESSAGE
Cluster/sample-cluster                                  True                     25m
├─ClusterInfrastructure - Metal3Cluster/sample-cluster  True                     30m
├─ControlPlane - RKE2ControlPlane/sample-cluster        True                     25m
│ └─Machine/sample-cluster-chflc                        True                     27m
└─Workers
  └─MachineDeployment/sample-cluster                    True                     22m
    └─Machine/sample-cluster-56df5b4499-zfljj           True                     23m

1.3.9 Desprovisionamento do cluster

É possível desprovisionar o cluster downstream excluindo os recursos que foram aplicados nas etapas de criação acima:

% kubectl delete -f rke2-agent.yaml
% kubectl delete -f rke2-control-plane.yaml

Esse procedimento aciona o desprovisionamento dos recursos do BareMetalHost, o que pode levar bastante tempo. Depois disso, eles deverão voltar para o estado disponível:

% kubectl get bmh
NAME             STATE            CONSUMER                            ONLINE   ERROR   AGE
controlplane-0   deprovisioning   sample-cluster-controlplane-vlrt6   false            10m
worker-0         deprovisioning   sample-cluster-workers-785x5        false            10m

...

% kubectl get bmh
NAME             STATE       CONSUMER   ONLINE   ERROR   AGE
controlplane-0   available              false            15m
worker-0         available              false            15m

1.4 Problemas conhecidos

  • O controlador de gerenciamento de endereços IP upstream não é suportado no momento porque ainda não é compatível com a nossa seleção de ferramentas de configuração de rede e conjunto de ferramentas de primeira inicialização no SLEMicro.

  • De modo semelhante, os recursos IPAM e os campos networkData de Metal3DataTemplate não são suportados no momento.

  • Apenas há suporte para implantação por redfish-virtualmedia.

1.5 Alterações planejadas

  • Habilitar suporte de recursos e configuração do IPAM pelos campos networkData

1.6 Recursos adicionais

A documentação do SUSE Edge for Telco (Capítulo 37, SUSE Edge for Telco) tem exemplos de uso mais avançado do Metal3 para casos de uso de telecomunicações.

1.6.1 Configuração de nó único

Para ambientes de teste/PoC em que o cluster de gerenciamento é um nó único, é possível evitar o requisito de IP flutuante adicional gerenciado por MetalLB.

Nesse modo, o endpoint para as APIs do cluster de gerenciamento é o IP do cluster de gerenciamento, portanto, ele deve ser reservado ao usar DHCP ou configurado estaticamente para garantir que não seja alterado. Mencionado abaixo como <MANAGEMENT_CLUSTER_IP>.

Para possibilitar esse cenário, os valores do gráfico do Metal3 necessários são estes:

global:
  ironicIP: <MANAGEMENT_CLUSTER_IP>
metal3-ironic:
  service:
    type: NodePort

1.6.2 Desabilitando TLS para anexo de ISO de mídia virtual

Alguns fornecedores de servidor verificam a conexão SSL ao anexar imagens ISO de mídia virtual ao BMC, o que pode causar um problema porque os certificados gerados para a implantação do Metal3 são autoassinados. Para solucionar esse problema, desabilite o TLS apenas para anexo de disco de mídia virtual com os valores do gráfico do Metal3 a seguir:

global:
  enable_vmedia_tls: false

Uma solução alternativa é configurar os BMCs com o certificado de CA. Nesse caso, você pode ler os certificados do cluster usando o kubectl:

kubectl get secret -n metal3-system ironic-vmedia-cert -o yaml

Depois disso, o certificado poderá ser configurado no console de BMC do servidor, embora o processo para isso seja específico do fornecedor (e pode não ser possível para todos os fornecedores e, consequentemente, exigir o uso do sinalizador enable_vmedia_tls).

1.6.3 Configuração do armazenamento

Para ambientes de teste/PoC em que o cluster de gerenciamento é um nó único, não há necessidade de armazenamento persistente; mas em casos de uso de produção, a recomendação é instalar o SUSE Storage (Longhorn) no cluster de gerenciamento para que as imagens relacionadas ao Metal3 persistam durante a reinicialização/reprogramação de um pod.

Para habilitar o armazenamento persistente, os valores do gráfico do Metal3 necessários são estes:

metal3-ironic:
  persistence:
    ironic:
      size: "5Gi"

A documentação para cluster de gerenciamento do SUSE Edge for Telco (Capítulo 40, Configurando o cluster de gerenciamento) tem mais detalhes sobre como configurar um cluster de gerenciamento com armazenamento persistente.

Documentation survey