40 Configurando o cluster de gerenciamento #
40.1 Introdução #
O cluster de gerenciamento é a parte do SUSE Edge for Telco usada para gerenciar o provisionamento e o ciclo de vida das pilhas de runtime. Do ponto de vista técnico, esse cluster contém os seguintes componentes:
SUSE Linux Micro
como sistema operacional. Dependendo do caso de uso, é possível personalizar algumas configurações, como rede, armazenamento, usuários e argumentos do kernel.RKE2
como cluster Kubernetes. Dependendo do caso de uso, é possível configurá-lo para usar plug-ins de CNI específicos, comoMultus
,Cilium
,Calico
etc.Rancher
como plataforma de gerenciamento para gerenciar o ciclo de vida dos clusters.Metal3
como componente para gerenciar o ciclo de vida dos nós bare metal.CAPI
como componente para gerenciar o ciclo de vida dos clusters Kubernetes (downstream). Oprovedor CAPI RKE2
é usado para gerenciar o ciclo de vida dos clusters RKE2.
Com todos os componentes mencionados acima, o cluster de gerenciamento pode gerenciar o ciclo de vida dos clusters downstream, aplicando uma abordagem declarativa para gerenciar a infraestrutura e os aplicativos.
Para obter mais informações sobre o SUSE Linux Micro
,
consulte: SUSE Linux Micro (Capítulo 9, SUSE Linux Micro)
Para obter mais informações sobre o RKE2
, consulte: RKE2
(Capítulo 16, RKE2)
Para obter mais informações sobre o Rancher
, consulte:
Rancher (Capítulo 5, Rancher)
Para obter mais informações sobre o
Metal3
, consulte: Metal3
(Capítulo 10, Metal3)
40.2 Etapas para configurar o cluster de gerenciamento #
As seguintes etapas são necessárias para configurar o cluster de gerenciamento (de nó único):
Veja a seguir as etapas principais para configurar o cluster de gerenciamento com uma abordagem declarativa:
Preparação da imagem para ambientes conectados (Seção 40.3, “Preparação da imagem para ambientes conectados”): a primeira etapa é preparar o manifesto e os arquivos com todas as configurações necessárias aos ambientes conectados.
Estrutura de diretórios para ambientes conectados (Seção 40.3.1, “Estrutura de diretórios”): esta etapa cria uma estrutura de diretórios que o Edge Image Builder usará para armazenar os arquivos de configuração e a própria imagem.
Arquivo de definição do cluster de gerenciamento (Seção 40.3.2, “Arquivo de definição do cluster de gerenciamento”): o
mgmt-cluster.yaml
é o principal arquivo de definição do cluster de gerenciamento. Ele inclui as seguintes informações sobre a imagem que será criada:Informações da imagem: as informações relacionadas à imagem que será criada usando a imagem base.
Sistema operacional: a configuração do sistema operacional que será usada na imagem.
Kubernetes: repositórios e gráficos Helm, versão do kubernetes, configuração de rede e os nós que serão usados no cluster.
Pasta custom (Seção 40.3.3, “Pasta custom”): a pasta
custom
contém os arquivos de configuração e os scripts que o Edge Image Builder usará para implantar um cluster totalmente funcional.Arquivos: contêm os arquivos de configuração que serão usados pelo cluster de gerenciamento.
Scripts: contêm os scripts que serão usados pelo cluster de gerenciamento.
Pasta kubernetes (Seção 40.3.4, “Pasta kubernetes”): a pasta
kubernetes
contém os arquivos de configuração que serão usados pelo cluster de gerenciamento.Manifestos: contêm os manifestos que serão usados pelo cluster de gerenciamento.
Helm: contém os arquivos de valores do Helm que serão usados pelo cluster de gerenciamento.
Config: contém os arquivos de configuração que serão usados pelo cluster de gerenciamento.
Pasta network (Seção 40.3.5, “Pasta de rede”): a pasta
network
contém os arquivos de configuração de rede que serão usados pelos nós do cluster de gerenciamento.
Preparação da imagem para ambientes air-gapped (Seção 40.4, “Preparação da imagem para ambientes air-gapped”): a etapa mostra as diferenças para preparar os manifestos e os arquivos que serão usados em um cenário air-gapped.
Modificações no arquivo de definição (Seção 40.4.1, “Modificações no arquivo de definição”): o arquivo
mgmt-cluster.yaml
deve ser modificado para incluir a seçãoembeddedArtifactRegistry
com o campoimages
definido para que todas as imagens do contêiner sejam incluídas na imagem de saída do EIB.Modificações na pasta custom (Seção 40.4.2, “Modificações na pasta custom”): a pasta
custom
deve ser modificada para incluir os recursos necessários para executar o cluster de gerenciamento em um ambiente air-gapped.Script de registro: o script
custom/scripts/99-register.sh
deve ser removido quando você usa um ambiente air-gapped.
Modificações na pasta de valores do Helm (Seção 40.4.3, “Modificações na pasta de valores do Helm”): a pasta
helm/values
deve ser modificada para incluir a configuração necessária para executar o cluster de gerenciamento em um ambiente air-gapped.
Criação da imagem (Seção 40.5, “Criação de imagem”): esta etapa abrange a criação da imagem com a ferramenta Edge Image Builder (para os cenários tanto conectados quanto air-gapped). Consulte os pré-requisitos (Capítulo 11, Edge Image Builder) para executar a ferramenta Edge Image Builder no seu sistema.
Provisionamento do cluster de gerenciamento (Seção 40.6, “Provisionar o cluster de gerenciamento”): esta etapa aborda o provisionamento do cluster de gerenciamento usando a imagem criada na etapa anterior (para os cenários tanto conectados quanto air-gapped). Para executá-la, é possível usar um laptop, um servidor, uma VM ou qualquer outro sistema AMD64/Intel 64 com uma porta USB.
Para obter mais informações sobre o Edge Image Builder, consulte o respectivo guia (Capítulo 11, Edge Image Builder) e o Guia de Início Rápido (Capítulo 3, Clusters independentes com o Edge Image Builder).
40.3 Preparação da imagem para ambientes conectados #
O Edge Image Builder é usado para criar a imagem do cluster de gerenciamento. Neste documento, explicamos a configuração mínima necessária para configurar o cluster de gerenciamento.
O Edge Image Builder é executado dentro de um contêiner, portanto, um tempo de execução do contêiner é necessário, como Podman ou Rancher Desktop. Neste guia, consideramos que o podman esteja disponível.
Também como pré-requisito para implantar um cluster de gerenciamento altamente disponível, você precisa reservar três IPs na sua rede:
apiVIP
para o endereço VIP da API (usado para acessar o servidor da API Kubernetes).ingressVIP
para o endereço VIP de entrada (consumido pela IU do Rancher, por exemplo).metal3VIP
para o endereço VIP do Metal3.
40.3.1 Estrutura de diretórios #
Ao executar o EIB, um diretório é montado do host, portanto, a primeira etapa é criar uma estrutura de diretórios para o EIB usar para armazenar os arquivos de configuração e a própria imagem. Esse diretório tem a seguinte estrutura:
eib
├── mgmt-cluster.yaml
├── network
│ └── mgmt-cluster-node1.yaml
├── kubernetes
│ ├── manifests
│ │ ├── rke2-ingress-config.yaml
│ │ ├── neuvector-namespace.yaml
│ │ ├── ingress-l2-adv.yaml
│ │ └── ingress-ippool.yaml
│ ├── helm
│ │ └── values
│ │ ├── rancher.yaml
│ │ ├── neuvector.yaml
│ │ ├── metal3.yaml
│ │ └── certmanager.yaml
│ └── config
│ └── server.yaml
├── custom
│ ├── scripts
│ │ ├── 99-register.sh
│ │ ├── 99-mgmt-setup.sh
│ │ └── 99-alias.sh
│ └── files
│ ├── rancher.sh
│ ├── mgmt-stack-setup.service
│ ├── metal3.sh
│ └── basic-setup.sh
└── base-images
É necessário fazer download da imagem
SL-Micro.x86_64-6.1-Base-SelfInstall-GM.install.iso
do
SUSE Customer Center ou da
página de downloads
da SUSE e salvá-la na pasta base-images
.
Confira o checksum SHA256 da imagem para garantir que ela não tenha sido adulterada. O checksum está no mesmo local em que a imagem foi baixada.
Há um exemplo da estrutura de diretórios disponível no repositório SUSE Edge do GitHub na pasta "telco-examples".
40.3.2 Arquivo de definição do cluster de gerenciamento #
O mgmt-cluster.yaml
é o principal arquivo de definição do
cluster de gerenciamento. Ele contém as seguintes informações:
apiVersion: 1.2
image:
imageType: iso
arch: x86_64
baseImage: SL-Micro.x86_64-6.1-Base-SelfInstall-GM.install.iso
outputImageName: eib-mgmt-cluster-image.iso
operatingSystem:
isoConfiguration:
installDevice: /dev/sda
users:
- username: root
encryptedPassword: $ROOT_PASSWORD
packages:
packageList:
- git
- jq
sccRegistrationCode: $SCC_REGISTRATION_CODE
kubernetes:
version: v1.32.4+rke2r1
helm:
charts:
- name: cert-manager
repositoryName: jetstack
version: 1.15.3
targetNamespace: cert-manager
valuesFile: certmanager.yaml
createNamespace: true
installationNamespace: kube-system
- name: longhorn-crd
version: 106.2.0+up1.8.1
repositoryName: rancher-charts
targetNamespace: longhorn-system
createNamespace: true
installationNamespace: kube-system
- name: longhorn
version: 106.2.0+up1.8.1
repositoryName: rancher-charts
targetNamespace: longhorn-system
createNamespace: true
installationNamespace: kube-system
- name: metal3
version: 303.0.7+up0.11.5
repositoryName: suse-edge-charts
targetNamespace: metal3-system
createNamespace: true
installationNamespace: kube-system
valuesFile: metal3.yaml
- name: rancher-turtles
version: 303.0.4+up0.20.0
repositoryName: suse-edge-charts
targetNamespace: rancher-turtles-system
createNamespace: true
installationNamespace: kube-system
- name: neuvector-crd
version: 106.0.1+up2.8.6
repositoryName: rancher-charts
targetNamespace: neuvector
createNamespace: true
installationNamespace: kube-system
valuesFile: neuvector.yaml
- name: neuvector
version: 106.0.1+up2.8.6
repositoryName: rancher-charts
targetNamespace: neuvector
createNamespace: true
installationNamespace: kube-system
valuesFile: neuvector.yaml
- name: rancher
version: 2.11.2
repositoryName: rancher-prime
targetNamespace: cattle-system
createNamespace: true
installationNamespace: kube-system
valuesFile: rancher.yaml
repositories:
- name: jetstack
url: https://charts.jetstack.io
- name: rancher-charts
url: https://charts.rancher.io/
- name: suse-edge-charts
url: oci://registry.suse.com/edge/charts
- name: rancher-prime
url: https://charts.rancher.com/server-charts/prime
network:
apiHost: $API_HOST
apiVIP: $API_VIP
nodes:
- hostname: mgmt-cluster-node1
initializer: true
type: server
# - hostname: mgmt-cluster-node2
# type: server
# - hostname: mgmt-cluster-node3
# type: server
Para explicar os campos e os valores no arquivo de definição
mgmt-cluster.yaml
, dividimos esse arquivo nas seções a
seguir.
Seção da imagem (arquivo de definição):
image:
imageType: iso
arch: x86_64
baseImage: SL-Micro.x86_64-6.1-Base-SelfInstall-GM.install.iso
outputImageName: eib-mgmt-cluster-image.iso
em que baseImage
é a imagem original que você baixou do
SUSE Customer Center ou da página de downloads da
SUSE. outputImageName
é o nome da nova imagem que será
usada para provisionar o cluster de gerenciamento.
Seção do sistema operacional (arquivo de definição):
operatingSystem:
isoConfiguration:
installDevice: /dev/sda
users:
- username: root
encryptedPassword: $ROOT_PASSWORD
packages:
packageList:
- jq
sccRegistrationCode: $SCC_REGISTRATION_CODE
em que installDevice
é o dispositivo usado para instalar
o sistema operacional, username
e
encryptedPassword
são as credenciais usadas para acessar
o sistema, packageList
é a lista dos pacotes que devem
ser instalados (jq
é obrigatório internamente durante o
processo de instalação) e sccRegistrationCode
é o código
de registro usado para obter os pacotes e as dependências no momento da
criação e pode ser recuperado do SUSE Customer Center. É possível gerar a
senha criptografada usando o comando openssl
da seguinte
maneira:
openssl passwd -6 MyPassword!123
A saída é similar a esta:
$6$UrXB1sAGs46DOiSq$HSwi9GFJLCorm0J53nF2Sq8YEoyINhHcObHzX2R8h13mswUIsMwzx4eUzn/rRx0QPV4JIb0eWCoNrxGiKH4R31
Seção do Kubernetes (arquivo de definição):
kubernetes:
version: v1.32.4+rke2r1
helm:
charts:
- name: cert-manager
repositoryName: jetstack
version: 1.15.3
targetNamespace: cert-manager
valuesFile: certmanager.yaml
createNamespace: true
installationNamespace: kube-system
- name: longhorn-crd
version: 106.2.0+up1.8.1
repositoryName: rancher-charts
targetNamespace: longhorn-system
createNamespace: true
installationNamespace: kube-system
- name: longhorn
version: 106.2.0+up1.8.1
repositoryName: rancher-charts
targetNamespace: longhorn-system
createNamespace: true
installationNamespace: kube-system
- name: metal3
version: 303.0.7+up0.11.5
repositoryName: suse-edge-charts
targetNamespace: metal3-system
createNamespace: true
installationNamespace: kube-system
valuesFile: metal3.yaml
- name: rancher-turtles
version: 303.0.4+up0.20.0
repositoryName: suse-edge-charts
targetNamespace: rancher-turtles-system
createNamespace: true
installationNamespace: kube-system
- name: neuvector-crd
version: 106.0.1+up2.8.6
repositoryName: rancher-charts
targetNamespace: neuvector
createNamespace: true
installationNamespace: kube-system
valuesFile: neuvector.yaml
- name: neuvector
version: 106.0.1+up2.8.6
repositoryName: rancher-charts
targetNamespace: neuvector
createNamespace: true
installationNamespace: kube-system
valuesFile: neuvector.yaml
- name: rancher
version: 2.11.2
repositoryName: rancher-prime
targetNamespace: cattle-system
createNamespace: true
installationNamespace: kube-system
valuesFile: rancher.yaml
repositories:
- name: jetstack
url: https://charts.jetstack.io
- name: rancher-charts
url: https://charts.rancher.io/
- name: suse-edge-charts
url: oci://registry.suse.com/edge/charts
- name: rancher-prime
url: https://charts.rancher.com/server-charts/prime
network:
apiHost: $API_HOST
apiVIP: $API_VIP
nodes:
- hostname: mgmt-cluster-node1
initializer: true
type: server
# - hostname: mgmt-cluster-node2
# type: server
# - hostname: mgmt-cluster-node3
# type: server
A seção helm
contém a lista de gráficos Helm para
instalação, os repositórios que serão usados e a configuração da versão de
todos eles.
A seção network
contém a configuração da rede, como o
apiHost
e o apiVIP
que o componente
RKE2
usará. O apiVIP
deve ser um
endereço IP não usado na rede e que não faça parte do pool DHCP (se DHCP for
usado). Além disso, quando usamos o apiVIP
em um cluster
de vários nós, ele é usado para acessar o servidor da API Kubernetes. O
apiHost
é a resolução de nome para o
apiVIP
que o componente RKE2
usará.
A seção nodes
contém a lista dos nós usados no
cluster. Neste exemplo, usamos um cluster de nó único, mas é possível
estendê-lo para um cluster de vários nós adicionando nós à lista (removendo
o marcador de comentário das linhas).
Os nomes dos nós devem ser exclusivos no cluster.
Se preferir, use o campo
initializer
para especificar o host de inicialização; do contrário, ele será o primeiro nó da lista.Os nomes dos nós devem ser iguais aos nomes de host definidos na pasta de rede (Seção 40.3.5, “Pasta de rede”) quando a configuração de rede é obrigatória.
40.3.3 Pasta custom #
A pasta custom
contém as seguintes subpastas:
...
├── custom
│ ├── scripts
│ │ ├── 99-register.sh
│ │ ├── 99-mgmt-setup.sh
│ │ └── 99-alias.sh
│ └── files
│ ├── rancher.sh
│ ├── mgmt-stack-setup.service
│ ├── metal3.sh
│ └── basic-setup.sh
...
A pasta
custom/files
contém os arquivos de configuração usados pelo cluster de gerenciamento.A pasta
custom/scripts
contém os scripts usados pelo cluster de gerenciamento.
A pasta custom/files
contém os seguintes arquivos:
basic-setup.sh
: inclui os parâmetros de configuração paraMetal3
,Rancher
eMetalLB
. Modifique esse arquivo apenas para alterar os namespaces usados.#!/bin/bash # Pre-requisites. Cluster already running export KUBECTL="/var/lib/rancher/rke2/bin/kubectl" export KUBECONFIG="/etc/rancher/rke2/rke2.yaml" ################## # METAL3 DETAILS # ################## export METAL3_CHART_TARGETNAMESPACE="metal3-system" ########### # METALLB # ########### export METALLBNAMESPACE="metallb-system" ########### # RANCHER # ########### export RANCHER_CHART_TARGETNAMESPACE="cattle-system" export RANCHER_FINALPASSWORD="adminadminadmin" die(){ echo ${1} 1>&2 exit ${2} }
metal3.sh
: inclui a configuração para o componenteMetal3
usado (sem necessidade de modificação). Em versões futuras, esse script será usado no lugar doRancher Turtles
para facilitar o uso.#!/bin/bash set -euo pipefail BASEDIR="$(dirname "$0")" source ${BASEDIR}/basic-setup.sh METAL3LOCKNAMESPACE="default" METAL3LOCKCMNAME="metal3-lock" trap 'catch $? $LINENO' EXIT catch() { if [ "$1" != "0" ]; then echo "Error $1 occurred on $2" ${KUBECTL} delete configmap ${METAL3LOCKCMNAME} -n ${METAL3LOCKNAMESPACE} fi } # Get or create the lock to run all those steps just in a single node # As the first node is created WAY before the others, this should be enough # TODO: Investigate if leases is better if [ $(${KUBECTL} get cm -n ${METAL3LOCKNAMESPACE} ${METAL3LOCKCMNAME} -o name | wc -l) -lt 1 ]; then ${KUBECTL} create configmap ${METAL3LOCKCMNAME} -n ${METAL3LOCKNAMESPACE} --from-literal foo=bar else exit 0 fi # Wait for metal3 while ! ${KUBECTL} wait --for condition=ready -n ${METAL3_CHART_TARGETNAMESPACE} $(${KUBECTL} get pods -n ${METAL3_CHART_TARGETNAMESPACE} -l app.kubernetes.io/name=metal3-ironic -o name) --timeout=10s; do sleep 2 ; done # Get the ironic IP IRONICIP=$(${KUBECTL} get cm -n ${METAL3_CHART_TARGETNAMESPACE} ironic-bmo -o jsonpath='{.data.IRONIC_IP}') # If LoadBalancer, use metallb, else it is NodePort if [ $(${KUBECTL} get svc -n ${METAL3_CHART_TARGETNAMESPACE} metal3-metal3-ironic -o jsonpath='{.spec.type}') == "LoadBalancer" ]; then # Wait for metallb while ! ${KUBECTL} wait --for condition=ready -n ${METALLBNAMESPACE} $(${KUBECTL} get pods -n ${METALLBNAMESPACE} -l app.kubernetes.io/component=controller -o name) --timeout=10s; do sleep 2 ; done # Do not create the ippool if already created ${KUBECTL} get ipaddresspool -n ${METALLBNAMESPACE} ironic-ip-pool -o name || cat <<-EOF | ${KUBECTL} apply -f - apiVersion: metallb.io/v1beta1 kind: IPAddressPool metadata: name: ironic-ip-pool namespace: ${METALLBNAMESPACE} spec: addresses: - ${IRONICIP}/32 serviceAllocation: priority: 100 serviceSelectors: - matchExpressions: - {key: app.kubernetes.io/name, operator: In, values: [metal3-ironic]} EOF # Same for L2 Advs ${KUBECTL} get L2Advertisement -n ${METALLBNAMESPACE} ironic-ip-pool-l2-adv -o name || cat <<-EOF | ${KUBECTL} apply -f - apiVersion: metallb.io/v1beta1 kind: L2Advertisement metadata: name: ironic-ip-pool-l2-adv namespace: ${METALLBNAMESPACE} spec: ipAddressPools: - ironic-ip-pool EOF fi # If rancher is deployed if [ $(${KUBECTL} get pods -n ${RANCHER_CHART_TARGETNAMESPACE} -l app=rancher -o name | wc -l) -ge 1 ]; then cat <<-EOF | ${KUBECTL} apply -f - apiVersion: management.cattle.io/v3 kind: Feature metadata: name: embedded-cluster-api spec: value: false EOF # Disable Rancher webhooks for CAPI ${KUBECTL} delete --ignore-not-found=true mutatingwebhookconfiguration.admissionregistration.k8s.io mutating-webhook-configuration ${KUBECTL} delete --ignore-not-found=true validatingwebhookconfigurations.admissionregistration.k8s.io validating-webhook-configuration ${KUBECTL} wait --for=delete namespace/cattle-provisioning-capi-system --timeout=300s fi # Clean up the lock cm ${KUBECTL} delete configmap ${METAL3LOCKCMNAME} -n ${METAL3LOCKNAMESPACE}
rancher.sh
: inclui a configuração para o componenteRancher
usado (sem necessidade de modificação).#!/bin/bash set -euo pipefail BASEDIR="$(dirname "$0")" source ${BASEDIR}/basic-setup.sh RANCHERLOCKNAMESPACE="default" RANCHERLOCKCMNAME="rancher-lock" if [ -z "${RANCHER_FINALPASSWORD}" ]; then # If there is no final password, then finish the setup right away exit 0 fi trap 'catch $? $LINENO' EXIT catch() { if [ "$1" != "0" ]; then echo "Error $1 occurred on $2" ${KUBECTL} delete configmap ${RANCHERLOCKCMNAME} -n ${RANCHERLOCKNAMESPACE} fi } # Get or create the lock to run all those steps just in a single node # As the first node is created WAY before the others, this should be enough # TODO: Investigate if leases is better if [ $(${KUBECTL} get cm -n ${RANCHERLOCKNAMESPACE} ${RANCHERLOCKCMNAME} -o name | wc -l) -lt 1 ]; then ${KUBECTL} create configmap ${RANCHERLOCKCMNAME} -n ${RANCHERLOCKNAMESPACE} --from-literal foo=bar else exit 0 fi # Wait for rancher to be deployed while ! ${KUBECTL} wait --for condition=ready -n ${RANCHER_CHART_TARGETNAMESPACE} $(${KUBECTL} get pods -n ${RANCHER_CHART_TARGETNAMESPACE} -l app=rancher -o name) --timeout=10s; do sleep 2 ; done until ${KUBECTL} get ingress -n ${RANCHER_CHART_TARGETNAMESPACE} rancher > /dev/null 2>&1; do sleep 10; done RANCHERBOOTSTRAPPASSWORD=$(${KUBECTL} get secret -n ${RANCHER_CHART_TARGETNAMESPACE} bootstrap-secret -o jsonpath='{.data.bootstrapPassword}' | base64 -d) RANCHERHOSTNAME=$(${KUBECTL} get ingress -n ${RANCHER_CHART_TARGETNAMESPACE} rancher -o jsonpath='{.spec.rules[0].host}') # Skip the whole process if things have been set already if [ -z $(${KUBECTL} get settings.management.cattle.io first-login -ojsonpath='{.value}') ]; then # Add the protocol RANCHERHOSTNAME="https://${RANCHERHOSTNAME}" TOKEN="" while [ -z "${TOKEN}" ]; do # Get token sleep 2 TOKEN=$(curl -sk -X POST ${RANCHERHOSTNAME}/v3-public/localProviders/local?action=login -H 'content-type: application/json' -d "{\"username\":\"admin\",\"password\":\"${RANCHERBOOTSTRAPPASSWORD}\"}" | jq -r .token) done # Set password curl -sk ${RANCHERHOSTNAME}/v3/users?action=changepassword -H 'content-type: application/json' -H "Authorization: Bearer $TOKEN" -d "{\"currentPassword\":\"${RANCHERBOOTSTRAPPASSWORD}\",\"newPassword\":\"${RANCHER_FINALPASSWORD}\"}" # Create a temporary API token (ttl=60 minutes) APITOKEN=$(curl -sk ${RANCHERHOSTNAME}/v3/token -H 'content-type: application/json' -H "Authorization: Bearer ${TOKEN}" -d '{"type":"token","description":"automation","ttl":3600000}' | jq -r .token) curl -sk ${RANCHERHOSTNAME}/v3/settings/server-url -H 'content-type: application/json' -H "Authorization: Bearer ${APITOKEN}" -X PUT -d "{\"name\":\"server-url\",\"value\":\"${RANCHERHOSTNAME}\"}" curl -sk ${RANCHERHOSTNAME}/v3/settings/telemetry-opt -X PUT -H 'content-type: application/json' -H 'accept: application/json' -H "Authorization: Bearer ${APITOKEN}" -d '{"value":"out"}' fi # Clean up the lock cm ${KUBECTL} delete configmap ${RANCHERLOCKCMNAME} -n ${RANCHERLOCKNAMESPACE}
mgmt-stack-setup.service
: contém a configuração para criar o serviço systemd para executar os scripts durante a primeira inicialização (nenhuma modificação é necessária).[Unit] Description=Setup Management stack components Wants=network-online.target # It requires rke2 or k3s running, but it will not fail if those services are not present After=network.target network-online.target rke2-server.service k3s.service # At least, the basic-setup.sh one needs to be present ConditionPathExists=/opt/mgmt/bin/basic-setup.sh [Service] User=root Type=forking # Metal3 can take A LOT to download the IPA image TimeoutStartSec=1800 ExecStartPre=/bin/sh -c "echo 'Setting up Management components...'" # Scripts are executed in StartPre because Start can only run a single one ExecStartPre=/opt/mgmt/bin/rancher.sh ExecStartPre=/opt/mgmt/bin/metal3.sh ExecStart=/bin/sh -c "echo 'Finished setting up Management components'" RemainAfterExit=yes KillMode=process # Disable & delete everything ExecStartPost=rm -f /opt/mgmt/bin/rancher.sh ExecStartPost=rm -f /opt/mgmt/bin/metal3.sh ExecStartPost=rm -f /opt/mgmt/bin/basic-setup.sh ExecStartPost=/bin/sh -c "systemctl disable mgmt-stack-setup.service" ExecStartPost=rm -f /etc/systemd/system/mgmt-stack-setup.service [Install] WantedBy=multi-user.target
A pasta custom/scripts
contém os seguintes arquivos:
Script
99-alias.sh
: contém o álias que o cluster de gerenciamento usa para carregar o arquivo kubeconfig na primeira inicialização (sem necessidade de modificação).#!/bin/bash echo "alias k=kubectl" >> /etc/profile.local echo "alias kubectl=/var/lib/rancher/rke2/bin/kubectl" >> /etc/profile.local echo "export KUBECONFIG=/etc/rancher/rke2/rke2.yaml" >> /etc/profile.local
Script
99-mgmt-setup.sh
: contém a configuração para copiar os scripts durante a primeira inicialização (sem necessidade de modificação).#!/bin/bash # Copy the scripts from combustion to the final location mkdir -p /opt/mgmt/bin/ for script in basic-setup.sh rancher.sh metal3.sh; do cp ${script} /opt/mgmt/bin/ done # Copy the systemd unit file and enable it at boot cp mgmt-stack-setup.service /etc/systemd/system/mgmt-stack-setup.service systemctl enable mgmt-stack-setup.service
Script
99-register.sh
: contém a configuração para registrar o sistema usando o código de registro do SCC. O${SCC_ACCOUNT_EMAIL}
e o${SCC_REGISTRATION_CODE}
devem ser devidamente definidos para registrar o sistema com a sua conta.#!/bin/bash set -euo pipefail # Registration https://www.suse.com/support/kb/doc/?id=000018564 if ! which SUSEConnect > /dev/null 2>&1; then zypper --non-interactive install suseconnect-ng fi SUSEConnect --email "${SCC_ACCOUNT_EMAIL}" --url "https://scc.suse.com" --regcode "${SCC_REGISTRATION_CODE}"
40.3.4 Pasta kubernetes #
A pasta kubernetes
contém as seguintes subpastas:
...
├── kubernetes
│ ├── manifests
│ │ ├── rke2-ingress-config.yaml
│ │ ├── neuvector-namespace.yaml
│ │ ├── ingress-l2-adv.yaml
│ │ └── ingress-ippool.yaml
│ ├── helm
│ │ └── values
│ │ ├── rancher.yaml
│ │ ├── neuvector.yaml
│ │ ├── metal3.yaml
│ │ └── certmanager.yaml
│ └── config
│ └── server.yaml
...
A pasta kubernetes/config
contém os seguintes arquivos:
server.yaml
: por padrão, o plug-in deCNI
instalado é oCilium
, portanto, você não precisa criar a pasta nem o arquivo. Caso seja necessário personalizar o plug-in deCNI
, use o arquivoserver.yaml
na pastakubernetes/config
, que contém as seguintes informações:cni: - multus - cilium
Esse é um arquivo opcional para definir personalizações do Kubernetes, como os plug-ins de CNI usados ou várias opções que você pode conferir na documentação oficial.
A pasta kubernetes/manifests
contém os seguintes
arquivos:
rke2-ingress-config.yaml
: contém a configuração para criar o serviçoIngress
para o cluster de gerenciamento (sem necessidade de modificação).apiVersion: helm.cattle.io/v1 kind: HelmChartConfig metadata: name: rke2-ingress-nginx namespace: kube-system spec: valuesContent: |- controller: config: use-forwarded-headers: "true" enable-real-ip: "true" publishService: enabled: true service: enabled: true type: LoadBalancer externalTrafficPolicy: Local
neuvector-namespace.yaml
: contém a configuração para criar o namespaceNeuVector
(sem necessidade de modificação).apiVersion: v1 kind: Namespace metadata: labels: pod-security.kubernetes.io/enforce: privileged name: neuvector
ingress-l2-adv.yaml
: contém a configuração para criar oL2Advertisement
para o componenteMetalLB
(sem necessidade de modificação).apiVersion: metallb.io/v1beta1 kind: L2Advertisement metadata: name: ingress-l2-adv namespace: metallb-system spec: ipAddressPools: - ingress-ippool
ingress-ippool.yaml
: contém a configuração para criar oIPAddressPool
para o componenterke2-ingress-nginx
. O${INGRESS_VIP}
deve ser definido apropriadamente para especificar o endereço IP reservado que o componenterke2-ingress-nginx
usará.apiVersion: metallb.io/v1beta1 kind: IPAddressPool metadata: name: ingress-ippool namespace: metallb-system spec: addresses: - ${INGRESS_VIP}/32 serviceAllocation: priority: 100 serviceSelectors: - matchExpressions: - {key: app.kubernetes.io/name, operator: In, values: [rke2-ingress-nginx]}
A pasta kubernetes/helm/values
contém os seguintes
arquivos:
rancher.yaml
: contém a configuração para criar o componenteRancher
. É necessário definir apropriadamente o${INGRESS_VIP}
para especificar o endereço IP que o componenteRancher
consumirá. O URL para acessar o componenteRancher
seráhttps://rancher-${INGRESS_VIP}.sslip.io
.hostname: rancher-${INGRESS_VIP}.sslip.io bootstrapPassword: "foobar" replicas: 1 global.cattle.psp.enabled: "false"
neuvector.yaml
: contém a configuração para criar o componenteNeuVector
(sem necessidade de modificação).controller: replicas: 1 ranchersso: enabled: true manager: enabled: false cve: scanner: enabled: false replicas: 1 k3s: enabled: true crdwebhook: enabled: false
metal3.yaml
: contém a configuração para criar o componenteMetal3
. É necessário definir apropriadamente o${METAL3_VIP}
para especificar o endereço IP que o componenteMetal3
consumirá.global: ironicIP: ${METAL3_VIP} enable_vmedia_tls: false additionalTrustedCAs: false metal3-ironic: global: predictableNicNames: "true" persistence: ironic: size: "5Gi"
Para implantar clusters downstream arm64 usando esse cluster de gerenciamento x86_64, você precisa adicionar a seguinte
deployArchitecture: arm64
à seçãoglobal
do arquivometal3.yaml
:global: ironicIP: ${METAL3_VIP} enable_vmedia_tls: false additionalTrustedCAs: false deployArchitecture: arm64 metal3-ironic: global: predictableNicNames: "true" persistence: ironic: size: "5Gi"
Na versão atual, existe uma limitação referente ao uso da
deployArchitecture: arm64
. Especificamente, se você
permitir a implantação de clusters downstream arm64 usando essa diretiva, o
cluster de gerenciamento apenas poderá implantar essa arquitetura no
futuro. Para implantar clusters nas duas arquiteturas (x86_64 e arm64),
provisione dois clusters de gerenciamento separados. Essa limitação será
removida em uma versão futura.
O servidor de mídia é um recurso opcional incluído no Metal3 (que está desabilitado por padrão). Para usar o recurso Metal3, configure-o no manifesto anterior. Para usar o servidor de mídia Metal3, especifique a seguinte variável:
adicione
enable_metal3_media_server
atrue
para habilitar o recurso de servidor de mídia na seção global.inclua a seguinte configuração sobre o servidor de mídia, em que ${MEDIA_VOLUME_PATH} é o caminho para o volume da mídia (por exemplo,
/home/metal3/bmh-image-cache
).metal3-media: mediaVolume: hostPath: ${MEDIA_VOLUME_PATH}
É possível usar um servidor de mídia externo para armazenar as imagens e, caso você queira usá-lo com TLS, precisará modificar as seguintes configurações:
defina
additionalTrustedCAs
comotrue
no arquivometal3.yaml
anterior para permitir as CAs confiáveis adicionais do servidor de mídia externo.inclua a seguinte configuração de segredo na pasta
kubernetes/manifests/metal3-cacert-secret.yaml
para armazenar o certificado CA do servidor de mídia externo.apiVersion: v1 kind: Namespace metadata: name: metal3-system --- apiVersion: v1 kind: Secret metadata: name: tls-ca-additional namespace: metal3-system type: Opaque data: ca-additional.crt: {{ additional_ca_cert | b64encode }}
O additional_ca_cert
é o certificado CA codificado em
base64 do servidor de mídia externo. É possível usar o seguinte comando para
codificar o certificado e gerar o segredo manualmente:
kubectl -n meta3-system create secret generic tls-ca-additional --from-file=ca-additional.crt=./ca-additional.crt
certmanager.yaml
: contém a configuração para criar o componenteCert-Manager
(sem necessidade de modificação).installCRDs: "true"
40.3.5 Pasta de rede #
A pasta network
contém o mesmo número de arquivos e nós
no cluster de gerenciamento. Em nosso caso, temos apenas um nó, portanto,
temos somente um arquivo chamado
mgmt-cluster-node1.yaml
. O nome do arquivo deve ser igual
ao nome de host especificado no arquivo de definição
mgmt-cluster.yaml
incluído na seção network/node descrita
acima.
Se você precisa personalizar a configuração de rede, por exemplo, para usar
um endereço IP estático específico (cenário sem DHCP), use o arquivo
mgmt-cluster-node1.yaml
na pasta
network
, que contém as seguintes informações:
${MGMT_GATEWAY}
: o endereço IP do gateway.${MGMT_DNS}
: o endereço IP do servidor DNS.${MGMT_MAC}
: o endereço MAC da interface de rede.${MGMT_NODE_IP}
: o endereço IP do cluster de gerenciamento.
routes:
config:
- destination: 0.0.0.0/0
metric: 100
next-hop-address: ${MGMT_GATEWAY}
next-hop-interface: eth0
table-id: 254
dns-resolver:
config:
server:
- ${MGMT_DNS}
- 8.8.8.8
interfaces:
- name: eth0
type: ethernet
state: up
mac-address: ${MGMT_MAC}
ipv4:
address:
- ip: ${MGMT_NODE_IP}
prefix-length: 24
dhcp: false
enabled: true
ipv6:
enabled: false
Para usar DHCP para obter o endereço IP, você pode definir a seguinte
configuração (o endereço MAC
deve ser devidamente
definido por meio da variável ${MGMT_MAC}
):
## This is an example of a dhcp network configuration for a management cluster
interfaces:
- name: eth0
type: ethernet
state: up
mac-address: ${MGMT_MAC}
ipv4:
dhcp: true
enabled: true
ipv6:
enabled: false
Dependendo do número de nós no cluster de gerenciamento, você poderá criar mais arquivos, como
mgmt-cluster-node2.yaml
,mgmt-cluster-node3.yaml
etc., para configurar o restante dos nós.A seção
routes
é usada para definir a tabela de roteamento para o cluster de gerenciamento.
40.4 Preparação da imagem para ambientes air-gapped #
Esta seção descreve como preparar a imagem para ambientes air-gapped mostrando apenas as diferenças das seções anteriores. As seguintes alterações na seção anterior (Preparação da imagem para ambientes conectados (Seção 40.3, “Preparação da imagem para ambientes conectados”)) são necessárias para preparar a imagem para os ambientes air-gapped:
É necessário modificar o arquivo
mgmt-cluster.yaml
para incluir a seçãoembeddedArtifactRegistry
com o campoimages
definido para que todas as imagens do contêiner sejam incluídas na imagem de saída do EIB.É necessário modificar o arquivo
mgmt-cluster.yaml
para incluir o gráfico Helmrancher-turtles-airgap-resources
.É necessário remover o script
custom/scripts/99-register.sh
ao usar um ambiente air-gapped.
40.4.1 Modificações no arquivo de definição #
É necessário modificar o arquivo mgmt-cluster.yaml
para
incluir a seção embeddedArtifactRegistry
. Nessa seção, o
campo images
deve conter a lista de todas as imagens do
contêiner que serão incluídas na imagem de saída.
Veja a seguir um exemplo do arquivo mgmt-cluster.yaml
com
a seção embeddedArtifactRegistry
incluída. Garanta que as
imagens listadas contenham as versões dos componentes necessárias.
É necessário também adicionar o gráfico Helm
rancher-turtles-airgap-resources
para criar os recursos
conforme descrito na documentação
do Rancher Turtles sobre ambientes air-gapped. Isso também requer um
arquivo de valores turtles.yaml para que o gráfico rancher-turtles
especifique a configuração necessária.
apiVersion: 1.2
image:
imageType: iso
arch: x86_64
baseImage: SL-Micro.x86_64-6.1-Base-SelfInstall-GM.install.iso
outputImageName: eib-mgmt-cluster-image.iso
operatingSystem:
isoConfiguration:
installDevice: /dev/sda
users:
- username: root
encryptedPassword: $ROOT_PASSWORD
packages:
packageList:
- jq
sccRegistrationCode: $SCC_REGISTRATION_CODE
kubernetes:
version: v1.32.4+rke2r1
helm:
charts:
- name: cert-manager
repositoryName: jetstack
version: 1.15.3
targetNamespace: cert-manager
valuesFile: certmanager.yaml
createNamespace: true
installationNamespace: kube-system
- name: longhorn-crd
version: 106.2.0+up1.8.1
repositoryName: rancher-charts
targetNamespace: longhorn-system
createNamespace: true
installationNamespace: kube-system
- name: longhorn
version: 106.2.0+up1.8.1
repositoryName: rancher-charts
targetNamespace: longhorn-system
createNamespace: true
installationNamespace: kube-system
- name: metal3
version: 303.0.7+up0.11.5
repositoryName: suse-edge-charts
targetNamespace: metal3-system
createNamespace: true
installationNamespace: kube-system
valuesFile: metal3.yaml
- name: rancher-turtles
version: 303.0.4+up0.20.0
repositoryName: suse-edge-charts
targetNamespace: rancher-turtles-system
createNamespace: true
installationNamespace: kube-system
valuesFile: turtles.yaml
- name: rancher-turtles-airgap-resources
version: 303.0.4+up0.20.0
repositoryName: suse-edge-charts
targetNamespace: rancher-turtles-system
createNamespace: true
installationNamespace: kube-system
- name: neuvector-crd
version: 106.0.1+up2.8.6
repositoryName: rancher-charts
targetNamespace: neuvector
createNamespace: true
installationNamespace: kube-system
valuesFile: neuvector.yaml
- name: neuvector
version: 106.0.1+up2.8.6
repositoryName: rancher-charts
targetNamespace: neuvector
createNamespace: true
installationNamespace: kube-system
valuesFile: neuvector.yaml
- name: rancher
version: 2.11.2
repositoryName: rancher-prime
targetNamespace: cattle-system
createNamespace: true
installationNamespace: kube-system
valuesFile: rancher.yaml
repositories:
- name: jetstack
url: https://charts.jetstack.io
- name: rancher-charts
url: https://charts.rancher.io/
- name: suse-edge-charts
url: oci://registry.suse.com/edge/charts
- name: rancher-prime
url: https://charts.rancher.com/server-charts/prime
network:
apiHost: $API_HOST
apiVIP: $API_VIP
nodes:
- hostname: mgmt-cluster-node1
initializer: true
type: server
# - hostname: mgmt-cluster-node2
# type: server
# - hostname: mgmt-cluster-node3
# type: server
# type: server
embeddedArtifactRegistry:
images:
- name: registry.suse.com/rancher/hardened-cluster-autoscaler:v1.9.0-build20241203
- name: registry.suse.com/rancher/hardened-cni-plugins:v1.6.2-build20250306
- name: registry.suse.com/rancher/hardened-coredns:v1.12.1-build20250401
- name: registry.suse.com/rancher/hardened-k8s-metrics-server:v0.7.2-build20250110
- name: registry.suse.com/rancher/hardened-multus-cni:v4.2.0-build20250326
- name: registry.suse.com/rancher/klipper-helm:v0.9.5-build20250306
- name: registry.suse.com/rancher/mirrored-cilium-cilium:v1.17.3
- name: registry.suse.com/rancher/mirrored-cilium-operator-generic:v1.17.3
- name: registry.suse.com/rancher/mirrored-longhornio-csi-attacher:v4.8.1
- name: registry.suse.com/rancher/mirrored-longhornio-csi-node-driver-registrar:v2.13.0
- name: registry.suse.com/rancher/mirrored-longhornio-csi-provisioner:v5.2.0
- name: registry.suse.com/rancher/mirrored-longhornio-csi-resizer:v1.13.2
- name: registry.suse.com/rancher/mirrored-longhornio-csi-snapshotter:v8.2.0
- name: registry.suse.com/rancher/mirrored-longhornio-livenessprobe:v2.15.0
- name: registry.suse.com/rancher/mirrored-longhornio-longhorn-engine:v1.8.1
- name: registry.suse.com/rancher/mirrored-longhornio-longhorn-instance-manager:v1.8.1
- name: registry.suse.com/rancher/mirrored-longhornio-longhorn-manager:v1.8.1
- name: registry.suse.com/rancher/mirrored-longhornio-longhorn-share-manager:v1.8.1
- name: registry.suse.com/rancher/mirrored-longhornio-longhorn-ui:v1.8.1
- name: registry.suse.com/rancher/mirrored-sig-storage-snapshot-controller:v8.2.0
- name: registry.suse.com/rancher/neuvector-compliance-config:1.0.5
- name: registry.suse.com/rancher/neuvector-controller:5.4.4
- name: registry.suse.com/rancher/neuvector-enforcer:5.4.4
- name: registry.suse.com/rancher/nginx-ingress-controller:v1.12.1-hardened3
- name: registry.rancher.com/rancher/cluster-api-addon-provider-fleet:v0.10.0
- name: registry.rancher.com/rancher/cluster-api-operator:v0.17.0
- name: registry.rancher.com/rancher/fleet-agent:v0.12.3
- name: registry.rancher.com/rancher/fleet:v0.12.3
- name: registry.rancher.com/rancher/hardened-node-feature-discovery:v0.15.7-build20250425
- name: registry.rancher.com/rancher/rancher-webhook:v0.7.2
- name: registry.rancher.com/rancher/rancher/turtles:v0.20.0
- name: registry.rancher.com/rancher/rancher:v2.11.2
- name: registry.rancher.com/rancher/shell:v0.4.1
- name: registry.rancher.com/rancher/system-upgrade-controller:v0.15.2
- name: registry.suse.com/rancher/cluster-api-controller:v1.9.5
- name: registry.suse.com/rancher/cluster-api-provider-metal3:v1.9.3
- name: registry.suse.com/rancher/cluster-api-provider-rke2-bootstrap:v0.16.1
- name: registry.suse.com/rancher/cluster-api-provider-rke2-controlplane:v0.16.1
- name: registry.suse.com/rancher/hardened-sriov-network-operator:v1.5.0-build20250425
- name: registry.suse.com/rancher/ip-address-manager:v1.9.4
- name: registry.rancher.com/rancher/kubectl:v1.32.2
40.4.2 Modificações na pasta custom #
É necessário remover o script
custom/scripts/99-register.sh
ao usar um ambiente air-gapped. Conforme você pode observar na estrutura de diretórios, o script99-register.sh
não está incluído na pastacustom/scripts
.
40.4.3 Modificações na pasta de valores do Helm #
O
turtles.yaml
: contém a configuração necessária para especificar a operação air-gapped para o Rancher Turtles. Observe que isso depende da instalação do gráfico rancher-turtles-airgap-resources.cluster-api-operator: cluster-api: core: fetchConfig: selector: "{\"matchLabels\": {\"provider-components\": \"core\"}}" rke2: bootstrap: fetchConfig: selector: "{\"matchLabels\": {\"provider-components\": \"rke2-bootstrap\"}}" controlPlane: fetchConfig: selector: "{\"matchLabels\": {\"provider-components\": \"rke2-control-plane\"}}" metal3: infrastructure: fetchConfig: selector: "{\"matchLabels\": {\"provider-components\": \"metal3\"}}"
40.5 Criação de imagem #
Depois que a estrutura de diretórios foi preparada de acordo com as seções anteriores (para os cenários tanto conectados quanto air-gapped), execute o comando abaixo 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 mgmt-cluster.yaml
Isso cria o arquivo de imagem ISO de saída que, com base na definição da
imagem descrita acima, no nosso caso é
eib-mgmt-cluster-image.iso
.
40.6 Provisionar o cluster de gerenciamento #
A imagem anterior contém todos os componentes explicados acima e pode ser usada para provisionar o cluster de gerenciamento usando uma máquina virtual ou um servidor bare metal (com o recurso de mídia virtual).