|Index|SUSE Telco Cloud Documentação
SUSE Telco Cloud 3.6

SUSE Telco Cloud Documentação

Data de Publicação: 2026-05-27

SUSE Telco Cloud 3.6 Documentação

Bem-vindo à SUSE Telco Cloud documentação. Você encontrará a visão geral arquitetônica de alto nível, guias de início rápido, designs validados, orientação sobre uso de componentes, integrações de terceiros e melhores práticas para gerenciar sua infraestrutura de computação distribuída e cargas de trabalho.

1 O que é o comando SUSE Telco Cloud?

SUSE Telco Cloud é uma plataforma de computação otimizada para telecomunicações que permite que operadoras de telecomunicações e fornecedores de redes de telecomunicações inovem e acelerem a modernização de suas redes.

SUSE Telco Cloud é uma pilha nativa de nuvem completa habilitada para telecomunicações para hospedar CNFs, cobrindo todos os domínios de telecomunicações: Packet Core, RAN, OSS e BSS.

  • Automatiza a implantação zero-touch e o gerenciamento do ciclo de vida de configurações complexas de pilha de computação distribuída em escala de telecomunicações.

  • Garante continuamente a qualidade em hardware de nível de telecomunicações, usando configurações e cargas de trabalho específicas para telecomunicações.

  • Consiste em componentes criados especificamente para computação distribuída e, portanto, possuem menor pegada e maior desempenho por watt.

  • Mantém uma estratégia de plataforma flexível com APIs neutras em relação ao fornecedor e 100% de código aberto.

2 Filosofia de Design

A solução foi projetada com a noção de que não existe uma plataforma de computação distribuída de "tamanho único" devido aos requisitos e expectativas amplamente variados dos clientes. As implantações de computação distribuída nos levam a resolver, e evoluir continuamente, alguns dos problemas mais desafiadores, incluindo escalabilidade massiva, disponibilidade de rede restrita, restrições de espaço físico, novas ameaças de segurança e vetores de ataque, variações na arquitetura de hardware e recursos do sistema, a necessidade de implantar e interagir com infraestrutura e aplicativos legados, e soluções de clientes que possuem vida útil estendida. Como muitos desses desafios são diferentes das formas tradicionais de pensar, por exemplo, a implantação de infraestrutura e aplicações em data centers ou na nuvem pública, precisamos analisar o design com muito mais detalhes granulares e repensar muitas suposições comuns.

Por exemplo, encontramos valor no minimalismo, na modularidade e na facilidade de operações. O minimalismo é importante para ambientes de computação distribuída, já que quanto mais complexo um sistema é, maior a probabilidade de falha. Ao observar centenas de locais, até centenas de milhares, sistemas complexos falharão de maneiras complexas. A modularidade em nossa solução permite mais escolha do usuário, ao mesmo tempo em que remove a complexidade desnecessária na plataforma implantada. Também precisamos equilibrar isso com a facilidade de operações. Os humanos podem cometer erros ao repetir um processo milhares de vezes, portanto, a plataforma deve garantir que quaisquer erros potenciais sejam recuperáveis, eliminando a necessidade de visitas de técnicos ao local, mas também se esforçar pela consistência e padronização.

3 Arquitetura de alto nível

A arquitetura de alto nível do sistema do SUSE Telco Cloud é dividida em duas categorias principais, a saber, clusters de "gerenciamento" e "downstream". O cluster de gerenciamento é responsável pelo gerenciamento remoto de um ou mais clusters downstream, embora seja reconhecido que, em certas circunstâncias, os clusters downstream precisam operar sem gerenciamento remoto, por exemplo, em situações em que um local de borda não tem conectividade externa e precisa operar de forma independente. No SUSE Telco Cloud, os componentes técnicos utilizados para a operação dos clusters de gerenciamento e downstream são amplamente comuns, embora provavelmente se diferenciem tanto nas especificações do sistema quanto nas aplicações que residem sobre eles; ou seja, o cluster de gerenciamento executa aplicações que permitem o gerenciamento de sistemas e operações do ciclo de vida, enquanto os clusters downstream atendem aos requisitos para servir aplicações de usuário.

3.1 Componentes usados no SUSE Telco Cloud

O SUSE Telco Cloud é composto por componentes existentes da SUSE e do Rancher, juntamente com recursos e componentes adicionais criados pela equipe de computação distribuída para nos permitir abordar as restrições e complexidades necessárias na computação distribuída. Os componentes usados tanto no cluster de gerenciamento quanto nos clusters downstream são explicados abaixo, com um diagrama de arquitetura de alto nível simplificado, observando que esta não é uma lista exaustiva:

3.1.1 Cluster de gerenciamento

suse edge management cluster
  • Gerenciamento: Esta é a parte centralizada do SUSE Telco Cloud que é usada para gerenciar o provisionamento e o ciclo de vida dos clusters downstream conectados. O cluster de gerenciamento normalmente inclui os seguintes componentes:

    • Gerenciamento de múltiplos clusters com Rancher Prime (Capítulo 6, Rancher), permitindo um painel comum para integração de clusters downstream e gerenciamento contínuo do ciclo de vida de VMs de infraestrutura e aplicações, também fornecendo isolamento abrangente de locatários e integrações de IDP (Provedor de Identidade), um grande marketplace de integrações e extensões de terceiros e uma API neutra em relação ao fornecedor.

    • Gerenciamento de sistemas Linux com SUSE Multi-Linux Manager, permitindo o gerenciamento automatizado de patches e configurações do sistema operacional Linux subjacente (*SUSE Linux Micro (Capítulo 10, SUSE Linux Micro)) que é executado nos clusters downstream. Observe que, embora este componente seja conteinerizado, ele atualmente precisa ser executado em um sistema separado do restante dos componentes de gerenciamento, sendo, portanto, rotulado como "Gerenciamento de Linux" no diagrama acima.

    • Um controlador dedicado de Gerenciamento de Ciclo de Vida (Capítulo 21, Upgrade Controller) que lida com fazer upgrade dos componentes do cluster de gerenciamento para uma determinada versão SUSE Telco Cloud.

    • Um suporte opcional de ciclo de vida e gerenciamento completo de bare-metal com Metal3 (Capítulo 11, Metal3), MetalLB (Capítulo 17, MetalLB) e provedores de infraestrutura CAPI (Cluster API), permitindo o provisionamento completo de ponta a ponta de sistemas bare-metal que possuem recursos de gerenciamento remoto.

    • Um mecanismo GitOps opcional chamado Fleet (Capítulo 9, Fleet) para gerenciar o provisionamento e o ciclo de vida de clusters downstream e as aplicações que residem neles.

    • A base do cluster de gerenciamento em si é o SUSE Linux Micro (Capítulo 10, SUSE Linux Micro) como sistema operacional base e o RKE2 (Capítulo 14, RKE2) como a distribuição Kubernetes que suporta as aplicações do cluster de gerenciamento.

3.1.2 Clusters downstream

suse edge downstream cluster
  • Downstream: Esta é a parte distribuída do SUSE Telco Cloud que é usada para executar as cargas de trabalho dos usuários na computação distribuída, ou seja, o software que é executado no próprio local de computação distribuída, e é tipicamente composto pelos seguintes componentes:

    • RKE2, uma distribuição Kubernetes reforçada e certificada, otimizada para uso em governo e setores regulamentados

    • SUSE Security (Capítulo 16, SUSE Security) para habilitar recursos de segurança como verificação de vulnerabilidade de imagem, inspeção profunda de pacotes e proteção contra ameaças e vulnerabilidades em tempo real.

    • Armazenamento em blocos de software com SUSE Storage (Capítulo 15, SUSE Storage) para habilitar armazenamento em blocos persistente, resiliente e escalável de forma leve.

    • Um sistema operacional Linux leve, otimizado para contêineres e reforçado com SUSE Linux Micro (Capítulo 10, SUSE Linux Micro), fornecendo um SO imutável e altamente resiliente para executar contêineres e máquinas virtuais na borda. O SUSE Linux Micro está disponível para arquiteturas AArch64 e AMD64/Intel 64, e também oferece suporte a Real-Time Kernel para aplicações sensíveis à latência (por exemplo, casos de uso de telecomunicações).

    • Para clusters conectados (ou seja, aqueles que possuem conectividade com o cluster de gerenciamento), dois agentes são implantados, nomeadamente o Rancher System Agent para gerenciar a conectividade com o Rancher Prime, e o venv-salt-minion para receber instruções do SUSE Multi-Linux Manager para aplicar atualizações de software Linux. Esses agentes não são necessários para o gerenciamento de clusters desconectados.

3.2 Conectividade

suse edge connected architecture

A imagem acima fornece uma visão geral arquitetônica de alto nível para clusters downstream conectados e sua conexão ao cluster de gerenciamento. O cluster de gerenciamento pode ser implantado em uma ampla variedade de plataformas de infraestrutura subjacentes, tanto em capacidades no local quanto em nuvem, dependendo da disponibilidade de rede entre os clusters downstream e o cluster de gerenciamento de destino. O único requisito para que isso funcione é que a API e as URLs de retorno sejam acessíveis pela rede que conecta os nós do cluster downstream à infraestrutura de gerenciamento.

É importante reconhecer que existem mecanismos distintos nos quais essa conectividade é estabelecida em relação ao mecanismo de implantação do cluster downstream. Os detalhes disso são explicados com muito mais profundidade na próxima seção, mas para estabelecer uma compreensão básica, existem três mecanismos principais para que clusters downstream conectados sejam estabelecidos como um cluster "gerenciado":

  1. Os clusters downstream são implantados em uma capacidade "desconectada" no início (por exemplo, via Edge Image Builder (Capítulo 12, Edge Image Builder)) e, em seguida, são importados para o cluster de gerenciamento se/quando a conectividade permitir.

  2. Os clusters downstream são configurados para utilizar o mecanismo de onboarding incorporado. e eles se registram automaticamente no cluster de gerenciamento na primeira inicialização, permitindo a vinculação tardia da configuração do cluster.

  3. Os clusters downstream foram provisionados com os recursos de gerenciamento bare metal (CAPI + Metal3) e são importados automaticamente para o cluster de gerenciamento assim que o cluster é implantado e configurado (via operador Rancher Turtles).

Nota
Nota

Recomenda-se que vários clusters de gerenciamento sejam implementados para acomodar a escala de grandes implantações, otimizar as questões de largura de banda e latência em ambientes geograficamente dispersos e minimizar a interrupção no caso de uma falha ou upgrade do cluster de gerenciamento. Você pode encontrar os limites atuais de escalabilidade do cluster de gerenciamento e os requisitos do sistema aqui.

4 Padrões comuns de implantação de borda

Devido ao conjunto variável de ambientes operacionais e requisitos de ciclo de vida, implementamos suporte para vários padrões de implantação distintos que se alinham vagamente aos segmentos de mercado e casos de uso em que o SUSE Telco Cloud opera. Documentamos um guia de início rápido para cada um desses padrões de implantação para ajudá-lo a se familiarizar com a plataforma SUSE Telco Cloud com base em suas necessidades. Os três padrões de implantação que suportamos hoje estão descritos abaixo, com um link para a respectiva página de início rápido.

4.1 Provisionamento de rede direcionado

O provisionamento de rede direcionado ocorre quando você conhece os detalhes do hardware no qual deseja implantar e tem acesso direto à interface de gerenciamento fora de banda para orquestrar e automatizar todo o processo de provisionamento. Neste cenário, nossos clientes esperam que uma solução seja capaz de provisionar locais de borda de forma totalmente automatizada a partir de um local centralizado, indo muito além da criação de uma imagem de inicialização ao minimizar as operações manuais no local de borda; basta montar no rack, ligar e conectar as redes necessárias ao hardware físico, e o processo de automação liga a máquina via gerenciamento fora de banda (por exemplo, via API Redfish) e lida com o provisionamento, onboarding e implantação da infraestrutura sem intervenção do usuário. A chave para que isso funcione é que os sistemas sejam conhecidos pelos administradores; eles sabem qual hardware está em qual local, e que a implantação deve ser tratada centralmente.

Esta solução é a mais robusta, pois você está interagindo diretamente com a interface de gerenciamento do hardware, lidando com hardware conhecido e tendo menos restrições quanto à disponibilidade da rede. Em termos de funcionalidade, esta solução utiliza extensivamente o Cluster API e o Metal3 para provisionamento automatizado desde o bare metal, passando pelo sistema operacional, Kubernetes e aplicativos em camadas, e oferece a capacidade de vincular ao restante dos recursos comuns de gerenciamento de ciclo de vida do SUSE Telco Cloud pós-implantação. O início rápido para esta solução pode ser encontrado em Capítulo 4, Implantações automatizadas de BMC com Metal3.

4.2 Provisionamento baseado em imagem

Para clientes que precisam operar em ambientes autônomos, isolados (air-gapped) ou com rede limitada, o SUSE Telco Cloud fornece uma solução que permite aos clientes gerar mídia de instalação totalmente personalizada que contém todos os artefatos de implantação necessários para habilitar clusters Kubernetes de alta disponibilidade de nó único e multi-nó na borda, incluindo quaisquer cargas de trabalho ou componentes em camadas adicionais necessários, tudo sem qualquer conectividade de rede com o mundo exterior e sem a intervenção de uma plataforma de gerenciamento centralizada. A experiência do usuário segue de perto a solução "phone home", na qual a mídia de instalação é fornecida aos sistemas de destino, mas a solução fará o "bootstrap in-place". Neste cenário, é possível anexar os clusters resultantes ao Rancher para gerenciamento contínuo (ou seja, passar de um modo de operação "desconectado" para "conectado" sem grandes reconfigurações ou reimplantações), ou continuar operando isoladamente. Observe que, em ambos os casos, o mesmo mecanismo consistente para automatizar operações de ciclo de vida pode ser aplicado.

Além disso, esta solução pode ser usada para criar rapidamente clusters de gerenciamento que podem hospedar a infraestrutura centralizada que suporta tanto os modelos de "provisionamento de rede direcionado" quanto de "provisionamento de rede phone home", pois pode ser a maneira mais rápida e simples de provisionar todos os tipos de infraestrutura de Borda. Esta solução utiliza intensamente os recursos do SUSE Telco Cloud Image Builder para criar mídia de instalação totalmente personalizada e autônoma; o guia de início rápido pode ser encontrado em Capítulo 5, Clusters autônomos com o Edge Image Builder.

5 SUSE Telco Cloud Validação de Pilha

Todas as versões do SUSE Telco Cloud compreendem componentes fortemente integrados e completamente validados que são versionados como um só. Como parte dos esforços de integração contínua e validação de pilha que não apenas testam a integração entre os componentes, mas garantem que o sistema funcione conforme o esperado em cenários de falha forçada, a equipe do SUSE Telco Cloud publica todos os testes realizados e os resultados publicamente. Os resultados, juntamente com todos os parâmetros de entrada, podem ser encontrados em ci.edge.suse.com.

6 Lista Completa de Componentes

A lista completa de componentes, juntamente com um link para uma descrição de alto nível de cada um e como ele é usado no SUSE Telco Cloud, pode ser encontrada abaixo:

Parte I Conceito e arquitetura

O SUSE Telco Cloud é uma plataforma projetada para hospedar aplicativos modernos, nativos de nuvem, de telecomunicações em escala, do núcleo à borda.

Esta página explica a arquitetura e os componentes usados no SUSE Telco Cloud.

  • 1 Arquitetura do SUSE Telco Cloud
  • O diagrama a seguir mostra a arquitetura de alto nível do SUSE Telco Cloud:

  • 2 Componentes
  • Existem dois blocos diferentes, a pilha de gerenciamento e a pilha de runtime:

  • 3 Modelo de Implantação
  • O SUSE Telco Cloud segue um modelo de implantação de dois estágios: o cluster de gerenciamento é implantado usando uma imagem gerada pelo Edge Image Builder (Capítulo 12, Edge Image Builder), e os clusters downstream são provisionados via provisionamento de rede direcionado. Este capítulo fornece um…

1 Arquitetura do SUSE Telco Cloud

O diagrama a seguir mostra a arquitetura de alto nível do SUSE Telco Cloud:

product atip architecture1

2 Componentes

Existem dois blocos diferentes, a pilha de gerenciamento e a pilha de runtime:

  • Pilha de gerenciamento: Esta é a parte do SUSE Telco Cloud que é usada para gerenciar o provisionamento e o ciclo de vida das pilhas de runtime. Ela contém os seguintes componentes:

    • Gerenciamento de múltiplos clusters em ambientes de nuvem pública e privada com Rancher (Capítulo 6, Rancher)

    • Suporte a bare metal com Metal3 (Capítulo 11, Metal3), MetalLB (Capítulo 17, MetalLB) e provedores de infraestrutura CAPI (Cluster API)

    • Isolamento abrangente de locatários e integrações com IDP (Identity Provider)

    • Amplo marketplace de integrações e extensões de terceiros

    • API neutra em relação ao fornecedor e rico ecossistema de provedores

    • Controle as atualizações transacionais do SUSE Linux Micro

    • Mecanismo GitOps para gerenciar o ciclo de vida dos clusters usando repositórios Git com Fleet (Capítulo 9, Fleet)

  • Pilha de runtime: Esta é a parte do SUSE Telco Cloud que é usada para executar as cargas de trabalho.

    • RKE2 (Capítulo 14, RKE2) serve como a distribuição Kubernetes leve e com segurança reforçada, otimizada para ambientes de telecomunicações de borda e focados em conformidade.

    • (Opcional) SUSE Security (Capítulo 16, SUSE Security) para habilitar recursos de segurança como verificação de vulnerabilidade de imagem, inspeção profunda de pacotes e controle automático de tráfego intra-cluster.

    • (Opcional) Armazenamento em blocos com SUSE Storage (Capítulo 15, SUSE Storage) para permitir uma maneira simples e fácil de usar uma solução de armazenamento nativa de nuvem.

    • Sistema operacional otimizado com SUSE Linux Micro (Capítulo 10, SUSE Linux Micro) para permitir um SO seguro, leve e imutável (sistema de arquivos transacional) para executar contêineres. O SUSE Linux Micro está disponível nas arquiteturas AArch64 e AMD64/Intel 64, e também suporta Real-Time Kernel para casos de uso de Telecomunicações e borda.

3 Modelo de Implantação

O SUSE Telco Cloud segue um modelo de implantação de dois estágios: o cluster de gerenciamento é implantado usando uma imagem gerada pelo Edge Image Builder (Capítulo 12, Edge Image Builder), e os clusters downstream são provisionados via provisionamento de rede direcionado. Este capítulo fornece uma visão geral deste modelo de implantação, pois é a abordagem recomendada e suportada para ambientes SUSE Telco Cloud.

3.1 Por que este Modelo de Implantação?

O cluster de gerenciamento é uma implantação única, de local único. O Provisionamento baseado em imagem agrupa todos os componentes em uma única imagem inicializável. Dessa forma, o cluster de gerenciamento inicializará a si mesmo, exigindo complexidade operacional mínima. É a maneira mais simples e direta de colocá-lo em funcionamento.

Clusters downstream, no entanto, são uma história diferente. Em ambientes de telecomunicações, eles são implantados em escala em muitos data centers e locais de borda, muitas vezes sem experiência técnica local disponível. O Provisionamento de Rede Direcionado foi projetado para isso: ele exige que os servidores de destino suportem uma interface de gerenciamento fora de banda, como o Redfish, através da qual o cluster de gerenciamento liga, inspeciona e provisiona remotamente nós bare metal sem qualquer intervenção no local.

Incorporar toda a configuração específica do cluster em uma imagem de inicialização, como o Provisionamento baseado em imagem exigiria, significa que cada variação de local exige uma imagem diferente, e qualquer alteração de configuração requer a reconstrução e redistribuição de imagens em todos os locais. O Provisionamento de Rede Direcionado resolve isso mantendo a imagem do SO genérica e conduzindo toda a configuração específica do cluster, incluindo rede, Kubernetes e perfis de Telecomunicações, a partir do cluster de gerenciamento no momento do provisionamento. Os operadores simplesmente instalam em rack, ligam e conectam o hardware, e o cluster de gerenciamento cuida do resto.

Essa separação também desbloqueia a integração total com GitOps. Como toda a definição do cluster downstream é expressa como manifestos da API de Cluster, ela pode ser armazenada no Git e reconciliada pelo Fleet em todos os locais, tornando as operações de provisionamento, configuração e ciclo de vida totalmente auditáveis e repetíveis sem intervenção manual.

3.2 Implantação do Cluster de Gerenciamento

Usando o Edge Image Builder (Capítulo 12, Edge Image Builder) para criar uma nova imagem ISO com a pilha de gerenciamento incluída. Você pode então usar esta imagem ISO para instalar um novo cluster de gerenciamento em VMs ou bare-metal.

product atip architecture2
Nota
Nota

Para obter mais informações sobre como implantar um novo cluster de gerenciamento, consulte o guia do SUSE Telco Cloud Management Cluster (Parte V, “Configurando o cluster de gerenciamento”).

Nota
Nota

Para obter mais informações sobre como usar o Edge Image Builder, consulte o guia do Edge Image Builder (Capítulo 5, Clusters autônomos com o Edge Image Builder).

3.3 Implantação de um cluster downstream de nó único com perfis de Telco

Assim que tivermos o cluster de gerenciamento em funcionamento, podemos usá-lo para implantar um cluster downstream de nó único com todos os recursos de Telco habilitados e configurados usando o fluxo de trabalho de provisionamento de rede direcionado.

O diagrama a seguir mostra o fluxo de trabalho de alto nível para implantá-lo:

product atip architecture3
Nota
Nota

Para obter mais informações sobre como implantar um cluster downstream, consulte o guia de provisionamento automatizado do SUSE Telco Cloud. (Parte VII, “Provisionamento de rede direcionado totalmente automatizado”)

Nota
Nota

Para obter mais informações sobre os recursos do Telco, consulte o guia de recursos do Telco do SUSE Telco Cloud. (Parte VI, “Configuração de recursos de Telco”)

3.4 Implantação de um cluster de alta disponibilidade downstream

Assim que tivermos o cluster de gerenciamento em funcionamento, podemos usá-lo para implantar um cluster downstream de alta disponibilidade com o MetalLB como balanceador de carga usando o fluxo de trabalho de provisionamento de rede direcionado.

O diagrama a seguir mostra o fluxo de trabalho de alto nível para implantá-lo:

product atip architecture4
Nota
Nota

Para obter mais informações sobre como implantar um cluster downstream, consulte o guia de provisionamento automatizado do SUSE Telco Cloud (Parte VII, “Provisionamento de rede direcionado totalmente automatizado”)

Nota
Nota

Para obter mais informações sobre o MetalLB, consulte aqui: (Capítulo 17, MetalLB)

Parte II Inicializações rápidas

Inícios rápidos aqui

4 Implantações automatizadas de BMC com Metal3

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

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

Ele também possui suporte maduro para Cluster API (CAPI), que permite o gerenciamento de recursos de infraestrutura em vários provedores de infraestrutura por meio de APIs neutras de fornecedores amplamente adotadas.

4.1 Por que usar este método

Este método é útil para cenários em que o hardware de destino suporta gerenciamento fora de banda e deseja-se um fluxo de gerenciamento de infraestrutura totalmente automatizado.

Um cluster de gerenciamento é configurado para fornecer APIs declarativas que permitem o gerenciamento de inventário e estado de servidores bare-metal de clusters downstream, incluindo inspeção, limpeza e provisionamento/desprovisionamento automatizados.

4.2 Arquitetura de alto nível

quickstart metal3 architecture

4.3 Pré-requisitos

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

  • Cluster de gerenciamento

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

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

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

  • Hosts a serem controlados

    • Deve oferecer suporte a gerenciamento fora de banda via interfaces Redfish, iDRAC ou iLO

    • Deve oferecer suporte a implantação via mídia virtual (PXE não é suportado atualmente)

    • Deve ter conectividade de rede com o cluster de gerenciamento para acesso às APIs de provisionamento do Metal3

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

4.4 Implantação

4.4.1 Configurar Cluster de gerenciamento

As etapas básicas para instalar um cluster de gerenciamento e usar o 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 dependências do provedor CAPI

  6. Criar uma imagem do SO SLEMicro para hosts de cluster downstream

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

  8. Criar um cluster downstream definindo recursos CAPI

Este guia pressupõe que um cluster RKE2 e o Rancher (incluindo o cert-manager) existentes já foram instalados, por exemplo, usando o Edge Image Builder (Capítulo 12, Edge Image Builder).

Dica
Dica

As etapas aqui também podem ser totalmente automatizadas conforme descrito na Documentação do Cluster de gerenciamento (Parte V, “Configurando o cluster de gerenciamento”).

4.4.2 Instalando dependências do Metal3

Se não estiver instalado como parte da instalação do Rancher, o cert-manager deve estar instalado e em execução.

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

Dica
Dica

Se o cluster de gerenciamento for um nó único, o requisito de um IP flutuante adicional gerenciado via MetalLB pode ser evitado, veja Seção 4.7.1, “Configuração de nó único”

  1. Primeiro, instalamos o MetalLB:

    helm install \
      metallb oci://registry.suse.com/edge/charts/metallb \
      --namespace metallb-system \
      --create-namespace
  2. Em seguida, definimos um IPAddressPool e L2Advertisement usando o IP reservado, definido como STATIC_IRONIC_IP abaixo:

    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 o Metal3 pode ser instalado:

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

    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 prossiga para as etapas a seguir até que todos os pods no namespace metal3-system estejam em execução.

4.4.3 Instalando dependências do provedor de API de cluster

As dependências do provedor de API de cluster são gerenciadas por meio do gráfico Helm Rancher Turtles Providers:

helm install \
  rancher-turtles oci://registry.suse.com/edge/charts/rancher-turtles-providers \
  --namespace cattle-turtles-system \
  --create-namespace

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

4.4.4 Preparar imagem do cluster downstream

Kiwi (Capítulo 64, Criando imagens atualizadas do SUSE Linux Micro com o Kiwi) e Edge Image Builder (Capítulo 12, Edge Image Builder) são usados para preparar uma imagem base SLEMicro modificada que é provisionada nos hosts do cluster downstream.

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

4.4.4.1 Configuração de imagens

Nota
Nota

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

Ao executar o Edge Image Builder, um diretório é montado a partir do 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.2-Base-GM.raw
├── network/
|   └ configure-network.sh
└── custom/
    └ scripts/
        └ 01-fix-growfs.sh
4.4.4.1.1 Arquivo de definição de imagem do cluster downstream

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

apiVersion: 1.3
image:
  imageType: raw
  arch: x86_64
  baseImage: SL-Micro.x86_64-6.2-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
  systemd:
    disable:
      - rebootmgr
      - transactional-update.timer
      - transactional-update-cleanup.timer
  users:
    - username: root
      encryptedPassword: $ROOT_PASSWORD
      sshKeys:
      - $USERKEY1
      createHomeDir: true
  packages:
    packageList:
      - jq
    sccRegistrationCode: $SCC_REGISTRATION_CODE

Onde $SCC_REGISTRATION_CODE é o código de registro copiado do SUSE Customer Center, e a lista de pacotes contém jq, que é necessária.

$ROOT_PASSWORD é a senha criptografada para o usuário root, o que pode ser útil para testes/depuração. Ele pode ser gerado com o comando openssl passwd -6 PASSWORD.

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

Nota
Nota

Observe que ignition.platform.id=openstack é obrigatório - sem este argumento, a configuração do SUSE Linux Micro via ignition falhará no fluxo automatizado Metal3.

A seção time é opcional, mas é altamente recomendável que seja configurada para evitar possíveis problemas com certificados e discrepância de relógio. Os valores fornecidos neste exemplo são apenas para fins ilustrativos. Por favor, ajuste-os para atender aos seus requisitos específicos.

4.4.4.1.2 Script Growfs

Atualmente, um script personalizado (custom/scripts/01-fix-growfs.sh) é necessário para expandir o sistema de arquivos para corresponder ao 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 serem executados durante o processo de provisionamento usando a mesma abordagem. Para obter mais informações, consulte Capítulo 5, Clusters autônomos com o Edge Image Builder.

4.4.4.2 Criação de imagem

Uma vez que a estrutura de diretórios esteja preparada seguindo 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.6/edge-image-builder:1.3.3.1 \
 build --definition-file downstream-cluster-config.yaml

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

A imagem de saída deve então ser disponibilizada via servidor web, seja o contêiner media-server habilitado via o Metal3 chart (Nota) ou algum outro servidor acessível localmente. Nos exemplos abaixo, nos referimos a este servidor como imagecache.local:8080

Nota
Nota

Ao implantar imagens EIB em clusters downstream, também é necessário incluir a soma sha256 da imagem no objeto Metal3MachineTemplate. Ele pode ser gerado como:

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

4.4.5 Adicionando inventário BareMetalHost

O registro de servidores bare-metal para implantação automatizada requer a criação de dois recursos: um Secret armazenando credenciais de acesso BMC e um recurso Metal3 BareMetalHost definindo a conexã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:
  architecture: x86_64
  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 Secret deve estar codificado em base64. Observe que isso não deve incluir nenhuma quebra de linha ao final (por exemplo, use echo -n, não apenas echo!)

  • O rótulo cluster-role pode ser definido agora ou posteriormente na criação do cluster. No exemplo abaixo, esperamos control-plane ou worker

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

  • O endereço bmc é a conexão com a API de gerenciamento do BMC; os seguintes são suportados:

    • redfish-virtualmedia://<IP ADDRESS>/redfish/v1/Systems/<SYSTEM ID>: Mídia virtual Redfish, por exemplo, SuperMicro

    • idrac-virtualmedia://<IP ADDRESS>/redfish/v1/Systems/System.Embedded.1: Dell iDRAC

  • Consulte a documentação da API upstream para obter mais detalhes sobre a API BareMetalHost

4.4.5.1 Configurando IPs estáticos

O exemplo de BareMetalHost acima pressupõe que o DHCP forneça a configuração de rede do plano de controle, mas para cenários onde a configuração manual é necessária, como IPs estáticos, é possível fornecer configuração adicional, conforme descrito abaixo.

4.4.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 seguinte arquivo configure-network.sh.

Isso consome 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

META_DATA_FILE="/mnt/openstack/latest/meta_data.json"
if [ ! -f "${META_DATA_FILE}" ]; then
  umount /mnt
  echo "No meta_data.json found, skipping hostname 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

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

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
4.4.5.1.2 Segredo adicional com configuração de rede do host

Um segredo adicional contendo dados no formato nmstate suportado pelo NM Configurator (Capítulo 13, Rede de borda) pode ser definido para cada host.

O segredo é então referenciado no recurso BareMetalHost por meio do 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 circunstâncias, o endereço MAC pode ser omitido. Veja Seção 13.5.8, “Configurações de nó unificadas” para mais detalhes.

4.4.5.2 Preparação do BareMetalHost

Após criar o recurso BareMetalHost e os segredos associados conforme descrito acima, um fluxo de trabalho de preparação do host é acionado:

  • Uma imagem de ramdisk é inicializada por anexo de virtualmedia ao BMC do host de destino

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

  • Ao concluir este processo, os detalhes do hardware no campo BareMetalHost status.hardware são atualizados e podem ser verificados

Este processo pode levar vários minutos, mas quando concluído, você deverá ver o estado do BareMetalHost tornar-se available:

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

4.4.6 Criando clusters downstream

Agora criamos recursos do Cluster API que definem o cluster downstream, e recursos Machine que farão com que os recursos BareMetalHost sejam provisionados, e então inicializados para formar um cluster RKE2.

4.4.7 Implantação do plano de controle

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

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

  • O Metal3Cluster define o endpoint do plano de controle (IP do host para nó único, endpoint do LoadBalancer para multi-nó; este exemplo assume nó único)

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

  • O Metal3MachineTemplate define a imagem do SO a ser aplicada aos recursos BareMetalHost, e o hostSelector define quais BareMetalHosts consumir

  • O Metal3DataTemplate define metadados adicionais a serem passados para o BareMetalHost (observe que o networkData atualmente não é suportado na solução Edge)

Nota
Nota

Para simplificar, este exemplo assume um plano de controle de nó único onde o BareMetalHost está configurado com um IP de 192.168.125.200. Para exemplos mais avançados de multi-nó, consulte Parte VII, “Provisionamento de rede direcionado totalmente automatizado”.

apiVersion: cluster.x-k8s.io/v1beta2
kind: Cluster
metadata:
  name: sample-cluster
  namespace: default
  labels:
    cluster-api.cattle.io/rancher-auto-import: "true"
spec:
  clusterNetwork:
    pods:
      cidrBlocks:
        - 192.168.0.0/18
    services:
      cidrBlocks:
        - 10.96.0.0/12
  controlPlaneRef:
    apiGroup: controlplane.cluster.x-k8s.io
    kind: RKE2ControlPlane
    name: sample-cluster
  infrastructureRef:
    apiGroup: infrastructure.cluster.x-k8s.io
    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/v1beta2
kind: RKE2ControlPlane
metadata:
  name: sample-cluster
  namespace: default
spec:
  infrastructureRef:
    apiGroup: infrastructure.cluster.x-k8s.io
    kind: Metal3MachineTemplate
    name: sample-cluster-controlplane
  replicas: 1
  version: v1.35.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"
              ExecStart=/bin/sh -c "echo \"node-label:\" >> /etc/rancher/rke2/config.yaml"
              ExecStart=/bin/sh -c "echo \"  - metal3.io/uuid=$(jq -r .uuid /mnt/openstack/latest/meta_data.json)\" >> /etc/rancher/rke2/config.yaml"
              ExecStartPost=/bin/sh -c "umount /mnt"
              [Install]
              WantedBy=multi-user.target
          # rke2-traefik-deployment.service unit to be removed once "traefik" being the default ingress controller (starting with RKE2 v1.36)
          - name: rke2-traefik-deployment.service
            enabled: true
            contents: |
              [Unit]
              Description=rke2-traefik-deployment
              Wants=rke2-preinstall.service
              Before=rke2-install.service
              ConditionPathExists=!/run/cluster-api/bootstrap-success.complete
              [Service]
              Type=oneshot
              User=root
              ExecStart=/bin/sh -c "echo \"ingress-controller: traefik\" >> /etc/rancher/rke2/config.yaml"
              [Install]
              WantedBy=multi-user.target
        storage:
          directories:
          - path: /var/lib/rancher/rke2/server/manifests
            overwrite: true
          files:
          - path: /var/lib/rancher/rke2/server/manifests/rke2-traefik-config.yaml
            overwrite: true
            contents:
              inline: |
                apiVersion: helm.cattle.io/v1
                kind: HelmChartConfig
                metadata:
                  name: rke2-traefik
                  namespace: kube-system
                spec:
                  valuesContent: |-
                    ingressClass:
                      isDefaultClass: true
                    ports:
                      web:
                        hostPort: null    # disallow hostPort
                        exposedPort: 80
                      websecure:
                        hostPort: null    # disallow hostPort
                        exposedPort: 443
                    service:
                      enabled: true
                      type: LoadBalancer
                      spec:
                        externalTrafficPolicy: Local
                        allocateLoadBalancerNodePorts: false  # k8s GA from 1.24; supported by MetalLB
            mode: 0644
            user:
              name: root
            group:
              name: root
---
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
Nota
Nota

Adicionar o rótulo cluster-api.cattle.io/rancher-auto-import: "true" aos objetos cluster.x-k8s.io importará o cluster para o Rancher (criando um objeto clusters.management.cattle.io correspondente). Consulte a documentação do Cluster API para obter mais informações.

Uma vez adaptado ao seu ambiente, você pode aplicar o exemplo via kubectl e então monitorar o status do cluster via 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

4.4.8 Implantação de Worker/Compute

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 bootstrap/infraestrutura (neste caso, RKE2/Metal3)

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

  • Metal3MachineTemplate define a imagem do SO a ser aplicada aos recursos BareMetalHost, e o seletor de host define quais BareMetalHosts consumir

  • Metal3DataTemplate define metadados adicionais a serem passados para o BareMetalHost (observe que networkData não é suportado atualmente)

apiVersion: cluster.x-k8s.io/v1beta2
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:
          apiGroup: bootstrap.cluster.x-k8s.io
          kind: RKE2ConfigTemplate
          name: sample-cluster-workers
      clusterName: sample-cluster
      infrastructureRef:
        apiGroup: infrastructure.cluster.x-k8s.io
        kind: Metal3MachineTemplate
        name: sample-cluster-workers
      deletion:
        nodeDrainTimeoutSeconds: 0
      version: v1.35.4+rke2r1
---
apiVersion: bootstrap.cluster.x-k8s.io/v1beta2
kind: RKE2ConfigTemplate
metadata:
  name: sample-cluster-workers
  namespace: default
spec:
  template:
    spec:
      agentConfig:
        format: ignition
        version: v1.35.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"
                  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
---
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 tiver sido copiado e adaptado para atender ao seu ambiente, ele poderá ser aplicado via kubectl, então o status do cluster poderá ser monitorado com 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

4.4.9 Desprovisionamento de cluster

O cluster downstream pode ser desprovisionado excluindo os recursos aplicados nas etapas de criação acima:

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

Isso aciona o desprovisionamento dos recursos BareMetalHost, o que pode levar vários minutos, após os quais eles devem estar no estado disponível novamente:

% 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

4.5 Problemas conhecidos

  • O controlador de Gerenciamento de Endereço IP upstream não é suportado atualmente, pois ainda não é compatível com nossa escolha de ferramentas de configuração de rede e cadeia de ferramentas de primeira inicialização no SLEMicro.

  • Relacionado a isso, os recursos de IPAM e os campos networkData do Metal3DataTemplate não são suportados atualmente.

  • Apenas a implantação via redfish-virtualmedia é suportada atualmente.

4.6 Mudanças planejadas

  • Habilitar o suporte aos recursos de IPAM e configuração via campos networkData

4.7 Recursos adicionais

A SUSE Telco Cloud Management Cluster Documentation (Parte V, “Configurando o cluster de gerenciamento”) contém exemplos de uso mais avançado do Metal3 para casos de uso em telecomunicações.

4.7.1 Configuração de nó único

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

Neste 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 o IP do cluster de gerenciamento não mude - referido como <MANAGEMENT_CLUSTER_IP> abaixo.

Para habilitar este cenário, os valores do gráfico Metal3 necessários são os seguintes:

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

4.7.2 Desabilitando TLS para anexo de ISO de virtualmedia

Alguns fornecedores de servidores verificam a conexão SSL ao anexar imagens ISO de virtual-media ao BMC, o que pode causar um problema porque os certificados gerados para a implantação do Metal3 são autoassinados; para contornar esse problema, é possível desabilitar o TLS apenas para o anexo de disco de virtualmedia com os valores do gráfico Metal3 da seguinte forma:

global:
  enable_vmedia_tls: false

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

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

O certificado pode então ser configurado no console do BMC do servidor, embora o processo para isso seja específico do fornecedor (e não seja possível para todos os fornecedores, caso em que a flag enable_vmedia_tls pode ser necessária).

4.7.3 Configuração de armazenamento

Para ambientes de teste/PoC onde o cluster de gerenciamento é um nó único, nenhum armazenamento persistente é necessário, mas para casos de uso de produção, recomenda-se instalar o SUSE Storage (Longhorn) no cluster de gerenciamento para que as imagens relacionadas ao Metal3 possam ser persistidas durante uma reinicialização/reagendamento de pod.

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

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

A Documentação do SUSE Telco Cloud Management Cluster (Parte V, “Configurando o cluster de gerenciamento”) tem mais detalhes sobre como configurar um cluster de gerenciamento com armazenamento persistente.

5 Clusters autônomos com o Edge Image Builder

O Edge Image Builder (EIB) é uma ferramenta que simplifica o processo de geração de imagens de disco personalizadas e prontas para inicialização (CRB) para inicializar máquinas, mesmo em cenários totalmente air-gapped. O EIB é usado para criar imagens de implantação para uso em todos os três tipos de pegadas de implantação SUSE Telco Cloud, pois é flexível o suficiente para oferecer desde as menores personalizações, por exemplo, adicionar um usuário ou definir o fuso horário, até oferecer uma imagem configurada de forma abrangente que configura, por exemplo, configurações de rede complexas, implanta clusters Kubernetes de vários nós, implanta cargas de trabalho do cliente e registra na plataforma de gerenciamento centralizado via Rancher/Elemental e SUSE Multi-Linux Manager. O EIB é executado como uma imagem de contêiner, tornando-o incrivelmente portátil entre plataformas e garantindo que todas as dependências necessárias sejam autocontidas, tendo um impacto muito mínimo nos pacotes instalados do sistema que está sendo usado para operar a ferramenta.

Nota
Nota

Para cenários de vários nós, o EIB implanta automaticamente o MetalLB e o Endpoint Copier Operator para que os hosts provisionados usando a mesma imagem criada ingressem automaticamente em um cluster Kubernetes.

Para mais informações, leia a Introdução ao Edge Image Builder (Capítulo 12, Edge Image Builder).

Atenção
Atenção

O Edge Image Builder 1.3.3.1 oferece suporte à personalização de imagens do SUSE Linux Micro 6.2. Versões mais antigas, como o SUSE Linux Enterprise Micro 5.5 ou 6.0, não são suportadas.

5.1 Pré-requisitos

Nota
Nota

Para fins que não sejam de produção, o openSUSE Leap 15.6 ou o openSUSE Tumbleweed podem ser usados como máquina host de compilação. Outros sistemas operacionais podem funcionar, desde que um tempo de execução do contêiner compatível esteja disponível.

5.1.1 Obtendo a imagem do EIB

A imagem de contêiner do EIB está disponível publicamente e pode ser baixada do registro SUSE Telco Cloud executando o seguinte comando em seu host de compilação de imagem:

podman pull registry.suse.com/edge/3.6/edge-image-builder:1.3.3.1

5.2 Criando o diretório de configuração da imagem

Como o EIB é executado dentro de um contêiner, precisamos montar um diretório de configuração a partir do host, permitindo que você especifique a configuração desejada e, durante o processo de compilação, o EIB tenha acesso a quaisquer arquivos de entrada e artefatos de suporte necessários. Este diretório deve seguir uma estrutura específica. Vamos criá-lo, assumindo que este diretório existirá em seu diretório home e será chamado de "eib":

export CONFIG_DIR=$HOME/eib
mkdir -p $CONFIG_DIR/base-images

Na etapa anterior, criamos um diretório "base-images" que hospedará a imagem de entrada do SUSE Linux Micro 6.2, vamos garantir que a imagem seja copiada para o diretório de configuração:

cp /path/to/SL-Micro.x86_64-6.2-Base-SelfInstall-GM.install.iso $CONFIG_DIR/base-images/slemicro.iso
Nota
Nota

Durante a execução do EIB, a imagem base original não é modificada; uma versão nova e personalizada é criada com a configuração desejada na raiz do diretório de configuração do EIB.

O diretório de configuração neste ponto deve estar assim:

└── base-images/
    └── slemicro.iso

5.3 Criando o arquivo de definição de imagem

O arquivo de definição descreve a maioria das opções configuráveis que o Edge Image Builder suporta; um exemplo completo de opções pode ser encontrado aqui, e recomendamos que você dê uma olhada no guia de construção de imagens upstream para exemplos mais abrangentes do que o que vamos analisar abaixo. Vamos começar com um arquivo de definição muito básico para nossa imagem de SO:

cat << EOF > $CONFIG_DIR/iso-definition.yaml
apiVersion: 1.3
image:
  imageType: iso
  arch: x86_64
  baseImage: slemicro.iso
  outputImageName: eib-image.iso
EOF

Esta definição especifica que estamos gerando uma imagem de saída para um sistema baseado em AMD64/Intel 64. A imagem que será usada como base para modificações posteriores é uma imagem iso chamada slemicro.iso, esperada para estar localizada em $CONFIG_DIR/base-images/slemicro.iso. Ela também descreve que, após o EIB terminar de modificar a imagem, a imagem de saída será nomeada eib-image.iso e, por padrão, residirá em $CONFIG_DIR.

Agora, nossa estrutura de diretórios deve estar assim:

├── iso-definition.yaml
└── base-images/
    └── slemicro.iso

Nas seções a seguir, percorreremos alguns exemplos de operações comuns:

5.3.1 Configurando o Sistema Operacional (SO)

A seção operatingSystem do EIB destina-se a configurar onde o sistema operacional será instalado, o tamanho da imagem, etc. É uma seção opcional e não deve ser incluída, a menos que uma ou mais personalizações estejam sendo aplicadas.

apiVersion: 1.3
image:
  imageType: iso
  arch: x86_64
  baseImage: slemicro.iso
  outputImageName: eib-Base-RT-SelfInstall.iso
operatingSystem:
  isoConfiguration:
    installDevice: /dev/disk/by-id/ata-QEMU_HARDDISK_111-disk1 # first defined disk

Configuração específica do tipo. Dependendo do tipo de imagem que está sendo personalizada, uma das seguintes seções opcionais pode ser incluída.

  • isoConfiguration - Opcional; a configuração nesta seção aplica-se apenas à imagem ISO.

  • installDevice - Opcional; especifica o disco que deve ser usado como dispositivo de instalação. Este precisa ser um dispositivo de bloco e, por padrão, apagará automaticamente quaisquer dados encontrados no disco. Além disso, especificar este atributo aciona uma substituição do GRUB para instalar automaticamente o sistema operacional em vez de solicitar ao usuário que inicie a instalação, permitindo uma instalação totalmente autônoma e automatizada. Se omitido, o usuário é solicitado a selecionar a opção \"Install\" no menu do GRUB, além de ter que selecionar o disco de instalação e confirmar que o dispositivo será apagado no processo.

    Nota
    Nota

    O dispositivo sendo usado na seção installDevice pode ser especificado como /dev/sda ou usando a nomenclatura /dev/disk/by-id, /dev/disk/by-path para garantir que o dispositivo correto esteja sendo usado. Se estiver usando VMs libvirt, o valor do atributo serial pode ser especificado ao criar um disco para a VM (por exemplo, serial=111-disk1) para que possa ser usado no valor installDevice com a nomenclatura by-id, como por exemplo /dev/disk/by-id/ata-QEMU_HARDDISK_111-disk1 se estiver usando dispositivos ATA (libvirt prefixa automaticamente o ID com ata-QEMU_HARDDISK_ para dispositivos ATA, ou virtio- para dispositivos virtio, veja #17670 virtio issue para mais informações).

  • rawConfiguration - Opcional; a configuração nesta seção aplica-se apenas a imagens RAW.

  • diskSize - Opcional; define o tamanho desejado da imagem de disco bruta para o qual o EIB redimensionará a imagem resultante. Isso é importante para garantir que sua imagem de disco seja grande o suficiente para acomodar quaisquer artefatos sendo incorporados na imagem. É aconselhável definir isso como um valor ligeiramente menor que o tamanho do seu cartão SD (ou dispositivo de bloco, se estiver gravando diretamente em um disco), pois o sistema expandirá automaticamente no momento da inicialização para preencher o tamanho do dispositivo de bloco. Isso é opcional, mas altamente recomendado. Especifique como um número inteiro com \"M\" (Megabyte), \"G\" (Gigabyte) ou \"T\" (Terabyte) como sufixo (por exemplo, "32G").

  • luksKey - Obrigatório para imagens criptografadas; a chave LUKS fornecida para uma imagem RAW criptografada, que é necessária para que o EIB possa concluir o processo de construção.

  • expandEncryptedPartition - Opcional; desativado por padrão, quando ativado, expande automaticamente a partição criptografada para seu tamanho máximo. Por exemplo, se diskSize for 25G e este campo for true, o EIB expandirá a partição criptografada para 25G durante o processo de compilação.

5.3.2 Configurando usuários do SO

O EIB permite que você pré-configure usuários com informações de login, como senhas ou chaves SSH, incluindo a definição de uma senha de root fixa. Como parte deste exemplo, vamos definir a senha de root, e o primeiro passo é usar OpenSSL para criar uma senha criptografada de mão única:

openssl passwd -6 SecurePassword

Isso gerará algo semelhante a:

$6$G392FCbxVgn[...]Y7zTXnC1

Podemos então adicionar uma seção no arquivo de definição chamada operatingSystem com uma matriz users dentro dela. O arquivo resultante deve ter a seguinte aparência:

apiVersion: 1.3
image:
  imageType: iso
  arch: x86_64
  baseImage: slemicro.iso
  outputImageName: eib-image.iso
operatingSystem:
  users:
    - username: root
      encryptedPassword: $6$G392FCbxVgn[...]Y7zTXnC1
Nota
Nota

Também é possível adicionar usuários adicionais, criar os diretórios home, definir IDs de usuário, adicionar autenticação por chave SSH e modificar informações de grupo. Consulte o guia de criação de imagens upstream para obter mais exemplos.

5.3.3 Configurando o horário do SO

A seção time é opcional, mas é altamente recomendável que seja configurada para evitar possíveis problemas com certificados e desvio de relógio. O EIB configurará o chronyd e o /etc/localtime dependendo dos parâmetros aqui.

operatingSystem:
  time:
    timezone: Europe/London
    ntp:
      forceWait: true
      pools:
        - 2.suse.pool.ntp.org
      servers:
        - 10.0.0.1
        - 10.0.0.2
  • O timezone especifica o fuso horário no formato "Região/Localidade" (por exemplo, "Europe/London"). A lista completa pode ser encontrada executando timedatectl list-timezones em um sistema Linux.

  • ntp - Define atributos relacionados à configuração do NTP (usando chronyd):

  • forceWait - Solicita que o chronyd tente sincronizar as fontes de tempo antes de iniciar outros serviços, com um tempo limite de 180s.

  • pools - Especifica uma lista de pools que o chronyd usará como fontes de dados (usando iburst para melhorar o tempo necessário para a sincronização inicial).

  • servers - Especifica uma lista de servidores que o chronyd usará como fontes de dados (usando iburst para melhorar o tempo necessário para a sincronização inicial).

Nota
Nota

Os valores fornecidos neste exemplo são apenas para fins ilustrativos. Por favor, ajuste-os para atender aos seus requisitos específicos.

5.3.4 Adicionando certificados

Arquivos de certificado com a extensão ".pem" ou ".crt" armazenados no diretório certificates serão instalados no armazenamento de certificados de todo o sistema do nó:

.
├── definition.yaml
└── certificates
    ├── my-ca.pem
    └── my-ca.crt

Consulte o guia "Securing Communication with TLS Certificate" para obter mais informações.

5.3.5 Adicionando Arquivos de sistema operacional

Os arquivos colocados no diretório os-files no diretório de configuração da imagem são copiados automaticamente para o sistema de arquivos da imagem criada. O diretório exato será mantido quando eles forem copiados. Por exemplo, se um arquivo existe em um subdiretório chamado os-files/etc, ele é colocado no diretório /etc da imagem criada.

Nota
Nota

Se o diretório os-files existir, ele não pode estar vazio.

.
├── definition.yaml
└── os-files
    └── etc
        └── ssh
            └── sshd_config

5.3.6 Configurando pacotes RPM

Um dos principais recursos do EIB é fornecer um mecanismo para adicionar pacotes de software adicionais à imagem, para que, quando a instalação for concluída, o sistema seja capaz de aproveitar os pacotes instalados imediatamente. O EIB permite que os usuários especifiquem o seguinte:

  • Pacotes por seus nomes dentro de uma lista na definição da imagem

  • Repositórios de rede para pesquisar esses pacotes

  • Credenciais do SUSE Customer Center (SCC) para pesquisar repositórios oficiais da SUSE pelos pacotes listados

  • Por meio de um diretório $CONFIG_DIR/rpms, carregue pacotes RPM personalizados que não existem em repositórios de rede

  • Por meio do mesmo diretório ($CONFIG_DIR/rpms/gpg-keys), chaves GPG para permitir a validação de pacotes de terceiros

O EIB então executará um processo de resolução de pacotes no momento da criação da imagem, tomando a imagem base como entrada, e tentará baixar e instalar todos os pacotes fornecidos, seja especificados por meio da lista ou fornecidos localmente. O EIB baixa todos os pacotes, incluindo quaisquer dependências, para um repositório que existe dentro da imagem de saída e instrui o sistema a instalá-los durante o processo de primeira inicialização. Realizar esse processo durante a criação da imagem garante que os pacotes sejam instalados com sucesso durante a primeira inicialização na plataforma desejada, por exemplo, o nó na borda. Isso também é vantajoso em ambientes onde você deseja incluir os pacotes adicionais na imagem em vez de baixá-los pela rede durante a operação, por exemplo, para ambientes air-gapped ou com rede restrita.

Como um exemplo simples para demonstrar isso, vamos instalar o pacote RPM nvidia-container-toolkit encontrado no repositório NVIDIA suportado por terceiros:

  packages:
    packageList:
      - nvidia-container-toolkit
    additionalRepos:
      - url: https://nvidia.github.io/libnvidia-container/stable/rpm/x86_64

O arquivo de definição resultante parece com o seguinte:

apiVersion: 1.3
image:
  imageType: iso
  arch: x86_64
  baseImage: slemicro.iso
  outputImageName: eib-image.iso
operatingSystem:
  users:
    - username: root
      encryptedPassword: $6$G392FCbxVgn[...]Y7zTXnC1
  packages:
    packageList:
      - nvidia-container-toolkit
    additionalRepos:
      - url: https://nvidia.github.io/libnvidia-container/stable/rpm/x86_64

O exemplo acima é simples, mas para fins de completude, baixe a chave de assinatura do pacote NVIDIA antes de executar a geração da imagem:

$ mkdir -p $CONFIG_DIR/rpms/gpg-keys
$ curl -fsSL https://nvidia.github.io/libnvidia-container/gpgkey > $CONFIG_DIR/rpms/gpg-keys/nvidia.gpg
Atenção
Atenção

Adicionar pacotes RPM adicionais por meio deste método destina-se à adição de componentes de terceiros suportados ou pacotes fornecidos (e mantidos) pelo usuário; este mecanismo não deve ser usado para adicionar pacotes que normalmente não seriam suportados no SUSE Linux Micro. Se este mecanismo for usado para adicionar componentes de repositórios openSUSE (que não são suportados), incluindo de versões ou pacotes de serviço mais recentes, você pode acabar com uma configuração não suportada, especialmente quando a resolução de dependências resulta na substituição de partes principais do sistema operacional, mesmo que o sistema resultante possa parecer funcionar conforme o esperado. Se você não tiver certeza, entre em contato com seu representante SUSE para obter assistência na determinação da capacidade de suporte da configuração desejada.

Nota
Nota

Um guia mais abrangente com exemplos adicionais pode ser encontrado no guia de instalação de pacotes upstream.

5.3.7 Configurando o cluster Kubernetes e as cargas de trabalho do usuário

Outro recurso do EIB é sua capacidade de automatizar a implantação de clusters Kubernetes, tanto de nó único quanto de múltiplos nós altamente disponíveis que se inicializam no local (ou seja, não requerem qualquer forma de infraestrutura de gerenciamento centralizada para coordenação). O principal motivador por trás dessa abordagem são as implantações air-gapped ou ambientes com rede restrita, mas também serve como uma maneira de inicializar rapidamente clusters autônomos, mesmo que o acesso total e irrestrito à rede esteja disponível.

Este método permite não apenas a implantação do sistema operacional personalizado, mas também a capacidade de especificar a configuração do Kubernetes, quaisquer componentes em camadas adicionais via gráficos Helm e quaisquer cargas de trabalho do usuário via manifestos do Kubernetes fornecidos. No entanto, o princípio de design por trás deste método é que partimos do pressuposto de que o usuário deseja operar em ambiente air-gapped. Portanto, quaisquer itens especificados na definição da imagem serão incluídos na imagem, o que inclui cargas de trabalho fornecidas pelo usuário. O EIB garante que quaisquer imagens descobertas que sejam exigidas pelas definições sejam copiadas localmente e servidas pelo registro de imagem incorporado no sistema implantado resultante.

Neste próximo exemplo, vamos utilizar nossa definição de imagem existente e especificar uma configuração do Kubernetes (neste exemplo, como ela não lista os sistemas e suas funções, assumimos por padrão que se trata de um nó único), o que instruirá o EIB a provisionar um cluster Kubernetes RKE2 de nó único. Para demonstrar a automação na implantação tanto de cargas de trabalho fornecidas pelo usuário (via manifesto) quanto de componentes em camadas (via Helm), vamos instalar o KubeVirt utilizando o chart Helm SUSE Telco Cloud, assim como o NGINX por meio de um manifesto do Kubernetes. A configuração adicional que precisamos anexar à definição de imagem existente é a seguinte:

kubernetes:
  version: v1.35.4+rke2r1
  manifests:
    urls:
      - https://k8s.io/examples/application/nginx-app.yaml
  helm:
    charts:
      - name: kubevirt
        version: 306.0.2+up0.7.0
        repositoryName: suse-edge
    repositories:
      - name: suse-edge
        url: oci://registry.suse.com/edge/charts

O arquivo de definição completo resultante deve agora ter a seguinte aparência:

apiVersion: 1.3
image:
  imageType: iso
  arch: x86_64
  baseImage: slemicro.iso
  outputImageName: eib-image.iso
operatingSystem:
  users:
    - username: root
      encryptedPassword: $6$G392FCbxVgn[...]Y7zTXnC1
  packages:
    packageList:
      - nvidia-container-toolkit
    additionalRepos:
      - url: https://nvidia.github.io/libnvidia-container/stable/rpm/x86_64
kubernetes:
  version: v1.35.4+k3s1
  manifests:
    urls:
      - https://k8s.io/examples/application/nginx-app.yaml
  helm:
    charts:
      - name: kubevirt
        version: 306.0.2+up0.7.0
        repositoryName: suse-edge
    repositories:
      - name: suse-edge
        url: oci://registry.suse.com/edge/charts
Nota
Nota

Outros exemplos de opções, como implantações de vários nós, rede personalizada e opções/valores de gráfico Helm, podem ser encontrados na documentação upstream.

5.3.8 Configurando a rede

No último exemplo deste guia de início rápido, vamos configurar a rede que será ativada quando um sistema for provisionado com a imagem gerada pelo EIB. É importante entender que, a menos que uma configuração de rede seja fornecida, o modelo padrão é que o DHCP seja usado em todas as interfaces descobertas no momento da inicialização. No entanto, essa nem sempre é uma configuração desejável, especialmente se o DHCP não estiver disponível e você precisar fornecer configurações estáticas, ou se precisar configurar construções de rede mais complexas, por exemplo, bonds, LACP e VLANs, ou precisar substituir certos parâmetros, por exemplo, nomes de host, servidores DNS e rotas.

O EIB oferece a capacidade de fornecer configurações por nó (onde o sistema em questão é identificado exclusivamente pelo seu endereço MAC), ou uma substituição para fornecer uma configuração idêntica a cada máquina, o que é mais útil quando os endereços MAC do sistema não são conhecidos. Uma ferramenta adicional é usada pelo EIB chamada Network Manager Configurator, ou nmc para abreviar, que é uma ferramenta criada pela equipe SUSE Telco Cloud para permitir que configurações de rede personalizadas sejam aplicadas com base no esquema de rede declarativo nmstate.io e, no momento da inicialização, identificará o nó no qual está inicializando e aplicará a configuração de rede desejada antes que quaisquer serviços sejam iniciados.

Agora aplicaremos uma configuração de rede estática para um sistema com uma única interface descrevendo o estado de rede desejado em um arquivo específico do nó (com base no nome de host desejado) no diretório network necessário:

mkdir $CONFIG_DIR/network

cat << EOF > $CONFIG_DIR/network/host1.local.yaml
routes:
  config:
  - destination: 0.0.0.0/0
    metric: 100
    next-hop-address: 192.168.122.1
    next-hop-interface: eth0
    table-id: 254
  - destination: 192.168.122.0/24
    metric: 100
    next-hop-address: 192.168.122.1
    next-hop-interface: eth0
    table-id: 254
dns-resolver:
  config:
    server:
    - 192.168.122.1
    - 8.8.8.8
interfaces:
- name: eth0
  type: ethernet
  state: up
  mac-address: 34:8A:B1:4B:16:E7
  ipv4:
    address:
    - ip: 192.168.122.50
      prefix-length: 24
    dhcp: false
    enabled: true
  ipv6:
    enabled: false
EOF
Atenção
Atenção

O exemplo acima está configurado para a sub-rede 192.168.122.0/24 padrão, assumindo que o teste está sendo executado em uma máquina virtual. Por favor, adapte-o para o seu ambiente, não se esquecendo do endereço MAC. Como a mesma imagem pode ser usada para provisionar vários nós, a rede configurada pelo EIB (via nmc) depende de sua capacidade de identificar exclusivamente o nó pelo seu endereço MAC e, portanto, durante a inicialização, o nmc aplicará a configuração de rede correta a cada máquina. Isso significa que você precisará saber os endereços MAC dos sistemas nos quais deseja instalar. Alternativamente, o comportamento padrão é confiar no DHCP, mas você pode utilizar o hook configure-network.sh para aplicar uma configuração comum a todos os nós. Consulte o guia de redes (Capítulo 13, Rede de borda) para obter mais detalhes.

A estrutura de arquivos resultante deve ser semelhante a:

├── iso-definition.yaml
├── base-images/
│   └── slemicro.iso
└── network/
    └── host1.local.yaml

A configuração de rede que acabamos de criar será analisada e os arquivos de conexão do NetworkManager necessários serão gerados automaticamente e inseridos na nova imagem de instalação que o EIB criará. Esses arquivos serão aplicados durante o provisionamento do host, resultando em uma configuração de rede completa.

Nota
Nota

Consulte o componente Edge Networking (Capítulo 13, Rede de borda) para obter uma explicação mais abrangente da configuração acima e exemplos desse recurso.

5.4 Criando a imagem

Agora que temos uma imagem base e uma definição de imagem para o EIB consumir, vamos prosseguir e criar a imagem. Para isso, usamos simplesmente o podman para chamar o contêiner do EIB com o comando \"build\", especificando o arquivo de definição:

podman run --rm -it --privileged -v $CONFIG_DIR:/eib \
registry.suse.com/edge/3.6/edge-image-builder:1.3.3.1 \
build --definition-file iso-definition.yaml

A saída do comando deve ser semelhante a:

Setting up Podman API listener...
Downloading file: dl-manifest-1.yaml 100% (498/498 B, 9.5 MB/s)
Pulling selected Helm charts... 100% (1/1, 43 it/min)
Generating image customization components...
Identifier ................... [SUCCESS]
Custom Files ................. [SKIPPED]
Time ......................... [SKIPPED]
Network ...................... [SUCCESS]
Groups ....................... [SKIPPED]
Users ........................ [SUCCESS]
Proxy ........................ [SKIPPED]
Resolving package dependencies...
Rpm .......................... [SUCCESS]
Os Files ..................... [SKIPPED]
Systemd ...................... [SKIPPED]
Fips ......................... [SKIPPED]
Elemental .................... [SKIPPED]
Suma ......................... [SKIPPED]
Populating Embedded Artifact Registry... 100% (3/3, 10 it/min)
Embedded Artifact Registry ... [SUCCESS]
Keymap ....................... [SUCCESS]
Configuring Kubernetes component...
The Kubernetes CNI is not explicitly set, defaulting to 'cilium'.
Downloading file: rke2_installer.sh
Downloading file: rke2-images-core.linux-amd64.tar.zst 100% (657/657 MB, 48 MB/s)
Downloading file: rke2-images-cilium.linux-amd64.tar.zst 100% (368/368 MB, 48 MB/s)
Downloading file: rke2.linux-amd64.tar.gz 100% (35/35 MB, 50 MB/s)
Downloading file: sha256sum-amd64.txt 100% (4.3/4.3 kB, 6.2 MB/s)
Kubernetes ................... [SUCCESS]
Certificates ................. [SKIPPED]
Cleanup ...................... [SKIPPED]
Building ISO image...
Kernel Params ................ [SKIPPED]
Build complete, the image can be found at: eib-image.iso

A imagem ISO criada é armazenada em $CONFIG_DIR/eib-image.iso:

├── iso-definition.yaml
├── eib-image.iso
├── _build
│   └── cache/
│       └── ...
│   └── build-<timestamp>/
│       └── ...
├── base-images/
│   └── slemicro.iso
└── network/
    └── host1.local.yaml

Cada compilação cria uma pasta com carimbo de data/hora em $CONFIG_DIR/_build/ que inclui os logs da compilação, os artefatos usados durante a compilação, e os diretórios combustion e artefacts, que contêm todos os scripts e artefatos que são adicionados à imagem CRB.

O conteúdo deste diretório deve ser semelhante a:

├── build-<timestamp>/
│   │── combustion/
│   │   ├── 05-configure-network.sh
│   │   ├── 10-rpm-install.sh
│   │   ├── 12-keymap-setup.sh
│   │   ├── 13b-add-users.sh
│   │   ├── 20-k8s-install.sh
│   │   ├── 26-embedded-registry.sh
│   │   ├── 48-message.sh
│   │   ├── network/
│   │   │   ├── host1.local/
│   │   │   │   └── eth0.nmconnection
│   │   │   └── host_config.yaml
│   │   ├── nmc
│   │   └── script
│   │── artefacts/
│   │   │── registry/
│   │   │   ├── hauler
│   │   │   ├── nginx:<version>-registry.tar.zst
│   │   │   ├── rancher_kubectl:<version>-registry.tar.zst
│   │   │   └── registry.suse.com_suse_sles_15.6_virt-operator:<version>-registry.tar.zst
│   │   │── rpms/
│   │   │   └── rpm-repo
│   │   │       ├── addrepo0
│   │   │       │   ├── nvidia-container-toolkit-<version>.rpm
│   │   │       │   ├── nvidia-container-toolkit-base-<version>.rpm
│   │   │       │   ├── libnvidia-container1-<version>.rpm
│   │   │       │   └── libnvidia-container-tools-<version>.rpm
│   │   │       ├── repodata
│   │   │       │   ├── ...
│   │   │       └── zypper-success
│   │   └── kubernetes/
│   │       ├── rke2_installer.sh
│   │       ├── registries.yaml
│   │       ├── server.yaml
│   │       ├── images/
│   │       │   ├── rke2-images-cilium.linux-amd64.tar.zst
│   │       │   └── rke2-images-core.linux-amd64.tar.zst
│   │       ├── install/
│   │       │   ├── rke2.linux-amd64.tar.gz
│   │       │   └── sha256sum-amd64.txt
│   │       └── manifests/
│   │           ├── dl-manifest-1.yaml
│   │           └── kubevirt.yaml
│   ├── createrepo.log
│   ├── eib-build.log
│   ├── embedded-registry.log
│   ├── helm
│   │   └── kubevirt
│   │       └── kubevirt-0.4.0.tgz
│   ├── helm-pull.log
│   ├── helm-template.log
│   ├── iso-build.log
│   ├── iso-build.sh
│   ├── iso-extract
│   │   └── ...
│   ├── iso-extract.log
│   ├── iso-extract.sh
│   ├── modify-raw-image.sh
│   ├── network-config.log
│   ├── podman-image-build.log
│   ├── podman-system-service.log
│   ├── prepare-resolver-base-tarball-image.log
│   ├── prepare-resolver-base-tarball-image.sh
│   ├── raw-build.log
│   ├── raw-extract
│   │   └── ...
│   └── resolver-image-build
│       └──...
└── cache
    └── ...

Se a compilação falhar, eib-build.log é o primeiro log que contém informações. A partir daí, ele o direcionará para o componente que falhou para depuração.

Neste ponto, você deve ter uma imagem pronta para uso que irá:

  1. Implantar o SUSE Linux Micro 6.2

  2. Configurar a senha de root

  3. Instale o pacote nvidia-container-toolkit

  4. Configure um registro de contêiner incorporado para servir conteúdo localmente

  5. Instale o RKE2 de nó único

  6. Configure a rede estática

  7. Instale o KubeVirt

  8. Implante um manifesto fornecido pelo usuário

5.5 Depuração do processo de criação de imagem

Se o processo de criação de imagem falhar, consulte o guia de depuração upstream.

5.6 Testando sua imagem recém-criada

Para obter instruções sobre como testar a imagem CRB recém-criada, consulte o guia de teste de imagem upstream.

Parte III Componentes

Lista de componentes para Edge

6 Rancher

Consulte a documentação do Rancher em https://ranchermanager.docs.rancher.com/v2.14.

O Rancher é uma poderosa plataforma de gerenciamento de Kubernetes de código aberto que simplifica a implantação, as operações e o monitoramento de clusters Kubernetes em vários ambientes. Quer você gerencie clusters no local, na nuvem ou na borda, o Rancher fornece uma plataforma unificada e centralizada para todas as suas necessidades de Kubernetes.

6.1 Principais recursos do Rancher

  • Gerenciamento de vários clusters: A interface intuitiva do Rancher permite que você gerencie clusters Kubernetes de qualquer lugar — nuvens públicas, data centers privados e locais de borda.

  • Segurança e conformidade: O Rancher impõe políticas de segurança, controle de acesso com base em função (RBAC) e padrões de conformidade em todo o seu ambiente Kubernetes.

  • Operações de cluster simplificadas: O Rancher automatiza o provisionamento, as atualizações e a solução de problemas de clusters, simplificando as operações de Kubernetes para equipes de todos os tamanhos.

  • Catálogo de aplicativos centralizado: O catálogo de aplicativos do Rancher oferece uma gama diversificada de gráficos Helm e operadores Kubernetes, facilitando a implantação e o gerenciamento de aplicativos conteinerizados.

  • Entrega contínua: O Rancher oferece suporte a pipelines de GitOps e CI/CD, permitindo processos de entrega de aplicativos automatizados e simplificados.

6.2 Uso do Rancher em SUSE Telco Cloud

O Rancher fornece várias funcionalidades principais para a pilha SUSE Telco Cloud:

6.2.1 Gerenciamento centralizado de Kubernetes

Em implantações de borda típicas com inúmeros clusters distribuídos, o Rancher atua como um plano de controle central para gerenciar esses clusters Kubernetes. Ele oferece uma interface unificada para provisionamento, atualização, monitoramento e solução de problemas, simplificando as operações e garantindo a consistência.

6.2.2 Implantação simplificada de cluster

O Rancher simplifica a criação de clusters Kubernetes no sistema operacional leve SUSE Linux Micro, facilitando a implementação de infraestrutura de borda com recursos robustos de Kubernetes.

6.2.3 Implantação e gerenciamento de aplicativos

O catálogo de aplicativos integrado do Rancher pode simplificar a implantação e o gerenciamento de aplicativos conteinerizados em SUSE Telco Cloud clusters, permitindo a implantação sem interrupções de cargas de trabalho de borda.

6.2.4 Segurança e aplicação de políticas

O Rancher fornece ferramentas de governança baseadas em políticas, controle de acesso com base em função (RBAC) e integração com provedores de autenticação externos. Isso ajuda as implantações SUSE Telco Cloud a manter a segurança e a conformidade, o que é fundamental em ambientes distribuídos.

6.3 Melhores práticas

6.3.1 GitOps

O Rancher inclui o Fleet como um componente incorporado para permitir o gerenciamento de configurações de cluster e implantações de aplicativos com código armazenado no git.

6.3.2 Observabilidade

O Rancher inclui ferramentas incorporadas de monitoramento e registro como Prometheus e Grafana para obter insights abrangentes sobre a integridade e o desempenho do seu cluster.

6.4 Instalação com o Edge Image Builder

O SUSE Telco Cloud está usando o Capítulo 12, Edge Image Builder para personalizar imagens base do sistema operacional SUSE Linux Micro. Siga Seção 63.6, “Instalação do Rancher” para uma instalação air-gapped do Rancher sobre clusters Kubernetes provisionados pelo EIB.

6.5 Recursos adicionais

7 Extensões do Dashboard do Rancher

As extensões permitem que usuários, desenvolvedores, parceiros e clientes estendam e aprimorem a interface do Rancher. SUSE Telco Cloud fornece extensões do Dashboard do KubeVirt.

Consulte Rancher documentation para obter informações gerais sobre as Extensões do Dashboard do Rancher.

7.1 Instalação

Todos os componentes SUSE Telco Cloud 3.6, incluindo extensões do Dashboard, são distribuídos como artefatos OCI. Para instalar as Extensões SUSE Telco Cloud, você pode usar a interface do Dashboard do Rancher, Helm ou Fleet:

7.1.1 Instalando com a interface do Dashboard do Rancher

  1. Clique em Extensions na seção Configuração da barra lateral de navegação.

  2. Na página Extensions, clique no menu de três pontos no canto superior direito e selecione Manage Repositories.

    Cada extensão é distribuída por meio de seu próprio artefato OCI. Elas estão disponíveis no SUSE Telco Cloud repositório de charts Helm.

  3. Na página de repositórios, clique em Create.

  4. No formulário, especifique o nome e a URL do repositório e clique em Create.

    SUSE Telco Cloud URL do repositório de charts Helm: oci://registry.suse.com/edge/charts

    dashboard extensions create oci repository
  5. Você pode ver que o repositório de extensão foi adicionado à lista e está no estado Active.

    dashboard extensions repositories list
  6. Navegue de volta para Extensions na seção Configuração da barra lateral de navegação.

    Na guia Available, você pode ver as extensões disponíveis para instalação.

    dashboard extensions available extensions
  7. No cartão da extensão, clique em Install e confirme a instalação.

    Assim que a extensão for instalada, a interface do Rancher solicitará que você recarregue a página, conforme descrito em https://ranchermanager.docs.rancher.com/v2.14/integrations-in-rancher/rancher-extensions#installing-extensions.

7.1.2 Instalando com Helm

# KubeVirt extension
helm install kubevirt-dashboard-extension oci://registry.suse.com/edge/charts/kubevirt-dashboard-extension --version 306.0.4+up1.3.3 --namespace cattle-ui-plugin-system
Nota
Nota

As extensões precisam ser instaladas no namespace cattle-ui-plugin-system.

Nota
Nota

Após a instalação de uma extensão, a interface do Dashboard do Rancher precisa ser recarregada.

7.1.3 Instalando com Fleet

A instalação de extensões do Dashboard com Fleet requer a definição de um recurso gitRepo que aponte para um repositório Git com arquivo(s) de configuração de bundle fleet.yaml personalizado(s).

# KubeVirt extension fleet.yaml
defaultNamespace: cattle-ui-plugin-system
helm:
  releaseName: kubevirt-dashboard-extension
  chart: oci://registry.suse.com/edge/charts/kubevirt-dashboard-extension
  version: "306.0.4+up1.3.3"
Nota
Nota

A propriedade releaseName é obrigatória e precisa corresponder ao nome da extensão para que ela seja instalada corretamente.

cat <<- EOF | kubectl apply -f -
apiVersion: fleet.cattle.io/v1alpha1
metadata:
  name: edge-dashboard-extensions
  namespace: fleet-local
spec:
  repo: https://github.com/suse-edge/fleet-examples.git
  branch: main
  paths:
  - fleets/kubevirt-dashboard-extension/
EOF

Para obter mais informações, consulte Capítulo 9, Fleet e o repositório fleet-examples.

Uma vez que as extensões estejam instaladas, elas são listadas na seção Extensions sob as guias Installed. Como elas não são instaladas via Apps/Marketplace, elas são marcadas com o rótulo Third-Party.

installed dashboard extensions

7.2 Extensão de Dashboard do KubeVirt

A extensão do KubeVirt fornece gerenciamento básico de máquinas virtuais para a interface do Dashboard do Rancher. Suas capacidades estão descritas em Seção 19.7.2, “Usando a Extensão do Painel do Rancher para KubeVirt”.

8 Rancher Turtles

Consulte a documentação do Rancher Turtles em https://documentation.suse.com/cloudnative/cluster-api/

O Rancher Turtles é um operador do Kubernetes que faz a integração entre o Rancher Manager e a Cluster API (CAPI) com o objetivo de levar suporte completo à CAPI para o Rancher

8.1 Principais recursos do Rancher Turtles

  • Importe automaticamente clusters CAPI para o Rancher, instalando o Rancher Cluster Agent em clusters provisionados pelo CAPI.

  • Instale e configure as dependências do controlador CAPI por meio do CAPI Operator.

  • Gerencie as dependências do provedor CAPI instaladas por meio da CAPIProvider API

8.2 Uso do Rancher Turtles no SUSE Telco Cloud

A pilha SUSE Telco Cloud fornece um gráfico helm rancher-turtles-providers que habilita determinados provedores CAPI por meio da CAPIProvider API:

Apenas os provedores padrão instalados por meio do agrupador são suportados – provedores alternativos de plano de controle, de inicializar e de infraestrutura não são suportados atualmente como parte da pilha SUSE Telco Cloud.

8.3 Instalando o Rancher Turtles

Desde o Rancher 2.13, o Rancher Turtles é habilitado por padrão ao instalar o Rancher.

Os Provedores do Rancher Turtles podem ser instalados seguindo o guia Metal3 Quickstart (Capítulo 4, Implantações automatizadas de BMC com Metal3) ou a documentação do Management Cluster (Parte V, “Configurando o cluster de gerenciamento”).

8.4 Recursos adicionais

9 Fleet

Fleet é um mecanismo de gerenciamento e implantação de contêineres projetado para oferecer aos usuários mais controle sobre o cluster local e monitoramento constante por meio de GitOps. O Fleet foca não apenas na capacidade de escalar, mas também oferece aos usuários um alto grau de controle e visibilidade para monitorar exatamente o que está instalado no cluster.

O Fleet pode gerenciar implantações a partir do Git de YAML bruto do Kubernetes, charts Helm, Kustomize ou qualquer combinação dos três. Independentemente da origem, todos os recursos são transformados dinamicamente em charts Helm, e o Helm é usado como o mecanismo para implantar todos os recursos no cluster. Como resultado, os usuários podem desfrutar de um alto grau de controle, consistência e auditabilidade de seus clusters.

Para obter informações sobre como o Fleet funciona, consulte Fleet Architecture.

9.1 Instalando o Fleet com Helm

O Fleet vem incorporado ao Rancher, mas também pode ser instalado como um aplicativo independente em qualquer cluster Kubernetes usando Helm.

9.2 Usando o Fleet com o Rancher

O Rancher usa o Fleet para implantar aplicativos em clusters gerenciados. A entrega contínua com o Fleet introduz o GitOps em escala, projetado para gerenciar aplicativos em execução em um grande número de clusters.

O Fleet se destaca como uma parte integrada do Rancher. Os clusters gerenciados com o Rancher recebem automaticamente o Fleet agent implantado como parte do processo de instalação/importação e o cluster fica imediatamente disponível para ser gerenciado pelo Fleet.

9.3 Acessando o Fleet na interface do usuário do Rancher

O Fleet vem incorporado no Rancher e é gerenciado pela opção Entrega contínua na interface do usuário do Rancher.

fleet dashboard

A seção Entrega contínua consiste nos seguintes itens:

9.3.1 Painel

Uma página de visão geral de todos os repositórios GitOps em todos os espaços de trabalho. Apenas os espaços de trabalho com repositórios são exibidos.

9.3.2 Repositórios Git

Uma lista de repositórios GitOps no espaço de trabalho selecionado. Selecione o espaço de trabalho ativo usando a lista suspensa na parte superior da página.

9.3.3 Clusters

Uma lista de clusters gerenciados. Por padrão, todos os clusters gerenciados pelo Rancher são adicionados ao espaço de trabalho fleet-default. O espaço de trabalho fleet-local inclui o cluster local (de gerenciamento). A partir daqui, é possível Pause ou Force update os clusters ou mover o cluster para outro espaço de trabalho. Editar o cluster permite atualizar rótulos e anotações usados para agrupar os clusters.

9.3.4 Grupos de clusters

Esta seção permite o agrupamento personalizado dos clusters dentro do espaço de trabalho usando seletores.

9.3.5 Avançado

A seção "Avançado" permite gerenciar espaços de trabalho e outros recursos relacionados do Fleet.

9.4 Exemplo de instalação do KubeVirt com Rancher e Fleet usando o painel do Rancher

  1. Crie um repositório Git contendo o arquivo fleet.yaml:

    defaultNamespace: kubevirt
    helm:
      chart: "oci://registry.suse.com/edge/charts/kubevirt"
      version: "306.0.2+up0.7.0"
      # kubevirt namespace is created by kubevirt as well, we need to take ownership of it
      takeOwnership: true
  2. No painel do Rancher, navegue até ☰ > Entrega contínua > Repositórios Git e clique em Add Repository.

  3. O assistente de criação de repositório orienta durante a criação do repositório Git. Forneça Nome, URL do repositório (referenciando o repositório Git criado na etapa anterior) e selecione a branch ou revisão apropriada. No caso de um repositório mais complexo, especifique Caminhos para usar vários diretórios em um único repositório.

    fleet create repo1
  4. Clique em Next.

  5. Na próxima etapa, você pode definir onde as cargas de trabalho serão implantadas. A seleção de clusters oferece várias opções básicas: você pode não selecionar nenhum cluster, selecionar todos os clusters ou escolher diretamente um cluster gerenciado específico ou um grupo de clusters (se definido). A opção "Avançado" permite editar diretamente os seletores via YAML.

    fleet create repo2
  6. Clique em Create. O repositório é criado. A partir de agora, as cargas de trabalho são instaladas e mantidas sincronizadas nos clusters que correspondem à definição do repositório.

9.5 Depuração e solução de problemas

A seção de navegação "Avançado" fornece visões gerais de recursos de nível inferior do Fleet. Um bundle é um recurso interno usado para a orquestração de recursos a partir do Git. Quando um repositório Git é verificado, ele produz um ou mais bundles.

Para encontrar bundles relevantes para um repositório específico, vá para a página de detalhes do repositório Git e clique na guia Bundles.

fleet repo bundles

Para cada cluster, o bundle é aplicado a um recurso BundleDeployment que é criado. Para visualizar os detalhes do BundleDeployment, clique no botão Graph no canto superior direito da página de detalhes do repositório Git. Um gráfico de Repositório > Bundles > BundleDeployments é carregado. Clique no BundleDeployment no gráfico para ver seus detalhes e clique em Id para visualizar o YAML do BundleDeployment.

fleet repo graph

Para obter informações adicionais sobre dicas de solução de problemas do Fleet, consulte aqui.

9.6 Exemplos do Fleet

A equipe Edge mantém um repositório com exemplos de instalação de projetos Edge com o Fleet.

O projeto Fleet inclui um repositório fleet-examples que cobre todos os casos de uso para estrutura de repositório Git.

10 SUSE Linux Micro

Consulte a documentação oficial do SUSE Linux Micro

O SUSE Linux Micro é um sistema operacional leve e seguro para a borda. Ele funde os componentes corporativos robustos do SUSE Linux Enterprise com os recursos que os desenvolvedores desejam em um sistema operacional moderno e estável. Como resultado, você obtém uma plataforma de infraestrutura confiável, simples de usar e com a mais alta conformidade da categoria.

10.1 Como o SUSE Telco Cloud usa o SUSE Linux Micro?

Usamos o SUSE Linux Micro como o sistema operacional base para nossa pilha de plataforma. Isso nos fornece uma base segura, estável e mínima para construir.

O SUSE Linux Micro é único em seu uso de instantâneos do sistema de arquivos (Btrfs) para permitir rollbacks fáceis caso algo dê errado durante o fazer upgrade. Isso permite fazer upgrade remoto para toda a plataforma, mesmo sem acesso físico em caso de problemas.

10.2 Melhores práticas

10.2.1 Mídia de instalação

O SUSE Telco Cloud usa o Edge Image Builder (Capítulo 12, Edge Image Builder) para pré-configurar a imagem de instalação para auto-instalação do SUSE Linux Micro.

10.2.2 Administração local

O SUSE Linux Micro vem com o Cockpit para permitir o gerenciamento local do host por meio de um aplicativo Web.

Este serviço está desativado por padrão, mas pode ser iniciado ativando o serviço systemd cockpit.socket. Como o Cockpit proíbe o login root por padrão, a criação de um usuário com privilégios administrativos é recomendada; consulte a documentação oficial do SUSE Linux Micro para obter mais informações.

10.3 Problemas conhecidos

  • Não há ambiente de desktop disponível no SUSE Linux Micro no momento, mas uma solução conteinerizada está em desenvolvimento.

11 Metal3

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

O Metal3 fornece recursos nativos do Kubernetes para gerenciar o ciclo de vida de servidores bare-metal que oferecem suporte a gerenciamento via protocolos fora de banda, como Redfish.

Ele também possui suporte maduro para Cluster API (CAPI). Isso permite o gerenciamento de recursos de hardware em vários provedores de infraestrutura por meio de APIs neutras de fornecedores amplamente adotadas. O Cluster API usa o Metal3 como um backend de infraestrutura para objetos Machine.

11.1 Como o SUSE Telco Cloud usa o Metal3?

O SUSE Telco Cloud usa o Metal3 para gerenciar o ciclo de vida de hardware físico, como servidores. O hardware precisa oferecer suporte a um protocolo de gerenciamento fora de banda que seja suportado pelo Metal3 (por exemplo, Redfish). Quando um cluster de gerenciamento SUSE Telco Cloud provisiona ou desprovisiona clusters downstream, o Metal3 interagirá com o BMC de um servidor via Redfish. As seguintes ações geralmente fazem parte dessa interação:

  • Montar e desmontar Mídia Virtual.

  • Ligar, desligar e reiniciar servidores.

Essa abordagem é útil para cenários onde o hardware de destino oferece suporte a gerenciamento fora de banda e um fluxo de gerenciamento de infraestrutura totalmente automatizado é desejado.

O Metal3 e o CAPI fornecem APIs declarativas que permitem o gerenciamento de inventário e estado de servidores bare-metal, incluindo inspeção, limpeza e provisionamento/desprovisionamento automatizados.

11.2 Problemas conhecidos

  • O controlador de Gerenciamento de Endereço IP upstream não é suportado atualmente, pois ainda não é compatível com nossa escolha de ferramentas de configuração de rede. No entanto, o pod ipam-controller-manager hospedado no namespace metal3-ipam-system é necessário, pois o CAPM3 requer que os CRDs ipam existam.

  • Relacionado a isso, os recursos de IPAM e os campos networkData do Metal3DataTemplate não são suportados.

  • Apenas a implantação via redfish-virtualmedia é suportada atualmente.

12 Edge Image Builder

Consulte o Repositório Oficial.

O Edge Image Builder (EIB) é uma ferramenta que simplifica a geração de imagens de disco personalizadas e prontas para inicialização (CRB) para máquinas de bootstrapping. Essas imagens permitem a implantação de ponta a ponta de toda a pilha de software SUSE com uma única imagem.

Embora o EIB possa criar imagens CRB para todos os cenários de provisionamento, o EIB demonstra um valor tremendo em implantações air-gapped com redes limitadas ou completamente isoladas.

12.1 Como o SUSE Telco Cloud usa o Edge Image Builder?

SUSE Telco Cloud usa o EIB para a configuração simplificada e rápida de imagens personalizadas do SUSE Linux Micro para uma variedade de cenários. Esses cenários incluem o bootstrapping de máquinas virtuais e bare metal:

  • Implantações totalmente air-gapped de K3s/RKE2 Kubernetes (nó único e multi-nó)

  • Implantações totalmente air-gapped de Helm charts e manifestos do Kubernetes

  • Registro no Rancher via API Elemental

  • Metal3

  • Rede personalizada (por exemplo, IP estático, nome de host, VLANs, bonding, etc.)

  • Configurações personalizadas do sistema operacional (por exemplo, usuários, grupos, senhas, chaves SSH, proxies, NTP, certificados SSL personalizados, etc.)

  • Instalação air-gapped de pacotes RPM em nível de host e carregados lateralmente (incluindo resolução de dependências)

  • Registro no SUSE Multi-Linux Manager para gerenciamento do sistema operacional

  • Imagens de contêiner incorporadas

  • Argumentos da linha de comando do kernel

  • Unidades do systemd a serem habilitadas/desabilitadas no momento da inicialização

  • Scripts e arquivos personalizados para quaisquer tarefas manuais

12.2 Operações iniciais

Documentação abrangente para o uso e teste do Edge Image Builder pode ser encontrada aqui.

Adicionalmente, veja Capítulo 5, Clusters autônomos com o Edge Image Builder cobrindo um cenário básico de implantação.

Assim que estiver familiarizado com esta ferramenta, encontre mais informações úteis em nossa página seção de Dicas e Truques do EIB (Parte X, “Dicas e truques”).

12.3 Problemas conhecidos

  • O EIB aplica air-gap aos Helm charts por meio da criação de templates para os Helm charts e da análise de todas as imagens presentes no template. Se um Helm chart não mantiver todas as suas imagens dentro do template e, em vez disso, carregá-las lateralmente, o EIB não será capaz de air-gap essas imagens automaticamente. A solução para isso é adicionar manualmente quaisquer imagens não detectadas à seção embeddedArtifactRegistry do arquivo de definição.

13 Rede de borda

Esta seção descreve a abordagem para a configuração de rede na solução SUSE Telco Cloud. Mostraremos como configurar o NetworkManager no SUSE Linux Micro de maneira declarativa e explicaremos como as ferramentas relacionadas são integradas.

13.1 Visão geral do NetworkManager

O NetworkManager é uma ferramenta que gerencia a conexão de rede principal e outras interfaces de conexão.

O NetworkManager armazena configurações de rede como arquivos de conexão que contêm o estado desejado. Essas conexões são armazenadas como arquivos no diretório /etc/NetworkManager/system-connections/.

Detalhes sobre o NetworkManager podem ser encontrados na documentação do SUSE Linux Micro.

13.2 Visão geral do nmstate

O nmstate é uma biblioteca amplamente adotada (com uma ferramenta de CLI associada) que oferece uma API declarativa para configurações de rede por meio de um esquema predefinido.

Detalhes sobre o nmstate podem ser encontrados na documentação upstream.

13.3 Digite: NetworkManager Configurator (nmc)

As opções de personalização de rede disponíveis no SUSE Telco Cloud são obtidas por meio de uma ferramenta de CLI chamada NetworkManager Configurator ou nmc, para abreviar. Ela aproveita a funcionalidade fornecida pela biblioteca nmstate e, como tal, é totalmente capaz de configurar endereços IP estáticos, servidores DNS, VLANs, vínculo de rede, bridges, etc. Esta ferramenta nos permite gerar configurações de rede a partir de estados desejados predefinidos e aplicá-las em muitos nós diferentes de forma automatizada.

Detalhes sobre o NetworkManager Configurator (nmc) podem ser encontrados no repositório upstream.

13.4 Como o SUSE Telco Cloud usa o NetworkManager Configurator?

O SUSE Telco Cloud utiliza o nmc para as personalizações de rede nos vários modelos de provisionamento diferentes: * Configurações de rede personalizadas nos cenários de provisionamento de rede direcionado (Capítulo 4, Implantações automatizadas de BMC com Metal3) * Configurações estáticas declarativas nos cenários de Provisionamento Baseado em Imagem (Capítulo 5, Clusters autônomos com o Edge Image Builder)

13.5 Configurando com o Edge Image Builder

O Edge Image Builder (EIB) é uma ferramenta que permite configurar vários hosts com uma única imagem de SO. Nesta seção, mostraremos como você pode usar uma abordagem declarativa para descrever os estados de rede desejados, como eles são convertidos para as respectivas conexões do NetworkManager e, em seguida, aplicados durante o processo de provisionamento.

13.5.1 Pré-requisitos

Se você está seguindo este guia, presume-se que você já tenha o seguinte disponível:

  • Um AMD64/Intel 64 host físico (ou máquina virtual) executando o SLES 15 SP6 ou openSUSE Leap 15.6

  • Um tempo de execução do contêiner disponível (por exemplo, Podman)

  • Uma cópia da imagem RAW do SUSE Linux Micro 6.2 encontrada aqui

13.5.2 Obtendo a imagem de contêiner do Edge Image Builder

A imagem de contêiner do EIB está disponível publicamente e pode ser baixada do registro SUSE Telco Cloud executando:

podman pull registry.suse.com/edge/3.6/edge-image-builder:1.3.3.1

13.5.3 Criando o diretório de configuração da imagem

Vamos começar criando o diretório de configuração:

export CONFIG_DIR=$HOME/eib
mkdir -p $CONFIG_DIR/base-images

Agora, garantiremos que a cópia da imagem base baixada seja movida para o diretório de configuração:

mv /path/to/downloads/SL-Micro.x86_64-6.2-Base-GM.raw $CONFIG_DIR/base-images/
Nota
Nota

O EIB nunca modificará a entrada da imagem base. Ele criará uma nova imagem com suas modificações.

O diretório de configuração neste ponto deve estar assim:

└── base-images/
    └── SL-Micro.x86_64-6.2-Base-GM.raw

13.5.4 Criando o arquivo de definição da imagem

O arquivo de definição descreve a maioria das opções configuráveis que o Edge Image Builder suporta.

Vamos começar com um arquivo de definição bem básico para nossa imagem de SO:

cat << EOF > $CONFIG_DIR/definition.yaml
apiVersion: 1.3
image:
  arch: x86_64
  imageType: raw
  baseImage: SL-Micro.x86_64-6.2-Base-GM.raw
  outputImageName: modified-image.raw
operatingSystem:
  users:
    - username: root
      encryptedPassword: $6$jHugJNNd3HElGsUZ$eodjVe4te5ps44SVcWshdfWizrP.xAyd71CVEXazBJ/.v799/WRCBXxfYmunlBO2yp1hm/zb4r8EmnrrNCF.P/
EOF

A seção image é obrigatória e especifica a imagem de entrada, sua arquitetura e tipo, bem como o nome que a imagem de saída terá. A seção operatingSystem é opcional e contém a configuração para habilitar o login nos sistemas provisionados com o nome de usuário/senha root/eib.

Nota
Nota

Sinta-se à vontade para usar sua própria senha criptografada executando openssl passwd -6 <password>.

O diretório de configuração neste ponto deve estar assim:

├── definition.yaml
└── base-images/
    └── SL-Micro.x86_64-6.2-Base-GM.raw

13.5.5 Definindo as configurações de rede

As configurações de rede desejadas não fazem parte do arquivo de definição de imagem que acabamos de criar. Agora vamos preenchê-las no diretório especial network/. Vamos criá-lo:

mkdir -p $CONFIG_DIR/network

Como mencionado anteriormente, a ferramenta NetworkManager Configurator (nmc) espera uma entrada na forma de um esquema predefinido. Você pode encontrar como configurar uma ampla variedade de diferentes opções de rede na documentação de exemplos upstream do NMState.

Este guia explicará como configurar a rede em três nós diferentes:

  • Um nó que usa duas interfaces Ethernet

  • Um nó que usa vínculo de rede

  • Um nó que usa uma ponte de rede

Atenção
Atenção

O uso de configurações de rede completamente diferentes não é recomendado em compilações de produção, especialmente se estiver configurando clusters Kubernetes. As configurações de rede geralmente devem ser homogêneas entre os nós ou, pelo menos, entre as funções dentro de um determinado cluster. Este guia inclui várias opções diferentes apenas para servir como uma referência de exemplo.

Nota
Nota

O seguinte pressupõe uma rede libvirt padrão com um intervalo de endereços IP 192.168.122.1/24. Ajuste de acordo se isso for diferente em seu ambiente.

Vamos criar os estados desejados para o primeiro nó que chamaremos de node1.suse.com:

cat << EOF > $CONFIG_DIR/network/node1.suse.com.yaml
routes:
  config:
    - destination: 0.0.0.0/0
      metric: 100
      next-hop-address: 192.168.122.1
      next-hop-interface: eth0
      table-id: 254
    - destination: 192.168.122.0/24
      metric: 100
      next-hop-address: 192.168.122.1
      next-hop-interface: eth0
      table-id: 254
dns-resolver:
  config:
    server:
      - 192.168.122.1
      - 8.8.8.8
interfaces:
  - name: eth0
    type: ethernet
    state: up
    mac-address: 34:8A:B1:4B:16:E1
    ipv4:
      address:
        - ip: 192.168.122.50
          prefix-length: 24
      dhcp: false
      enabled: true
    ipv6:
      enabled: false
  - name: eth3
    type: ethernet
    state: down
    mac-address: 34:8A:B1:4B:16:E2
    ipv4:
      address:
        - ip: 192.168.122.55
          prefix-length: 24
      dhcp: false
      enabled: true
    ipv6:
      enabled: false
EOF

Neste exemplo, definimos um estado desejado de duas interfaces Ethernet (eth0 e eth3), seus endereços IP solicitados, roteamento e resolução de DNS.

Atenção
Atenção

Você deve garantir que os endereços MAC de todas as interfaces Ethernet estejam listados. Eles são usados durante o processo de provisionamento como os identificadores dos nós e servem para determinar quais configurações devem ser aplicadas. É assim que conseguimos configurar vários nós usando uma única imagem ISO ou RAW.

A seguir, temos o segundo nó, que chamaremos de node2.suse.com e que usará vínculo de rede:

cat << EOF > $CONFIG_DIR/network/node2.suse.com.yaml
routes:
  config:
    - destination: 0.0.0.0/0
      metric: 100
      next-hop-address: 192.168.122.1
      next-hop-interface: bond99
      table-id: 254
    - destination: 192.168.122.0/24
      metric: 100
      next-hop-address: 192.168.122.1
      next-hop-interface: bond99
      table-id: 254
dns-resolver:
  config:
    server:
      - 192.168.122.1
      - 8.8.8.8
interfaces:
  - name: bond99
    type: bond
    state: up
    ipv4:
      address:
        - ip: 192.168.122.60
          prefix-length: 24
      enabled: true
    link-aggregation:
      mode: balance-rr
      options:
        miimon: '140'
      port:
        - eth0
        - eth1
  - name: eth0
    type: ethernet
    state: up
    mac-address: 34:8A:B1:4B:16:E3
    ipv4:
      enabled: false
    ipv6:
      enabled: false
  - name: eth1
    type: ethernet
    state: up
    mac-address: 34:8A:B1:4B:16:E4
    ipv4:
      enabled: false
    ipv6:
      enabled: false
EOF

Neste exemplo, definimos um estado desejado de duas interfaces Ethernet (eth0 e eth1) que não estão habilitando o endereçamento IP, bem como um vínculo de rede com uma política round-robin e seu respectivo endereço, que será usado para encaminhar o tráfego de rede.

Por último, criaremos o terceiro e último arquivo de estado desejado, que utilizará uma ponte de rede e que chamaremos de node3.suse.com:

cat << EOF > $CONFIG_DIR/network/node3.suse.com.yaml
routes:
  config:
    - destination: 0.0.0.0/0
      metric: 100
      next-hop-address: 192.168.122.1
      next-hop-interface: linux-br0
      table-id: 254
    - destination: 192.168.122.0/24
      metric: 100
      next-hop-address: 192.168.122.1
      next-hop-interface: linux-br0
      table-id: 254
dns-resolver:
  config:
    server:
      - 192.168.122.1
      - 8.8.8.8
interfaces:
  - name: eth0
    type: ethernet
    state: up
    mac-address: 34:8A:B1:4B:16:E5
    ipv4:
      enabled: false
    ipv6:
      enabled: false
  - name: linux-br0
    type: linux-bridge
    state: up
    ipv4:
      address:
        - ip: 192.168.122.70
          prefix-length: 24
      dhcp: false
      enabled: true
    bridge:
      options:
        group-forward-mask: 0
        mac-ageing-time: 300
        multicast-snooping: true
        stp:
          enabled: true
          forward-delay: 15
          hello-time: 2
          max-age: 20
          priority: 32768
      port:
        - name: eth0
          stp-hairpin-mode: false
          stp-path-cost: 100
          stp-priority: 32
EOF

O diretório de configuração neste ponto deve estar assim:

├── definition.yaml
├── network/
│   │── node1.suse.com.yaml
│   │── node2.suse.com.yaml
│   └── node3.suse.com.yaml
└── base-images/
    └── SL-Micro.x86_64-6.2-Base-GM.raw
Nota
Nota

Os nomes dos arquivos no diretório network/ são intencionais. Eles correspondem aos nomes de host que serão definidos durante o processo de provisionamento.

13.5.6 Criando a imagem do SO

Agora que todas as configurações necessárias estão no lugar, podemos criar a imagem simplesmente executando:

podman run --rm -it -v $CONFIG_DIR:/eib registry.suse.com/edge/3.6/edge-image-builder:1.3.3.1 build --definition-file definition.yaml

A saída deve ser similar ao seguinte:

Generating image customization components...
Identifier ................... [SUCCESS]
Custom Files ................. [SKIPPED]
Time ......................... [SKIPPED]
Network ...................... [SUCCESS]
Groups ....................... [SKIPPED]
Users ........................ [SUCCESS]
Proxy ........................ [SKIPPED]
Rpm .......................... [SKIPPED]
Systemd ...................... [SKIPPED]
Elemental .................... [SKIPPED]
Suma ......................... [SKIPPED]
Embedded Artifact Registry ... [SKIPPED]
Keymap ....................... [SUCCESS]
Kubernetes ................... [SKIPPED]
Certificates ................. [SKIPPED]
Building RAW image...
Kernel Params ................ [SKIPPED]
Image build complete!

O trecho acima nos diz que o componente Network foi configurado com sucesso, e podemos prosseguir com o provisionamento de nossos nós de borda.

Nota
Nota

Um arquivo de log (network-config.log) e os respectivos arquivos de conexão do NetworkManager podem ser inspecionados no diretório _build resultante, dentro de um diretório com carimbo de data/hora para a execução da imagem.

13.5.7 Provisionando os nós de borda

Vamos copiar a imagem RAW resultante:

mkdir edge-nodes && cd edge-nodes
for i in {1..4}; do cp $CONFIG_DIR/modified-image.raw node$i.raw; done

Você notará que copiamos a imagem criada quatro vezes, mas especificamos as configurações de rede apenas para três nós. Isso ocorre porque também queremos mostrar o que acontecerá se provisionarmos um nó que não corresponda a nenhuma das configurações desejadas.

Nota
Nota

Este guia usará virtualização para os exemplos de provisionamento de nós. Certifique-se de que as extensões necessárias estejam habilitadas no BIOS (consulte aqui para obter detalhes).

Usaremos o virt-install para criar máquinas virtuais usando os discos brutos copiados. Cada máquina virtual usará 10 GB de RAM e 6 vCPUs.

13.5.7.1 Provisionando o primeiro nó

Vamos criar a máquina virtual:

virt-install --name node1 --ram 10000 --vcpus 6 --disk path=node1.raw,format=raw --osinfo detect=on,name=sle-unknown --graphics none --console pty,target_type=serial --network default,mac=34:8A:B1:4B:16:E1 --network default,mac=34:8A:B1:4B:16:E2 --virt-type kvm --import
Nota
Nota

É importante que criemos as interfaces de rede com os mesmos endereços MAC que os descritos no estado desejado acima.

Assim que a operação for concluída, veremos algo semelhante ao seguinte:

Starting install...
Creating domain...

Running text console command: virsh --connect qemu:///system console node1
Connected to domain 'node1'
Escape character is ^] (Ctrl + ])


Welcome to SUSE Linux Micro 6.0 (x86_64) - Kernel 6.4.0-18-default (tty1).

SSH host key: SHA256:XN/R5Tw43reG+QsOw480LxCnhkc/1uqMdwlI6KUBY70 (RSA)
SSH host key: SHA256:/96yGrPGKlhn04f1rb9cXv/2WJt4TtrIN5yEcN66r3s (DSA)
SSH host key: SHA256:Dy/YjBQ7LwjZGaaVcMhTWZNSOstxXBsPsvgJTJq5t00 (ECDSA)
SSH host key: SHA256:TNGqY1LRddpxD/jn/8dkT/9YmVl9hiwulqmayP+wOWQ (ED25519)
eth0: 192.168.122.50
eth1:


Configured with the Edge Image Builder
Activate the web console with: systemctl enable --now cockpit.socket

node1 login:

Agora podemos fazer login com o par de credenciais root:eib. Também podemos acessar o host via SSH se preferirmos isso em vez do virsh console que nos é apresentado aqui.

Uma vez logado, vamos confirmar se todas as configurações estão no lugar.

Verifique se o nome do host está definido corretamente:

node1:~ # hostnamectl
 Static hostname: node1.suse.com
 ...

Verifique se o roteamento está configurado corretamente:

node1:~ # ip r
default via 192.168.122.1 dev eth0 proto static metric 100
192.168.122.0/24 dev eth0 proto static scope link metric 100
192.168.122.0/24 dev eth0 proto kernel scope link src 192.168.122.50 metric 100

Verifique se a conexão com a Internet está disponível:

node1:~ # ping google.com
PING google.com (142.250.72.78) 56(84) bytes of data.
64 bytes from den16s09-in-f14.1e100.net (142.250.72.78): icmp_seq=1 ttl=56 time=13.2 ms
64 bytes from den16s09-in-f14.1e100.net (142.250.72.78): icmp_seq=2 ttl=56 time=13.4 ms
^C
--- google.com ping statistics ---
2 packets transmitted, 2 received, 0% packet loss, time 1002ms
rtt min/avg/max/mdev = 13.248/13.304/13.361/0.056 ms

Verifique se exatamente duas interfaces Ethernet estão configuradas e apenas uma delas está ativa:

node1:~ # ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host
       valid_lft forever preferred_lft forever
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
    link/ether 34:8a:b1:4b:16:e1 brd ff:ff:ff:ff:ff:ff
    altname enp0s2
    altname ens2
    inet 192.168.122.50/24 brd 192.168.122.255 scope global noprefixroute eth0
       valid_lft forever preferred_lft forever
3: eth1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
    link/ether 34:8a:b1:4b:16:e2 brd ff:ff:ff:ff:ff:ff
    altname enp0s3
    altname ens3

node1:~ # nmcli -f NAME,UUID,TYPE,DEVICE,FILENAME con show
NAME  UUID                                  TYPE      DEVICE  FILENAME
eth0  dfd202f5-562f-5f07-8f2a-a7717756fb70  ethernet  eth0    /etc/NetworkManager/system-connections/eth0.nmconnection
eth1  7e211aea-3d14-59cf-a4fa-be91dac5dbba  ethernet  --      /etc/NetworkManager/system-connections/eth1.nmconnection

Você notará que a segunda interface é eth1 em vez da eth3 predefinida em nosso estado de rede desejado. Isso ocorre porque o Configurador do NetworkManager (nmc) é capaz de detectar que o SO deu um nome diferente para a NIC com endereço MAC 34:8a:b1:4b:16:e2 e ajusta suas configurações de acordo.

Verifique se isso realmente aconteceu inspecionando a fase de Combustion do provisionamento:

node1:~ # journalctl -u combustion | grep nmc
Apr 23 09:20:19 localhost.localdomain combustion[1360]: [2024-04-23T09:20:19Z INFO  nmc::apply_conf] Identified host: node1.suse.com
Apr 23 09:20:19 localhost.localdomain combustion[1360]: [2024-04-23T09:20:19Z INFO  nmc::apply_conf] Set hostname: node1.suse.com
Apr 23 09:20:19 localhost.localdomain combustion[1360]: [2024-04-23T09:20:19Z INFO  nmc::apply_conf] Processing interface 'eth0'...
Apr 23 09:20:19 localhost.localdomain combustion[1360]: [2024-04-23T09:20:19Z INFO  nmc::apply_conf] Processing interface 'eth3'...
Apr 23 09:20:19 localhost.localdomain combustion[1360]: [2024-04-23T09:20:19Z INFO  nmc::apply_conf] Using interface name 'eth1' instead of the preconfigured 'eth3'
Apr 23 09:20:19 localhost.localdomain combustion[1360]: [2024-04-23T09:20:19Z INFO  nmc] Successfully applied config

Provisionaremos agora o restante dos nós, mas mostraremos apenas as diferenças na configuração final. Sinta-se à vontade para aplicar qualquer uma ou todas as verificações acima para todos os nós que você está prestes a provisionar.

13.5.7.2 Provisionando o segundo nó

Vamos criar a máquina virtual:

virt-install --name node2 --ram 10000 --vcpus 6 --disk path=node2.raw,format=raw --osinfo detect=on,name=sle-unknown --graphics none --console pty,target_type=serial --network default,mac=34:8A:B1:4B:16:E3 --network default,mac=34:8A:B1:4B:16:E4 --virt-type kvm --import

Assim que a máquina virtual estiver em execução, podemos confirmar que este nó está usando interfaces de vínculo.

node2:~ # ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host
       valid_lft forever preferred_lft forever
2: eth0: <BROADCAST,MULTICAST,SLAVE,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast master bond99 state UP group default qlen 1000
    link/ether 34:8a:b1:4b:16:e3 brd ff:ff:ff:ff:ff:ff
    altname enp0s2
    altname ens2
3: eth1: <BROADCAST,MULTICAST,SLAVE,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast master bond99 state UP group default qlen 1000
    link/ether 34:8a:b1:4b:16:e3 brd ff:ff:ff:ff:ff:ff permaddr 34:8a:b1:4b:16:e4
    altname enp0s3
    altname ens3
4: bond99: <BROADCAST,MULTICAST,MASTER,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000
    link/ether 34:8a:b1:4b:16:e3 brd ff:ff:ff:ff:ff:ff
    inet 192.168.122.60/24 brd 192.168.122.255 scope global noprefixroute bond99
       valid_lft forever preferred_lft forever

Confirme que o roteamento está usando a interface de vínculo:

node2:~ # ip r
default via 192.168.122.1 dev bond99 proto static metric 100
192.168.122.0/24 dev bond99 proto static scope link metric 100
192.168.122.0/24 dev bond99 proto kernel scope link src 192.168.122.60 metric 300

Garanta que os arquivos de conexão estática sejam utilizados corretamente:

node2:~ # nmcli -f NAME,UUID,TYPE,DEVICE,FILENAME con show
NAME    UUID                                  TYPE      DEVICE  FILENAME
bond99  4a920503-4862-5505-80fd-4738d07f44c6  bond      bond99  /etc/NetworkManager/system-connections/bond99.nmconnection
eth0    dfd202f5-562f-5f07-8f2a-a7717756fb70  ethernet  eth0    /etc/NetworkManager/system-connections/eth0.nmconnection
eth1    0523c0a1-5f5e-5603-bcf2-68155d5d322e  ethernet  eth1    /etc/NetworkManager/system-connections/eth1.nmconnection

13.5.7.3 Provisionando o terceiro nó

Vamos criar a máquina virtual:

virt-install --name node3 --ram 10000 --vcpus 6 --disk path=node3.raw,format=raw --osinfo detect=on,name=sle-unknown --graphics none --console pty,target_type=serial --network default,mac=34:8A:B1:4B:16:E5 --virt-type kvm --import

Assim que a máquina virtual estiver em execução, podemos confirmar que este nó está usando uma ponte de rede:

node3:~ # ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host
       valid_lft forever preferred_lft forever
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast master linux-br0 state UP group default qlen 1000
    link/ether 34:8a:b1:4b:16:e5 brd ff:ff:ff:ff:ff:ff
    altname enp0s2
    altname ens2
3: linux-br0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000
    link/ether 34:8a:b1:4b:16:e5 brd ff:ff:ff:ff:ff:ff
    inet 192.168.122.70/24 brd 192.168.122.255 scope global noprefixroute linux-br0
       valid_lft forever preferred_lft forever

Confirme que o roteamento está usando a ponte:

node3:~ # ip r
default via 192.168.122.1 dev linux-br0 proto static metric 100
192.168.122.0/24 dev linux-br0 proto static scope link metric 100
192.168.122.0/24 dev linux-br0 proto kernel scope link src 192.168.122.70 metric 425

Garanta que os arquivos de conexão estática sejam utilizados corretamente:

node3:~ # nmcli -f NAME,UUID,TYPE,DEVICE,FILENAME con show
NAME       UUID                                  TYPE      DEVICE     FILENAME
linux-br0  1f8f1469-ed20-5f2c-bacb-a6767bee9bc0  bridge    linux-br0  /etc/NetworkManager/system-connections/linux-br0.nmconnection
eth0       dfd202f5-562f-5f07-8f2a-a7717756fb70  ethernet  eth0       /etc/NetworkManager/system-connections/eth0.nmconnection

13.5.7.4 Provisionando o quarto nó

Por último, provisionaremos um nó que não corresponderá a nenhuma das configurações predefinidas por um endereço MAC. Nestes casos, usaremos o DHCP por padrão para configurar as interfaces de rede.

Vamos criar a máquina virtual:

virt-install --name node4 --ram 10000 --vcpus 6 --disk path=node4.raw,format=raw --osinfo detect=on,name=sle-unknown --graphics none --console pty,target_type=serial --network default --virt-type kvm --import

Assim que a máquina virtual estiver em execução, podemos confirmar que este nó está usando um endereço IP aleatório para sua interface de rede:

localhost:~ # ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host
       valid_lft forever preferred_lft forever
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
    link/ether 52:54:00:56:63:71 brd ff:ff:ff:ff:ff:ff
    altname enp0s2
    altname ens2
    inet 192.168.122.86/24 brd 192.168.122.255 scope global dynamic noprefixroute eth0
       valid_lft 3542sec preferred_lft 3542sec
    inet6 fe80::5054:ff:fe56:6371/64 scope link noprefixroute
       valid_lft forever preferred_lft forever

Verifique se o nmc falhou ao aplicar configurações estáticas para este nó:

localhost:~ # journalctl -u combustion | grep nmc
Apr 23 12:15:45 localhost.localdomain combustion[1357]: [2024-04-23T12:15:45Z ERROR nmc] Applying config failed: None of the preconfigured hosts match local NICs

Verifique se a interface Ethernet foi configurada via DHCP:

localhost:~ # journalctl | grep eth0
Apr 23 12:15:29 localhost.localdomain NetworkManager[704]: <info>  [1713874529.7801] manager: (eth0): new Ethernet device (/org/freedesktop/NetworkManager/Devices/2)
Apr 23 12:15:29 localhost.localdomain NetworkManager[704]: <info>  [1713874529.7802] device (eth0): state change: unmanaged -> unavailable (reason 'managed', sys-iface-state: 'external')
Apr 23 12:15:29 localhost.localdomain NetworkManager[704]: <info>  [1713874529.7929] device (eth0): carrier: link connected
Apr 23 12:15:29 localhost.localdomain NetworkManager[704]: <info>  [1713874529.7931] device (eth0): state change: unavailable -> disconnected (reason 'carrier-changed', sys-iface-state: 'managed')
Apr 23 12:15:29 localhost.localdomain NetworkManager[704]: <info>  [1713874529.7944] device (eth0): Activation: starting connection 'Wired Connection' (300ed658-08d4-4281-9f8c-d1b8882d29b9)
Apr 23 12:15:29 localhost.localdomain NetworkManager[704]: <info>  [1713874529.7945] device (eth0): state change: disconnected -> prepare (reason 'none', sys-iface-state: 'managed')
Apr 23 12:15:29 localhost.localdomain NetworkManager[704]: <info>  [1713874529.7947] device (eth0): state change: prepare -> config (reason 'none', sys-iface-state: 'managed')
Apr 23 12:15:29 localhost.localdomain NetworkManager[704]: <info>  [1713874529.7953] device (eth0): state change: config -> ip-config (reason 'none', sys-iface-state: 'managed')
Apr 23 12:15:29 localhost.localdomain NetworkManager[704]: <info>  [1713874529.7964] dhcp4 (eth0): activation: beginning transaction (timeout in 90 seconds)
Apr 23 12:15:33 localhost.localdomain NetworkManager[704]: <info>  [1713874533.1272] dhcp4 (eth0): state changed new lease, address=192.168.122.86

localhost:~ # nmcli -f NAME,UUID,TYPE,DEVICE,FILENAME con show
NAME              UUID                                  TYPE      DEVICE  FILENAME
Wired Connection  300ed658-08d4-4281-9f8c-d1b8882d29b9  ethernet  eth0    /var/run/NetworkManager/system-connections/default_connection.nmconnection

13.5.8 Configurações de nó unificadas

Existem ocasiões em que depender de endereços MAC conhecidos não é uma opção. Nestes casos, podemos optar pela chamada configuração unificada, que nos permite especificar configurações em um arquivo _all.yaml que serão então aplicadas a todos os nós provisionados.

Vamos construir e provisionar um nó de borda usando uma estrutura de configuração diferente. Siga todos os passos começando de Seção 13.5.3, “Criando o diretório de configuração da imagem” até Seção 13.5.5, “Definindo as configurações de rede”.

Neste exemplo, definimos um estado desejado de duas interfaces Ethernet (eth0 e eth1) - uma usando DHCP e outra com um endereço IP estático atribuído.

mkdir -p $CONFIG_DIR/network

cat <<- EOF > $CONFIG_DIR/network/_all.yaml
interfaces:
- name: eth0
  type: ethernet
  state: up
  ipv4:
    dhcp: true
    enabled: true
  ipv6:
    enabled: false
- name: eth1
  type: ethernet
  state: up
  ipv4:
    address:
    - ip: 10.0.0.1
      prefix-length: 24
    enabled: true
    dhcp: false
  ipv6:
    enabled: false
EOF

Vamos construir a imagem:

podman run --rm -it -v $CONFIG_DIR:/eib registry.suse.com/edge/3.6/edge-image-builder:1.3.3.1 build --definition-file definition.yaml

Assim que a imagem for construída com sucesso, vamos criar uma máquina virtual usando-a:

virt-install --name node1 --ram 10000 --vcpus 6 --disk path=$CONFIG_DIR/modified-image.raw,format=raw --osinfo detect=on,name=sle-unknown --graphics none --console pty,target_type=serial --network default --network default --virt-type kvm --import

O processo de provisionamento pode levar alguns minutos. Assim que terminar, faça login no sistema com as credenciais fornecidas.

Verifique se o roteamento está configurado corretamente:

localhost:~ # ip r
default via 192.168.122.1 dev eth0 proto dhcp src 192.168.122.100 metric 100
10.0.0.0/24 dev eth1 proto kernel scope link src 10.0.0.1 metric 101
192.168.122.0/24 dev eth0 proto kernel scope link src 192.168.122.100 metric 100

Verifique se a conexão com a Internet está disponível:

localhost:~ # ping google.com
PING google.com (142.250.72.46) 56(84) bytes of data.
64 bytes from den16s08-in-f14.1e100.net (142.250.72.46): icmp_seq=1 ttl=56 time=14.3 ms
64 bytes from den16s08-in-f14.1e100.net (142.250.72.46): icmp_seq=2 ttl=56 time=14.2 ms
^C
--- google.com ping statistics ---
2 packets transmitted, 2 received, 0% packet loss, time 1001ms
rtt min/avg/max/mdev = 14.196/14.260/14.324/0.064 ms

Verifique se as interfaces Ethernet estão configuradas e ativas:

localhost:~ # ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host
       valid_lft forever preferred_lft forever
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
    link/ether 52:54:00:26:44:7a brd ff:ff:ff:ff:ff:ff
    altname enp1s0
    inet 192.168.122.100/24 brd 192.168.122.255 scope global dynamic noprefixroute eth0
       valid_lft 3505sec preferred_lft 3505sec
3: eth1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
    link/ether 52:54:00:ec:57:9e brd ff:ff:ff:ff:ff:ff
    altname enp7s0
    inet 10.0.0.1/24 brd 10.0.0.255 scope global noprefixroute eth1
       valid_lft forever preferred_lft forever

localhost:~ # nmcli -f NAME,UUID,TYPE,DEVICE,FILENAME con show
NAME  UUID                                  TYPE      DEVICE  FILENAME
eth0  dfd202f5-562f-5f07-8f2a-a7717756fb70  ethernet  eth0    /etc/NetworkManager/system-connections/eth0.nmconnection
eth1  0523c0a1-5f5e-5603-bcf2-68155d5d322e  ethernet  eth1    /etc/NetworkManager/system-connections/eth1.nmconnection

localhost:~ # cat /etc/NetworkManager/system-connections/eth0.nmconnection
[connection]
autoconnect=true
autoconnect-slaves=-1
id=eth0
interface-name=eth0
type=802-3-ethernet
uuid=dfd202f5-562f-5f07-8f2a-a7717756fb70

[ipv4]
dhcp-client-id=mac
dhcp-send-hostname=true
dhcp-timeout=2147483647
ignore-auto-dns=false
ignore-auto-routes=false
method=auto
never-default=false

[ipv6]
addr-gen-mode=0
dhcp-timeout=2147483647
method=disabled

localhost:~ # cat /etc/NetworkManager/system-connections/eth1.nmconnection
[connection]
autoconnect=true
autoconnect-slaves=-1
id=eth1
interface-name=eth1
type=802-3-ethernet
uuid=0523c0a1-5f5e-5603-bcf2-68155d5d322e

[ipv4]
address0=10.0.0.1/24
dhcp-timeout=2147483647
method=manual

[ipv6]
addr-gen-mode=0
dhcp-timeout=2147483647
method=disabled

13.5.9 Configurações de rede personalizadas

Já cobrimos a configuração de rede padrão para o Edge Image Builder, que depende do NetworkManager Configurator. No entanto, também existe a opção de modificá-la por meio de um script personalizado. Embora essa opção seja muito flexível e também não dependa do endereço MAC, sua limitação decorre do fato de que usá-la é muito menos conveniente ao inicializar vários nós com uma única imagem.

Nota
Nota

Recomenda-se usar a configuração de rede padrão por meio de arquivos que descrevem os estados de rede desejados no diretório /network. Opte pelo script personalizado apenas quando esse comportamento não for aplicável ao seu caso de uso.

Vamos construir e provisionar um nó de borda usando uma estrutura de configuração diferente. Siga todos os passos começando de Seção 13.5.3, “Criando o diretório de configuração da imagem” até Seção 13.5.5, “Definindo as configurações de rede”.

Neste exemplo, criaremos um script personalizado que aplica uma configuração estática para a interface eth0 em todos os nós provisionados, além de remover e desabilitar as conexões com fio criadas automaticamente pelo NetworkManager. Isso é benéfico em situações em que você deseja garantir que cada nó em seu cluster tenha uma configuração de rede idêntica e, como tal, você não precisa se preocupar com o endereço MAC de cada nó antes da criação da imagem.

Vamos começar armazenando o arquivo de conexão no diretório /custom/files:

mkdir -p $CONFIG_DIR/custom/files

cat << EOF > $CONFIG_DIR/custom/files/eth0.nmconnection
[connection]
autoconnect=true
autoconnect-slaves=-1
autoconnect-retries=1
id=eth0
interface-name=eth0
type=802-3-ethernet
uuid=dfd202f5-562f-5f07-8f2a-a7717756fb70
wait-device-timeout=60000

[ipv4]
dhcp-timeout=2147483647
method=auto

[ipv6]
addr-gen-mode=eui64
dhcp-timeout=2147483647
method=disabled
EOF

Agora que a configuração estática foi criada, também criaremos nosso script de rede personalizado:

mkdir -p $CONFIG_DIR/network

cat << EOF > $CONFIG_DIR/network/configure-network.sh
#!/bin/bash
set -eux

# Remove and disable wired connections
mkdir -p /etc/NetworkManager/conf.d/
printf "[main]\nno-auto-default=*\n" > /etc/NetworkManager/conf.d/no-auto-default.conf
rm -f /var/run/NetworkManager/system-connections/* || true

# Copy pre-configured network configuration files into NetworkManager
mkdir -p /etc/NetworkManager/system-connections/
cp eth0.nmconnection /etc/NetworkManager/system-connections/
chmod 600 /etc/NetworkManager/system-connections/*.nmconnection
EOF

chmod a+x $CONFIG_DIR/network/configure-network.sh
Nota
Nota

O binário nmc ainda será incluído por padrão, portanto, ele também pode ser usado no script configure-network.sh, se necessário.

Atenção
Atenção

O script personalizado deve sempre ser fornecido em /network/configure-network.sh no diretório de configuração. Se presente, todos os outros arquivos serão ignorados. NÃO é possível configurar uma rede trabalhando com configurações estáticas em formato YAML e um script personalizado simultaneamente.

O diretório de configuração neste ponto deve estar assim:

├── definition.yaml
├── custom/
│   └── files/
│       └── eth0.nmconnection
├── network/
│   └── configure-network.sh
└── base-images/
    └── SL-Micro.x86_64-6.2-Base-GM.raw

Vamos construir a imagem:

podman run --rm -it -v $CONFIG_DIR:/eib registry.suse.com/edge/3.6/edge-image-builder:1.3.3.1 build --definition-file definition.yaml

Assim que a imagem for construída com sucesso, vamos criar uma máquina virtual usando-a:

virt-install --name node1 --ram 10000 --vcpus 6 --disk path=$CONFIG_DIR/modified-image.raw,format=raw --osinfo detect=on,name=sle-unknown --graphics none --console pty,target_type=serial --network default --virt-type kvm --import

O processo de provisionamento pode levar alguns minutos. Assim que terminar, faça login no sistema com as credenciais fornecidas.

Verifique se o roteamento está configurado corretamente:

localhost:~ # ip r
default via 192.168.122.1 dev eth0 proto dhcp src 192.168.122.185 metric 100
192.168.122.0/24 dev eth0 proto kernel scope link src 192.168.122.185 metric 100

Verifique se a conexão com a Internet está disponível:

localhost:~ # ping google.com
PING google.com (142.250.72.78) 56(84) bytes of data.
64 bytes from den16s09-in-f14.1e100.net (142.250.72.78): icmp_seq=1 ttl=56 time=13.6 ms
64 bytes from den16s09-in-f14.1e100.net (142.250.72.78): icmp_seq=2 ttl=56 time=13.6 ms
^C
--- google.com ping statistics ---
2 packets transmitted, 2 received, 0% packet loss, time 1001ms
rtt min/avg/max/mdev = 13.592/13.599/13.606/0.007 ms

Verifique se uma interface Ethernet está configurada estaticamente usando nosso arquivo de conexão e se está ativa:

localhost:~ # ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host
       valid_lft forever preferred_lft forever
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
    link/ether 52:54:00:31:d0:1b brd ff:ff:ff:ff:ff:ff
    altname enp0s2
    altname ens2
    inet 192.168.122.185/24 brd 192.168.122.255 scope global dynamic noprefixroute eth0

localhost:~ # nmcli -f NAME,UUID,TYPE,DEVICE,FILENAME con show
NAME  UUID                                  TYPE      DEVICE  FILENAME
eth0  dfd202f5-562f-5f07-8f2a-a7717756fb70  ethernet  eth0    /etc/NetworkManager/system-connections/eth0.nmconnection

localhost:~ # cat  /etc/NetworkManager/system-connections/eth0.nmconnection
[connection]
autoconnect=true
autoconnect-slaves=-1
autoconnect-retries=1
id=eth0
interface-name=eth0
type=802-3-ethernet
uuid=dfd202f5-562f-5f07-8f2a-a7717756fb70
wait-device-timeout=60000

[ipv4]
dhcp-timeout=2147483647
method=auto

[ipv6]
addr-gen-mode=eui64
dhcp-timeout=2147483647
method=disabled

14 RKE2

Consulte a documentação oficial do RKE2.

O RKE2 é uma distribuição Kubernetes totalmente compatível que se dedica à segurança e conformidade por meio de:

  • Fornecimento de padrões e opções de configuração que permitem que os clusters cumpram o CIS Kubernetes Benchmark v1.6 ou v1.23 com um mínimo de intervenção do operador

  • Habilitação da conformidade com FIPS 140-2

  • Verificando regularmente os componentes em busca de CVEs usando trivy no pipeline de build do RKE2

O RKE2 inicia os componentes do plano de controle como pods estáticos, gerenciados pelo kubelet. O tempo de execução do contêiner incorporado é o containerd.

Nota: O RKE2 também é conhecido como RKE Government para transmitir outro caso de uso e setor que ele atende atualmente.

14.1 RKE2 vs K3s

O K3s é uma distribuição Kubernetes totalmente compatível e leve, focada em Edge, IoT, ARM - otimizada para facilidade de uso e ambientes com recursos limitados.

O RKE2 combina o melhor dos dois mundos da versão 1.x do RKE (doravante denominada RKE1) e do K3s.

Do K3s, ele herda a usabilidade, a facilidade de operação e o modelo de implantação.

Do RKE1, ele herda o alinhamento próximo com o Kubernetes upstream. Em alguns pontos, o K3s divergiu do Kubernetes upstream para otimizar implantações de edge, mas o RKE1 e o RKE2 podem permanecer estreitamente alinhados com o upstream.

14.2 Como o SUSE Telco Cloud usa o RKE2?

O RKE2 é uma peça fundamental da pilha SUSE Telco Cloud. Ele fica sobre o SUSE Linux Micro (Capítulo 10, SUSE Linux Micro), fornecendo uma interface Kubernetes padrão necessária para implantar cargas de trabalho de Edge.

14.3 Melhores práticas

14.3.1 Instalação

A maneira recomendada de instalar o RKE2 como parte da pilha SUSE Telco Cloud é usando o Edge Image Builder (EIB). Consulte a documentação do EIB (Capítulo 12, Edge Image Builder) para obter mais detalhes sobre como configurá-lo para implantar o RKE2.

O EIB é flexível o suficiente para suportar qualquer parâmetro exigido pelo RKE2, como especificar a versão do RKE2, a configuração dos servidores ou dos agentes, cobrindo todos os casos de uso de Edge.

Para outros casos de uso envolvendo o Metal3, o RKE2 também está sendo usado e instalado. Nesses casos específicos, o Cluster API Provider RKE2 implanta automaticamente o RKE2 em clusters que estão sendo provisionados com o Metal3 usando a Edge Stack.

Nesses casos, a configuração do RKE2 deve ser aplicada nos diferentes CRDs envolvidos. Um exemplo de como fornecer um CNI diferente usando o RKE2ControlPlane CRD é o seguinte:

apiVersion: controlplane.cluster.x-k8s.io/v1beta2
kind: RKE2ControlPlane
metadata:
  name: single-node-cluster
  namespace: default
spec:
  serverConfig:
    cni: calico
    cniMultusEnable: true
...

Para mais informações sobre os casos de uso do Metal3, consulte Capítulo 11, Metal3.

14.3.2 Alta disponibilidade

Para implantações de HA, o EIB implanta e configura automaticamente o MetalLB (Capítulo 17, MetalLB) e o Endpoint Copier Operator (Capítulo 18, Operador Endpoint Copier) para expor o endpoint da API do RKE2 externamente.

14.3.3 Projeto de Rede

A pilha SUSE Telco Cloud oferece suporte ao Cilium, Calico, com o Cilium como seu CNI padrão. O meta-plugin Multus também pode ser usado quando os pods exigem múltiplas interfaces de rede. O RKE2 independente oferece suporte a uma gama mais ampla de opções de CNI.

14.3.4 Armazenamento

O RKE2 não fornece nenhum tipo de classe de armazenamento persistente ou operadores. Para clusters que abrangem vários nós, recomenda-se usar o SUSE Storage (Capítulo 15, SUSE Storage).

O SUSE Storage é um sistema de armazenamento em blocos distribuído, leve, confiável e fácil de usar, projetado para o Kubernetes. É um produto baseado no Longhorn, um projeto de código aberto inicialmente desenvolvido pela Rancher Labs e atualmente incubado na CNCF.

15.1 Pré-requisitos

Se você está seguindo este guia, ele pressupõe que você já tenha o seguinte disponível:

  • Pelo menos um host com o SUSE Linux Micro 6.2 instalado; isso pode ser físico ou virtual

  • Um cluster Kubernetes instalado; seja K3s ou RKE2

  • Helm

15.2 Instalação manual do SUSE Storage

15.2.1 Instalando o Open-iSCSI

Um requisito fundamental para implantar e usar o SUSE Storage é a instalação do pacote open-iscsi e o daemon iscsid em execução em todos os nós do Kubernetes. Isso é necessário, já que o Longhorn depende do iscsiadm no host para fornecer volumes persistentes ao Kubernetes.

Vamos instalá-lo:

transactional-update pkg install open-iscsi

É importante observar que, uma vez concluída a operação, o pacote é instalado apenas em um novo snapshot, já que o SUSE Linux Micro é um sistema operacional imutável. Para carregá-lo e para que o daemon iscsid comece a ser executado, devemos reiniciar no novo snapshot que acabamos de criar. Emita o comando reboot quando estiver pronto:

reboot
Dica
Dica

Para obter ajuda adicional na instalação do open-iscsi, consulte a documentação oficial do Longhorn.

15.2.2 Instalando o SUSE Storage

Existem várias maneiras de instalar o SUSE Storage em seus clusters Kubernetes. Este guia seguirá a instalação via Helm; no entanto, sinta-se à vontade para seguir a documentação oficial caso deseje outra abordagem.

  1. Faça login na Coleção de Aplicativos do Rancher:

    helm registry login dp.apps.rancher.io --username $APPS.RANCHER.IO_USERNAME --password $APPS.RANCHER.IO_ACCESS_TOKEN
  2. Instale o SUSE Storage no namespace longhorn-system e adicione suas credenciais de registro de contêiner:

    helm install longhorn oci://dp.apps.rancher.io/charts/suse-storage \
      --version 1.11.2 \
      --namespace longhorn-system \
      --create-namespace \
      --set privateRegistry.createSecret=true \
      --set privateRegistry.registryUrl=dp.apps.rancher.io \
      --set privateRegistry.registryUser=$APPS.RANCHER.IO_USERNAME \
      --set privateRegistry.registryPasswd=$APPS.RANCHER.IO_ACCESS_TOKEN \
      --set privateRegistry.registrySecret=application-collection
  3. Confirme se a implantação foi bem-sucedida:

    kubectl -n longhorn-system get pods
    localhost:~ # kubectl -n longhorn-system get pods
    NAME                                                READY   STATUS    RESTARTS        AGE
    csi-attacher-7656559cf4-pkhh6                       1/1     Running   0               103s
    csi-attacher-7656559cf4-pnzw5                       1/1     Running   0               103s
    csi-attacher-7656559cf4-z94mm                       1/1     Running   0               103s
    csi-provisioner-6d9cf6456d-kcwtq                    1/1     Running   0               103s
    csi-provisioner-6d9cf6456d-mvvml                    1/1     Running   0               103s
    csi-provisioner-6d9cf6456d-q4f88                    1/1     Running   0               103s
    csi-resizer-f587cd467-clr2n                         1/1     Running   0               103s
    csi-resizer-f587cd467-z28v4                         1/1     Running   0               103s
    csi-resizer-f587cd467-zxmtx                         1/1     Running   0               103s
    csi-snapshotter-6dcdf78684-757mg                    1/1     Running   0               103s
    csi-snapshotter-6dcdf78684-8ktgc                    1/1     Running   0               103s
    csi-snapshotter-6dcdf78684-ffsqr                    1/1     Running   0               103s
    engine-image-ei-099f845a-lvdtr                      1/1     Running   0               2m21s
    instance-manager-4adffddaffe02374cd5635b8a6113de7   1/1     Running   0               111s
    longhorn-csi-plugin-w7pwr                           3/3     Running   0               103s
    longhorn-driver-deployer-6886fb84bc-wm9h6           1/1     Running   2 (2m32s ago)   2m45s
    longhorn-manager-zblbl                              2/2     Running   0               2m45s
    longhorn-ui-6bcc65d4bd-mcn6r                        1/1     Running   0               2m45s
    longhorn-ui-6bcc65d4bd-rwf97                        1/1     Running   0               2m45s

15.3 Criando volumes do SUSE Storage

O SUSE Storage utiliza recursos do Kubernetes chamados StorageClass para provisionar automaticamente objetos PersistentVolume para pods. Pense em StorageClass como uma maneira de os administradores descreverem as classes ou perfis de armazenamento que oferecem.

Vamos criar um StorageClass com algumas opções padrão:

kubectl apply -f - <<EOF
kind: StorageClass
apiVersion: storage.k8s.io/v1
metadata:
  name: longhorn-example
provisioner: driver.longhorn.io
allowVolumeExpansion: true
parameters:
  numberOfReplicas: "3"
  staleReplicaTimeout: "2880" # 48 hours in minutes
  fromBackup: ""
  fsType: "ext4"
EOF

Agora que temos nosso StorageClass disponível, precisamos de um PersistentVolumeClaim referenciando-o. Uma PersistentVolumeClaim (PVC) é uma solicitação de armazenamento feita por um usuário. PVCs consomem recursos de PersistentVolume. As solicitações podem pedir tamanhos e modos de acesso específicos (por exemplo, podem ser montadas uma vez como leitura/gravação ou várias vezes como somente leitura).

Vamos criar um PersistentVolumeClaim:

kubectl apply -f - <<EOF
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: longhorn-volv-pvc
  namespace: longhorn-system
spec:
  accessModes:
    - ReadWriteOnce
  storageClassName: longhorn-example
  resources:
    requests:
      storage: 2Gi
EOF

É isso! Assim que tivermos o PersistentVolumeClaim criado, podemos prosseguir com a anexação dele a um Pod. Quando o Pod é implantado, o Kubernetes cria o volume Longhorn e o vincula ao Pod se houver armazenamento disponível.

kubectl apply -f - <<EOF
apiVersion: v1
kind: Pod
metadata:
  name: volume-test
  namespace: longhorn-system
spec:
  containers:
  - name: volume-test
    image: nginx:stable-alpine
    imagePullPolicy: IfNotPresent
    volumeMounts:
    - name: volv
      mountPath: /data
    ports:
    - containerPort: 80
  volumes:
  - name: volv
    persistentVolumeClaim:
      claimName: longhorn-volv-pvc
EOF
Dica
Dica

O conceito de armazenamento no Kubernetes é um tópico complexo, mas importante. Mencionamos brevemente alguns dos recursos mais comuns do Kubernetes, no entanto, sugerimos que você se familiarize com a documentação de terminologia que o Longhorn oferece.

Neste exemplo, o resultado deve ser semelhante a isto:

localhost:~ # kubectl get storageclass
NAME                 PROVISIONER          RECLAIMPOLICY   VOLUMEBINDINGMODE   ALLOWVOLUMEEXPANSION   AGE
longhorn (default)   driver.longhorn.io   Delete          Immediate           true                   12m
longhorn-example     driver.longhorn.io   Delete          Immediate           true                   24s

localhost:~ # kubectl get pvc -n longhorn-system
NAME                STATUS   VOLUME                                     CAPACITY   ACCESS MODES   STORAGECLASS       AGE
longhorn-volv-pvc   Bound    pvc-f663a92e-ac32-49ae-b8e5-8a6cc29a7d1e   2Gi        RWO            longhorn-example   54s

localhost:~ # kubectl get pods -n longhorn-system
NAME                                                READY   STATUS    RESTARTS      AGE
csi-attacher-5c4bfdcf59-qmjtz                       1/1     Running   0             14m
csi-attacher-5c4bfdcf59-s7n65                       1/1     Running   0             14m
csi-attacher-5c4bfdcf59-w9xgs                       1/1     Running   0             14m
csi-provisioner-667796df57-fmz2d                    1/1     Running   0             14m
csi-provisioner-667796df57-p7rjr                    1/1     Running   0             14m
csi-provisioner-667796df57-w9fdq                    1/1     Running   0             14m
csi-resizer-694f8f5f64-2rb8v                        1/1     Running   0             14m
csi-resizer-694f8f5f64-z9v9x                        1/1     Running   0             14m
csi-resizer-694f8f5f64-zlncz                        1/1     Running   0             14m
csi-snapshotter-959b69d4b-5dpvj                     1/1     Running   0             14m
csi-snapshotter-959b69d4b-lwwkv                     1/1     Running   0             14m
csi-snapshotter-959b69d4b-tzhwc                     1/1     Running   0             14m
engine-image-ei-5cefaf2b-hvdv5                      1/1     Running   0             14m
instance-manager-0ee452a2e9583753e35ad00602250c5b   1/1     Running   0             14m
longhorn-csi-plugin-gd2jx                           3/3     Running   0             14m
longhorn-driver-deployer-9f4fc86-j6h2b              1/1     Running   0             15m
longhorn-manager-z4lnl                              1/1     Running   0             15m
longhorn-ui-5f4b7bbf69-bln7h                        1/1     Running   3 (14m ago)   15m
longhorn-ui-5f4b7bbf69-lh97n                        1/1     Running   3 (14m ago)   15m
volume-test                                         1/1     Running   0             26s

15.4 Acessando a interface do usuário

Se você instalou o SUSE Storage com kubectl ou Helm, precisará configurar um controlador Ingress para permitir tráfego externo no cluster. A autenticação não está habilitada por padrão. Se o aplicativo de catálogo do Rancher foi usado, o Rancher criou automaticamente um controlador Ingress com controle de acesso (o rancher-proxy).

  1. Obtenha o endereço IP do serviço externo do Longhorn:

    kubectl -n longhorn-system get svc
  2. Depois de recuperar o endereço IP longhorn-frontend, você pode começar a usar a interface do usuário navegando até ele em seu navegador.

15.5 Instalando com o Edge Image Builder

O SUSE Telco Cloud está usando o Capítulo 12, Edge Image Builder para personalizar imagens base do SUSE Linux Micro OS. Vamos demonstrar como fazer isso para provisionar um cluster RKE2 com o SUSE Storage sobre ele.

Vamos criar o arquivo de definição:

export CONFIG_DIR=$HOME/eib
mkdir -p $CONFIG_DIR

cat << EOF > $CONFIG_DIR/iso-definition.yaml
apiVersion: 1.3
image:
  imageType: iso
  baseImage: SL-Micro.x86_64-6.2-Base-SelfInstall-GM.install.iso
  arch: x86_64
  outputImageName: eib-image.iso
kubernetes:
  version: v1.35.4+rke2r1
  helm:
    charts:
      - name: suse-storage
        releaseName: longhorn
        version: 1.11.2
        repositoryName: rancher-application-collection
        targetNamespace: longhorn-system
        createNamespace: true
        installationNamespace: kube-system
    repositories:
      - name: rancher-application-collection
        url: oci://dp.apps.rancher.io/charts
        authentication:
          username: $APPS.RANCHER.IO_USERNAME
          password: $APPS.RANCHER.IO_ACCESS_TOKEN
embeddedArtifactRegistry:
  registries:
    - uri: dp.apps.rancher.io
      authentication:
        username: $APPS.RANCHER.IO_USERNAME
        password: $APPS.RANCHER.IO_ACCESS_TOKEN
  images:
    - name: dp.apps.rancher.io/containers/kubernetes-csi-external-attacher:4.11.0-13.2
    - name: dp.apps.rancher.io/containers/kubernetes-csi-external-provisioner:5.3.0-14.1
    - name: dp.apps.rancher.io/containers/kubernetes-csi-external-resizer:2.1.0-6.2
    - name: dp.apps.rancher.io/containers/kubernetes-csi-external-snapshotter:8.5.0-13.2
    - name: dp.apps.rancher.io/containers/kubernetes-csi-livenessprobe:2.18.0-13.2
    - name: dp.apps.rancher.io/containers/kubernetes-csi-node-driver-registrar:2.16.0-13.2
    - name: dp.apps.rancher.io/containers/longhorn-backing-image-manager:1.11.2-4.1
    - name: dp.apps.rancher.io/containers/longhorn-engine:1.11.2-4.2
    - name: dp.apps.rancher.io/containers/longhorn-instance-manager:1.11.2-4.3
    - name: dp.apps.rancher.io/containers/longhorn-manager:1.11.2-4.2
    - name: dp.apps.rancher.io/containers/longhorn-share-manager:1.11.2-4.1
    - name: dp.apps.rancher.io/containers/longhorn-ui:1.11.2-4.1
    - name: dp.apps.rancher.io/containers/rancher-support-bundle-kit:0.0.84-9.4
operatingSystem:
  packages:
    sccRegistrationCode: <reg-code>
    packageList:
      - open-iscsi
  users:
  - username: root
    encryptedPassword: \$6\$jHugJNNd3HElGsUZ\$eodjVe4te5ps44SVcWshdfWizrP.xAyd71CVEXazBJ/.v799/WRCBXxfYmunlBO2yp1hm/zb4r8EmnrrNCF.P/
EOF
Nota
Nota

A personalização de qualquer um dos valores do gráfico Helm é possível por meio de um arquivo separado fornecido em helm.charts[].valuesFile. Consulte a documentação upstream para obter detalhes.

Vamos criar a imagem:

podman run --rm --privileged -it -v $CONFIG_DIR:/eib registry.suse.com/edge/3.6/edge-image-builder:1.3.3.1 build --definition-file $CONFIG_DIR/iso-definition.yaml

Após a criação da imagem, você pode usá-la para instalar seu SO em um host físico ou virtual. Assim que o provisionamento for concluído, você poderá fazer login no sistema usando o par de credenciais root:eib.

Certifique-se de que o SUSE Storage tenha sido implantado com sucesso:

localhost:~ # /var/lib/rancher/rke2/bin/kubectl --kubeconfig /etc/rancher/rke2/rke2.yaml -n longhorn-system get pods
NAME                                                READY   STATUS    RESTARTS        AGE
csi-attacher-5c4bfdcf59-qmjtz                       1/1     Running   0               103s
csi-attacher-5c4bfdcf59-s7n65                       1/1     Running   0               103s
csi-attacher-5c4bfdcf59-w9xgs                       1/1     Running   0               103s
csi-provisioner-667796df57-fmz2d                    1/1     Running   0               103s
csi-provisioner-667796df57-p7rjr                    1/1     Running   0               103s
csi-provisioner-667796df57-w9fdq                    1/1     Running   0               103s
csi-resizer-694f8f5f64-2rb8v                        1/1     Running   0               103s
csi-resizer-694f8f5f64-z9v9x                        1/1     Running   0               103s
csi-resizer-694f8f5f64-zlncz                        1/1     Running   0               103s
csi-snapshotter-959b69d4b-5dpvj                     1/1     Running   0               103s
csi-snapshotter-959b69d4b-lwwkv                     1/1     Running   0               103s
csi-snapshotter-959b69d4b-tzhwc                     1/1     Running   0               103s
engine-image-ei-5cefaf2b-hvdv5                      1/1     Running   0               109s
instance-manager-0ee452a2e9583753e35ad00602250c5b   1/1     Running   0               109s
longhorn-csi-plugin-gd2jx                           3/3     Running   0               103s
longhorn-driver-deployer-9f4fc86-j6h2b              1/1     Running   0               2m28s
longhorn-manager-z4lnl                              1/1     Running   0               2m28s
longhorn-ui-5f4b7bbf69-bln7h                        1/1     Running   3 (2m7s ago)    2m28s
longhorn-ui-5f4b7bbf69-lh97n                        1/1     Running   3 (2m10s ago)   2m28s
Nota
Nota

Esta instalação não funcionará para ambientes totalmente air-gapped. Nesses casos, consulte Seção 63.8, “Instalação do SUSE Storage”.

O SUSE Security é uma solução de segurança para Kubernetes que fornece segurança de rede L7, segurança de tempo de execução, segurança da cadeia de suprimento e verificações de conformidade em um pacote coeso.

O SUSE Security é um produto que é implantado como uma plataforma de múltiplos contêineres, cada um comunicando-se por várias portas e interfaces. Internamente, ele usa o NeuVector como seu componente de segurança de contêiner subjacente. Os seguintes contêineres compõem a plataforma SUSE Security:

  • Gerente. Um contêiner sem estado que apresenta o console baseado na Web. Normalmente, apenas um é necessário e ele pode ser executado em qualquer lugar. A falha do Gerente não afeta nenhuma das operações do controller ou enforcer. No entanto, certas notificações (eventos) e dados de conexão recentes são armazenados em cache na memória pelo Gerente, portanto, a visualização deles seria afetada.

  • Controller. O ‘plano de controle’ para o SUSE Security deve ser implantado em uma configuração de HA, para que a configuração não seja perdida em uma falha de nó. Eles podem ser executados em qualquer lugar, embora os clientes frequentemente escolham colocá-los em nós de ‘gerenciamento’, master ou infra devido à sua criticidade.

  • Enforcer. Este contêiner é implantado como um DaemonSet, portanto, um Enforcer está em cada nó a ser protegido. Normalmente é implantado em cada nó de trabalho, mas o agendamento pode ser habilitado para nós master e infra para implantar lá também. Nota: Se o Enforcer não estiver em um nó de cluster e as conexões vierem de um pod nesse nó, o SUSE Security os rotula como cargas de trabalho 'não gerenciadas'.

  • Scanner. Realiza a verificação de vulnerabilidade usando o banco de dados CVE incorporado, conforme direcionado pelo Controller. Vários scanners podem ser implantados para aumentar a capacidade de verificação. Os scanners podem ser executados em qualquer lugar, mas geralmente são executados nos nós onde os controllers são executados. Veja abaixo as considerações de dimensionamento dos nós do scanner. Um scanner também pode ser invocado independentemente quando usado para verificação na fase de compilação, por exemplo, dentro de um pipeline que aciona uma verificação, recupera os resultados e interrompe o scanner. O scanner contém o banco de dados CVE mais recente, portanto, deve ser atualizado diariamente.

  • Updater. O atualizador aciona uma atualização do scanner por meio de um cron job do Kubernetes quando uma atualização do banco de dados CVE é desejada. Certifique-se de configurar isso para o seu ambiente.

Uma documentação mais detalhada sobre a integração e as melhores práticas do SUSE Security pode ser encontrada aqui.

16.1 Como o SUSE Telco Cloud usa o SUSE Security?

O SUSE Telco Cloud fornece uma configuração mais enxuta do SUSE Security como ponto de partida para implantações de borda.

16.2 Notas importantes

  • O contêiner Scanner deve ter memória suficiente para carregar a imagem a ser escaneada na memória e expandi-la. Para verificar imagens que excedam 1 GB, aumente a memória do scanner para um valor ligeiramente superior ao tamanho da maior imagem esperada.

  • Alto número de conexões de rede esperado no modo Protect. O Enforcer requer CPU e memória quando está no modo Protect (bloqueio de firewall em linha) para manter e inspecionar conexões e possíveis cargas úteis (DLP). Aumentar a memória e dedicar um núcleo de CPU ao Enforcer pode garantir uma capacidade adequada de filtragem de pacotes.

16.3 Instalando com o Edge Image Builder

SUSE Telco Cloud está usando Capítulo 12, Edge Image Builder para personalizar imagens base do SUSE Linux Micro OS. Siga Seção 63.7, “Instalação do SUSE Security” para uma instalação air-gapped do SUSE Security sobre clusters Kubernetes provisionados pelo EIB.

17 MetalLB

Consulte a documentação oficial do MetalLB.

O MetalLB é uma implementação de balanceador de carga para clusters Kubernetes bare metal, usando protocolos de roteamento padrão.

Em ambientes bare metal, configurar balanceadores de carga de rede é notavelmente mais complexo do que em ambientes de nuvem. Ao contrário das chamadas de API diretas em configurações de nuvem, o bare metal requer dispositivos de rede dedicados ou uma combinação de balanceadores de carga e configurações de IP Virtual (VIP) para gerenciar a alta disponibilidade (HA) ou resolver o potencial ponto único de falha (SPOF) inerente a um balanceador de carga de nó único. Essas configurações não são facilmente automatizadas, apresentando desafios nas implantações do Kubernetes, onde os componentes aumentam e diminuem de escala dinamicamente.

O MetalLB resolve esses desafios aproveitando o modelo do Kubernetes para criar serviços do tipo LoadBalancer como se estivessem operando em um ambiente de nuvem, mesmo em configurações bare metal.

Existem duas abordagens diferentes, via modo L2 (usando truques de ARP) ou via BGP. Principalmente, o L2 não precisa de nenhum equipamento de rede especial, mas o BGP é, em geral, melhor. Depende dos casos de uso.

17.1 Como o SUSE Telco Cloud usa o MetalLB?

O SUSE Telco Cloud usa o MetalLB de três maneiras principais:

  • Como uma solução de balanceador de carga: O MetalLB serve como a solução de balanceador de carga para máquinas bare metal.

  • Para uma configuração de HA K3s/RKE2: O MetalLB permite o balanceamento de carga da API do Kubernetes usando um endereço IP virtual.

  • Como uma solução BGP L3 onde o MetalLB anuncia rotas para os IPs de serviço para roteadores próximos.

Nota
Nota

Para ser possível expor a API, o Endpoint Copier Operator (Capítulo 18, Operador Endpoint Copier) é usado para manter sincronizados os endpoints da API do K8s do serviço kubernetes para um serviço kubernetes-vip LoadBalancer.

17.2 Melhores práticas

A instalação do MetalLB no modo L2 é descrita em Capítulo 60, MetalLB no K3s (usando o modo camada 2) e para o modo L3 em Capítulo 61, MetalLB no K3s (usando modo de camada 3).

Um guia sobre a instalação do MetalLB à frente do kube-api-server para obter uma topologia de alta disponibilidade pode ser encontrado em Capítulo 62, MetalLB na frente do servidor de API do Kubernetes.

17.3 Problemas conhecidos

  • O K3s vem com sua solução de balanceador de carga chamada Klipper. Para usar o MetalLB, o Klipper deve ser desativado. Isso pode ser feito iniciando o servidor K3s com a opção --disable servicelb, conforme descrito na documentação do K3s.

18 Operador Endpoint Copier

O Operador Endpoint Copier é um operador do Kubernetes cujo objetivo é criar uma cópia de um Serviço e Endpoint do Kubernetes e mantê-los sincronizados.

18.1 Como o SUSE Telco Cloud usa o Operador Endpoint Copier?

Na SUSE Telco Cloud, o Operador Endpoint Copier desempenha um papel crucial na obtenção de uma configuração de Alta Disponibilidade (HA) para clusters K3s/RKE2. Isso é realizado criando um serviço kubernetes-vip do tipo LoadBalancer, garantindo que seu Endpoint permaneça em sincronização constante com o Endpoint do Kubernetes. MetalLB (Capítulo 17, MetalLB) é utilizado para gerenciar o serviço kubernetes-vip, já que o endereço IP exposto é usado por outros nós para ingressar no cluster.

18.2 Melhores práticas

A documentação abrangente para usar o Operador Endpoint Copier pode ser encontrada aqui.

Além disso, consulte nosso guia (Capítulo 60, MetalLB no K3s (usando o modo camada 2)) sobre como obter uma configuração de HA para K3s/RKE2 usando o Operador Endpoint Copier e MetalLB.

18.3 Problemas conhecidos

Atualmente, o Operador Endpoint Copier está limitado a trabalhar com apenas um Serviço/Endpoint. Melhorias para oferecer suporte a múltiplos Serviços/Endpoints estão planejadas para o futuro.

19 virtualização de borda

Esta seção descreve como você pode usar a virtualização de borda para executar máquinas virtuais em seus nós de borda. A virtualização de borda foi projetada para casos de uso de virtualização leve, onde se espera que um fluxo de trabalho comum para a implantação e gerenciamento de aplicativos virtualizados e conteinerizados seja utilizado.

SUSE Telco Cloud A virtualização suporta dois métodos de execução de máquinas virtuais:

  1. Implantar as máquinas virtuais manualmente via libvirt+qemu-kvm no nível do host (onde o Kubernetes não está envolvido)

  2. Implantar o operador KubeVirt para gerenciamento de máquinas virtuais baseado em Kubernetes

Ambas as opções são válidas, mas apenas a segunda é abordada abaixo. Se você deseja usar os mecanismos de virtualização padrão prontos para uso fornecidos pelo SUSE Linux Micro, um guia abrangente pode ser encontrado aqui, e embora tenha sido escrito principalmente para o SUSE Linux Enterprise Server, os conceitos são quase idênticos.

Este guia explica inicialmente como implantar os componentes de virtualização adicionais em um sistema que já foi pré-implantado, mas segue com uma seção que descreve como incorporar essa configuração na implantação inicial via Edge Image Builder. Se você não quiser passar pelo básico e configurar as coisas manualmente, pule direto para essa seção.

19.1 Visão geral do KubeVirt

O KubeVirt permite gerenciar Máquinas Virtuais com o Kubernetes juntamente com o restante de suas cargas de trabalho conteinerizadas. Ele faz isso executando a parte do espaço do usuário da pilha de virtualização do Linux em um contêiner. Isso minimiza os requisitos no sistema host, permitindo uma configuração e gerenciamento mais fáceis.

Detalhes sobre a arquitetura do KubeVirt podem ser encontrados em na documentação upstream.

19.2 Pré-requisitos

Se você está seguindo este guia, presumimos que você já tenha o seguinte disponível:

  • Pelo menos um host físico com SUSE Linux Micro 6.2 instalado e com extensões de virtualização habilitadas no BIOS (veja aqui para detalhes).

  • Em seus nós, um cluster Kubernetes K3s/RKE2 já implantado e com um kubeconfig apropriado que permite acesso de superusuário ao cluster.

  • Acesso ao usuário root — estas instruções presumem que você é o usuário root e não está elevando seus privilégios via sudo.

  • Você tem Helm disponível localmente com uma conexão de rede adequada para conseguir enviar configurações para seu cluster Kubernetes e baixar as imagens necessárias.

19.3 Instalação manual da virtualização de borda

Este guia não o conduzirá pela implantação do Kubernetes, mas pressupõe que você tenha instalado a versão apropriada do SUSE Telco Cloud de K3s ou RKE2 e que você tenha seu kubeconfig configurado adequadamente para que comandos kubectl padrão possam ser executados como superusuário. Presumimos que seu nó forma um cluster de nó único, embora não sejam esperadas diferenças significativas para implantação de vários nós.

SUSE Telco Cloud A virtualização é implantada por meio de três charts Helm separados, especificamente:

  • KubeVirt: Os componentes principais de virtualização, ou seja, CRDs do Kubernetes, operadores e outros componentes necessários para permitir que o Kubernetes implante e gerencie máquinas virtuais.

  • Extensão do Painel do KubeVirt: Uma extensão opcional da interface do Rancher que permite o gerenciamento básico de máquinas virtuais, por exemplo, iniciar/parar máquinas virtuais, bem como acessar o console.

  • Importador de Dados Conteinerizados (CDI): Um componente adicional que permite a integração de armazenamento persistente para o KubeVirt, fornecendo recursos para que as máquinas virtuais usem back-ends de armazenamento do Kubernetes existentes para dados, mas também permitindo que os usuários importem ou clonem volumes de dados para máquinas virtuais.

Cada um desses gráficos Helm é versionado de acordo com a versão do SUSE Telco Cloud que você está usando atualmente. Para uso em produção/suportado, empregue os artefatos que podem ser encontrados no Registro SUSE.

Primeiro, certifique-se de que seu acesso kubectl esteja funcionando:

$ kubectl get nodes

Isso deve mostrar algo semelhante ao seguinte:

NAME                   STATUS   ROLES                       AGE     VERSION
node1.edge.rdo.wales   Ready    control-plane,etcd,master   4h20m   v1.30.5+rke2r1
node2.edge.rdo.wales   Ready    control-plane,etcd,master   4h15m   v1.30.5+rke2r1
node3.edge.rdo.wales   Ready    control-plane,etcd,master   4h15m   v1.30.5+rke2r1

Agora você pode prosseguir para instalar os gráficos Helm KubeVirt e Importador de Dados Conteinerizados (CDI):

$ helm install kubevirt oci://registry.suse.com/edge/charts/kubevirt --namespace kubevirt-system --create-namespace
$ helm install cdi oci://registry.suse.com/edge/charts/cdi --namespace cdi-system --create-namespace

Em alguns minutos, você deverá ter todos os componentes do KubeVirt e do CDI implantados. Você pode validar isso verificando todos os recursos implantados nos namespaces kubevirt-system e cdi-system.

Verifique os recursos do KubeVirt:

$ kubectl get all -n kubevirt-system

Isso deve mostrar algo semelhante ao seguinte:

NAME                                   READY   STATUS    RESTARTS      AGE
pod/virt-operator-5fbcf48d58-p7xpm     1/1     Running   0             2m24s
pod/virt-operator-5fbcf48d58-wnf6s     1/1     Running   0             2m24s
pod/virt-handler-t594x                 1/1     Running   0             93s
pod/virt-controller-5f84c69884-cwjvd   1/1     Running   1 (64s ago)   93s
pod/virt-controller-5f84c69884-xxw6q   1/1     Running   1 (64s ago)   93s
pod/virt-api-7dfc54cf95-v8kcl          1/1     Running   1 (59s ago)   118s

NAME                                  TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)   AGE
service/kubevirt-prometheus-metrics   ClusterIP   None            <none>        443/TCP   2m1s
service/virt-api                      ClusterIP   10.43.56.140    <none>        443/TCP   2m1s
service/kubevirt-operator-webhook     ClusterIP   10.43.201.121   <none>        443/TCP   2m1s
service/virt-exportproxy              ClusterIP   10.43.83.23     <none>        443/TCP   2m1s

NAME                          DESIRED   CURRENT   READY   UP-TO-DATE   AVAILABLE   NODE SELECTOR            AGE
daemonset.apps/virt-handler   1         1         1       1            1           kubernetes.io/os=linux   93s

NAME                              READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/virt-operator     2/2     2            2           2m24s
deployment.apps/virt-controller   2/2     2            2           93s
deployment.apps/virt-api          1/1     1            1           118s

NAME                                         DESIRED   CURRENT   READY   AGE
replicaset.apps/virt-operator-5fbcf48d58     2         2         2       2m24s
replicaset.apps/virt-controller-5f84c69884   2         2         2       93s
replicaset.apps/virt-api-7dfc54cf95          1         1         1       118s

NAME                            AGE     PHASE
kubevirt.kubevirt.io/kubevirt   2m24s   Deployed

Verifique os recursos do CDI:

$ kubectl get all -n cdi-system

Isso deve mostrar algo semelhante ao seguinte:

NAME                                   READY   STATUS    RESTARTS   AGE
pod/cdi-operator-55c74f4b86-692xb      1/1     Running   0          2m24s
pod/cdi-apiserver-db465b888-62lvr      1/1     Running   0          2m21s
pod/cdi-deployment-56c7d74995-mgkfn    1/1     Running   0          2m21s
pod/cdi-uploadproxy-7d7b94b968-6kxc2   1/1     Running   0          2m22s

NAME                             TYPE        CLUSTER-IP     EXTERNAL-IP   PORT(S)    AGE
service/cdi-uploadproxy          ClusterIP   10.43.117.7    <none>        443/TCP    2m22s
service/cdi-api                  ClusterIP   10.43.20.101   <none>        443/TCP    2m22s
service/cdi-prometheus-metrics   ClusterIP   10.43.39.153   <none>        8080/TCP   2m21s

NAME                              READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/cdi-operator      1/1     1            1           2m24s
deployment.apps/cdi-apiserver     1/1     1            1           2m22s
deployment.apps/cdi-deployment    1/1     1            1           2m21s
deployment.apps/cdi-uploadproxy   1/1     1            1           2m22s

NAME                                         DESIRED   CURRENT   READY   AGE
replicaset.apps/cdi-operator-55c74f4b86      1         1         1       2m24s
replicaset.apps/cdi-apiserver-db465b888      1         1         1       2m21s
replicaset.apps/cdi-deployment-56c7d74995    1         1         1       2m21s
replicaset.apps/cdi-uploadproxy-7d7b94b968   1         1         1       2m22s

Para verificar se as definições de recursos personalizados (CRDs) VirtualMachine estão implantadas, você pode validar com:

$ kubectl explain virtualmachine

Isso deve imprimir a definição do objeto VirtualMachine, que deve ser exibida da seguinte forma:

GROUP:      kubevirt.io
KIND:       VirtualMachine
VERSION:    v1

DESCRIPTION:
    VirtualMachine handles the VirtualMachines that are not running or are in a
    stopped state The VirtualMachine contains the template to create the
    VirtualMachineInstance. It also mirrors the running state of the created
    VirtualMachineInstance in its status.
(snip)

19.4 Implantando máquinas virtuais

Agora que o KubeVirt e o CDI estão implantados, vamos definir uma máquina virtual simples baseada no openSUSE Tumbleweed. Esta máquina virtual tem a mais simples das configurações, usando "rede de pod" padrão para uma configuração de rede idêntica a qualquer outro pod. Ela também emprega armazenamento não persistente, garantindo que o armazenamento seja efêmero, assim como em qualquer contêiner que não possua um PVC.

$ cat <<EOF > user-data.yaml
#cloud-config
disable_root: false
ssh_pwauth: True
users:
  - default
  - name: suse
    groups: sudo
    shell: /bin/bash
    sudo:  ALL=(ALL) NOPASSWD:ALL
    lock_passwd: False
    plain_text_passwd: 'suse'
EOF
$ kubectl apply -f - <<EOF
apiVersion: kubevirt.io/v1
kind: VirtualMachine
metadata:
  name: tumbleweed
  namespace: default
spec:
  runStrategy: Always
  template:
    spec:
      domain:
        devices: {}
        machine:
          type: q35
        memory:
          guest: 2Gi
        resources: {}
      volumes:
      - containerDisk:
          image: quay.io/containerdisks/opensuse-tumbleweed:1.0.0
        name: tumbleweed-containerdisk-0
      - cloudInitNoCloud:
          userDataBase64: $(cat user-data.yaml | base64 -w 0)
        name: cloudinitdisk
EOF

Isso deve exibir que um VirtualMachine foi criado:

virtualmachine.kubevirt.io/tumbleweed created

Esta definição de VirtualMachine é mínima, especificando pouco sobre a configuração. Ela simplesmente descreve que é um tipo de máquina "q35" com 2 GB de memória que usa uma imagem de disco baseada em um containerDisk efêmero (ou seja, uma imagem de disco que é armazenada em uma imagem de contêiner de um repositório de imagens remoto), e especifica um disco cloudInit codificado em base64, que usamos apenas para criação de usuário e imposição de senha no momento da inicialização (use base64 -d para decodificá-lo).

Nota
Nota

Esta imagem de máquina virtual é apenas para teste. A imagem não é oficialmente suportada e destina-se apenas a um exemplo de documentação.

Esta máquina leva alguns minutos para inicializar, pois precisa baixar a imagem de disco do openSUSE Tumbleweed, mas assim que o fizer, você poderá visualizar mais detalhes sobre a máquina virtual verificando as informações da máquina virtual:

$ kubectl get vmi

Isso deve exibir o nó no qual a máquina virtual foi iniciada e o endereço IP da máquina virtual. Lembre-se, como ela usa rede de pod, o endereço IP relatado será igual ao de qualquer outro pod, e roteável como tal:

NAME         AGE     PHASE     IP           NODENAME               READY
tumbleweed   4m24s   Running   10.42.2.98   node3.edge.rdo.wales   True

Ao executar esses comandos nos próprios nós do cluster Kubernetes, com uma CNI que roteia o tráfego diretamente para os pods (por exemplo, Cilium), você deve conseguir ssh diretamente para a própria máquina. Substitua o seguinte endereço IP pelo que foi atribuído à sua máquina virtual:

$ ssh suse@10.42.2.98
(password is "suse")

Uma vez dentro desta máquina virtual, você pode explorar, mas lembre-se de que ela é limitada em termos de recursos e possui apenas 1 GB de espaço em disco. Quando terminar, Ctrl-D ou exit para desconectar da sessão SSH.

O processo da máquina virtual ainda está envolvido em um pod padrão do Kubernetes. O CRD VirtualMachine é uma representação da máquina virtual desejada, mas o processo no qual a máquina virtual é realmente iniciada é via pod virt-launcher, um pod padrão do Kubernetes, assim como qualquer outra aplicação. Para cada máquina virtual iniciada, você pode ver que existe um pod virt-launcher:

$ kubectl get pods

Isso deve mostrar o único pod virt-launcher para a máquina Tumbleweed que definimos:

NAME                             READY   STATUS    RESTARTS   AGE
virt-launcher-tumbleweed-8gcn4   3/3     Running   0          10m

Se dermos uma olhada neste pod virt-launcher, você verá que ele está executando os processos libvirt e qemu-kvm. Podemos entrar no próprio pod e dar uma olhada nos bastidores, observando que você precisa adaptar o seguinte comando para o nome do seu pod:

$ kubectl exec -it virt-launcher-tumbleweed-8gcn4 -- bash

Assim que estiver no pod, tente executar comandos virsh juntamente com a observação dos processos. Você verá o binário qemu-system-x86_64 em execução, juntamente com certos processos para monitorar a máquina virtual. Você também verá a localização da imagem de disco e como a rede está conectada (como um dispositivo tap):

qemu@tumbleweed:/> ps ax
  PID TTY      STAT   TIME COMMAND
    1 ?        Ssl    0:00 /usr/bin/virt-launcher-monitor --qemu-timeout 269s --name tumbleweed --uid b9655c11-38f7-4fa8-8f5d-bfe987dab42c --namespace default --kubevirt-share-dir /var/run/kubevirt --ephemeral-disk-dir /var/run/kubevirt-ephemeral-disks --container-disk-dir /var/run/kube
   12 ?        Sl     0:01 /usr/bin/virt-launcher --qemu-timeout 269s --name tumbleweed --uid b9655c11-38f7-4fa8-8f5d-bfe987dab42c --namespace default --kubevirt-share-dir /var/run/kubevirt --ephemeral-disk-dir /var/run/kubevirt-ephemeral-disks --container-disk-dir /var/run/kubevirt/con
   24 ?        Sl     0:00 /usr/sbin/virtlogd -f /etc/libvirt/virtlogd.conf
   25 ?        Sl     0:01 /usr/sbin/virtqemud -f /var/run/libvirt/virtqemud.conf
   83 ?        Sl     0:31 /usr/bin/qemu-system-x86_64 -name guest=default_tumbleweed,debug-threads=on -S -object {"qom-type":"secret","id":"masterKey0","format":"raw","file":"/var/run/kubevirt-private/libvirt/qemu/lib/domain-1-default_tumbleweed/master-key.aes"} -machine pc-q35-7.1,usb
  286 pts/0    Ss     0:00 bash
  320 pts/0    R+     0:00 ps ax

qemu@tumbleweed:/> virsh list --all
 Id   Name                 State
------------------------------------
 1    default_tumbleweed   running

qemu@tumbleweed:/> virsh domblklist 1
 Target   Source
---------------------------------------------------------------------------------------------
 sda      /var/run/kubevirt-ephemeral-disks/disk-data/tumbleweed-containerdisk-0/disk.qcow2
 sdb      /var/run/kubevirt-ephemeral-disks/cloud-init-data/default/tumbleweed/noCloud.iso

qemu@tumbleweed:/> virsh domiflist 1
 Interface   Type       Source   Model                     MAC
------------------------------------------------------------------------------
 tap0        ethernet   -        virtio-non-transitional   e6:e9:1a:05:c0:92

qemu@tumbleweed:/> exit
exit

Finalmente, vamos excluir esta máquina virtual para limpar:

$ kubectl delete vm/tumbleweed
virtualmachine.kubevirt.io "tumbleweed" deleted

19.5 Usando o virtctl

Junto com as ferramentas de CLI padrão do Kubernetes, isto é, kubectl, o KubeVirt vem com um utilitário de CLI complementar que permite interagir com seu cluster de uma maneira que preenche algumas lacunas entre o mundo da virtualização e o mundo para o qual o Kubernetes foi projetado. Por exemplo, a ferramenta virtctl oferece a capacidade de gerenciar o ciclo de vida de máquinas virtuais (iniciar, parar, reiniciar etc.), fornecendo acesso aos consoles virtuais, fazendo upload de imagens de máquinas virtuais, bem como interagindo com recursos do Kubernetes, como serviços, sem usar a API ou os CRDs diretamente.

Vamos baixar a versão estável mais recente da ferramenta virtctl:

$ export VERSION=v0.7.0
$ wget https://github.com/kubevirt/kubevirt/releases/download/$VERSION/virtctl-$VERSION-linux-amd64

Se você estiver usando uma arquitetura diferente ou uma máquina que não seja Linux, poderá encontrar outras versões aqui. Você precisa tornar isso executável antes de prosseguir, e pode ser útil movê-lo para um local dentro do seu $PATH:

$ mv virtctl-$VERSION-linux-amd64 /usr/local/bin/virtctl
$ chmod a+x /usr/local/bin/virtctl

Você pode então usar a ferramenta de linha de comando virtctl para criar máquinas virtuais. Vamos replicar nossa máquina virtual anterior, observando que estamos enviando a saída diretamente para o kubectl apply:

$ cat <<EOF >  user-data.yaml
#cloud-config
disable_root: false
ssh_pwauth: True
users:
  - default
  - name: suse
    groups: sudo
    shell: /bin/bash
    sudo:  ALL=(ALL) NOPASSWD:ALL
    lock_passwd: False
    plain_text_passwd: 'suse'
EOF
$ alias virtctl=echo
$ virtctl create vm --name virtctl-example --memory=1Gi \
    --volume-containerdisk=src:quay.io/containerdisks/opensuse-tumbleweed:1.0.0 \
    --cloud-init-user-data "$(cat user-data.yaml | base64 -w 0)"

Isso deve mostrar a máquina virtual em execução (ela deve iniciar muito mais rápido desta vez, já que a imagem do contêiner estará em cache):

$ kubectl get vmi
NAME              AGE   PHASE     IP           NODENAME               READY
virtctl-example   52s   Running   10.42.2.29   node3.edge.rdo.wales   True

Agora podemos usar virtctl para conectar diretamente à máquina virtual:

$ virtctl ssh suse@virtctl-example
(password is "suse" - Ctrl-D to exit)

Existem muitos outros comandos que podem ser usados pela virtctl. Por exemplo, virtctl console pode lhe dar acesso ao console serial se a rede não estiver funcionando, e você pode usar virtctl guestosinfo para obter informações abrangentes do SO, desde que o convidado tenha o qemu-guest-agent instalado e em execução.

Finalmente, vamos pausar e retomar a máquina virtual:

$ virtctl pause vm virtctl-example
VMI virtctl-example was scheduled to pause

Você descobre que o objeto VirtualMachine aparece como Pausada e o objeto VirtualMachineInstance aparece como Em execução, mas READY=False:

$ kubectl get vm
NAME              AGE     STATUS   READY
virtctl-example   8m14s   Paused   False

$ kubectl get vmi
NAME              AGE     PHASE     IP           NODENAME               READY
virtctl-example   8m15s   Running   10.42.2.29   node3.edge.rdo.wales   False

Você também descobre que não consegue mais se conectar à máquina virtual:

$ virtctl ssh suse@virtctl-example
can't access VMI virtctl-example: Operation cannot be fulfilled on virtualmachineinstance.kubevirt.io "virtctl-example": VMI is paused

Vamos retomar a máquina virtual e tentar novamente:

$ virtctl unpause vm virtctl-example
VMI virtctl-example was scheduled to unpause

Agora devemos ser capazes de restabelecer uma conexão:

$ virtctl ssh suse@virtctl-example
suse@vmi/virtctl-example.default's password:
suse@virtctl-example:~> exit
logout

Finalmente, vamos remover a máquina virtual:

$ kubectl delete vm/virtctl-example
virtualmachine.kubevirt.io "virtctl-example" deleted

19.6 Rede de entrada simples

Nesta seção, mostramos como você pode expor máquinas virtuais como serviços padrão do Kubernetes e disponibilizá-las por meio do serviço de entrada do Kubernetes, por exemplo, Traefik com RKE2 ou Traefik com K3s. Este documento pressupõe que esses componentes já estejam configurados adequadamente e que você tenha um ponteiro DNS apropriado, por exemplo, via curinga, para apontar para seus nós de servidor Kubernetes ou seu IP virtual de entrada para a resolução de entrada adequada.

Nota
Nota

Em SUSE Telco Cloud 3.1+, se você estiver usando o K3s em uma configuração de nó de servidor múltiplo, talvez tenha precisado configurar um VIP baseado em MetalLB para Ingress; isso não é necessário para o RKE2.

No ambiente de exemplo, outra máquina virtual openSUSE Tumbleweed é implantada, o cloud-init é usado para instalar o NGINX como um servidor Web simples no momento da inicialização, e uma mensagem simples é configurada para ser retornada para verificar se funciona conforme o esperado quando uma chamada é feita. Para ver como isso é feito, simplesmente base64 -d a seção cloud-init na saída abaixo.

Vamos criar esta máquina virtual agora:

$ cat <<EOF > user-data.yaml
#cloud-config
disable_root: false
ssh_pwauth: True
users:
  - default
  - name: suse
    groups: sudo
    shell: /bin/bash
    sudo:  ALL=(ALL) NOPASSWD:ALL
    lock_passwd: False
    plain_text_passwd: 'suse'
EOF
$ kubectl apply -f - <<EOF
apiVersion: kubevirt.io/v1
kind: VirtualMachine
metadata:
  name: ingress-example
  namespace: default
spec:
  runStrategy: Always
  template:
    metadata:
      labels:
        app: nginx
    spec:
      domain:
        devices: {}
        machine:
          type: q35
        memory:
          guest: 2Gi
        resources: {}
      volumes:
      - containerDisk:
          image: quay.io/containerdisks/opensuse-tumbleweed:1.0.0
        name: tumbleweed-containerdisk-0
      - cloudInitNoCloud:
          userDataBase64: $(cat user-data.yaml | base64 -w 0)
        name: cloudinitdisk
EOF

Quando esta máquina virtual tiver iniciado com sucesso, podemos usar o comando virtctl para expor a VirtualMachineInstance com uma porta externa de 8080 e uma porta de destino de 80 (onde o NGINX escuta por padrão). Usamos o comando virtctl aqui, pois ele entende o mapeamento entre o objeto da máquina virtual e o pod. Isso cria um novo serviço para nós:

$ virtctl expose vmi ingress-example --port=8080 --target-port=80 --name=ingress-example
Service ingress-example successfully exposed for vmi ingress-example

Teremos então um serviço apropriado criado automaticamente:

$ kubectl get svc/ingress-example
NAME              TYPE           CLUSTER-IP      EXTERNAL-IP       PORT(S)                         AGE
ingress-example   ClusterIP      10.43.217.19    <none>            8080/TCP                        9s

Em seguida, se você usar kubectl create ingress, podemos criar um objeto ingress que aponte para este serviço. Adapte a URL (conhecida como "host" no objeto ingress) aqui para corresponder à sua configuração de DNS e certifique-se de apontá-la para a porta 8080:

$ kubectl create ingress ingress-example --rule=ingress-example.suse.local/=ingress-example:8080

Com o DNS configurado corretamente, você deve conseguir usar o curl na URL imediatamente:

$ curl ingress-example.suse.local
It works!

Vamos fazer uma limpeza removendo esta máquina virtual e seus recursos de serviço e ingress:

$ kubectl delete vm/ingress-example svc/ingress-example ingress/ingress-example
virtualmachine.kubevirt.io "ingress-example" deleted
service "ingress-example" deleted
ingress.networking.k8s.io "ingress-example" deleted

19.7 Usando a extensão da interface do usuário do Rancher

SUSE Telco Cloud A extensão de Virtualização fornece uma extensão da interface do usuário para o Rancher Manager, permitindo o gerenciamento básico de máquinas virtuais usando o painel do Rancher.

19.7.1 Instalação

Consulte Rancher Dashboard Extensions (Capítulo 7, Extensões do Dashboard do Rancher) para obter orientações de instalação.

19.7.2 Usando a Extensão do Painel do Rancher para KubeVirt

A extensão introduz uma nova seção KubeVirt ao Cluster Explorer. Esta seção é adicionada a qualquer cluster gerenciado que tenha o KubeVirt instalado.

A extensão permite que você interaja diretamente com os recursos de Máquina Virtual do KubeVirt para gerenciar o ciclo de vida das Máquinas Virtuais.

19.7.2.1 Criando uma máquina virtual

  1. Navegue até Cluster Explorer clicando em um cluster gerenciado habilitado para KubeVirt na navegação à esquerda.

  2. Navegue até a página KubeVirt > Virtual Machines e clique em Create from YAML no canto superior direito da tela.

  3. Preencha ou cole uma definição de máquina virtual e pressione Create. Use a definição de máquina virtual da seção Implantando Máquinas Virtuais como inspiração.

virtual machines page

19.7.2.2 Ações de Máquina Virtual

Você pode usar o menu de ações acessado a partir da lista suspensa ⋮ à direita de cada máquina virtual para realizar ações de iniciar, parar, pausar ou reinicialização suave. Alternativamente, você também pode usar ações em grupo na parte superior da lista selecionando as máquinas virtuais nas quais deseja realizar a ação.

A execução das ações pode ter um efeito na Estratégia de Execução da Máquina Virtual. Consulte a tabela na documentação do KubeVirt para obter mais detalhes.

19.7.2.3 Acessando o console da máquina virtual

A lista de "Máquinas virtuais" fornece uma lista suspensa Console que permite conectar à máquina usando VNC ou Console Serial. Esta ação só está disponível para máquinas em execução.

Em alguns casos, leva um pouco de tempo até que o console esteja acessível em uma máquina virtual recém-iniciada.

vnc console ui

19.8 Instalando com o Edge Image Builder

SUSE Telco Cloud está usando Capítulo 12, Edge Image Builder para personalizar imagens base do SUSE Linux Micro OS. Siga Seção 63.9, “Instalação do KubeVirt e CDI” para uma instalação air-gapped do KubeVirt e do CDI sobre clusters Kubernetes provisionados pelo EIB.

20 Upgrade Controller do Sistema

Consulte a documentação do Upgrade Controller do Sistema.

O Upgrade Controller do Sistema (SUC) visa fornecer um Upgrade Controller de uso geral, nativo do Kubernetes (para nós). Ele introduz um novo CRD, o Plano, para definir todas e quaisquer políticas e requisitos para fazer upgrade. Um Plano representa a intenção de modificar os nós do seu cluster.

20.1 Como o SUSE Telco Cloud usa o Upgrade Controller do Sistema?

O SUSE Telco Cloud usa o SUC para facilitar várias operações de "Dia 2" relacionadas a atualizações de versão do SO e do Kubernetes em clusters de gerenciamento e downstream.

As operações de "Dia 2" são definidas por meio do SUC Plans. Com base nesses planos, o SUC implanta cargas de trabalho em cada nó para executar a respectiva operação de "Dia 2".

O SUC também é usado dentro do Capítulo 21, Upgrade Controller. Para saber mais sobre as principais diferenças entre o SUC e o Upgrade Controller, consulte Seção 21.2, “Upgrade Controller vs System Upgrade Controller”.

20.2 Instalando o Upgrade Controller do Sistema

Importante
Importante

A partir do Rancher v2.10.0, o System Upgrade Controller é instalado automaticamente.

Siga as etapas abaixo apenas se o seu ambiente não for gerenciado pelo Rancher, ou se a sua versão do Rancher for inferior a v2.10.0.

Recomendamos que você instale o SUC por meio do Fleet (Capítulo 9, Fleet) localizado no repositório suse-edge/fleet-examples.

Nota
Nota

Os recursos oferecidos pelo repositório suse-edge/fleet-examples devem ser sempre usados a partir de uma versão do fleet-examples válida. Para determinar qual versão você precisa usar, consulte as Notas de Versão (Capítulo 75, Notas de versão).

Se você não puder usar o Fleet para a instalação do SUC, poderá instalá-lo através do repositório de Helm charts do Rancher ou incorporar o Helm chart do Rancher em seu próprio fluxo de trabalho GitOps de terceiros.

Esta seção aborda:

20.2.1 Instalação do Upgrade Controller do Sistema via Fleet

Usando o Fleet, existem dois recursos possíveis que podem ser usados para implantar o SUC:

20.2.1.1 Instalação do Upgrade Controller - GitRepo

Nota
Nota

Este processo também pode ser feito através da interface do usuário do Rancher, caso esteja disponível. Para mais informações, consulte Acessar o Fleet na interface do usuário do Rancher.

No seu cluster de gerenciamento:

  1. Determine em quais clusters você deseja implantar o SUC. Isso é feito implantando um recurso GitRepo do SUC no workspace do Fleet correto em seu cluster de gerenciamento. Por padrão, o Fleet possui dois workspaces:

    • fleet-local - para recursos que precisam ser implantados no cluster de gerenciamento.

    • fleet-default - para recursos que precisam ser implantados em clusters downstream.

      Para obter mais informações sobre os workspaces do Fleet, consulte a documentação upstream.

  2. Implante o recurso GitRepo:

    • Para implantar o SUC em seu cluster de gerenciamento:

      kubectl apply -n fleet-local -f - <<EOF
      apiVersion: fleet.cattle.io/v1alpha1
      kind: GitRepo
      metadata:
        name: system-upgrade-controller
      spec:
        revision: release-3.6.1
        paths:
        - fleets/day2/system-upgrade-controller
        repo: https://github.com/suse-edge/fleet-examples.git
      EOF
    • Para implantar o SUC em seus clusters downstream:

      Nota
      Nota

      Antes de implantar o recurso abaixo, você deve fornecer uma configuração targets válida, para que o Fleet saiba em quais clusters downstream implantar seu recurso. Para obter informações sobre como mapear para clusters downstream, consulte Mapping to Downstream Clusters.

      kubectl apply -n fleet-default -f - <<EOF
      apiVersion: fleet.cattle.io/v1alpha1
      kind: GitRepo
      metadata:
        name: system-upgrade-controller
      spec:
        revision: release-3.6.1
        paths:
        - fleets/day2/system-upgrade-controller
        repo: https://github.com/suse-edge/fleet-examples.git
        targets:
        - clusterSelector: CHANGEME
        # Example matching all clusters:
        # targets:
        # - clusterSelector: {}
      EOF
  3. Valide se o recurso GitRepo está implantado:

    # Namespace will vary based on where you want to deploy SUC
    kubectl get gitrepo system-upgrade-controller -n <fleet-local/fleet-default>
    
    NAME                        REPO                                              COMMIT          BUNDLEDEPLOYMENTS-READY   STATUS
    system-upgrade-controller   https://github.com/suse-edge/fleet-examples.git   release-3.6.1   1/1
  4. Valide a implantação do Upgrade Controller do Sistema:

    kubectl get deployment system-upgrade-controller -n cattle-system
    NAME                        READY   UP-TO-DATE   AVAILABLE   AGE
    system-upgrade-controller   1/1     1            1           2m20s

20.2.1.2 Instalação do Upgrade Controller - Bundle

Esta seção ilustra como criar e implantar um recurso Bundle a partir de uma configuração padrão do Fleet usando o fleet-cli.

  1. Em uma máquina com acesso à rede, baixe o fleet-cli:

    Nota
    Nota

    Certifique-se de que a versão do fleet-cli que você baixar corresponda à versão do Fleet que foi implantada em seu cluster.

    • Para usuários de Mac, existe uma fleet-cli Homebrew Formulae.

    • Para usuários de Linux e Windows, os binários estão presentes como assets em cada release do Fleet.

      • Linux AMD:

        curl -L -o fleet-cli https://github.com/rancher/fleet/releases/download/vv0.15.2/fleet-linux-amd64
      • Linux ARM:

        curl -L -o fleet-cli https://github.com/rancher/fleet/releases/download/vv0.15.2/fleet-linux-arm64
  2. Torne o fleet-cli executável:

    chmod +x fleet-cli
  3. Clone a suse-edge/fleet-examples release que você deseja usar:

    git clone -b release-3.6.1 https://github.com/suse-edge/fleet-examples.git
  4. Navegue até o fleet do SUC, localizado no repositório fleet-examples:

    cd fleet-examples/fleets/day2/system-upgrade-controller
  5. Determine em quais clusters você deseja implantar o SUC. Isso é feito implantando o SUC Bundle no workspace do Fleet correto dentro do seu cluster de gerenciamento. Por padrão, o Fleet possui dois workspaces:

    • fleet-local - para recursos que precisam ser implantados no cluster de gerenciamento.

    • fleet-default - para recursos que precisam ser implantados em clusters downstream.

      Para obter mais informações sobre os workspaces do Fleet, consulte a documentação upstream.

  6. Se você pretende implantar o SUC apenas em clusters downstream, crie um arquivo targets.yaml que corresponda aos clusters específicos:

    cat > targets.yaml <<EOF
    targets:
    - clusterSelector: CHANGEME
    EOF

    Para obter informações sobre como mapear para clusters downstream, consulte Mapping to Downstream Clusters

  7. Prossiga para a construção do Bundle:

    Nota
    Nota

    Certifique-se de não baixar o fleet-cli no diretório fleet-examples/fleets/day2/system-upgrade-controller, caso contrário, ele será empacotado com o Bundle, o que não é recomendado.

    • Para implantar o SUC no seu cluster de gerenciamento, execute:

      fleet-cli apply --compress -n fleet-local -o - system-upgrade-controller . > system-upgrade-controller-bundle.yaml
    • Para implantar o SUC nos seus clusters downstream, execute:

      fleet-cli apply --compress --targets-file=targets.yaml -n fleet-default -o - system-upgrade-controller . > system-upgrade-controller-bundle.yaml

      Para mais informações sobre este processo, consulte Convert a Helm Chart into a Bundle.

      Para mais informações sobre o comando fleet-cli apply, consulte fleet apply.

  8. Transfira o Bundle system-upgrade-controller-bundle.yaml para a máquina do seu cluster de gerenciamento:

    scp system-upgrade-controller-bundle.yaml <machine-address>:<filesystem-path>
  9. No seu cluster de gerenciamento, implante o Bundle system-upgrade-controller-bundle.yaml:

    kubectl apply -f system-upgrade-controller-bundle.yaml
  10. No seu cluster de gerenciamento, valide se o Bundle está implantado:

    # Namespace will vary based on where you want to deploy SUC
    kubectl get bundle system-upgrade-controller -n <fleet-local/fleet-default>
    
    NAME                        BUNDLEDEPLOYMENTS-READY   STATUS
    system-upgrade-controller   1/1
  11. Com base no workspace do Fleet no qual você implantou seu Bundle, navegue até o cluster e valide a implantação do SUC:

    Nota
    Nota

    O SUC é sempre implantado no namespace cattle-system.

    kubectl get deployment system-upgrade-controller -n cattle-system
    NAME                        READY   UP-TO-DATE   AVAILABLE   AGE
    system-upgrade-controller   1/1     1            1           111s

20.2.2 Instalação do Helm do Upgrade Controller do Sistema

  1. Adicione o repositório de charts do Rancher:

    helm repo add rancher-charts https://charts.rancher.io/
  2. Implante o chart do SUC:

    helm install system-upgrade-controller rancher-charts/system-upgrade-controller --version 109.0.1 --set global.cattle.psp.enabled=false -n cattle-system --create-namespace

    Isso instalará a versão v0.19.1 do SUC, que é necessária pela plataforma Edge 3.6.

  3. Valide a implantação do SUC:

    kubectl get deployment system-upgrade-controller -n cattle-system
    NAME                        READY   UP-TO-DATE   AVAILABLE   AGE
    system-upgrade-controller   1/1     1            1           37s

20.3 Monitoramento de Planos do Upgrade Controller do Sistema

Os Planos SUC podem ser visualizados das seguintes maneiras:

Importante
Importante

Os Pods implantados para Planos SUC são mantidos ativos por 15 minutos após uma execução bem-sucedida. Após esse período, eles são removidos pelo Job correspondente que os criou. Para ter acesso aos logs do Pod após esse período, você deve habilitar o registro em log para seu cluster. Para obter informações sobre como fazer isso no Rancher, consulte Rancher Integration with Logging Services.

20.3.1 Monitoramento de Planos do Upgrade Controller do Sistema - Rancher UI

Para verificar os logs do Pod para o plano SUC específico:

  1. No canto superior esquerdo, ☰ → <your-cluster-name>

  2. Selecione Workloads → Pods

  3. Selecione o menu suspenso Only User Namespaces e adicione o namespace cattle-system

  4. Na barra de filtro de Pods, escreva o nome do Pod do seu Plano SUC. O nome estará no seguinte formato de modelo: apply-<plan_name>-on-<node_name>

    Nota
    Nota

    Podem existir Pods Completed e Unknown para um Plano SUC específico. Isso é esperado e acontece devido à natureza de algumas das atualizações.

  5. Selecione o pod cujos logs você deseja revisar e navegue até ⋮ → View Logs

20.3.2 Monitoramento de Planos do Upgrade Controller do Sistema - Manual

Nota
Nota

As etapas abaixo pressupõem que kubectl foi configurado para se conectar ao cluster onde os Planos SUC foram implantados.

  1. Liste os Planos SUC implantados:

    kubectl get plans -n cattle-system
  2. Obtenha o Pod para o plano SUC:

    kubectl get pods -l upgrade.cattle.io/plan=<plan_name> -n cattle-system
    Nota
    Nota

    Podem existir tanto Completed Pods quanto Unknown para um Plano SUC específico. Isso é esperado e acontece devido à natureza de alguns dos upgrades.

  3. Obtenha os logs para o Pod:

    kubectl logs <pod_name> -n cattle-system

21 Upgrade Controller

Um controlador Kubernetes capaz de realizar atualizações nos seguintes SUSE Telco Cloud componentes da plataforma:

  • Sistema Operacional (SUSE Linux Micro)

  • Kubernetes (K3s & RKE2)

  • Componentes adicionais (Rancher, Elemental, SUSE Security, etc.)

O Upgrade Controller simplifica o processo de atualização para os componentes mencionados acima, encapsulando suas complexidades dentro de um único user-facing recurso que serve como um gatilho para a atualização. Os usuários só precisam configurar este recurso e o Upgrade Controller cuida do resto.

Nota
Nota

O Upgrade Controller atualmente suporta SUSE Telco Cloud atualizações de plataforma apenas para clusters de gerenciamento não air-gapped. Consulte a seção Seção 21.8, “Limitações conhecidas” para obter mais informações.

21.1 Como o SUSE Telco Cloud usa o Upgrade Controller?

O Upgrade Controller é essencial na automação das operações de "Dia 2" (anteriormente manuais) necessárias para atualizar clusters de gerenciamento de uma versão de lançamento SUSE Telco Cloud para a próxima.

Para alcançar essa automação, o Upgrade Controller utiliza ferramentas como o System Upgrade Controller (Capítulo 20, Upgrade Controller do Sistema) e o Helm Controller.

Para mais detalhes sobre como o Upgrade Controller funciona, consulte Seção 21.5, “Como funciona o Upgrade Controller?”.

Para limitações conhecidas que o Upgrade Controller possui, consulte Seção 21.8, “Limitações conhecidas”.

Para obter informações sobre a diferença entre o Upgrade Controller e o System Upgrade Controller, consulte Seção 21.2, “Upgrade Controller vs System Upgrade Controller”.

21.2 Upgrade Controller vs System Upgrade Controller

O System Upgrade Controller (SUC) (Capítulo 20, Upgrade Controller do Sistema) é uma ferramenta de propósito geral que propaga instruções de atualização para nós específicos do Kubernetes.

Embora ele suporte algumas operações de "Dia 2" para a plataforma SUSE Telco Cloud, ele não cobre todas elas. Além disso, mesmo para operações suportadas, os usuários precisam configurar, manter e implantar manualmente múltiplos SUC Plans — um processo sujeito a erros que pode levar a problemas inesperados.

Isso levou à necessidade de uma ferramenta que automatize e abstraia a complexidade de gerenciar várias operações de "Dia 2" para a plataforma SUSE Telco Cloud. Assim, o Upgrade Controller foi desenvolvido. Ele simplifica o processo de atualização ao introduzir um único user-facing resource que conduz a atualização. Os usuários só precisam gerenciar esse recurso, enquanto o Upgrade Controller cuida do resto.

21.3 Instalando o Upgrade Controller

21.3.1 Pré-requisitos

21.3.2 Etapas

  1. Instale o chart Helm do Upgrade Controller no seu cluster de gerenciamento:

    helm install upgrade-controller oci://registry.suse.com/edge/charts/upgrade-controller --version 306.0.4+up0.1.3 --create-namespace --namespace upgrade-controller-system
  2. Valide a implantação do Upgrade Controller:

    kubectl get deployment -n upgrade-controller-system
  3. Valide o pod do Upgrade Controller:

    kubectl get pods -n upgrade-controller-system
  4. Valide os logs do pod do Upgrade Controller:

    kubectl logs <pod_name> -n upgrade-controller-system

21.4 Instalando o Upgrade Controller via Edge Image Builder

Como alternativa à instalação manual descrita acima, é possível instalar o Upgrade Controller como parte da implantação inicial orquestrada pelo Edge Image Builder (Capítulo 12, Edge Image Builder).

Nesse caso, é necessário adicionar a seguinte configuração de chart helm ao arquivo de configuração do EIB:

kubernetes:
  helm:
    charts:
      - name: cert-manager
        repositoryName: jetstack
        version: {version-cert-manager}
        targetNamespace: cert-manager
        valuesFile: certmanager-values.yaml
        createNamespace: true
        installationNamespace: kube-system
      - name: upgrade-controller
        version: {version-upgrade-controller-chart}
        repositoryName: suse-edge-charts
        targetNamespace: upgrade-controller-system
        createNamespace: true
        installationNamespace: kube-system

21.5 Como funciona o Upgrade Controller?

Para realizar uma atualização de versão do Edge, o Upgrade Controller introduz dois novos recursos personalizados do Kubernetes:

  • UpgradePlan (Seção 21.6.1, “UpgradePlan”) - criado pelo usuário; contém configurações referentes a uma atualização de versão do Edge.

  • ReleaseManifest (Seção 21.6.2, “ReleaseManifest”) - criado pelo Upgrade Controller; contém versões de componentes específicas para uma determinada versão de lançamento do Edge. Este arquivo não deve ser editado pelos usuários.

O Upgrade Controller prossegue criando um recurso ReleaseManifest que contém os dados do componente para a versão de lançamento do Edge especificada pelo usuário na propriedade releaseVersion no recurso UpgradePlan.

Usando os dados do componente do ReleaseManifest, o Upgrade Controller prossegue com a atualização dos componentes da versão do Edge na seguinte ordem:

Nota
Nota

Durante o processo de atualização, o Upgrade Controller gera continuamente informações de atualização para o UpgradePlan criado. Para obter mais informações sobre como acompanhar o processo de atualização, consulte Acompanhando o processo de atualização (Seção 21.7, “Acompanhando o processo de atualização”).

21.5.1 Atualização do Sistema operacional

Para atualizar o sistema operacional, o Upgrade Controller cria planos SUC (Capítulo 20, Upgrade Controller do Sistema) que possuem o seguinte modelo de nomenclatura:

  • Para planos SUC relacionados a atualizações do SO dos nós do plano de controle - control-plane-<os-name>-<os-version>-<suffix>.

  • Para planos SUC relacionados a atualizações do SO dos nós de trabalho - workers-<os-name>-<os-version>-<suffix>.

Com base nesses planos, o SUC prossegue criando cargas de trabalho em cada nó do cluster que realizam a atualização do SO propriamente dita.

Dependendo do ReleaseManifest, a atualização do SO pode incluir:

  • Atualizações apenas de pacotes - para casos de uso em que a versão do SO não muda entre as versões do Edge.

  • Migração completa do SO - para casos de uso em que a versão do SO muda entre as versões do Edge.

A atualização é executada um nó por vez, começando pelos nós do plano de controle. Somente se a atualização do nó do plano de controle terminar, os nós de trabalho começarão a ser atualizados.

Nota
Nota

O Controlador de Atualização configura os Planos SUC do SO para realizar um dreno dos nós do cluster se o cluster tiver mais de um nó do tipo especificado.

Para clusters onde os nós do plano de controle são maiores que um e há apenas um nó de trabalho, um dreno será realizado apenas para os nós do plano de controle e vice-versa.

Para obter informações sobre como desativar completamente os drenos de nós, consulte a seção UpgradePlan (Seção 21.6.1, “UpgradePlan”).

21.5.2 Fazer upgrade do Kubernetes

Para fazer upgrade da distribuição Kubernetes de um cluster, o Upgrade Controller cria Planos SUC (Capítulo 20, Upgrade Controller do Sistema) que possuem o seguinte modelo de nomenclatura:

  • Para Planos SUC relacionados a atualizações do Kubernetes de nós do plano de controle - control-plane-<k8s-version>-<suffix>.

  • Para Planos SUC relacionados a atualizações do Kubernetes de nós de trabalho - workers-<k8s-version>-<suffix>.

Com base nesses planos, o SUC prossegue criando cargas de trabalho em cada nó do cluster que realizam a atualização real do Kubernetes.

A atualização do Kubernetes ocorrerá um nó por vez, começando pelos nós do plano de controle. Somente se a atualização do nó do plano de controle terminar, os nós de trabalho começarão a ser atualizados.

Nota
Nota

O Controlador de Atualização configura os Planos SUC do Kubernetes para realizar um dreno dos nós do cluster se o cluster tiver mais de um nó do tipo especificado.

Para clusters onde os nós do plano de controle são maiores que um e há apenas um nó de trabalho, um dreno será realizado apenas para os nós do plano de controle e vice-versa.

Para obter informações sobre como desativar completamente os drenos de nós, consulte Seção 21.6.1, “UpgradePlan”.

21.5.3 Atualizações de Componentes Adicionais

Atualmente, todos os componentes adicionais são instalados via charts Helm. Para obter uma lista completa dos componentes de uma versão específica, consulte as Release Notes (Capítulo 75, Notas de versão).

Para charts Helm implantados por meio do EIB (Capítulo 12, Edge Image Builder), o Upgrade Controller atualiza o HelmChart CR existente de cada componente.

Para charts Helm implantados fora do EIB, o Upgrade Controller cria um recurso HelmChart para cada componente.

Após a criação/atualização do recurso HelmChart, o Upgrade Controller depende do helm-controller para detectar essa alteração e prosseguir com a atualização real do componente.

Os charts serão atualizados sequencialmente com base na ordem deles no ReleaseManifest. Valores adicionais também podem ser passados através do UpgradePlan. Se a versão de um chart permanecer inalterada na nova release SUSE Telco Cloud, ele não será atualizado. Para obter mais informações sobre isso, consulte a Seção 21.6.1, “UpgradePlan”.

21.6 Extensões da API do Kubernetes

Extensões para a API do Kubernetes introduzidas pelo Upgrade Controller.

21.6.1 UpgradePlan

O Upgrade Controller introduz um novo recurso personalizado do Kubernetes chamado UpgradePlan.

O UpgradePlan serve como um mecanismo de instrução para o Upgrade Controller e suporta as seguintes configurações:

  • releaseVersion - Versão da release do Edge para a qual o cluster deve ser atualizado. A versão da release deve seguir o versionamento semântico e deve ser obtida nas Release Notes (Capítulo 75, Notas de versão).

  • disableDrain - Opcional; instrui o Upgrade Controller sobre desabilitar os drains de nós. Útil para quando você tem cargas de trabalho com Orçamentos de Interrupção.

    • Exemplo para desativação da drenagem de nós do plano de controle:

      spec:
        disableDrain:
          controlPlane: true
    • Exemplo para desativação da drenagem dos nós do plano de controle e dos nós worker:

      spec:
        disableDrain:
          controlPlane: true
          worker: true
  • helm - Opcional; especifica valores adicionais para componentes instalados via Helm.

    Atenção
    Atenção

    É aconselhável usar este campo apenas para valores que são críticos para atualizações. Atualizações padrão de valores de chart devem ser realizadas após os respectivos charts terem sido atualizados para a próxima versão.

    • Exemplo:

      spec:
        helm:
        - chart: foo
          values:
            bar: baz

21.6.2 ReleaseManifest

O Upgrade Controller introduz um novo recurso personalizado do Kubernetes chamado ReleaseManifest.

O recurso ReleaseManifest é criado pelo Upgrade Controller e mantém dados de componentes para uma versão de lançamento do Edge específica. Isso significa que cada upgrade da versão de lançamento do Edge será representado por um recurso ReleaseManifest diferente.

Atenção
Atenção

O Manifesto de Lançamento deve ser sempre criado pelo Upgrade Controller.

Não é aconselhável criar ou editar manualmente os recursos ReleaseManifest. Usuários que decidirem fazer isso devem fazê-lo por sua própria conta e risco.

Os dados do componente que o Manifesto de Lançamento envia incluem, mas não estão limitados a:

  • Dados do Sistema Operacional - versão, arquiteturas suportadas, dados adicionais de atualização, etc.

  • Dados de distribuição do Kubernetes - versões suportadas do RKE2/K3s

  • Dados de componentes adicionais - dados do gráfico Helm da SUSE (localização, versão, nome, etc.)

Para um exemplo de como um Manifesto de Lançamento pode parecer, consulte a https://github.com/suse-edge/upgrade-controller/blob/main/config/samples/lifecycle_v1alpha1_releasemanifest.yamldocumentação [upstream]. Observe que este é apenas um exemplo e não se destina a ser criado como um recurso ReleaseManifest válido.

21.7 Acompanhando o processo de atualização

Esta seção serve como um meio para rastrear e depurar o processo de atualização que o Controlador de Atualização inicia assim que o usuário cria um recurso UpgradePlan.

21.7.1 Geral

Informações gerais sobre o estado do processo de atualização podem ser visualizadas nas condições de status do Plano de Atualização.

O status do recurso Plano de Atualização pode ser visualizado da seguinte forma:

kubectl get upgradeplan <upgradeplan_name> -n upgrade-controller-system -o yaml
Exemplo 21.1: Exemplo de Plano de Atualização em execução:
apiVersion: lifecycle.suse.com/v1alpha1
kind: UpgradePlan
metadata:
  name: upgrade-plan-mgmt
  namespace: upgrade-controller-system
spec:
  releaseVersion: 3.6
status:
  conditions:
  - lastTransitionTime: "2024-10-01T06:26:27Z"
    message: Control plane nodes are being upgraded
    reason: InProgress
    status: "False"
    type: OSUpgraded
  - lastTransitionTime: "2024-10-01T06:26:27Z"
    message: Kubernetes upgrade is not yet started
    reason: Pending
    status: Unknown
    type: KubernetesUpgraded
  - lastTransitionTime: "2024-10-01T06:26:27Z"
    message: Rancher upgrade is not yet started
    reason: Pending
    status: Unknown
    type: RancherUpgraded
  - lastTransitionTime: "2024-10-01T06:26:27Z"
    message: Longhorn upgrade is not yet started
    reason: Pending
    status: Unknown
    type: LonghornUpgraded
  - lastTransitionTime: "2024-10-01T06:26:27Z"
    message: MetalLB upgrade is not yet started
    reason: Pending
    status: Unknown
    type: MetalLBUpgraded
  - lastTransitionTime: "2024-10-01T06:26:27Z"
    message: CDI upgrade is not yet started
    reason: Pending
    status: Unknown
    type: CDIUpgraded
  - lastTransitionTime: "2024-10-01T06:26:27Z"
    message: KubeVirt upgrade is not yet started
    reason: Pending
    status: Unknown
    type: KubeVirtUpgraded
  - lastTransitionTime: "2024-10-01T06:26:27Z"
    message: NeuVector upgrade is not yet started
    reason: Pending
    status: Unknown
    type: NeuVectorUpgraded
  - lastTransitionTime: "2024-10-01T06:26:27Z"
    message: EndpointCopierOperator upgrade is not yet started
    reason: Pending
    status: Unknown
    type: EndpointCopierOperatorUpgraded
  - lastTransitionTime: "2024-10-01T06:26:27Z"
    message: Elemental upgrade is not yet started
    reason: Pending
    status: Unknown
    type: ElementalUpgraded
  - lastTransitionTime: "2024-10-01T06:26:27Z"
    message: SRIOV upgrade is not yet started
    reason: Pending
    status: Unknown
    type: SRIOVUpgraded
  - lastTransitionTime: "2024-10-01T06:26:27Z"
    message: Metal3 upgrade is not yet started
    reason: Pending
    status: Unknown
    type: Metal3Upgraded
  - lastTransitionTime: "2024-10-01T06:26:27Z"
    message: RancherTurtles upgrade is not yet started
    reason: Pending
    status: Unknown
    type: RancherTurtlesUpgraded
  observedGeneration: 1
  sucNameSuffix: 90315a2b6d

Aqui você pode visualizar cada componente para o qual o Controlador de Atualização tentará agendar uma atualização. Cada condição segue o modelo abaixo:

  • lastTransitionTime - a última vez que esta condição de componente transitou de um status para outro.

  • message - mensagem que indica o estado atual de atualização da condição específica do componente.

  • reason - o estado atual de atualização da condição específica do componente. Possíveis reasons incluem:

    • Succeeded - a atualização do componente específico foi bem-sucedida.

    • Failed - a atualização do componente específico falhou.

    • InProgress - o fazer upgrade do componente específico está em andamento.

    • Pending - o fazer upgrade do componente específico ainda não está agendado.

    • Skipped - o componente específico não foi encontrado no cluster, portanto, seu fazer upgrade será ignorado.

    • Error - o componente específico encontrou um erro transitório durante o fazer upgrade.

  • status - status da condição atual type, uma das True, False, Unknown.

  • type - indicador para o componente atualmente em fazer upgrade.

O Upgrade Controller cria Planos SUC para condições de componente do tipo OSUpgraded e KubernetesUpgraded. Para acompanhar melhor os Planos SUC criados para esses componentes, consulte Seção 20.3, “Monitoramento de Planos do Upgrade Controller do Sistema”.

Todos os outros tipos de condição de componente podem ser acompanhados visualizando os recursos criados para eles pelo helm-controller. Para obter mais informações, consulte Seção 21.7.2, “Helm Controller”.

Um Plano de Atualização agendado pelo Upgrade Controller pode ser marcado como successful quando:

  1. Não há condições de componente Pending ou InProgress.

  2. A propriedade lastSuccessfulReleaseVersion aponta para o releaseVersion que é especificado na configuração do Plano de Atualização. Esta propriedade é adicionada ao status do Plano de Atualização pelo Upgrade Controller assim que o processo de fazer upgrade for bem-sucedido.

Exemplo 21.2: Exemplo de UpgradePlan bem-sucedida:
apiVersion: lifecycle.suse.com/v1alpha1
kind: UpgradePlan
metadata:
  name: upgrade-plan-mgmt
  namespace: upgrade-controller-system
spec:
  releaseVersion: 3.6
status:
  conditions:
  - lastTransitionTime: "2024-10-01T06:26:48Z"
    message: All cluster nodes are upgraded
    reason: Succeeded
    status: "True"
    type: OSUpgraded
  - lastTransitionTime: "2024-10-01T06:26:59Z"
    message: All cluster nodes are upgraded
    reason: Succeeded
    status: "True"
    type: KubernetesUpgraded
  - lastTransitionTime: "2024-10-01T06:27:13Z"
    message: Chart rancher upgrade succeeded
    reason: Succeeded
    status: "True"
    type: RancherUpgraded
  - lastTransitionTime: "2024-10-01T06:27:13Z"
    message: Chart longhorn is not installed
    reason: Skipped
    status: "False"
    type: LonghornUpgraded
  - lastTransitionTime: "2024-10-01T06:27:13Z"
    message: Specified version of chart metallb is already installed
    reason: Skipped
    status: "False"
    type: MetalLBUpgraded
  - lastTransitionTime: "2024-10-01T06:27:13Z"
    message: Chart cdi is not installed
    reason: Skipped
    status: "False"
    type: CDIUpgraded
  - lastTransitionTime: "2024-10-01T06:27:13Z"
    message: Chart kubevirt is not installed
    reason: Skipped
    status: "False"
    type: KubeVirtUpgraded
  - lastTransitionTime: "2024-10-01T06:27:13Z"
    message: Chart neuvector-crd is not installed
    reason: Skipped
    status: "False"
    type: NeuVectorUpgraded
  - lastTransitionTime: "2024-10-01T06:27:14Z"
    message: Specified version of chart endpoint-copier-operator is already installed
    reason: Skipped
    status: "False"
    type: EndpointCopierOperatorUpgraded
  - lastTransitionTime: "2024-10-01T06:27:14Z"
    message: Chart elemental-operator upgrade succeeded
    reason: Succeeded
    status: "True"
    type: ElementalUpgraded
  - lastTransitionTime: "2024-10-01T06:27:15Z"
    message: Chart sriov-crd is not installed
    reason: Skipped
    status: "False"
    type: SRIOVUpgraded
  - lastTransitionTime: "2024-10-01T06:27:19Z"
    message: Chart metal3 is not installed
    reason: Skipped
    status: "False"
    type: Metal3Upgraded
  - lastTransitionTime: "2024-10-01T06:27:27Z"
    message: Chart rancher-turtles is not installed
    reason: Skipped
    status: "False"
    type: RancherTurtlesUpgraded
  lastSuccessfulReleaseVersion: 3.6
  observedGeneration: 1
  sucNameSuffix: 90315a2b6d

21.7.2 Helm Controller

Esta seção aborda como rastrear recursos criados pelo helm-controller.

Nota
Nota

As etapas abaixo pressupõem que o kubectl foi configurado para se conectar ao cluster onde o Upgrade Controller foi implantado.

  1. Localize o recurso HelmChart para o componente específico:

    kubectl get helmcharts -n kube-system
  2. Usando o nome do recurso HelmChart, localize o Pod de fazer upgrade que foi criado pelo helm-controller:

    kubectl get pods -l helmcharts.helm.cattle.io/chart=<helmchart_name> -n kube-system
    
    # Example for Rancher
    kubectl get pods -l helmcharts.helm.cattle.io/chart=rancher -n kube-system
    NAME                         READY   STATUS      RESTARTS   AGE
    helm-install-rancher-tv9wn   0/1     Completed   0          16m
  3. Visualize os logs do pod específico de fazer upgrade do componente:

    kubectl logs <pod_name> -n kube-system

21.8 Limitações conhecidas

  • O Upgrade Controller espera que quaisquer gráficos Helm SUSE Telco Cloud adicionais implantados por meio do EIB (Capítulo 12, Edge Image Builder) tenham seu HelmChart CR implantado no namespace kube-system. Para fazer isso, configure a propriedade installationNamespace no seu arquivo de definição EIB. Para obter mais informações, consulte a documentação upstream.

  • Atualmente, o Upgrade Controller não tem como determinar a versão de lançamento do Edge atualmente em execução no cluster de gerenciamento. Certifique-se de fornecer uma versão de lançamento do Edge que seja superior à versão de lançamento do Edge atualmente em execução no cluster.

  • Atualmente, o Upgrade Controller oferece suporte apenas a fazer upgrade de ambientes non air-gapped. Fazer upgrade em ambientes air-gapped ainda não é possível.

Parte IV Requisitos e premissas

  • 22 Hardware
  • Os requisitos de hardware para o SUSE Telco Cloud são os seguintes:

  • 23 Rede
  • Como referência para a arquitetura de rede, o diagrama a seguir mostra uma arquitetura de rede típica para um ambiente de telecomunicações:

  • 24 Requisitos de porta
  • Para operar corretamente, uma implantação do SUSE Telco Cloud requer que várias portas estejam acessíveis nos nós do cluster de gerenciamento e nos nós do cluster Kubernetes downstream.

  • 25 Serviços (DHCP, DNS, etc.)
  • Alguns serviços externos como DHCP, DNS, etc. podem ser necessários dependendo do tipo de ambiente onde são implantados:

  • 26 Desativando serviços do systemd
  • Para cargas de trabalho de telecomunicações, é importante desativar ou configurar adequadamente alguns dos serviços em execução nos nós para evitar qualquer impacto no desempenho da carga de trabalho em execução nos nós (latência).

22 Hardware

Os requisitos de hardware para o SUSE Telco Cloud são os seguintes:

  • Cluster de gerenciamento: O cluster de gerenciamento contém componentes como SUSE Linux Micro, RKE2, SUSE Rancher Prime, Metal3, e é usado para gerenciar vários clusters downstream. Dependendo do número de clusters downstream a serem gerenciados, os requisitos de hardware para o servidor podem variar.

    • Os requisitos mínimos para o servidor (VM ou bare-metal) são:

      • RAM: 8 GB Mínimo (recomendamos pelo menos 16 GB)

      • CPU: 2 Mínimo (recomendamos pelo menos 4 CPU)

  • Downstream clusters: Os clusters downstream são os clusters implantados para executar cargas de trabalho de Telco. Requisitos específicos são necessários para habilitar certas capacidades de Telco como SR-IOV, CPU Performance Optimization, etc.

    • SR-IOV: para anexar VFs (Virtual Functions) em modo de passagem a CNFs/VNFs, a NIC deve suportar SR-IOV e o VT-d/AMD-Vi deve estar habilitado no BIOS.

    • Processadores de CPU: Para executar cargas de trabalho Telco específicas, o modelo de processador de CPU deve ser adaptado para habilitar a maioria dos recursos disponíveis nesta tabela de referência (Parte VI, “Configuração de recursos de Telco”).

    • Requisitos de firmware para instalação com mídia virtual:

      Hardware do servidorModelo de BMCGerenciamento

      Hardware Dell

      15ª Geração

      iDRAC9

      Hardware Supermicro

      01.00.25

      Supermicro SMC - redfish

      Hardware HPE

      1.50

      iLO6

23 Rede

Como referência para a arquitetura de rede, o diagrama a seguir mostra uma arquitetura de rede típica para um ambiente de telecomunicações:

product atip requirements1

A arquitetura de rede é baseada nos seguintes componentes:

  • Rede de gerenciamento: Esta rede é usada para o gerenciamento de nós de clusters downstream. Ela é usada para o gerenciamento fora de banda. Geralmente, esta rede também é conectada a um switch de gerenciamento separado, mas pode ser conectada ao mesmo switch de serviço usando VLANs para isolar o tráfego.

  • Rede do plano de controle: Esta rede é usada para a comunicação entre os nós do cluster downstream e os serviços que estão sendo executados neles. Esta rede também é usada para a comunicação entre os nós e os serviços externos, como os servidores DHCP ou DNS. Em alguns casos, para ambientes conectados, o switch/roteador pode lidar com o tráfego através da Internet.

  • Outras redes: Em alguns casos, os nós podem ser conectados a outras redes para fins específicos.

Nota
Nota

Para usar o fluxo de trabalho de provisionamento de rede direcionado, o cluster de gerenciamento deve ter conectividade de rede com o Baseboard Management Controller (BMC) do servidor do cluster downstream para que a preparação e o provisionamento do host possam ser automatizados.

24 Requisitos de porta

Para operar corretamente, uma implantação do SUSE Telco Cloud requer que várias portas estejam acessíveis nos nós do cluster de gerenciamento e nos nós do cluster Kubernetes downstream.

Nota
Nota

A lista exata depende dos componentes opcionais implantados e das opções de implantação selecionadas (por exemplo, plug-in CNI).

24.1 Nós de gerenciamento

A tabela a seguir lista as portas abertas nos nós que executam o cluster de gerenciamento:

Nota
Nota

Para portas relacionadas ao plug-in CNI, consulte requisitos de porta específicos do CNI (Seção 24.3, “Requisitos de porta específicos de CNI”).

Tabela 24.1: Regras de rede de entrada para nós de gerenciamento
ProtocoloPortarOrigemDescrição

TCP

22

Qualquer origem que exija acesso SSH

Acesso SSH aos nós do cluster de gerenciamento

TCP

80

Balanceador de carga/proxy que realiza terminação TLS externa

UI/API do Rancher quando a terminação TLS externa é usada

TCP

443

Qualquer origem que exija acesso TLS à UI/API do Rancher

Agente do Rancher, UI/API do Rancher

TCP

2379

Nós de servidor RKE2 (cluster de gerenciamento)

etcd Porta de cliente

TCP

2380

Nós de servidor RKE2 (cluster de gerenciamento)

etcd Porta de par

TCP

6180

Qualquer BMC(1) instruído anteriormente pelo Metal3/ironic a extrair uma imagem de ramdisk IPA(2) desta porta exposta (sem TLS)

Ironic Servidor web httpd sem TLS fornecendo imagem ISO IPA(2) para inicialização baseada em mídia virtual

Caso esta porta esteja habilitada, a funcionalmente equivalente, porém habilitada para TLS (veja abaixo), não é aberta

TCP

6185

Qualquer BMC(1) instruído anteriormente pelo Metal3/ironic a extrair uma imagem de ramdisk IPA(2) desta porta exposta (com TLS)

Ironic Servidor web httpd habilitado para TLS fornecendo imagem ISO IPA(2) para inicialização baseada em mídia virtual

Caso esta porta esteja habilitada, a funcionalmente equivalente, porém desabilitada para TLS (veja acima), não é aberta

TCP

6385

Qualquer imagem de ramdisk Metal3/ironic IPA(1) implantada e em execução em uma instância BareMetalHost "inscrita"

API do Ironic

TCP

6443

Qualquer nó do cluster de gerenciamento; qualquer cliente Kubernetes externo (ao cluster de gerenciamento)

API Kubernetes

TCP

6545

Qualquer nó do cluster de gerenciamento

Extrair artefatos de um registro compatível com OCI (Hauler)

TCP

9345

Nós de servidor e agente RKE2 (cluster de gerenciamento)

API do supervisor RKE2 para registro de nós (porta aberta em todos os nós de servidor RKE2)

TCP

10250

Qualquer nó do cluster de gerenciamento

kubelet métricas

TCP/UDP/SCTP

30000-32767

Qualquer fonte externa (ao cluster de gerenciamento) acessando um serviço exposto na rede primária através de um spec.type: NodePort ou spec.type: LoadBalancer objeto de API de serviço

NodePort Intervalo de porta disponível

(1) BMC: Baseboard Management Controller
(2) IPA: Ironic Python Agent

24.2 Nós downstream

No SUSE Telco Cloud, antes que qualquer servidor downstream se torne parte de um cluster Kubernetes downstream em execução (ou execute um cluster Kubernetes downstream de nó único), é necessário passar por alguns dos estados de provisionamento BaremetalHost.

  • O Baseboard Management Controller (BMC) de um servidor downstream recém-declarado deve estar acessível através da rede out-of-band. O BMC é instruído (pelo serviço ironic em execução no cluster de gerenciamento) sobre as etapas iniciais a serem seguidas:

    1. Extrair e carregar a imagem de ramdisk IPA indicada no virtual media oferecido pelo BMC.

    2. Ligar o servidor.

Espera-se que as seguintes portas sejam expostas pelo BMC (elas podem diferir dependendo do hardware exato):

Tabela 24.2: Regras de rede de entrada para Baseboard Management Controllers
ProtocoloPortarOrigemDescrição

TCP

80

Ironic conductor (do cluster de gerenciamento)

Acesso à API Redfish (HTTP)

TCP

443

Ironic conductor (do cluster de gerenciamento)

Acesso à API Redfish (HTTPS)

  • Assim que a imagem de ramdisk do IPA carregada no BMC virtual media for usada para inicializar a imagem do servidor downstream, a fase de inspeção de hardware começa. A tabela a seguir lista as portas expostas por uma imagem de ramdisk do IPA em execução:

Tabela 24.3: Regras de rede de entrada para nós downstream - Metal3/Ironic fase de provisionamento
ProtocoloPortarOrigemDescrição

TCP

22

Qualquer origem que exija acesso SSH à imagem de ramdisk do IPA

Acesso SSH a um nó de cluster downstream sendo inspecionado

TCP

9999

Ironic conductor (do cluster de gerenciamento)

Comandos Ironic para a imagem de ramdisk em execução

  • Assim que o host baremetal for provisionado corretamente e tiver ingressado em um cluster Kubernetes downstream, ele expõe as seguintes portas:

Nota
Nota

Para portas relacionadas ao plug-in CNI, consulte requisitos de porta específicos do CNI (Seção 24.3, “Requisitos de porta específicos de CNI”).

Tabela 24.4: Regras de rede de entrada para nós downstream
ProtocoloPortarOrigemDescrição

TCP

22

Qualquer origem que exija acesso SSH

Acesso SSH a nós de cluster downstream

TCP

80

Balanceador de carga/proxy que realiza terminação TLS externa

UI/API do Rancher quando a terminação TLS externa é usada

TCP

443

Qualquer origem que exija acesso TLS à UI/API do Rancher

Agente do Rancher, UI/API do Rancher

TCP

2379

Nós de servidor RKE2 (cluster downstream)

etcd Porta de cliente

TCP

2380

Nós de servidor RKE2 (cluster downstream)

etcd Porta de par

TCP

6443

Qualquer nó de cluster downstream; qualquer cliente Kubernetes externo (ao cluster downstream).

API Kubernetes

TCP

9345

Nós de servidor e agente RKE2 (cluster downstream)

API do supervisor RKE2 para registro de nós (porta aberta em todos os nós de servidor RKE2)

TCP

10250

Qualquer nó de cluster downstream

kubelet métricas

TCP

10255

Qualquer nó de cluster downstream

kubelet Acesso somente leitura

TCP/UDP/SCTP

30000-32767

Qualquer origem externa (ao cluster downstream) acessando um serviço exposto na rede primária por meio de um spec.type: NodePort ou spec.type: LoadBalancer objeto de API de serviço

NodePort Intervalo de porta disponível

24.3 Requisitos de porta específicos de CNI

Cada variante de CNI suportada vem com seu próprio conjunto de requisitos de porta. Para mais detalhes, consulte Regras de rede de entrada específicas de CNI na documentação do RKE2.

Quando o cilium é definido como plug-in CNI padrão/primário, a seguinte porta TCP é adicionalmente exposta quando a carga de trabalho cilium-operator é configurada para expor métricas fora do cluster Kubernetes no qual está implantada. Isso garante que uma instância de servidor Prometheus externa, executada fora desse cluster Kubernetes, ainda possa coletar essas métricas.

Nota
Nota

Esta é a opção padrão ao implantar o cilium via gráfico Helm rke2-cilium.

Tabela 24.5: Regras de Rede de Entrada para Nós de Gerenciamento/Downstream - exposição de métricas externas do cilium-operator ativada
ProtocoloPortarOrigemDescrição

TCP

9963

Coletor de métricas externo (ao cluster Kubernetes)

exposição de métricas do cilium-operator

25 Serviços (DHCP, DNS, etc.)

Alguns serviços externos como DHCP, DNS, etc. podem ser necessários dependendo do tipo de ambiente onde são implantados:

  • Ambiente conectado: Neste caso, os nós estarão conectados à Internet (via protocolos de roteamento L3) e os serviços externos serão fornecidos pelo cliente.

  • Ambiente desconectado / air gap: Neste caso, os nós não terão conectividade IP com a Internet e serviços adicionais serão necessários para espelhar localmente o conteúdo exigido pelo fluxo de trabalho de provisionamento de rede direcionado.

  • Servidor de arquivos: Um servidor de arquivos é usado para armazenar as imagens do SO a serem provisionadas nos nós do cluster downstream durante o fluxo de trabalho de provisionamento de rede direcionado. O gráfico Helm Metal3 pode implantar um servidor de mídia para armazenar as imagens do SO — verifique a seção (Nota) a seguir, mas também é possível usar um servidor web local existente.

26 Desativando serviços do systemd

Para cargas de trabalho de telecomunicações, é importante desativar ou configurar adequadamente alguns dos serviços em execução nos nós para evitar qualquer impacto no desempenho da carga de trabalho em execução nos nós (latência).

  • rebootmgr é um serviço que permite configurar uma estratégia de reinicialização quando o sistema tem atualizações pendentes. Para cargas de trabalho de telecomunicações, é realmente importante desativar ou configurar adequadamente o serviço rebootmgr para evitar a reinicialização dos nós em caso de atualizações agendadas pelo sistema, para evitar qualquer impacto nos serviços em execução nos nós.

Nota
Nota

Para obter mais informações sobre o rebootmgr, consulte o repositório GitHub do rebootmgr.

Verifique a estratégia que está sendo usada executando:

cat /etc/rebootmgr.conf
[rebootmgr]
window-start=03:30
window-duration=1h30m
strategy=best-effort
lock-group=default

e você pode desativá-la executando:

sed -i 's/strategy=best-effort/strategy=off/g' /etc/rebootmgr.conf

ou usando o comando rebootmgrctl:

rebootmgrctl strategy off
Nota
Nota

Esta configuração para definir a estratégia rebootmgr pode ser automatizada usando o fluxo de trabalho de provisionamento de rede direcionado. Para obter mais informações, consulte a documentação de Provisionamento Automatizado (Parte VII, “Provisionamento de rede direcionado totalmente automatizado”).

  • transactional-update é um serviço que permite atualizações automáticas controladas pelo sistema. Para cargas de trabalho de telecomunicações, é importante desativar as atualizações automáticas para evitar qualquer impacto nos serviços em execução nos nós.

Para desativar as atualizações automáticas, você pode executar:

systemctl --now disable transactional-update.timer
systemctl --now disable transactional-update-cleanup.timer
  • fstrim é um serviço que permite realizar o trim dos sistemas de arquivos automaticamente toda semana. Para cargas de trabalho de telecomunicações, é importante desativar o trim automático para evitar qualquer impacto nos serviços em execução nos nós.

Para desativar o trim automático, você pode executar:

systemctl --now disable fstrim.timer

Parte V Configurando o cluster de gerenciamento

  • 27 Introdução
  • O cluster de gerenciamento é a parte do SUSE Telco Cloud que é usada para gerenciar o provisionamento e o ciclo de vida das pilhas de tempo de execução. Do ponto de vista técnico, o cluster de gerenciamento contém os seguintes componentes:

  • 28 Etapas para configurar o cluster de gerenciamento
  • As seguintes etapas são necessárias para configurar o cluster de gerenciamento (usando um único nó):

  • 29 Preparação de imagem para ambientes conectados
  • O Edge Image Builder é usado para criar a imagem para o cluster de gerenciamento; neste documento, abordamos a configuração mínima necessária para configurar o cluster de gerenciamento.

  • 30 Preparação de imagem para ambientes air-gap
  • Esta seção descreve como preparar a imagem para ambientes air-gap, mostrando apenas as diferenças em relação às seções anteriores. As seguintes alterações na seção anterior (Preparação de imagem para ambientes conectados (Capítulo 29, Preparação de imagem para ambientes conectados)) são necessárias …

  • 31 Criação de imagem
  • Uma vez que a estrutura de diretórios esteja preparada de acordo com as seções anteriores (para os cenários conectados e air-gap), execute o seguinte comando para criar a imagem:

  • 32 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 (usando o recurso de virtual-media).

  • 33 Considerações e configuração de pilha dupla
  • Os exemplos mostrados nas seções anteriores fornecem orientação e exemplos sobre como configurar um cluster de gerenciamento IPv4 de pilha única. Tal cluster de gerenciamento é independente do status operacional dos clusters downstream, que podem ser configurados individualmente para operar em confi…

27 Introdução

O cluster de gerenciamento é a parte do SUSE Telco Cloud que é usada para gerenciar o provisionamento e o ciclo de vida das pilhas de tempo de execução. Do ponto de vista técnico, o cluster de gerenciamento contém os seguintes componentes:

  • SUSE Linux Micro como o SO. Dependendo do caso de uso, algumas configurações como rede, armazenamento, usuários e argumentos de kernel podem ser personalizadas.

  • RKE2 como o cluster Kubernetes. Dependendo do caso de uso, ele pode ser configurado para usar plugins CNI específicos, como Multus, Cilium, Calico, etc.

  • Rancher como a plataforma de gerenciamento para gerenciar o ciclo de vida dos clusters.

  • Metal3 como o componente para gerenciar o ciclo de vida dos nós bare-metal.

  • CAPI como o componente para gerenciar o ciclo de vida dos clusters Kubernetes (clusters downstream). O RKE2 CAPI Provider é 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 de clusters downstream, usando uma abordagem declarativa para gerenciar a infraestrutura e os aplicativos.

Nota
Nota

Para obter mais informações sobre o SUSE Linux Micro, consulte: SUSE Linux Micro (Capítulo 10, SUSE Linux Micro)

Para obter mais informações sobre o RKE2, consulte: RKE2 (Capítulo 14, RKE2)

Para obter mais informações sobre o Rancher, consulte: Rancher (Capítulo 6, Rancher)

Para obter mais informações sobre o Metal3, consulte: Metal3 (Capítulo 11, Metal3)

28 Etapas para configurar o cluster de gerenciamento

As seguintes etapas são necessárias para configurar o cluster de gerenciamento (usando um único nó):

product atip mgmtcluster1

A seguir estão as principais etapas para configurar o cluster de gerenciamento usando uma abordagem declarativa:

  1. Preparação de imagem para ambientes conectados (Capítulo 29, Preparação de imagem para ambientes conectados): O primeiro passo é preparar os manifestos e arquivos com todas as configurações necessárias para serem usados em ambientes conectados.

    • Estrutura de diretório para ambientes conectados (Seção 29.1, “Estrutura de diretórios”): Este passo cria uma estrutura de diretório a ser usada pelo Edge Image Builder para armazenar os arquivos de configuração e a própria imagem.

    • Arquivo de definição do cluster de gerenciamento (Seção 29.2, “Arquivo de definição do cluster de gerenciamento”): O arquivo mgmt-cluster.yaml é o principal arquivo de definição para o cluster de gerenciamento. Ele contém as seguintes informações sobre a imagem a ser criada:

      • Informações da Imagem: As informações relacionadas à imagem a ser criada usando a imagem base.

      • Sistema operacional: As configurações do sistema operacional a serem usadas na imagem.

      • Kubernetes: Charts Helm e repositórios, versão do Kubernetes, configuração de rede e os nós a serem usados no cluster.

    • Pasta Personalizada (Seção 29.3, “Pasta Personalizada”): A pasta custom contém os arquivos de configuração e scripts a serem usados pelo Edge Image Builder para implantar um cluster de gerenciamento totalmente funcional.

      • Arquivos: Contém os arquivos de configuração a serem usados pelo cluster de gerenciamento.

      • Scripts: Contém os scripts a serem usados pelo cluster de gerenciamento.

    • Kubernetes folder (Seção 29.4, “Kubernetes folder”): A pasta kubernetes contém os arquivos de configuração a serem usados pelo cluster de gerenciamento.

      • Manifestos: Contém os manifestos a serem usados pelo cluster de gerenciamento.

      • Helm: Contém os arquivos de valores do Helm a serem usados pelo cluster de gerenciamento.

      • Configuração: Contém os arquivos de configuração a serem usados pelo cluster de gerenciamento.

    • Pasta de rede (Seção 29.5, “Pasta de rede”): A pasta network contém os arquivos de configuração de rede a serem usados pelos nós do cluster de gerenciamento.

  2. Preparação de imagem para ambientes air-gap (Capítulo 30, Preparação de imagem para ambientes air-gap): A etapa consiste em mostrar as diferenças para preparar os manifestos e arquivos a serem usados em um cenário air-gap.

    • Modificações no arquivo de definição (Seção 30.1, “Modificações no arquivo de definição”): O arquivo mgmt-cluster.yaml deve ser modificado para incluir a seção embeddedArtifactRegistry com o campo images definido para todas as imagens de contêiner a serem incluídas na imagem de saída do EIB.

    • Modificações na pasta personalizada (Seção 30.2, “Modificações na pasta personalizada”): A pasta custom deve ser modificada para incluir os recursos necessários para executar o cluster de gerenciamento em um ambiente air-gap.

      • Script de registro: O script custom/scripts/99-register.sh deve ser removido ao usar um ambiente air-gap.

  3. Criação de imagem (Capítulo 31, Criação de imagem): Esta etapa abrange a criação da imagem usando a ferramenta Edge Image Builder (para ambos os cenários, conectado e air-gap). Verifique os pré-requisitos (Capítulo 12, Edge Image Builder) para executar a ferramenta Edge Image Builder em seu sistema.

  4. Provisionamento do cluster de gerenciamento (Capítulo 32, Provisionar o cluster de gerenciamento): Esta etapa abrange o provisionamento do cluster de gerenciamento usando a imagem criada na etapa anterior (para ambos os cenários, conectado e air-gap). Esta etapa pode ser feita usando um laptop, servidor, VM ou qualquer outro sistema AMD64/Intel 64 com uma porta USB.

Nota
Nota

Para obter mais informações sobre o Edge Image Builder, consulte Edge Image Builder (Capítulo 12, Edge Image Builder) e Início Rápido do Edge Image Builder (Capítulo 5, Clusters autônomos com o Edge Image Builder).

29 Preparação de imagem para ambientes conectados

O Edge Image Builder é usado para criar a imagem para o cluster de gerenciamento; neste documento, abordamos a configuração mínima necessária para configurar o cluster de gerenciamento.

O Edge Image Builder é executado dentro de um contêiner, portanto, é necessário um tempo de execução do contêiner, como Podman ou Rancher Desktop. Para este guia, assumimos que o podman está disponível.

Além disso, como pré-requisito para implantar um cluster de gerenciamento de alta disponibilidade, você precisa reservar três IPs em sua rede:

  • apiVIP para o endereço VIP da API (usado para acessar o servidor de API do Kubernetes).

  • ingressVIP para o endereço VIP de Ingress (consumido, por exemplo, pela interface do usuário do Rancher).

  • metal3VIP para o endereço VIP do Metal3.

29.1 Estrutura de diretórios

Ao executar o EIB, um diretório é montado a partir do host, portanto, a primeira coisa a fazer é criar uma estrutura de diretórios a ser usada pelo EIB para armazenar os arquivos de configuração e a própria imagem. Este diretório tem a seguinte estrutura:

eib
├── mgmt-cluster.yaml
├── network
│ └── mgmt-cluster-node1.yaml
├── os-files
│ └── var
│   └── lib
│     └── rancher
│       └── rke2
│         └── server
│           └── manifests
│             └── rke2-ingress-config.yaml
├── kubernetes
│ ├── manifests
│ │ ├── neuvector-namespace.yaml
│ │ ├── ingress-l2-adv.yaml
│ │ └── ingress-ippool.yaml
│ ├── helm
│ │ └── values
│ │     ├── rancher.yaml
│ │     ├── neuvector.yaml
│ │     ├── longhorn.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
Nota
Nota

A imagem SL-Micro.x86_64-6.2-Base-SelfInstall-GM.install.iso deve ser baixada do SUSE Customer Center ou da página de download da SUSE, e deve estar localizada na pasta base-images.

Você deve verificar a soma de verificação SHA256 da imagem para garantir que ela não tenha sido adulterada. A soma de verificação pode ser encontrada no mesmo local onde a imagem foi baixada.

Um exemplo da estrutura de diretórios pode ser encontrado no SUSE Telco Cloud repositório do GitHub na pasta "telco-examples".

29.2 Arquivo de definição do cluster de gerenciamento

O arquivo mgmt-cluster.yaml é o principal arquivo de definição para o cluster de gerenciamento. Ele contém as seguintes informações:

apiVersion: 1.3
image:
  imageType: iso
  arch: x86_64
  baseImage: SL-Micro.x86_64-6.2-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
    - open-iscsi
    sccRegistrationCode: $SCC_REGISTRATION_CODE
kubernetes:
  version: v1.35.4+rke2r1
  helm:
    charts:
      - name: cert-manager
        repositoryName: jetstack
        version: 1.20.1
        targetNamespace: cert-manager
        valuesFile: certmanager.yaml
        createNamespace: true
        installationNamespace: kube-system
      - name: suse-storage
        releaseName: longhorn
        version: 1.11.2
        repositoryName: rancher-application-collection
        targetNamespace: longhorn-system
        createNamespace: true
        installationNamespace: kube-system
        valuesFile: longhorn.yaml
      - name: metallb
        version: 306.0.2+up0.15.3
        targetNamespace: metallb-system
        createNamespace: true
        repositoryName: suse-edge-charts
        installationNamespace: kube-system
      - name: metal3
        version: 306.0.29+up0.15.0
        repositoryName: suse-edge-charts
        targetNamespace: metal3-system
        createNamespace: true
        installationNamespace: kube-system
        valuesFile: metal3.yaml
      - name: rancher-turtles-providers
        version: 306.0.7+up0.26.2
        repositoryName: suse-edge-charts
        targetNamespace: cattle-turtles-system
        createNamespace: true
        installationNamespace: kube-system
      - name: neuvector-crd
        version: 109.0.2+up2.10.2
        repositoryName: rancher-charts
        targetNamespace: neuvector
        createNamespace: true
        installationNamespace: kube-system
        valuesFile: neuvector.yaml
      - name: neuvector
        version: 109.0.2+up2.10.2
        repositoryName: rancher-charts
        targetNamespace: neuvector
        createNamespace: true
        installationNamespace: kube-system
        valuesFile: neuvector.yaml
      - name: rancher
        version: 2.14.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
      - name: rancher-application-collection
        url: oci://dp.apps.rancher.io/charts
        authentication:
          username: $\{APPS.RANCHER.IO_USERNAME\}
          password: $\{APPS.RANCHER.IO_ACCESS_TOKEN\}
  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 valores no arquivo de definição mgmt-cluster.yaml, nós o dividimos nas seguintes seções.

  • Seção de imagem (arquivo de definição):

image:
  imageType: iso
  arch: x86_64
  baseImage: SL-Micro.x86_64-6.2-Base-SelfInstall-GM.install.iso
  outputImageName: eib-mgmt-cluster-image.iso

onde baseImage é a imagem original que você baixou do SUSE Customer Center ou da página de download 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

onde installDevice é o dispositivo a ser usado para instalar o sistema operacional, username e encryptedPassword são as credenciais a serem usadas para acessar o sistema, packageList é a lista de pacotes a serem instalados (jq é necessário internamente durante o processo de instalação) e sccRegistrationCode é o código de registro usado para obter os pacotes e dependências durante o build e pode ser obtido do SUSE Customer Center. A senha criptografada pode ser gerada usando o comando openssl da seguinte forma:

openssl passwd -6 MyPassword!123

Isso gera algo semelhante a:

$6$UrXB1sAGs46DOiSq$HSwi9GFJLCorm0J53nF2Sq8YEoyINhHcObHzX2R8h13mswUIsMwzx4eUzn/rRx0QPV4JIb0eWCoNrxGiKH4R31
  • Seção Kubernetes (arquivo de definição):

kubernetes:
  version: v1.35.4+rke2r1
  helm:
    charts:
      - name: cert-manager
        repositoryName: jetstack
        version: 1.20.1
        targetNamespace: cert-manager
        valuesFile: certmanager.yaml
        createNamespace: true
        installationNamespace: kube-system
      - name: suse-storage
        releaseName: longhorn
        version: 1.11.2
        repositoryName: rancher-application-collection
        targetNamespace: longhorn-system
        createNamespace: true
        installationNamespace: kube-system
        valuesFile: longhorn.yaml
      - name: metal3
        version: 306.0.29+up0.15.0
        repositoryName: suse-edge-charts
        targetNamespace: metal3-system
        createNamespace: true
        installationNamespace: kube-system
        valuesFile: metal3.yaml
      - name: metallb
        version: 306.0.2+up0.15.3
        targetNamespace: metallb-system
        createNamespace: true
        repositoryName: suse-edge-charts
        installationNamespace: kube-system
      - name: rancher-turtles-providers
        version: 306.0.7+up0.26.2
        repositoryName: suse-edge-charts
        targetNamespace: cattle-turtles-system
        createNamespace: true
        installationNamespace: kube-system
      - name: neuvector-crd
        version: 109.0.2+up2.10.2
        repositoryName: rancher-charts
        targetNamespace: neuvector
        createNamespace: true
        installationNamespace: kube-system
        valuesFile: neuvector.yaml
      - name: neuvector
        version: 109.0.2+up2.10.2
        repositoryName: rancher-charts
        targetNamespace: neuvector
        createNamespace: true
        installationNamespace: kube-system
        valuesFile: neuvector.yaml
      - name: rancher
        version: 2.14.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
      - name: rancher-application-collection
        url: oci://dp.apps.rancher.io/charts
        authentication:
          username: $\{APPS.RANCHER.IO_USERNAME\}
          password: $\{APPS.RANCHER.IO_ACCESS_TOKEN\}
    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 charts Helm a serem instalados, os repositórios a serem usados, e a configuração de versão para todos eles.

A seção network contém a configuração para a rede, como o apiHost e o apiVIP a serem usados pelo componente RKE2. O apiVIP deve ser um endereço IP que não seja usado na rede e não deve fazer parte do pool DHCP (caso usemos DHCP). Além disso, quando usamos o apiVIP em um cluster de vários nós, ele é usado para acessar o servidor de API do Kubernetes. O apiHost é a resolução de nomes para o apiVIP a ser usado pelo componente RKE2.

A seção nodes contém a lista de nós a serem usados no cluster. Neste exemplo, um cluster de nó único está sendo usado, mas ele pode ser estendido para um cluster de vários nós adicionando mais nós à lista (removendo o comentário das linhas).

Nota
Nota
  • Os nomes dos nós devem ser exclusivos no cluster.

  • Opcionalmente, use o campo initializer para especificar o host de inicialização; caso contrário, será o primeiro nó da lista.

  • Os nomes dos nós devem ser os mesmos que os nomes de host definidos na Pasta de rede (Seção 29.5, “Pasta de rede”) quando a configuração de rede for necessária.

29.3 Pasta Personalizada

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 a serem usados pelo cluster de gerenciamento.

  • A pasta custom/scripts contém os scripts a serem usados pelo cluster de gerenciamento.

A pasta custom/files contém os seguintes arquivos:

  • basic-setup.sh: contém parâmetros de configuração para Metal3, Rancher e MetalLB. Modifique este arquivo apenas se desejar alterar os namespaces a serem 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: contém a configuração para o componente Metal3 a ser usado (nenhuma modificação necessária). Em versões futuras, este script será substituído, utilizando Rancher Turtles em vez disso, para facilitar.

    #!/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 -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
    
    # Clean up the lock cm
    
    ${KUBECTL} delete configmap ${METAL3LOCKCMNAME} -n ${METAL3LOCKNAMESPACE}
    • rancher.sh: contém a configuração para o componente Rancher a ser usado (nenhuma modificação necessária).

      #!/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 a ser usado pelo cluster de gerenciamento para carregar o arquivo kubeconfig na primeira inicialização (nenhuma modificação necessária).

    #!/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 (nenhuma modificação necessária).

    #!/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 SCC. O ${SCC_ACCOUNT_EMAIL} e o ${SCC_REGISTRATION_CODE} devem ser definidos corretamente para registrar o sistema com 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}"

29.4 Kubernetes folder

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: O plug-in CNI instalado por padrão é o Cilium, portanto, você não precisa criar esta pasta e arquivo para definir isso. Caso você precise personalizar o plug-in CNI, você pode usar o arquivo server.yaml na pasta kubernetes/config. Ele contém as seguintes informações:

    cni:
    - multus
    - cilium
    ingress-controller: traefik
    write-kubeconfig-mode: '0644'
    selinux: true
    system-default-registry: registry.rancher.com
Nota
Nota

Este é um arquivo opcional para definir certas personalizações do Kubernetes, como os plug-ins CNI a serem usados ou muitas opções que você pode verificar na documentação oficial.

Atenção
Atenção

O provedor de ingress Traefik integrado ao RKE2/K3s é o único controlador de ingress suportado na versão SUSE Telco Cloud 3.6, sendo ainda possível executar temporariamente o Ingress-NGINX junto com o Traefik para suportar cenários complexos de migração de ingress, mas apenas após os clusters de Gerenciamento e/ou Downstream SUSE Telco Cloud terem sido atualizados para a versão 3.6 e pelo tempo necessário para realizar essa migração. Como o Traefik ainda não é o controlador de ingress padrão no RKE2 (ele será a partir do RKE2 v1.36 em diante), ele deve ser explicitamente "solicitado" no arquivo de configuração do servidor RKE2, resultando na necessidade de incluir o arquivo kubernetes/config/server.yaml em todas as imagens ISO de auto-instalação do EIB geradas para provisionar os nós dos clusters de Gerenciamento SUSE Telco Cloud 3.6.

O guia Migração de Ingress NGINX para Traefik do RKE2 fornece detalhes sobre os caminhos de migração de ingress disponíveis assim que o controlador de ingress Traefik substituir o Ingress-NGINX descontinuado.

A pasta os-files/var/lib/rancher/rke2/server/manifests contém o seguinte arquivo:

  • rke2-ingress-config.yaml: contém a configuração para criar o serviço Ingress para o cluster de gerenciamento (nenhuma modificação necessária).

    apiVersion: helm.cattle.io/v1
    kind: HelmChartConfig
    metadata:
      name: rke2-traefik
      namespace: kube-system
    spec:
      valuesContent: |-
        ingressClass:
          isDefaultClass: true
        ports:
          web:
            hostPort: null    # disallow hostPort
            exposedPort: 80
          websecure:
            hostPort: null    # disallow hostPort
            exposedPort: 443
        service:
          enabled: true
          type: LoadBalancer
          spec:
            externalTrafficPolicy: Local
            allocateLoadBalancerNodePorts: false  # k8s GA from 1.24; supported by MetalLB
        providers:
          kubernetesIngressNginx:  # this provider allows traefik to "understand" most of the ingress-nginx annotations
            enabled: true
            ingressClass: "rke2-ingress-nginx-migration"
            controllerClass: "rke2.​cattle.​io/ingress-nginx-migration"
Nota
Nota

O HelmChartConfig deve ser incluído via os-files no diretório /var/lib/rancher/rke2/server/manifests, não via kubernetes/manifests como descrito em versões anteriores.

A pasta kubernetes/manifests contém os seguintes arquivos:

  • neuvector-namespace.yaml: contém a configuração para criar o namespace NeuVector (nenhuma modificação necessária).

    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 o L2Advertisement para o componente MetalLB (nenhuma modificação necessária).

    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 o objeto IPAddressPool do MetalLB para o componente rke2-traefik. O ${INGRESS_VIP} deve ser definido corretamente para definir o endereço IP exposto reservado para ser usado para alcançar o serviço rke2-traefik (interno).

    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-traefik]}

A pasta kubernetes/helm/values contém os seguintes arquivos:

  • rancher.yaml: contém a configuração para criar o componente Rancher. O ${INGRESS_VIP} deve ser definido corretamente para definir o endereço IP a ser consumido pelo componente Rancher. A URL para acessar o componente Rancher será https://rancher-${INGRESS_VIP}.sslip.io.

    hostname: rancher-${INGRESS_VIP}.sslip.io
    bootstrapPassword: "foobar"
    replicas: 1
    global:
      cattle:
        systemDefaultRegistry: "registry.rancher.com"
  • neuvector.yaml: contém a configuração para criar o componente NeuVector (nenhuma modificação necessária).

    controller:
      replicas: 1
      ranchersso:
        enabled: true
    manager:
      enabled: false
    cve:
      scanner:
        enabled: false
        replicas: 1
    k3s:
      enabled: true
    crdwebhook:
      enabled: false
    registry: "registry.rancher.com"
    global:
      cattle:
        systemDefaultRegistry: "registry.rancher.com"
  • longhorn.yaml: contém a configuração para criar o componente Longhorn. Para garantir que as imagens de contêiner necessárias sejam baixadas no momento da inicialização, adicione suas credenciais da Rancher Application Collection.

    privateRegistry:
      createSecret: true
      registryUrl: dp.apps.rancher.io
      registryUser: $\{APPS.RANCHER.IO_USERNAME\}
      registryPasswd: $\{APPS.RANCHER.IO_ACCESS_TOKEN\}
      registrySecret: rancher-app-collection
  • metal3.yaml: contém a configuração para criar o componente Metal3. O ${METAL3_VIP} deve ser definido corretamente para definir o endereço IP a ser consumido pelo componente Metal3.

    global:
      ironicIP: ${METAL3_VIP}
      enable_vmedia_tls: false
      predictableNicNames: "true"
      # trustedCAs: tls-ca-bundle  # Optional: Uncomment and set to ConfigMap name for additional trusted CAs
    metal3-ironic:
      ipa:
        useHauler: false
      persistence:
        ironic:
          size: "5Gi"
    Importante
    Importante

    O parâmetro do Helm chart metal3-ironic.ipa.useHauler deve ser definido como true (valor booleano) em ambientes air-gapped; isso instrui o Metal3 a recuperar a imagem de contêiner ironic-python-agent (IPA) do registro de artefatos incorporado em vez de tentar baixá-la da internet. Esta imagem de contêiner IPA deve ser adicionalmente incluída na lista embeddedArtifactRegistry.images no arquivo de definição de imagem EIB para ambientes air-gap (Seção 30.1, “Modificações no arquivo de definição”).

Nota
Nota

O Servidor de Mídia é um recurso opcional incluído no Metal3 (por padrão, está desabilitado). Para usar o recurso Metal3, você precisa configurá-lo no manifesto anterior. Para usar o servidor de mídia Metal3, especifique a seguinte variável:

  • adicione enable_metal3_media_server a true para habilitar o recurso de servidor de mídia na seção global.

  • Inclua a seguinte configuração sobre o servidor de mídia, onde ${MEDIA_VOLUME_PATH} é o caminho para o volume de mídia (por exemplo, /home/metal3/bmh-image-cache).

    metal3-media:
      mediaVolume:
        hostPath: ${MEDIA_VOLUME_PATH}

Um servidor de mídia externo pode ser usado para armazenar as imagens e, caso você queira usá-lo com TLS, precisará fornecer o pacote de CA confiável para o Metal3.

Prepare o pacote de CA:

Primeiro, prepare seu arquivo de pacote de CA contendo todos os certificados necessários pelo Metal3. Isso inclui o(s) certificado(s) de CA do seu servidor de mídia externo.

+ Opcional – Pacote de CA do sistema: Se o Metal3 também precisar confiar em CAs públicas (por exemplo, ao acessar recursos HTTPS externos), você pode incluir o pacote de CA do sistema. Extraia-o de uma imagem de contêiner e concatene-o com seus certificados personalizados:

+

# Extract system CAs from a container image
podman run --rm registry.suse.com/bci/bci-base:latest cat /etc/ssl/certs/ca-certificates.crt > system-cas.pem

# Concatenate system CAs with your custom CA
cat system-cas.pem your-custom-ca.crt > ca-bundle.pem

+ Ou, se você precisar apenas da sua CA personalizada:

+

cp your-custom-ca.crt ca-bundle.pem

+

Se você incluir o pacote de CA do sistema, você se torna responsável por mantê-lo atualizado. As CAs do sistema em imagens de contêiner podem ficar desatualizadas à medida que os certificados expiram ou são revogados. Atualize periodicamente o pacote extraindo-o novamente de uma imagem de contêiner atualizada.

Crie o ConfigMap:

Você pode criar o ConfigMap de duas maneiras:

  1. Usando um arquivo de manifesto (recomendado para EIB): Crie o arquivo kubernetes/manifests/metal3-cacert-configmap.yaml e inclua o conteúdo do pacote de CA em linha. Você precisa recuar corretamente cada linha do certificado com 4 espaços:

    apiVersion: v1
    kind: Namespace
    metadata:
      name: metal3-system
    ---
    apiVersion: v1
    kind: ConfigMap
    metadata:
      name: tls-ca-bundle
      namespace: metal3-system
    data:
      ca-bundle.pem: |
        -----BEGIN CERTIFICATE-----
        MIIDXTCCAkWgAwIBAgIJAKJ... (your certificate content here)
        ...
        -----END CERTIFICATE-----
        -----BEGIN CERTIFICATE-----
        MIIEkjCCA3qgAwIBAgIQCgF... (additional certificates if any)
        ...
        -----END CERTIFICATE-----

    Para preencher este arquivo automaticamente a partir do seu ca-bundle.pem, você pode usar:

    cat > kubernetes/manifests/metal3-cacert-configmap.yaml <<EOF
    apiVersion: v1
    kind: Namespace
    metadata:
      name: metal3-system
    ---
    apiVersion: v1
    kind: ConfigMap
    metadata:
      name: tls-ca-bundle
      namespace: metal3-system
    data:
      ca-bundle.pem: |
    $(sed 's/^/    /' ca-bundle.pem)
    EOF
  2. Usando o kubectl diretamente (para implantação manual): Se você não estiver usando o EIB e quiser criar o ConfigMap diretamente no cluster:

    kubectl -n metal3-system create configmap tls-ca-bundle --from-file=ca-bundle.pem=./ca-bundle.pem
    • Defina o valor de global.trustedCAs no arquivo metal3.yaml para referenciar o nome do ConfigMap:

      global:
        trustedCAs: tls-ca-bundle
  • certmanager.yaml: contém a configuração para criar o componente Cert-Manager (nenhuma modificação necessária).

    installCRDs: true

29.5 Pasta de rede

A pasta network contém tantos arquivos quanto nós no cluster de gerenciamento. No nosso caso, temos apenas um nó, portanto, temos apenas um arquivo chamado mgmt-cluster-node1.yaml. O nome do arquivo deve corresponder ao nome do host definido no arquivo de definição mgmt-cluster.yaml na seção network/node descrita acima.

Se você precisar personalizar a configuração de rede, por exemplo, para usar um endereço IP estático específico (cenário sem DHCP), você pode usar o arquivo mgmt-cluster-node1.yaml na pasta network. Ele 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

Se você quiser usar DHCP para obter o endereço IP, você pode usar a seguinte configuração (o endereço MAC deve ser definido corretamente usando a 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
Nota
Nota
  • Dependendo do número de nós no cluster de gerenciamento, você pode 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.

30 Preparação de imagem para ambientes air-gap

Esta seção descreve como preparar a imagem para ambientes air-gap, mostrando apenas as diferenças em relação às seções anteriores. As seguintes alterações na seção anterior (Preparação de imagem para ambientes conectados (Capítulo 29, Preparação de imagem para ambientes conectados)) são necessárias para preparar a imagem para ambientes air-gap:

  • O arquivo mgmt-cluster.yaml deve ser modificado para incluir a seção embeddedArtifactRegistry com o campo images definido para todas as imagens de contêiner a serem incluídas na imagem de saída do EIB.

  • O script custom/scripts/99-register.sh deve ser removido ao usar um ambiente air-gap.

Para incluir o SUSE Private Registry no cluster de gerenciamento para futuras implantações downstream, as seguintes alterações também são necessárias:

  • O arquivo mgmt-cluster.yaml deve ser modificado para incluir a seção de helm chart, bem como os artefatos incorporados com as novas imagens para incluí-los na imagem de saída do EIB.

  • As pastas kubernetes/values e kubernetes/manifests devem incluir arquivos de manifesto adicionais para configurar corretamente o SUSE Private Registry no cluster de gerenciamento.

Nota
Nota

Você precisará de certas credenciais, que podem ser obtidas seguindo a documentação oficial do SUSE Private Registry.

30.1 Modificações no arquivo de definição

O arquivo mgmt-cluster.yaml deve ser modificado para incluir a seção embeddedArtifactRegistry. Nesta seção, o campo images deve conter a lista de todas as imagens de contêiner a serem incluídas na imagem de saída.

Nota
Nota

O seguinte exemplo de arquivo mgmt-cluster.yaml inclui tanto a seção embeddedArtifactRegistry quanto o recurso SUSE Private Registry. Certifique-se de que as imagens listadas contenham as versões dos componentes de que você precisa.

apiVersion: 1.3
image:
  imageType: iso
  arch: x86_64
  baseImage: SL-Micro.x86_64-6.2-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.35.4+rke2r1
  helm:
    charts:
      - name: private-registry-helm
        createNamespace: true
        installationNamespace: kube-system
        repositoryName: privateregistry
        targetNamespace: suse-private-registry
        valuesFile: privateregistry.yaml
        version: 1.1.1
      - name: cert-manager
        repositoryName: jetstack
        version: 1.20.1
        targetNamespace: cert-manager
        valuesFile: certmanager.yaml
        createNamespace: true
        installationNamespace: kube-system
      - name: longhorn
        version: 1.11.2
        repositoryName: rancher-application-collection
        targetNamespace: longhorn-system
        createNamespace: true
        installationNamespace: kube-system
        valuesFile: longhorn.yaml
      - name: metallb
        version: 306.0.2+up0.15.3
        targetNamespace: metallb-system
        createNamespace: true
        repositoryName: suse-edge-charts
        installationNamespace: kube-system
      - name: metal3
        version: 306.0.29+up0.15.0
        repositoryName: suse-edge-charts
        targetNamespace: metal3-system
        createNamespace: true
        installationNamespace: kube-system
        valuesFile: metal3.yaml
      - name: rancher-turtles-providers
        version: 306.0.7+up0.26.2
        repositoryName: suse-edge-charts
        targetNamespace: cattle-turtles-system
        createNamespace: true
        installationNamespace: kube-system
      - name: neuvector-crd
        version: 109.0.2+up2.10.2
        repositoryName: rancher-charts
        targetNamespace: neuvector
        createNamespace: true
        installationNamespace: kube-system
        valuesFile: neuvector.yaml
      - name: neuvector
        version: 109.0.2+up2.10.2
        repositoryName: rancher-charts
        targetNamespace: neuvector
        createNamespace: true
        installationNamespace: kube-system
        valuesFile: neuvector.yaml
      - name: rancher
        version: 2.14.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
      - name: rancher-application-collection
        url: oci://dp.apps.rancher.io/charts
        authentication:
          username: $\{APPS.RANCHER.IO_USERNAME\}
          password: $\{APPS.RANCHER.IO_ACCESS_TOKEN\}
      - name: privateregistry
        authentication:
          username: ${PRIVATE_REGISTRY_USERNAME}
          password: ${PRIVATE_REGISTRY_PASSWORD}
        plainHTTP: false
        skipTLSVerify: false
        url: oci://registry.suse.com/private-registry
    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
embeddedArtifactRegistry:
  registries:
    - uri: dp.apps.rancher.io
      authentication:
        username: $\{APPS.RANCHER.IO_USERNAME\}
        password: $\{APPS.RANCHER.IO_ACCESS_TOKEN\}
    - uri: registry.suse.com
      authentication:
        username: ${PRIVATE_REGISTRY_USERNAME}
        password: ${PRIVATE_REGISTRY_PASSWORD}
  images:
    - name: registry.suse.com/private-registry/harbor-core:1.1.1-1.19
    - name: registry.suse.com/private-registry/harbor-jobservice:1.1.1-1.19
    - name: registry.suse.com/private-registry/harbor-portal:1.1.1-1.20
    - name: registry.suse.com/private-registry/harbor-registry:1.1.1-1.19
    - name: registry.suse.com/private-registry/harbor-registryctl:1.1.1-1.19
    - name: registry.suse.com/private-registry/harbor-trivy-adapter:1.1.1-1.24
    - name: registry.rancher.com/rancher/hardened-cluster-autoscaler:v1.10.3-build20260414
    - name: registry.rancher.com/rancher/hardened-cni-plugins:v1.9.1-build20260415
    - name: registry.rancher.com/rancher/hardened-coredns:v1.14.2-build20260416
    - name: registry.rancher.com/rancher/hardened-k8s-metrics-server:v0.8.1-build20260413
    - name: registry.rancher.com/rancher/hardened-multus-cni:v4.2.4-build20260310
    - name: registry.rancher.com/rancher/hardened-traefik:v3.6.13-build20260416
    - name: registry.rancher.com/rancher/klipper-helm:v0.9.17-build20260422
    - name: registry.rancher.com/rancher/mirrored-cilium-cilium:v1.19.3
    - name: registry.rancher.com/rancher/mirrored-cilium-operator-generic:v1.19.3
    - name: dp.apps.rancher.io/containers/kubernetes-csi-external-attacher:4.11.0-13.2
    - name: dp.apps.rancher.io/containers/kubernetes-csi-external-provisioner:5.3.0-14.1
    - name: dp.apps.rancher.io/containers/kubernetes-csi-external-resizer:2.1.0-6.2
    - name: dp.apps.rancher.io/containers/kubernetes-csi-external-snapshotter:8.5.0-13.2
    - name: dp.apps.rancher.io/containers/kubernetes-csi-livenessprobe:2.18.0-13.2
    - name: dp.apps.rancher.io/containers/kubernetes-csi-node-driver-registrar:2.16.0-13.2
    - name: dp.apps.rancher.io/containers/longhorn-backing-image-manager:1.11.2-4.1
    - name: dp.apps.rancher.io/containers/longhorn-engine:1.11.2-4.2
    - name: dp.apps.rancher.io/containers/longhorn-instance-manager:1.11.2-4.3
    - name: dp.apps.rancher.io/containers/longhorn-manager:1.11.2-4.2
    - name: dp.apps.rancher.io/containers/longhorn-share-manager:1.11.2-4.1
    - name: dp.apps.rancher.io/containers/longhorn-ui:1.11.2-4.1
    - name: dp.apps.rancher.io/containers/rancher-support-bundle-kit:0.0.84-9.4
    - name: registry.rancher.com/rancher/mirrored-sig-storage-snapshot-controller:v8.2.0
    - name: registry.rancher.com/rancher/neuvector-compliance-config:1.0.12
    - name: registry.rancher.com/rancher/neuvector-controller:5.5.2
    - name: registry.rancher.com/rancher/neuvector-enforcer:5.5.2
    - name: registry.rancher.com/rancher/nginx-ingress-controller:v1.14.5-hardened2
    - name: registry.rancher.com/rancher/cluster-api-addon-provider-fleet:v0.14.1
    - name: registry.rancher.com/rancher/fleet-agent:v0.15.2
    - name: registry.rancher.com/rancher/fleet:v0.15.2
    - name: registry.rancher.com/rancher/rancher-webhook:v0.10.6
    - name: registry.rancher.com/rancher/turtles:v0.26.2
    - name: registry.rancher.com/rancher/rancher:v2.14.2
    - name: registry.rancher.com/rancher/shell:v0.1.24
    - name: registry.rancher.com/rancher/system-upgrade-controller:v0.19.1
    - name: registry.rancher.com/rancher/cluster-api-controller:v1.12.7
    - name: registry.suse.com/rancher/cluster-api-provider-metal3:v1.12.3
    - name: registry.rancher.com/rancher/cluster-api-provider-rke2-bootstrap:v0.24.4
    - name: registry.rancher.com/rancher/cluster-api-provider-rke2-controlplane:v0.24.4
    - name: registry.rancher.com/rancher/ip-address-manager:v1.12.3
    - name: registry.rancher.com/rancher/kubectl:v1.35.2
    - name: registry.rancher.com/rancher/scc-operator:v0.4.1
    - name: registry.rancher.com/rancher/kubectl:v1.33.1
    - name: registry.suse.com/edge/3.6/ironic-python-agent:3.0.9

30.2 Modificações na pasta personalizada

  • O script custom/scripts/99-register.sh deve ser removido ao usar um ambiente air-gap. Como você pode ver na estrutura de diretórios, o script 99-register.sh não está incluído na pasta custom/scripts.

30.3 Modificações na pasta kubernetes

  • Atualize o arquivo kubernetes/helm/values/metal3.yaml para definir o parâmetro do Helm chart metal3-ironic.ipa.useHauler como true (valor booleano).

    global:
      ironicIP: ${METAL3_VIP}
      enable_vmedia_tls: false
      predictableNicNames: "true"
      # trustedCAs: tls-ca-bundle  # Optional: Uncomment and set to ConfigMap name for additional trusted CAs
    metal3-ironic:
      ipa:
        useHauler: true
      persistence:
        ironic:
          size: "5Gi"
  • Atualize o arquivo kubernetes/helm/values/rancher.yaml para modificar o parâmetro hostname. Em ambientes air-gapped, serviços externos de resolução de DNS como o sslip.io não estão acessíveis. Há duas opções:

    1. Opção 1: Usar DNS interno (Recomendado): Configure seu servidor DNS interno para resolver o nome de host do Rancher e atualize o arquivo de acordo:

      hostname: rancher.yourdomain.internal
      bootstrapPassword: "foobar"
      replicas: 1
      global:
        cattle:
          systemDefaultRegistry: "registry.rancher.com"
    2. Opção 2: Usar injeção em /etc/hosts: Se você não tiver um servidor DNS interno, poderá injetar uma entrada estática /etc/hosts via EIB. Crie um arquivo em eib/os-files/etc/hosts na sua estrutura de diretórios EIB com um conteúdo como:

      # Static DNS resolution for Rancher in air-gapped environment
      ${INGRESS_VIP} rancher-${INGRESS_VIP}.sslip.io

      Em seguida, atualize o arquivo rancher.yaml para usar este nome de host:

      hostname: rancher-${INGRESS_VIP}.sslip.io
      bootstrapPassword: "foobar"
      replicas: 1
      global:
        cattle:
          systemDefaultRegistry: "registry.rancher.com"
      Importante
      Importante

      Ao usar a Opção 2, lembre-se de que o arquivo /etc/hosts precisará estar presente em qualquer sistema que precise acessar a interface do Rancher, não apenas nos nós do cluster de gerenciamento.

  • Você precisa modificar o ${MGMT_CLUSTER_REGISTRY_IP} com um IP estático reservado para o SUSE Private Registry nos seguintes arquivos:

    1. kubernetes/manifests/metallb-registry.yaml

      apiVersion: metallb.io/v1beta1
      kind: L2Advertisement
      metadata:
        name: private-registry
        namespace: metallb-system
      spec:
        ipAddressPools:
        - private-registry-pool
      ---
      apiVersion: metallb.io/v1beta1
      kind: IPAddressPool
      metadata:
        name: private-registry-pool
        namespace: metallb-system
      spec:
        addresses:
        - ${MGMT_CLUSTER_REGISTRY_IP}/32
        serviceAllocation:
          namespaces:
          - suse-private-registry
    2. kubernetes/helm/values/privateregistry.yaml

      core:
        secretName: suse-registry-tls
      expose:
        tls:
          certSource: secret
          enabled: true
          secret:
            secretName: suse-registry-tls
        type: loadBalancer
      externalURL: https://${MGMT_CLUSTER_REGISTRY_IP}
      persistence:
        persistentVolumeClaim:
          registry:
            size: 20Gi
  • O kubernetes/manifests/suse-private-registry-creds.yaml deve ser criado com o seguinte conteúdo:

apiVersion: v1
kind: Secret
metadata:
  name: suse-registry
  namespace: suse-private-registry
type: kubernetes.io/dockerconfigjson
data:
  .dockerconfigjson: ${DOCKER_CONFIG_JSON_BASE64}
---
apiVersion: v1
kind: Secret
metadata:
    name: suse-registry-tls
    namespace: suse-private-registry
type: kubernetes.io/tls
data:
    tls.crt: ${TLS_CRT_BASE64}
    tls.key: ${TLS_KEY_BASE64}

Você precisa modificar o ${DOCKER_CONFIG_JSON_BASE64}, ${TLS_CRT_BASE64} e ${TLS_KEY_BASE64}. Para configurar corretamente o docker config json (base64), você pode fazer o seguinte:

# ${DOCKER_CONFIG_JSON_BASE64} CONTENT
echo -n '{"auths":{"<MGMT_CLUSTER_REGISTRY_IP>":{"username":"<USERNAME>","password":"<PASSWORD>","auth":"<AUTH>"}}}' | base64 -w 0

onde o IP é o mesmo que o ${MGMT_CLUSTER_REGISTRY_IP} configurado anteriormente, e os valores <USERNAME> e <PASSWORD> podem ser recuperados da documentação oficial do SUSE Private Registry; o valor <AUTH> definido no campo auth é a codificação base64 da concatenação <USERNAME>:<PASSWORD>.

Para definir o conteúdo dos campos tls.crt e tls.key no manifesto do Secret suse-registry-tls acima, você pode gerar seu próprio certificado autoassinado TLS e a chave privada relacionada executando os seguintes comandos:

# Generate a self-signed certificate and key
openssl req -x509 -newkey rsa:4096 -keyout key.pem -out cert.pem -sha256 -days 365 -nodes

# Convert them to base64 for the suse-private-registry-creds.yaml file
cat cert.pem | base64 -w 0
cat key.pem | base64 -w 0

31 Criação de imagem

Uma vez que a estrutura de diretórios esteja preparada de acordo com as seções anteriores (para os cenários conectados e air-gap), execute o seguinte comando para criar a imagem:

podman run --rm --privileged -it -v $PWD:/eib \
 registry.suse.com/edge/3.6/edge-image-builder:1.3.3.1 \
 build --definition-file mgmt-cluster.yaml

Isso cria o arquivo de imagem de saída ISO que, em nosso caso, com base na definição de imagem descrita acima, é eib-mgmt-cluster-image.iso.

32 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 (usando o recurso de virtual-media).

33 Considerações e configuração de pilha dupla

Os exemplos mostrados nas seções anteriores fornecem orientação e exemplos sobre como configurar um cluster de gerenciamento IPv4 de pilha única. Tal cluster de gerenciamento é independente do status operacional dos clusters downstream, que podem ser configurados individualmente para operar em configuração de pilha única IPv4/IPv6 ou pilha dupla, uma vez implantados. No entanto, a maneira como o cluster de gerenciamento é configurado tem um impacto direto nos protocolos de comunicação que podem ser usados durante a fase de provisionamento, onde as comunicações in-band e out-of-band devem ocorrer de acordo com os protocolos suportados pelo cluster de gerenciamento e pelo host downstream. Caso se espere que alguns ou todos os BMCs e/ou nós do cluster downstream usem IPv6, uma configuração de pilha dupla para o cluster de gerenciamento é necessária.

Nota
Nota

Clusters de gerenciamento IPv6 de pilha única ainda não são suportados.

Para obter a funcionalidade de pilha dupla, o Kubernetes deve receber CIDRs IPv4 e IPv6 para PODs e Serviços. No entanto, outros componentes também exigem ajustes específicos antes de criar a imagem do cluster de gerenciamento com o EIB. Os serviços de provisionamento Metal3 (Ironic) podem ser configurados de diferentes maneiras, dependendo da sua infraestrutura ou requisitos:

  • Os serviços Ironic podem ser configurados para escutar em todas as interfaces do sistema em vez de um único endereço IP, portanto, desde que o(s) host(s) do cluster de gerenciamento tenha(m) endereços IPv4 e IPv6 atribuídos à interface relevante, qualquer um deles pode potencialmente ser usado durante o provisionamento. Observe que, neste momento, apenas um desses endereços pode ser selecionado para a geração da URL (para consumo por outros serviços, por exemplo, o Baremetal Operator, BMCs, etc.); como consequência, para habilitar comunicações IPv6 com os BMCs, o Baremetal Operator pode ser instruído a expor e transmitir uma URL IPv6 ao lidar com definições BMH que incluam um endereço IPv6. Em outras palavras, quando um BMC é identificado como compatível com IPv6, o provisionamento será realizado apenas via IPv6, e via IPv4 em todos os outros casos.

  • Um único nome de host, resolvendo para IPv4 e IPv6, pode ser usado pelo Metal3 para permitir que o Ironic use esses endereços para vinculação e criação de URL. Essa abordagem permite uma configuração fácil e comportamento flexível (tanto IPv4 quanto IPv6 permanecem viáveis em cada etapa de provisionamento), mas requer uma infraestrutura com servidores DNS, alocações de IP e registros preexistentes já em vigor.

Em ambos os casos, o Kubernetes precisará saber quais CIDRs usar para IPv4 e IPv6, portanto, você pode adicionar as seguintes linhas ao seu kubernetes/config/server.yaml no diretório EIB, certificando-se de listar o IPv4 primeiro:

service-cidr: 10.96.0.0/12,fd12:4567:789c::/112
cluster-cidr: 193.168.0.0/18,fd12:4567:789b::/48

Alguns contêineres aproveitam a rede do host, portanto, modifique a configuração de rede para o(s) host(s), no diretório network, para habilitar a conectividade IPv6:

routes:
  config:
  - destination: 0.0.0.0/0
    next-hop-address: ${MGMT_GATEWAY_V4}
    next-hop-interface: eth0
  - destination: ::/0
    next-hop-address: ${MGMT_GATEWAY_V6}
    next-hop-interface: eth0
dns-resolver:
  config:
    server:
    - ${MGMT_DNS}
    - 8.8.8.8
    - 2001:4860:4860::8888
interfaces:
- name: eth0
  type: ethernet
  state: up
  mac-address: ${MGMT_MAC}
  ipv4:
    address:
    - ip: ${MGMT_CLUSTER_IP_V4}
      prefix-length: 24
    dhcp: false
    enabled: true
  ipv6:
    address:
    - ip: ${MGMT_CLUSTER_IP_V6}
      prefix-length: 128
    dhcp: false
    autoconf: false
    enabled: true

Substitua os espaços reservados pelos endereços IP do gateway, servidor DNS adicional (se necessário), o endereço MAC da interface de rede e o endereço IP do cluster de gerenciamento. Se a autoconfiguração de endereço for preferida, consulte o trecho a seguir e apenas defina a variável ${MGMT_MAC}:

interfaces:
- name: eth0
  type: ethernet
  state: up
  mac-address: ${MGMT_MAC}
  ipv4:
    enabled: true
    dhcp: true
  ipv6:
    enabled: false
    dhcp: true
    autoconf: true

Agora podemos definir os arquivos restantes para uma configuração de nó único, começando pela primeira opção, criando kubernetes/helm/values/metal3.yaml como:

global:
  ironicIP: ${MGMT_CLUSTER_IP_V4}
  enable_vmedia_tls: false
  # trustedCAs: tls-ca-bundle  # Optional: Uncomment and set to ConfigMap name for trusted CA bundle
metal3-ironic:
  global:
    predictableNicNames: true
  listenOnAll: true
  persistence:
    ironic:
      size: "5Gi"
  service:
    type: NodePort
metal3-baremetal-operator:
  baremetaloperator:
    externalHttpIPv6: ${MGMT_CLUSTER_IP_V6}

e kubernetes/helm/values/rancher.yaml como:

hostname: rancher-${MGMT_CLUSTER_IP_V4}.sslip.io
bootstrapPassword: "foobar"
replicas: 1
global:
  cattle:
    systemDefaultRegistry: "registry.rancher.com"

onde ${MGMT_CLUSTER_IP_V4} e ${MGMT_CLUSTER_IP_V6} são os endereços IP atribuídos anteriormente ao host.

Alternativamente, para usar o nome do host em vez dos endereços IP, modifique kubernetes/helm/values/metal3.yaml para:

global:
  provisioningHostname: `${MGMT_CLUSTER_HOSTNAME}`
  enable_vmedia_tls: false
  # trustedCAs: tls-ca-bundle  # Optional: Uncomment and set to ConfigMap name for trusted CA bundle
metal3-ironic:
  global:
    predictableNicNames: true
  persistence:
    ironic:
      size: "5Gi"
  service:
    type: NodePort

e kubernetes/helm/values/rancher.yaml para:

hostname: rancher-${MGMT_CLUSTER_HOSTNAME}.sslip.io
bootstrapPassword: "foobar"
replicas: 1
global:
  cattle:
    systemDefaultRegistry: "registry.rancher.com"

onde ${MGMT_CLUSTER_HOSTNAME} deve ser um Nome de Domínio Completo e Qualificado que resolva para os endereços IP do seu host.

Para mais informações, visite SUSE Telco Cloud o repositório do GitHub na pasta \"dual-stack\", onde uma estrutura de diretório de exemplo pode ser encontrada.

Parte VI Configuração de recursos de Telco

Esta seção documenta e explica a configuração de recursos específicos de Telco em clusters implantados via SUSE Telco Cloud.

O método de implantação de provisionamento de rede direcionado é utilizado, conforme descrito na seção Provisionamento Automatizado (Parte VII, “Provisionamento de rede direcionado totalmente automatizado”).

Os tópicos a seguir estão incluídos nesta seção:

  • 34 Imagem do kernel para tempo real
  • A imagem do kernel de tempo real não é necessariamente melhor do que um kernel padrão. É um kernel diferente ajustado para um caso de uso específico. O kernel de tempo real é ajustado para menor latência ao custo de throughput. O kernel de tempo real não é recomendado para uso geral, mas, em nosso c…

  • 35 Argumentos do kernel para baixa latência e alto desempenho
  • Configurar os argumentos apropriados do kernel é essencial para otimizar o desempenho, alcançar baixa latência e garantir a implantação bem-sucedida de clusters para cargas de trabalho de telecomunicações. Embora alguns parâmetros sejam projetados especificamente para permitir que o kernel de tempo …

  • 36 Fixação de CPU no Host
  • A fixação de CPU, também conhecida como afinidade de processador, é a técnica de vincular um processo ou thread a um núcleo de CPU específico, impedindo que o agendador do sistema operacional o mova. Ao garantir que um processo sempre seja executado no mesmo núcleo, ele se beneficia do acesso mais r…

  • 37 Fixação de CPU no Kubernetes
  • Habilite a fixação de CPU em seu cluster RKE2 editando o arquivo de configuração do RKE2. Adicione os argumentos do kubelet abaixo no arquivo /etc/rancher/rke2/config.yaml. Certifique-se de especificar os núcleos de CPU de housekeeping nos argumentos kubelet-reserved e system-reserved:

  • 38 Configuração de CNI
  • Cilium é o plug-in de CNI padrão para o SUSE Telco Cloud. Para habilitar o Cilium no cluster RKE2 como o plug-in padrão, a seguinte configuração é necessária no arquivo /etc/rancher/rke2/config.yaml:

  • 39 SR-IOV
  • SR-IOV (Single Root I/O Virtualization) permite que um único dispositivo físico, como um adaptador de rede, separe seus recursos entre múltiplas PCIe funções de hardware. Isso permite acesso direto aos recursos para várias aplicações.

  • 40 DPDK
  • DPDK (Data Plane Development Kit) é um conjunto de bibliotecas e drivers para processamento rápido de pacotes. Ele é usado para acelerar cargas de trabalho de processamento de pacotes executadas em uma ampla variedade de arquiteturas de CPU. O DPDK inclui bibliotecas de plano de dados e drivers otim…

  • 41 Aceleração vRAN (Intel ACC100/VRB1/VRB2)
  • À medida que os provedores de serviços de comunicação migram de redes 4G para 5G, muitos estão adotando arquiteturas de rede de acesso via rádio virtualizada (vRAN) para maior capacidade de canal e implantação mais fácil de serviços e aplicações baseados em borda. As soluções vRAN estão idealmente l…

  • 42 Huge pages
  • Quando um processo usa RAM, o CPU marca-o como usado por esse processo. Para eficiência, o CPU aloca RAM em blocos; 4K bytes é o valor padrão em muitas plataformas. Esses blocos são chamados de páginas. As páginas podem ser trocadas para o disco, etc.

  • 43 Agendamento com reconhecimento de NUMA
  • O acesso não uniforme à memória ou a arquitetura de memória não uniforme (NUMA) é um design de memória física usado na arquitetura SMP (multiprocessadores), em que o tempo de acesso à memória depende da sua localização em relação a um processador. Sob NUMA, um processador pode acessar sua própria me…

  • 44 Metal LB
  • MetalLB é uma implementação de balanceador de carga para clusters Kubernetes bare metal, usando protocolos de roteamento padrão como L2 e BGP como protocolos de anúncio. É um balanceador de carga de rede que pode ser usado para expor serviços em um cluster Kubernetes para o mundo exterior devido à n…

  • 45 Configuração de registro privado
  • Containerd pode ser configurado para se conectar a registros privados e usá-los para extrair imagens privadas em cada nó.

  • 46 Precision Time Protocol
  • O Precision Time Protocol (PTP) é um protocolo de rede desenvolvido pelo Institute of Electrical and Electronics Engineers (IEEE) para permitir a sincronização de tempo em sub-microssegundos em uma rede de computadores. Desde a sua criação e há algumas décadas, o PTP tem sido usado em muitas indústr…

  • 47 SCTP - Stream Control Transmission Protocol
  • De Stream Control Transmission Protocol - Wikipedia

34 Imagem do kernel para tempo real

A imagem do kernel de tempo real não é necessariamente melhor do que um kernel padrão. É um kernel diferente ajustado para um caso de uso específico. O kernel de tempo real é ajustado para menor latência ao custo de throughput. O kernel de tempo real não é recomendado para uso geral, mas, em nosso caso, este é o kernel recomendado para cargas de trabalho de telecomunicações onde a latência é um fator chave.

Existem quatro recursos principais:

  • Execução determinística:

    Obtenha maior previsibilidade — garanta que processos de negócios críticos sejam concluídos a tempo, sempre, e forneça um serviço de alta qualidade, mesmo sob cargas pesadas do sistema. Ao proteger recursos essenciais do sistema para processos de alta prioridade, você pode garantir maior previsibilidade para aplicações sensíveis ao tempo.

  • Baixo jitter:

    O baixo jitter, construído sobre a tecnologia altamente determinística, ajuda a manter as aplicações sincronizadas com o mundo real. Isso ajuda serviços que precisam de cálculos contínuos e repetidos.

  • Herança de prioridades:

    Herança de prioridades refere-se à capacidade de um processo de menor prioridade assumir uma prioridade mais alta quando há um processo de maior prioridade que exige que o processo de menor prioridade termine antes que ele possa concluir sua tarefa. O SUSE Linux Enterprise Real Time resolve esses problemas de inversão de prioridade para processos de missão crítica.

  • Interrupções de thread:

    Processos executados em modo de interrupção em um sistema operacional de propósito geral não são preemptíveis. Com o SUSE Linux Enterprise Real Time, essas interrupções foram encapsuladas por threads do kernel, que são interrompíveis e permitem que as interrupções de hardware e software sejam preemptadas por processos de maior prioridade definidos pelo usuário.

    No nosso caso, se você instalou uma imagem de tempo real como SUSE Linux Micro RT, o kernel de tempo real já está instalado. A partir do SUSE Customer Center, você pode baixar a imagem do kernel de tempo real.

    Nota
    Nota

    Para mais informações sobre o kernel de tempo real, visite SUSE Real Time.

35 Argumentos do kernel para baixa latência e alto desempenho

Configurar os argumentos apropriados do kernel é essencial para otimizar o desempenho, alcançar baixa latência e garantir a implantação bem-sucedida de clusters para cargas de trabalho de telecomunicações. Embora alguns parâmetros sejam projetados especificamente para permitir que o kernel de tempo real funcione de forma ideal, esta seção se aplica tanto às configurações de kernel RT quanto às padrão. Além disso, certos argumentos são obrigatórios para que o método de Provisionamento de Rede Direcionado implante com sucesso nós de cluster downstream.

  • Remova kthread_cpus ao usar o kernel de tempo real do SUSE. Este parâmetro controla em quais CPUs as threads do kernel são criadas. Ele também controla quais CPUs são permitidos para o PID 1 e para o carregamento de módulos do kernel (o auxiliar de espaço do usuário kmod). Este parâmetro não é reconhecido e não tem qualquer efeito.

  • Isole os núcleos da CPU usando isolcpus, nohz_full, rcu_nocbs e irqaffinity. Para uma lista abrangente de técnicas de CPU pinning, consulte o capítulo CPU Pinning on Host (Capítulo 36, Fixação de CPU no Host).

  • Adicione as flags domain,nohz,managed_irq ao argumento de kernel isolcpus. Sem nenhuma flag, isolcpus é equivalente a especificar apenas a flag domain. Isso isola as CPUs especificadas do agendamento, incluindo tarefas do kernel. A flag nohz interrompe o tick do agendador nas CPUs especificadas (se apenas uma tarefa estiver executável em uma CPU), e a flag managed_irq evita o roteamento de interrupções externas (dispositivo) gerenciadas nas CPUs especificadas. Observe que as linhas IRQ de dispositivos NVMe são totalmente gerenciadas pelo kernel e, como consequência, serão roteadas para os núcleos não isolados (housekeeping). Por exemplo, a linha de comando fornecida ao final desta seção resultará em apenas quatro filas (mais uma fila de administração/controle) alocadas no sistema:

    for I in $(grep nvme0 /proc/interrupts | cut -d ':' -f1); do cat /proc/irq/${I}/effective_affinity_list; done | column
    39      0       19      20      39

    Este comportamento evita qualquer interrupção causada por E/S de disco em qualquer aplicação sensível ao tempo em execução nos núcleos isolados, mas pode exigir atenção e um projeto cuidadoso para cargas de trabalho focadas em armazenamento.

  • Ajuste os ticks (interrupções de temporizador periódicas do kernel):

    • skew_tick=1: os ticks podem, às vezes, ocorrer simultaneamente. Em vez de todas as CPUs receberem seu tick de temporizador exatamente no mesmo momento, skew_tick=1 faz com que ocorram em momentos ligeiramente deslocados. Isso ajuda a reduzir o jitter do sistema, resultando em tempos de resposta de interrupção mais consistentes e menores (um requisito essencial para aplicações sensíveis à latência).

    • nohz=on: interrompe o tick de temporizador periódico em CPUs ociosas.

    • nohz_full=<cpu-cores>: Interrompe o tick de temporizador periódico em CPUs especificadas que são dedicadas a aplicações de tempo real.

  • Desative o tratamento de Machine Check Exception (MCE) especificando mce=off. MCEs são erros de hardware detectados pelo processador e desativá-los pode evitar logs ruidosos.

  • Adicione nowatchdog para desativar o watchdog de soft-lockup, que é implementado como um temporizador em execução no contexto de interrupção de hardware do temporizador. Quando ele expira (ou seja, um soft lockup é detectado), ele imprimirá um aviso (no contexto de interrupção de hardware), executando quaisquer alvos de latência. Mesmo que nunca expire, ele entra na lista de temporizadores, aumentando ligeiramente a sobrecarga de cada interrupção de temporizador. Esta opção também desativa o watchdog NMI, para que os NMIs não possam interferir.

  • nmi_watchdog=0 desativa o watchdog NMI (Non-Maskable Interrupt). Isso pode ser omitido quando nowatchdog é usado.

  • RCU (Read-Copy-Update) é um mecanismo de kernel que permite acesso simultâneo e sem bloqueio para muitos leitores a dados compartilhados. Um callback RCU, uma função acionada após um 'período extra', garante que todos os leitores anteriores tenham terminado para que os dados antigos possam ser recuperados com segurança. Nós ajustamos o RCU, particularmente para cargas de trabalho sensíveis, para descarregar esses callbacks de CPUs dedicadas (fixadas), evitando que operações do kernel interfiram em tarefas críticas e sensíveis ao tempo.

    • Especifique as CPUs fixadas em rcu_nocbs para que os callbacks RCU não sejam executados nelas. Isso ajuda a reduzir o jitter e a latência para as cargas de trabalho de tempo real.

    • rcu_nocb_poll faz com que as CPUs sem callback façam 'polling' regularmente para verificar se o tratamento de callback é necessário. Isso pode reduzir a sobrecarga de interrupção.

    • rcupdate.rcu_cpu_stall_suppress=1 suprime avisos de travamento de CPU RCU, que às vezes podem ser falsos positivos em sistemas de tempo real com carga pesada

    • rcupdate.rcu_expedited=1 acelera o período extra para operações RCU, tornando as seções críticas de leitura mais responsivas

    • rcupdate.rcu_normal_after_boot=1 Quando usado com rcu_expedited, permite que o RCU reverta para a operação normal (não acelerada) após a inicialização do sistema.

    • rcupdate.rcu_task_stall_timeout=0 desativa o detector de travamento de tarefas RCU, evitando possíveis avisos ou paradas do sistema devido a tarefas RCU de longa duração.

    • rcutree.kthread_prio=99 define a prioridade da thread do kernel de callback RCU para a mais alta possível (99), garantindo que ela seja agendada e processe os callbacks RCU prontamente, quando necessário.

  • Adicione ignition.platform.id=openstack para que o Metal3 e a API de Cluster provisionem/desprovisionem o cluster com sucesso. Isso é usado pelo agente Python do Metal3, que se originou do Openstack Ironic.

  • Habilite Nomeação previsível de interface de rede via net.ifnames=1. A partir do SUSE Linux Micro 6.2, isso é habilitado por padrão e uma configuração explícita não é necessária. Para versões anteriores à 6.2, isso deve ser definido explicitamente como um argumento do kernel. Isso se alinha com a configuração predictableNicNames no gráfico Helm Metal3 do Cluster de Gerenciamento, que é necessária para que o Provisionamento de Rede Direcionado funcione corretamente. A nomenclatura consistente de interface de rede também é crítica quando o SR-IOV é utilizado.

  • Remova intel_pstate=passive. Esta opção configura intel_pstate para funcionar com governadores cpufreq genéricos, mas para fazer isso funcionar, ela desativa os P-states gerenciados por hardware (HWP) como um efeito colateral. Para reduzir a latência de hardware, esta opção não é recomendada para cargas de trabalho em tempo real.

  • Substitua intel_idle.max_cstate=0 processor.max_cstate=1 por idle=poll. Para evitar transições de C-State, a opção idle=poll é usada para desativar as transições de C-State e manter a CPU no C-State mais alto. A opção intel_idle.max_cstate=0 desativa intel_idle, portanto acpi_idle é usada, e acpi_idle.max_cstate=1 então define o C-state máximo para acpi_idle. Em arquiteturas AMD64/Intel 64, o primeiro ACPI C-State é sempre POLL, mas ele usa uma função poll_idle(), que pode introduzir uma pequena latência ao ler o clock periodicamente e reiniciar o loop principal em do_idle() após um tempo limite (isso também envolve limpar e definir a flag de tarefa TIF_POLL). Em contraste, idle=poll executa um loop contínuo, aguardando ativamente que uma tarefa seja reagendada. Isso minimiza a latência de saída do estado ocioso, mas ao custo de manter a CPU funcionando em velocidade máxima na thread ociosa.

  • Desative o C1E no BIOS. Esta opção é importante para desativar o estado C1E no BIOS para evitar que a CPU entre no estado C1E quando ociosa. O estado C1E é um estado de baixo consumo de energia que pode introduzir latência quando a CPU está ociosa.

O restante desta documentação aborda parâmetros adicionais, incluindo huge pages e IOMMU.

Isso fornece um exemplo de argumentos de kernel para um servidor Intel de 32 núcleos, incluindo os ajustes mencionados anteriormente:

$ cat /proc/cmdline
BOOT_IMAGE=/boot/vmlinuz-6.4.0-9-rt root=UUID=77b713de-5cc7-4d4c-8fc6-f5eca0a43cf9 skew_tick=1 rd.timeout=60 rd.retry=45 console=ttyS1,115200 console=tty0 default_hugepagesz=1G hugepagesz=1G hugepages=40 hugepagesz=2M hugepages=0 ignition.platform.id=openstack net.ifnames=1 intel_iommu=on iommu=pt irqaffinity=0,31,32,63 isolcpus=domain,nohz,managed_irq,1-30,33-62 nohz_full=1-30,33-62 nohz=on mce=off nosoftlockup nowatchdog nmi_watchdog=0 quiet rcu_nocb_poll rcu_nocbs=1-30,33-62 rcupdate.rcu_cpu_stall_suppress=1 rcupdate.rcu_expedited=1 rcupdate.rcu_normal_after_boot=1 rcupdate.rcu_task_stall_timeout=0 rcutree.kthread_prio=99 security=selinux selinux=1 idle=poll

Aqui está outro exemplo de configuração para um servidor AMD de 64 núcleos. Entre os 128 processadores lógicos (0-127), os primeiros 8 núcleos (0-7) são designados para manutenção, enquanto os 120 núcleos restantes (8-127) são fixados para os aplicativos:

$ cat /proc/cmdline
BOOT_IMAGE=/boot/vmlinuz-6.4.0-9-rt root=UUID=575291cf-74e8-42cf-8f2c-408a20dc00b8 skew_tick=1 console=ttyS1,115200 console=tty0 default_hugepagesz=1G hugepagesz=1G hugepages=40 hugepagesz=2M hugepages=0 ignition.platform.id=openstack net.ifnames=1 amd_iommu=on iommu=pt irqaffinity=0-7 isolcpus=domain,nohz,managed_irq,8-127 nohz_full=8-127 rcu_nocbs=8-127 mce=off nohz=on nowatchdog nmi_watchdog=0 nosoftlockup quiet rcu_nocb_poll rcupdate.rcu_cpu_stall_suppress=1 rcupdate.rcu_expedited=1 rcupdate.rcu_normal_after_boot=1 rcupdate.rcu_task_stall_timeout=0 rcutree.kthread_prio=99 security=selinux selinux=1 idle=poll

36 Fixação de CPU no Host

A fixação de CPU, também conhecida como afinidade de processador, é a técnica de vincular um processo ou thread a um núcleo de CPU específico, impedindo que o agendador do sistema operacional o mova. Ao garantir que um processo sempre seja executado no mesmo núcleo, ele se beneficia do acesso mais rápido aos dados que permanecem na memória cache desse núcleo. Essa prática é comum em ambientes de computação de alto desempenho porque melhora drasticamente o desempenho e reduz a sobrecarga.

36.1 Isolamento de CPUs via TuneD

tuned é uma ferramenta de ajuste de sistema que monitora as condições do sistema para otimizar o desempenho usando vários perfis predefinidos. Um recurso importante é sua capacidade de isolar núcleos de CPU para cargas de trabalho específicas, como aplicativos em tempo real. Isso evita que o SO utilize esses núcleos e potencialmente aumente a latência.

Para habilitar e configurar esse recurso, a primeira coisa é criar um perfil para os núcleos de CPU que queremos isolar. Neste exemplo, entre 64 núcleos, dedicamos 60 núcleos (1-30,33-62) para o aplicativo e os 4 núcleos restantes são usados para manutenção. Observe que o design de CPUs isoladas depende fortemente dos aplicativos em tempo real.

$ echo "export tuned_params" >> /etc/grub.d/00_tuned

$ echo "isolated_cores=1-30,33-62" >> /etc/tuned/cpu-partitioning-variables.conf

$ tuned-adm profile cpu-partitioning
Tuned (re)started, changes applied.

36.2 Isolamento de CPUs via argumentos do kernel

Em seguida, precisamos modificar a opção do GRUB para isolar os núcleos da CPU e outros parâmetros importantes para o uso da CPU. As seguintes opções são importantes para serem personalizadas com as especificações do seu hardware atual:

parametervaluedescrição

isolcpus

domain,nohz,managed_irq,1-30,33-62

Isole os núcleos 1-30 e 33-62. domain indica que essas CPUs fazem parte do domínio de isolamento. nohz habilita a operação sem tick nessas CPUs isoladas quando estão ociosas, para reduzir interrupções. managed_irq isola as CPUs fixadas de serem alvo de IRQs. Isso contempla irqaffinity=0-7, que já direciona a maioria das IRQs para os núcleos de manutenção.

skew_tick

1

Esta opção permite que o kernel desloque as interrupções do temporizador entre as CPUs isoladas.

nohz

on

Quando habilitada, a interrupção periódica do temporizador do kernel (o 'tick') parará em qualquer núcleo de CPU que esteja ocioso. Isso beneficia principalmente as CPUs de manutenção (0,31,32,63). Isso economiza energia e reduz as ativações desnecessárias nesses núcleos de uso geral.

nohz_full

1-30,33-62

Para os núcleos isolados, isso interrompe o tick e faz isso mesmo quando a CPU está executando uma única tarefa ativa. Isso significa que faz a CPU rodar em modo full tickless (ou 'dyntick'). O kernel só entregará interrupções de temporizador quando elas forem realmente necessárias.

rcu_nocbs

1-30,33-62

Esta opção descarrega o processamento de callback RCU de núcleos de CPU especificados.

rcu_nocb_poll

 

Quando esta opção está definida, as CPUs sem callback RCU farão polling regularmente para verificar se o tratamento de callback é necessário, em vez de serem explicitamente despertadas por outras CPUs. Isso pode reduzir a sobrecarga de interrupção.

irqaffinity

0,31,32,63

Esta opção permite que o kernel execute as interrupções nos núcleos de manutenção.

inativo

Fazer poll

Isso minimiza a latência de saída do estado ocioso, mas ao custo de manter a CPU funcionando em velocidade máxima na thread ociosa.

nmi_watchdog

0

Esta opção desativa apenas o watchdog NMI. Isso pode ser omitido quando nowatchdog estiver definido.

nowatchdog

 

Esta opção desativa o watchdog de soft-lockup, que é implementado como um temporizador executado no contexto de interrupção de hardware do temporizador.

Os comandos a seguir modificam a configuração do GRUB e aplicam as alterações mencionadas acima para que estejam presentes na próxima inicialização:

Edite o arquivo /etc/default/grub com os parâmetros acima e o arquivo ficará assim:

GRUB_CMDLINE_LINUX="BOOT_IMAGE=/boot/vmlinuz-6.4.0-9-rt root=UUID=77b713de-5cc7-4d4c-8fc6-f5eca0a43cf9 skew_tick=1 rd.timeout=60 rd.retry=45 console=ttyS1,115200 console=tty0 default_hugepagesz=1G hugepagesz=1G hugepages=40 hugepagesz=2M hugepages=0 ignition.platform.id=openstack net.ifnames=1 intel_iommu=on iommu=pt irqaffinity=0,31,32,63 isolcpus=domain,nohz,managed_irq,1-30,33-62 nohz_full=1-30,33-62 nohz=on mce=off nosoftlockup nowatchdog nmi_watchdog=0 quiet rcu_nocb_poll rcu_nocbs=1-30,33-62 rcupdate.rcu_cpu_stall_suppress=1 rcupdate.rcu_expedited=1 rcupdate.rcu_normal_after_boot=1 rcupdate.rcu_task_stall_timeout=0 rcutree.kthread_prio=99 security=selinux selinux=1 idle=poll"

Atualize a configuração do GRUB:

$ transactional-update grub.cfg
$ reboot

Para validar que os parâmetros sejam aplicados após a reinicialização, o seguinte comando pode ser usado para verificar a linha de comando do kernel:

$ cat /proc/cmdline

Existe outro script que pode ser usado para ajustar a configuração da CPU, que basicamente realiza as seguintes etapas:

  • Defina o governador da CPU como performance.

  • Desative a migração de timer para as CPUs isoladas.

  • Migre as threads kdaemon para as CPUs de manutenção.

  • Defina a latência das CPUs isoladas para o menor valor possível.

  • Atrase as atualizações do vmstat para 300 segundos.

O script está disponível em repositório de exemplos do SUSE Telco Cloud.

37 Fixação de CPU no Kubernetes

37.1 Versões do RKE2 < v1.32

Habilite a fixação de CPU em seu cluster RKE2 editando o arquivo de configuração do RKE2. Adicione os argumentos do kubelet abaixo no arquivo /etc/rancher/rke2/config.yaml. Certifique-se de especificar os núcleos de CPU de housekeeping nos argumentos kubelet-reserved e system-reserved:

kubelet-arg:
- "cpu-manager-policy=static"
- "cpu-manager-policy-options=full-pcpus-only=true"
- "cpu-manager-reconcile-period=0s"
- "kubelet-reserved=cpu=0,31,32,63"
- "system-reserved=cpu=0,31,32,63"

37.2 Versões do RKE2 >= v1.32

Se a sua versão do RKE2 for v1.32 ou superior, argumentos de linha de comando não podem ser usados para configurar o kubelet, seguindo a prática upstream do Kubernetes. Para configurar a fixação de CPU, um arquivo de configuração do kubelet precisa ser criado. Consulte documentação do RKE2.

Crie um novo arquivo de configuração do kubelet, como 01-cpu-pinning.conf, e coloque-o no diretório /var/lib/rancher/rke2/agent/etc/kubelet.conf.d/:

apiVersion: kubelet.config.k8s.io/v1beta1
kind: KubeletConfiguration
cpuManagerPolicy: static
reservedSystemCPUs: 0,31,32,63
topologyManagerPolicy: single-numa-node

Para que as alterações de configuração entrem em vigor, uma reinicialização do serviço RKE2 apropriado (servidor ou agente) é necessária. Esta ação interromperá brevemente o serviço RKE2 no host. Execute apenas um dos seguintes comandos, dependendo do tipo de nó:

# If the node is RKE2 agent
systemctl restart rke2-agent
# Else if the node is RKE2 server
systemctl restart rke2-server

37.3 Implante cargas de trabalho aproveitando a fixação de CPU.

Existem três maneiras de usar o recurso usando o Static Policy definido no kubelet, dependendo das solicitações e limites que você define em sua carga de trabalho:

  1. BestEffort Classe de QoS: Se você não definir nenhuma solicitação ou limite para CPU, o pod será agendado no primeiro CPU disponível no sistema.

    Um exemplo de uso da BestEffort Classe de QoS poderia ser:

    spec:
      containers:
      - name: nginx
        image: nginx
  2. Burstable Classe de QoS: Se você definir uma solicitação de CPU, que não é igual aos limites, ou se não houver solicitação de CPU.

    Exemplos de uso da Burstable Classe de QoS poderiam ser:

    spec:
      containers:
      - name: nginx
        image: nginx
        resources:
          limits:
            memory: "200Mi"
          requests:
            memory: "100Mi"

    ou

    spec:
      containers:
      - name: nginx
        image: nginx
        resources:
          limits:
            memory: "200Mi"
            cpu: "2"
          requests:
            memory: "100Mi"
            cpu: "1"
  3. Guaranteed Classe de QoS: Se você definir uma solicitação de CPU, que é igual aos limites.

    Um exemplo de uso da Classe de QoS Guaranteed poderia ser:

    spec:
      containers:
        - name: nginx
          image: nginx
          resources:
            limits:
              memory: "200Mi"
              cpu: "2"
            requests:
              memory: "200Mi"
              cpu: "2"

38 Configuração de CNI

38.1 Cilium

Cilium é o plug-in de CNI padrão para o SUSE Telco Cloud. Para habilitar o Cilium no cluster RKE2 como o plug-in padrão, a seguinte configuração é necessária no arquivo /etc/rancher/rke2/config.yaml:

cni:
- cilium

Isso também pode ser especificado com argumentos de linha de comando, ou seja, --cni=cilium na linha do servidor no arquivo /etc/systemd/system/rke2-server.

Para usar a rede SR-IOV descrita em Seção 39.2, “Opção 2 (Recomendada): Operador de Rede SR-IOV” junto com o Cilium, implante o meta plugin multus. Certifique-se de que multus esteja listado antes de outras CNIs.

cni:
- multus
- cilium

38.2 Calico

Calico é outro plug-in de CNI para SUSE Telco Cloud para Telco. Para habilitar o Calico no cluster RKE2 como o plug-in padrão, a seguinte configuração é necessária no arquivo /etc/rancher/rke2/config.yaml:

cni:
- calico

Isso também pode ser especificado com argumentos de linha de comando, ou seja, --cni=calico na linha do servidor no arquivo /etc/systemd/system/rke2-server.

Para usar a rede SR-IOV descrita em Seção 39.2, “Opção 2 (Recomendada): Operador de Rede SR-IOV” junto com o Calico, implante o meta plugin multus. Certifique-se de que multus esteja listado antes de outras CNIs.

cni:
- multus
- calico
Nota
Nota

Para mais informações sobre plug-ins CNI, consulte Opções de Rede.

38.3 Bond CNI

Em termos gerais, o bonding fornece um método para agregar múltiplas interfaces de rede em uma única interface lógica "bonded". Isso é normalmente usado para aumentar a disponibilidade do serviço introduzindo caminhos de rede redundantes, mas também pode ser usado para aumentar a largura de banda com certos modos de bond. Os seguintes plug-ins CNI são suportados para o plug-in Bond CNI em combinação com o multus:

  • MACVLAN

  • Dispositivo do Host

  • SR-IOV

38.3.1 Bond CNI com MACVLAN

Para usar o plug-in Bond CNI com MACVLAN, são necessárias duas interfaces livres no contêiner. O exemplo a seguir usa 'enp8s0' e 'enp9s0'. Comece criando definições de anexo de rede para eles:

NetworkAttachmentDefinition enp8s0

apiVersion: "k8s.cni.cncf.io/v1"
kind: NetworkAttachmentDefinition
metadata:
  name: enp8s0-conf
spec:
  config: '{
      "cniVersion": "0.3.1",
      "plugins": [
        {
          "type": "macvlan",
          "capabilities": { "ips": true },
          "master": "enp8s0",
          "mode": "bridge",
          "ipam": {}
        }, {
          "capabilities": { "mac": true },
          "type": "tuning"
        }
      ]
    }'

NetworkAttachmentDefinition enp9s0

apiVersion: "k8s.cni.cncf.io/v1"
kind: NetworkAttachmentDefinition
metadata:
  name: enp9s0-conf
spec:
  config: '{
      "cniVersion": "0.3.1",
      "plugins": [
        {
          "type": "macvlan",
          "capabilities": { "ips": true },
          "master": "enp9s0",
          "mode": "bridge",
          "ipam": {}
        }, {
          "capabilities": { "mac": true },
          "type": "tuning"
        }
      ]
    }'

Depois disso, adicione uma definição de anexo de rede para o próprio bond.

NetworkAttachmentDefinition bond

apiVersion: "k8s.cni.cncf.io/v1"
kind: NetworkAttachmentDefinition
metadata:
  name: bond-net1
spec:
  config: '{
  "type": "bond",
  "cniVersion": "0.3.1",
  "name": "bond-net1",
  "mode": "active-backup",
  "failOverMac": 1,
  "linksInContainer": true,
  "miimon": "100",
  "mtu": 1500,
  "links": [
     {"name": "net1"},
     {"name": "net2"}
  ],
  "ipam": {
    "type": "static",
    "addresses": [
      {
        "address": "192.168.200.100/24",
        "gateway": "192.168.200.1"
      }
    ],
    "subnet": "192.168.200.0/24",
    "routes": [{
      "dst": "0.0.0.0/0"
    }]
  }
}'

A atribuição de endereço IP aqui é estática e define o endereço do bond como '192.168.200.100' em uma rede /24, com um gateway residindo no primeiro endereço disponível da rede. No anexo de rede do bond, também definimos o tipo de bond que desejamos. Neste caso, é active-backup.

Para usar este bond, o pod precisa conhecer todas as interfaces. Uma definição de pod de exemplo pode ser assim:

apiVersion: v1
kind: Pod
metadata:
  name: test-pod
  annotations:
        k8s.v1.cni.cncf.io/networks: '[
{"name": "enp8s0-conf",
"interface": "net1"
},
{"name": "enp9s0-conf",
"interface": "net2"
},
{"name": "bond-net1",
"interface": "bond0"
}]'
spec:
  restartPolicy: Never
  containers:
  - name: bond-test
    image: alpine:latest
    command:
      - /bin/sh
      - "-c"
      - "sleep 60m"
    imagePullPolicy: IfNotPresent

Observe como a anotação se refere a todas as redes e como ela define o mapeamento entre as interfaces 'enp8s0 → net1' e 'enp9s0 → net2'.

38.3.2 Bond CNI com Dispositivo Host

Para usar o plugin Bond CNI com dispositivo host, são necessárias duas interfaces livres no host. Essas interfaces são então mapeadas para o contêiner. O exemplo a seguir usa 'enp8s0' e 'enp9s0'. Comece criando definições de anexo de rede para eles:

NetworkAttachmentDefinition enp8s0

apiVersion: "k8s.cni.cncf.io/v1"
kind: NetworkAttachmentDefinition
metadata:
  name: enp8s0-hostdev
spec:
  config: '{
      "cniVersion": "0.3.1",
      "plugins": [
        {
          "type": "host-device",
          "name": "host0",
          "device": "enp8s0",
          "ipam": {}
        }]
    }'

NetworkAttachmentDefinition enp9s0

apiVersion: "k8s.cni.cncf.io/v1"
kind: NetworkAttachmentDefinition
metadata:
  name: enp9s0-hostdev
spec:
  config: '{
      "cniVersion": "0.3.1",
      "plugins": [
        {
          "type": "host-device",
          "name": "host0",
          "device": "enp9s0",
          "ipam": {}
        }]
    }'

Após isso, adicione a definição de anexo de rede para o próprio bond. Isso é semelhante ao caso de uso de MACVLAN.

NetworkAttachmentDefinition bond

apiVersion: "k8s.cni.cncf.io/v1"
kind: NetworkAttachmentDefinition
metadata:
  name: bond-net1
spec:
  config: '{
  "type": "bond",
  "cniVersion": "0.3.1",
  "name": "bond-net1",
  "mode": "active-backup",
  "failOverMac": 1,
  "linksInContainer": true,
  "miimon": "100",
  "mtu": 1500,
  "links": [
     {"name": "net1"},
     {"name": "net2"}
  ],
  "ipam": {
    "type": "static",
    "addresses": [
      {
        "address": "192.168.200.100/24",
        "gateway": "192.168.200.1"
      }
    ],
    "subnet": "192.168.200.0/24",
    "routes": [{
      "dst": "0.0.0.0/0"
    }]
  }
}'

A atribuição de endereço IP aqui é estática e define o endereço do bond como '192.168.200.100' em uma rede /24, com um gateway residindo no primeiro endereço disponível da rede. No anexo de rede do bond, defina o tipo de bond. Neste caso, é active-backup.

Para usar este bond, o pod precisa conhecer todas as interfaces. Um exemplo de definição de pod para bond com dispositivos host pode ser assim:

apiVersion: v1
kind: Pod
metadata:
  name: test-pod
  annotations:
        k8s.v1.cni.cncf.io/networks: '[
{"name": "enp8s0-hostdev",
"interface": "net1"
},
{"name": "enp9s0-hostdev",
"interface": "net2"
},
{"name": "bond-net1",
"interface": "bond0"
}]'
spec:
  restartPolicy: Never
  containers:
  - name: bond-test
    image: alpine:latest
    command:
      - /bin/sh
      - "-c"
      - "sleep 60m"
    imagePullPolicy: IfNotPresent

38.3.3 Bond CNI com SR-IOV

Usar o Bond CNI com SR-IOV é bastante simples. Para mais detalhes sobre como configurar o SR-IOV, consulte Capítulo 39, SR-IOV. Conforme descrito lá, você deve criar SriovNetworkNodePolicies que define resourceNames, bem como o número de funções virtuais e afins. As resourceNames estão sendo usadas pelo SriovNetwork, que é usado como interfaces na definição do pod. A definição do bond é exatamente a mesma dos casos de MACVLAN e dispositivo host.

Nota
Nota

O Bond CNI com SR-IOV só é aplicável a Funções Virtuais (VF) SRIOV usando o driver de kernel. VFs de driver de espaço de usuário - como aquelas usadas em cargas de trabalho DPDK - não podem ser vinculadas com o Bond CNI.

39 SR-IOV

SR-IOV (Single Root I/O Virtualization) permite que um único dispositivo físico, como um adaptador de rede, separe seus recursos entre múltiplas PCIe funções de hardware. Isso permite acesso direto aos recursos para várias aplicações.

Fornecemos dois métodos distintos para implantar SR-IOV em seu cluster:

Em casos raros em que você precisa de ambas as soluções - usando o Operador de Rede para dispositivos de rede e o Plugin de Dispositivo para Aceleradores vRAN - você deve implantá-los em namespaces separados do Kubernetes. Essa separação é essencial para evitar conflitos entre as duas implantações.

39.1 Opção 1: Daemonset e configMap do Plugin de Dispositivo de Rede SR-IOV

O Plugin de Dispositivo de Rede SR-IOV descobre e anuncia recursos de rede, como funções físicas (PFs) PCI e suas funções virtuais (VFs), em um host Kubernetes.

  • Prepare o configMap para o plugin de dispositivo

Precisamos criar um configMap que defina pools de recursos SR-IOV. Execute o comando lspci para recuperar as informações:

$ lspci | grep -i acc
07:00.0 Processing accelerators: Intel Corporation Device 57c2
07:00.1 Processing accelerators: Intel Corporation Device 57c3
07:00.2 Processing accelerators: Intel Corporation Device 57c3
07:00.3 Processing accelerators: Intel Corporation Device 57c3
07:00.4 Processing accelerators: Intel Corporation Device 57c3
07:00.5 Processing accelerators: Intel Corporation Device 57c3
07:00.6 Processing accelerators: Intel Corporation Device 57c3
07:00.7 Processing accelerators: Intel Corporation Device 57c3
07:01.0 Processing accelerators: Intel Corporation Device 57c3
07:01.1 Processing accelerators: Intel Corporation Device 57c3
07:01.2 Processing accelerators: Intel Corporation Device 57c3
07:01.3 Processing accelerators: Intel Corporation Device 57c3
07:01.4 Processing accelerators: Intel Corporation Device 57c3
07:01.5 Processing accelerators: Intel Corporation Device 57c3
07:01.6 Processing accelerators: Intel Corporation Device 57c3
07:01.7 Processing accelerators: Intel Corporation Device 57c3
07:02.0 Processing accelerators: Intel Corporation Device 57c3
0a:00.0 Processing accelerators: Intel Corporation Device 57c2

$ lspci | grep -i net
19:00.0 Ethernet controller: Broadcom Inc. and subsidiaries BCM57504 NetXtreme-E 10Gb/25Gb/40Gb/50Gb/100Gb/200Gb Ethernet (rev 11)
19:00.1 Ethernet controller: Broadcom Inc. and subsidiaries BCM57504 NetXtreme-E 10Gb/25Gb/40Gb/50Gb/100Gb/200Gb Ethernet (rev 11)
19:00.2 Ethernet controller: Broadcom Inc. and subsidiaries BCM57504 NetXtreme-E 10Gb/25Gb/40Gb/50Gb/100Gb/200Gb Ethernet (rev 11)
19:00.3 Ethernet controller: Broadcom Inc. and subsidiaries BCM57504 NetXtreme-E 10Gb/25Gb/40Gb/50Gb/100Gb/200Gb Ethernet (rev 11)
51:00.0 Ethernet controller: Intel Corporation Ethernet Controller E810-C for QSFP (rev 02)
51:00.1 Ethernet controller: Intel Corporation Ethernet Controller E810-C for QSFP (rev 02)
51:01.0 Ethernet controller: Intel Corporation Ethernet Adaptive Virtual Function (rev 02)
51:01.1 Ethernet controller: Intel Corporation Ethernet Adaptive Virtual Function (rev 02)
51:01.2 Ethernet controller: Intel Corporation Ethernet Adaptive Virtual Function (rev 02)
51:01.3 Ethernet controller: Intel Corporation Ethernet Adaptive Virtual Function (rev 02)
51:11.0 Ethernet controller: Intel Corporation Ethernet Adaptive Virtual Function (rev 02)
51:11.1 Ethernet controller: Intel Corporation Ethernet Adaptive Virtual Function (rev 02)
51:11.2 Ethernet controller: Intel Corporation Ethernet Adaptive Virtual Function (rev 02)
51:11.3 Ethernet controller: Intel Corporation Ethernet Adaptive Virtual Function (rev 02)

O Plugin de Dispositivo SR-IOV usa um configMap contendo um arquivo JSON para definir quais recursos de hardware o Kubernetes deve expor. Esta configuração baseia-se em dois conceitos principais: selectors (para descoberta de hardware) e resources (para exposição no Kubernetes).

Um resource é a entidade nomeada que os pods consomem (por exemplo, rancher.io/intel_fec_5g). Os recursos podem ser definidos como um de dois tipos:

  • accelerator: Usado para placas aceleradoras vRAN (como ACC100/vRAN Boost).

  • netdevice: Usado para interfaces de rede padrão (NICs).

Você define os dispositivos de destino usando selectors para filtrar o hardware no nó:

  • vendors: 8086 (Intel)

  • devices: 57c3 (FEC VF), 1889 (NIC VF)

  • drivers: vfio-pci

  • pfNames: p2p1 (nome da interface física)

Para placas de rede, você também pode selecionar um subconjunto de Funções Virtuais (VFs) de uma Função Física:

  • pfNames: ["eth1#1,2,3,4,5,6"] ou [eth1#1-6]

Para permitir que os pods solicitem os dispositivos, cada recurso deve ter um nome, que é composto por um prefixo e um nome:

  • resourceName: pci_sriov_net_bh_dpdk

  • resourcePrefix: rancher.io

Os pods então solicitariam o nome do recurso combinado: rancher.io/pci_sriov_net_bh_dpdk.

Nota
Nota

Este documento não lista todos os seletores possíveis. Diferentes tipos de recursos usam diferentes conjuntos de seletores. Para detalhes abrangentes, consulte o repositório do SR-IOV Network Device Plugin.

O ConfigMap abaixo é um exemplo que cria três recursos: um para a placa aceleradora vRAN (FEC) e dois para duas portas NIC diferentes.

Para a placa FEC, você deve primeiro recuperar o ID do dispositivo e o token VFIO. Siga as instruções no capítulo Capítulo 41, Aceleração vRAN (Intel ACC100/VRB1/VRB2) para os pré-requisitos.

apiVersion: v1
kind: ConfigMap
metadata:
  name: sriovdp-config
  namespace: kube-system
data:
  config.json: |
    {
        "resourceList": [
            {
                "resourcePrefix": "rancher.io",
                "resourceName": "intel_fec_5g",
                "deviceType": "accelerator",
                "selectors": {
                    "vendors": ["8086"],
                    "devices": ["57c3"]
                },
                "additionalInfo": {
                      "*": {
                        "VFIO_TOKEN": "00112233-4455-6677-8899-aabbccddeeff"
                      }
                  }
            },
            {
                "resourcePrefix": "rancher.io",
                "resourceName": "intel_sriov_odu",
                "deviceType": "netdevice",
                "selectors": {
                    "vendors": ["8086"],
                    "devices": ["1889"],
                    "drivers": ["vfio-pci"],
                    "pfNames": ["p2p1"]
                }
            },
            {
                "resourcePrefix": "rancher.io",
                "resourceName": "intel_sriov_oru",
                "deviceType": "netdevice",
                "selectors": {
                    "vendors": ["8086"],
                    "devices": ["1889"],
                    "drivers": ["vfio-pci"],
                    "pfNames": ["p2p2"]
                }
            }
        ]
    }
  • Prepare o arquivo daemonset para implantar o plugin de dispositivo.

O plugin de dispositivo suporta várias arquiteturas (arm, amd, ppc64le), portanto, o mesmo arquivo pode ser usado para diferentes arquiteturas implantando vários daemonset para cada arquitetura.

apiVersion: v1
kind: ServiceAccount
metadata:
  name: sriov-device-plugin
  namespace: kube-system
---
apiVersion: apps/v1
kind: DaemonSet
metadata:
  name: kube-sriov-device-plugin-amd64
  namespace: kube-system
  labels:
    tier: node
    app: sriovdp
spec:
  selector:
    matchLabels:
      name: sriov-device-plugin
  template:
    metadata:
      labels:
        name: sriov-device-plugin
        tier: node
        app: sriovdp
    spec:
      hostNetwork: true
      nodeSelector:
        kubernetes.io/arch: amd64
      tolerations:
      - key: node-role.kubernetes.io/master
        operator: Exists
        effect: NoSchedule
      serviceAccountName: sriov-device-plugin
      containers:
      - name: kube-sriovdp
        image: registry.suse.com/rancher/hardened-sriov-network-device-plugin:v3.9.0-build20250425
        imagePullPolicy: IfNotPresent
        args:
        - --log-dir=sriovdp
        - --log-level=10
        securityContext:
          privileged: true
        resources:
          requests:
            cpu: "250m"
            memory: "40Mi"
          limits:
            cpu: 1
            memory: "200Mi"
        volumeMounts:
        - name: devicesock
          mountPath: /var/lib/kubelet/
          readOnly: false
        - name: log
          mountPath: /var/log
        - name: config-volume
          mountPath: /etc/pcidp
        - name: device-info
          mountPath: /var/run/k8s.cni.cncf.io/devinfo/dp
      volumes:
        - name: devicesock
          hostPath:
            path: /var/lib/kubelet/
        - name: log
          hostPath:
            path: /var/log
        - name: device-info
          hostPath:
            path: /var/run/k8s.cni.cncf.io/devinfo/dp
            type: DirectoryOrCreate
        - name: config-volume
          configMap:
            name: sriovdp-config
            items:
            - key: config.json
              path: config.json
  • Após aplicar o configMap e o daemonset, o plugin de dispositivo será implantado e as interfaces serão descobertas e disponibilizadas para os pods.

    $ kubectl get pods -n kube-system | grep sriov
    kube-system  kube-sriov-device-plugin-amd64-twjfl  1/1  Running  0  2m
  • Verifique em todos os nós se as interfaces foram descobertas e disponibilizadas para os pods:

    $ kubectl get nodes -o json | jq '.items[] | {name: .metadata.name, allocatable: .status.allocatable}'
    {
      "name": "node1.suse.edge.com",
      "allocatable": {
          "cpu": "64",
          "ephemeral-storage": "256196109726",
          "hugepages-1Gi": "40Gi",
          "hugepages-2Mi": "0",
          "rancher.io/intel_fec_5g": "16",
          "rancher.io/intel_sriov_odu": "4",
          "rancher.io/intel_sriov_oru": "4",
          "memory": "221396384Ki",
          "pods": "110"
      }
    }
  • O nome do recurso para o acelerador FEC é rancher.io/intel_fec_5g e 16 VFs estão disponíveis para uso.

  • Os nomes do recurso para as placas NIC são rancher.io/intel_sriov_odu e rancher.io/intel_sriov_oru. Cada recurso fornece 4 VFs.

Importante
Importante

Se nenhuma interface for detectada como recurso alocável nos nós do Kubernetes, é essencial resolver esse problema. Uma causa comum é uma especificação de configMap mal formada, portanto, é melhor revisar o configMap e seus seletores.

39.2 Opção 2 (Recomendada): Operador de Rede SR-IOV

  • Obtenha o Helm se não estiver presente:

$ curl https://raw.githubusercontent.com/helm/helm/main/scripts/get-helm-3 | bash
  • Instale o Operador de Rede SR-IOV no namespace sriov-network-operator:

helm install sriov-crd oci://registry.suse.com/edge/charts/sriov-crd -n sriov-network-operator
helm install sriov-network-operator oci://registry.suse.com/edge/charts/sriov-network-operator -n sriov-network-operator
  • Verifique os CRDs e pods implantados:

$ kubectl get crd
$ kubectl -n sriov-network-operator get pods
  • Verifique se o rótulo SR-IOV foi aplicado aos nós.

Com todos os recursos em execução, o rótulo aparece automaticamente em seu nó:

$ kubectl get nodes -oyaml | grep feature.node.kubernetes.io/network-sriov.capable

feature.node.kubernetes.io/network-sriov.capable: "true"
  • Revise o daemonset para ver o novo sriov-network-config-daemon e sriov-rancher-nfd-worker como ativos e prontos:

$ kubectl get daemonset -n sriov-network-operator
NAMESPACE             NAME                            DESIRED   CURRENT   READY   UP-TO-DATE   AVAILABLE   NODE SELECTOR                                           AGE
sriov-network-operator   sriov-network-config-daemon     1         1         1       1            1           feature.node.kubernetes.io/network-sriov.capable=true   45m
sriov-network-operator   sriov-rancher-nfd-worker        1         1         1       1            1           <none>                                                  45m

Em alguns minutos, os nós serão detectados e totalmente configurados com capacidades SR-IOV. A atualização pode levar, às vezes, até 10 minutos:

$ kubectl get sriovnetworknodestates -A
NAMESPACE             NAME     AGE
sriov-network-operator   xr11-2   83s
  • Verifique se as interfaces foram detectadas.

As interfaces descobertas devem ser o endereço PCI do dispositivo de rede. Verifique esta informação com o comando lspci no host.

$ kubectl get sriovnetworknodestates -n sriov-network-operator -oyaml
apiVersion: v1
items:
- apiVersion: sriovnetwork.openshift.io/v1
  kind: SriovNetworkNodeState
  metadata:
    creationTimestamp: "2023-06-07T09:52:37Z"
    generation: 1
    name: xr11-2
    namespace: sriov-network-operator
    ownerReferences:
    - apiVersion: sriovnetwork.openshift.io/v1
      blockOwnerDeletion: true
      controller: true
      kind: SriovNetworkNodePolicy
      name: default
      uid: 80b72499-e26b-4072-a75c-f9a6218ec357
    resourceVersion: "356603"
    uid: e1f1654b-92b3-44d9-9f87-2571792cc1ad
  spec:
    dpConfigVersion: "356507"
  status:
    interfaces:
    - deviceID: "1592"
      driver: ice
      eSwitchMode: legacy
      linkType: ETH
      mac: 40:a6:b7:9b:35:f0
      mtu: 1500
      name: p2p1
      pciAddress: "0000:51:00.0"
      totalvfs: 128
      vendor: "8086"
    - deviceID: "1592"
      driver: ice
      eSwitchMode: legacy
      linkType: ETH
      mac: 40:a6:b7:9b:35:f1
      mtu: 1500
      name: p2p2
      pciAddress: "0000:51:00.1"
      totalvfs: 128
      vendor: "8086"
    syncStatus: Succeeded
kind: List
metadata:
  resourceVersion: ""
Nota
Nota

Se sua interface não for detectada aqui, certifique-se de que ela esteja presente no próximo config map:

$ kubectl get cm supported-nic-ids -oyaml -n sriov-network-operator

Se seu dispositivo não estiver listado, edite o config map adicionando os valores corretos para que seja descoberto. Em seguida, reinicie os sriov-network-config-daemon pods em cada nó para que a atualização entre em vigor.

  • Crie o SriovNetworkNodePolicy para configurar o VFs

Esta política cria o recurso intelnicsDpdk para consumo do pod. Ela também vincula o driver vfio-pci ao dispositivo PCI fornecido e cria 8 VFs com um tamanho de MTU de 1500:

Nota
Nota

O campo resourceName não deve conter caracteres especiais e deve ser exclusivo em todo o cluster. O exemplo usa o deviceType: vfio-pci porque o DPDK é usado em combinação com SR-IOV. Se você não usar o DPDK, configure deviceType: netdevice (valor padrão).

apiVersion: sriovnetwork.openshift.io/v1
kind: SriovNetworkNodePolicy
metadata:
  name: policy-dpdk
  namespace: sriov-network-operator
spec:
  nodeSelector:
    feature.node.kubernetes.io/network-sriov.capable: "true"
  resourceName: intelnicsDpdk
  deviceType: vfio-pci
  numVfs: 8
  mtu: 1500
  nicSelector:
    deviceID: "1592"
    vendor: "8086"
    rootDevices:
    - 0000:51:00.0
  • Valide as configurações em todos os nós:

Com o resourcePrefix rancher.io predefinido, um recurso rancher.io/intelnicsDpdk com 8 VFs deve ser descoberto.

$ kubectl get nodes -o jsonpath='{"items": [ { "name": @.metadata.name, "allocatable": @.status.allocatable } ]}' | jq
{
  "name": "node1.suse.edge.com",
  "allocatable": {
      "cpu": "64",
      "ephemeral-storage": "256196109726",
      "hugepages-1Gi": "60Gi",
      "hugepages-2Mi": "0",
      "rancher.io/intel_fec_5g": "16",
      "memory": "200424836Ki",
      "pods": "110",
      "rancher.io/intelnicsDpdk": "8"
  }
}
  • (Opcional) Crie o sriovnetwork

Esta etapa é opcional e necessária apenas para definições de rede personalizadas. Especifique o resourceName para vincular à política de nó criada anteriormente.

Se o networkNamespace estiver definido, a rede será exposta aos pods nesse namespace. Caso contrário, a rede ficará disponível no namespace de instalação do Network Operator.

apiVersion: sriovnetwork.openshift.io/v1
kind: SriovNetwork
metadata:
  name: network-dpdk
  namespace: sriov-network-operator        # where SRIOV Operator is installed
spec:
  ipam: |
    {
      "type": "host-local",
      "subnet": "192.168.0.0/24",
      "rangeStart": "192.168.0.20",
      "rangeEnd": "192.168.0.60",
      "routes": [{
        "dst": "0.0.0.0/0"
      }],
      "gateway": "192.168.0.1"
    }
  vlan: 500
  resourceName: intelnicsDpdk
  networkNamespace: default         # where workloads are deployed
  • Se a atualização for bem-sucedida, uma NetworkAttachmentDefinition (NAD) será criada no cluster de destino.

$ kubectl get net-attach-def -A -oyaml

apiVersion: v1
items:
- apiVersion: k8s.cni.cncf.io/v1
  kind: NetworkAttachmentDefinition
  metadata:
    annotations:
      k8s.v1.cni.cncf.io/resourceName: rancher.io/intelnicsDpdk
    creationTimestamp: "2023-06-08T11:22:27Z"
    generation: 1
    name: network-dpdk
    namespace: default
    resourceVersion: "13124"
    uid: df7c89f5-177c-4f30-ae72-7aef3294fb15
  spec:
    config: '{ "cniVersion":"0.4.0", "name":"network-dpdk","type":"sriov","vlan":500,"vlanQoS":0,"ipam":{"type":"host-local","subnet":"192.168.0.0/24","rangeStart":"192.168.0.10","rangeEnd":"192.168.0.60","routes":[{"dst":"0.0.0.0/0"}],"gateway":"192.168.0.1"}
      }'
kind: List
metadata:
  resourceVersion: ""

Os pods de carga de trabalho podem usar o resourceName rancher.io/intelnicsDpdk para usar os VFs da interface de rede.

40 DPDK

DPDK (Data Plane Development Kit) é um conjunto de bibliotecas e drivers para processamento rápido de pacotes. Ele é usado para acelerar cargas de trabalho de processamento de pacotes executadas em uma ampla variedade de arquiteturas de CPU. O DPDK inclui bibliotecas de plano de dados e drivers otimizados para a placa de interface de rede (NIC) para os seguintes fins:

  1. Um gerenciador de filas implementa filas sem bloqueio.

  2. Um gerenciador de buffers pré-aloca buffers de tamanho fixo.

  3. Um gerenciador de memória aloca pools de objetos na memória e usa um anel para armazenar objetos livres; garante que os objetos sejam distribuídos igualmente em todos os canais DRAM.

  4. Drivers de modo de polling (PMD) são projetados para funcionar sem notificações assíncronas, reduzindo a sobrecarga.

  5. Uma estrutura de pacotes consiste em um conjunto de bibliotecas que auxiliam no desenvolvimento do processamento de pacotes.

As etapas a seguir mostrarão como habilitar DPDK e como criar VFs a partir do NICs para serem usados pelas interfaces DPDK:

  • Instale o pacote DPDK:

$ transactional-update pkg install dpdk dpdk-tools libdpdk-25
$ reboot
  • Parâmetros kernel:

Para usar o DPDK, empregue alguns drivers para habilitar certos parâmetros do kernel:

parametervaluedescrição

iommu

pt

Esta opção habilita o uso do driver vfio para as interfaces DPDK.

intel_iommu or amd_iommu

on

Esta opção habilita o uso de vfio para VFs.

Para habilitar os parâmetros, adicione-os ao arquivo /etc/default/grub:

GRUB_CMDLINE_LINUX="BOOT_IMAGE=/boot/vmlinuz-6.4.0-9-rt root=UUID=77b713de-5cc7-4d4c-8fc6-f5eca0a43cf9 skew_tick=1 rd.timeout=60 rd.retry=45 console=ttyS1,115200 console=tty0 default_hugepagesz=1G hugepagesz=1G hugepages=40 hugepagesz=2M hugepages=0 ignition.platform.id=openstack net.ifnames=1 intel_iommu=on iommu=pt irqaffinity=0,31,32,63 isolcpus=domain,nohz,managed_irq,1-30,33-62 nohz_full=1-30,33-62 nohz=on mce=off nosoftlockup nowatchdog nmi_watchdog=0 quiet rcu_nocb_poll rcu_nocbs=1-30,33-62 rcupdate.rcu_cpu_stall_suppress=1 rcupdate.rcu_expedited=1 rcupdate.rcu_normal_after_boot=1 rcupdate.rcu_task_stall_timeout=0 rcutree.kthread_prio=99 security=selinux selinux=1 idle=poll"

Atualize a configuração do GRUB e reinicie o sistema para aplicar as alterações:

$ transactional-update grub.cfg
$ reboot
  • Carregue o módulo do kernel vfio-pci e habilite SR-IOV nas NICs. O primeiro argumento indica o driver vfio-pci para suportar SR-IOV, e o segundo argumento impede que o dispositivo PCI entre em um estado de baixo consumo de energia quando está ocioso:

$ modprobe vfio-pci enable_sriov=1 disable_idle_d3=1
  • Crie algumas funções virtuais (VFs) a partir do NICs.

Para criar para VFs, por exemplo, para dois NICs diferentes, os seguintes comandos são necessários:

$ echo 4 > /sys/bus/pci/devices/0000:51:00.0/sriov_numvfs
$ echo 4 > /sys/bus/pci/devices/0000:51:00.1/sriov_numvfs
  • Vincule as novas VFs com o driver vfio-pci:

$ dpdk-devbind.py -b vfio-pci 0000:51:01.0 0000:51:01.1 0000:51:01.2 0000:51:01.3 \
                              0000:51:11.0 0000:51:11.1 0000:51:11.2 0000:51:11.3
  • Revise se a configuração foi aplicada corretamente:

$ dpdk-devbind.py -s

Network devices using DPDK-compatible driver
============================================
0000:51:01.0 'Ethernet Adaptive Virtual Function 1889' drv=vfio-pci unused=iavf,igb_uio
0000:51:01.1 'Ethernet Adaptive Virtual Function 1889' drv=vfio-pci unused=iavf,igb_uio
0000:51:01.2 'Ethernet Adaptive Virtual Function 1889' drv=vfio-pci unused=iavf,igb_uio
0000:51:01.3 'Ethernet Adaptive Virtual Function 1889' drv=vfio-pci unused=iavf,igb_uio
0000:51:01.0 'Ethernet Adaptive Virtual Function 1889' drv=vfio-pci unused=iavf,igb_uio
0000:51:11.1 'Ethernet Adaptive Virtual Function 1889' drv=vfio-pci unused=iavf,igb_uio
0000:51:21.2 'Ethernet Adaptive Virtual Function 1889' drv=vfio-pci unused=iavf,igb_uio
0000:51:31.3 'Ethernet Adaptive Virtual Function 1889' drv=vfio-pci unused=iavf,igb_uio

Network devices using kernel driver
===================================
0000:19:00.0 'BCM57504 NetXtreme-E 10Gb/25Gb/40Gb/50Gb/100Gb/200Gb Ethernet 1751' if=em1 drv=bnxt_en unused=igb_uio,vfio-pci *Active*
0000:19:00.1 'BCM57504 NetXtreme-E 10Gb/25Gb/40Gb/50Gb/100Gb/200Gb Ethernet 1751' if=em2 drv=bnxt_en unused=igb_uio,vfio-pci
0000:19:00.2 'BCM57504 NetXtreme-E 10Gb/25Gb/40Gb/50Gb/100Gb/200Gb Ethernet 1751' if=em3 drv=bnxt_en unused=igb_uio,vfio-pci
0000:19:00.3 'BCM57504 NetXtreme-E 10Gb/25Gb/40Gb/50Gb/100Gb/200Gb Ethernet 1751' if=em4 drv=bnxt_en unused=igb_uio,vfio-pci
0000:51:00.0 'Ethernet Controller E810-C for QSFP 1592' if=eth13 drv=ice unused=igb_uio,vfio-pci
0000:51:00.1 'Ethernet Controller E810-C for QSFP 1592' if=rename8 drv=ice unused=igb_uio,vfio-pci

41 Aceleração vRAN (Intel ACC100/VRB1/VRB2)

À medida que os provedores de serviços de comunicação migram de redes 4G para 5G, muitos estão adotando arquiteturas de rede de acesso via rádio virtualizada (vRAN) para maior capacidade de canal e implantação mais fácil de serviços e aplicações baseados em borda. As soluções vRAN estão idealmente localizadas para fornecer serviços de baixa latência com a flexibilidade de aumentar ou diminuir a capacidade com base no volume de tráfego em tempo real e na demanda na rede.

Uma das cargas de trabalho 4G e 5G que mais consomem processamento é a camada 1 de RAN (L1) FEC, que resolve erros de transmissão de dados em canais de comunicação não confiáveis ou ruidosos. A tecnologia FEC detecta e corrige um número limitado de erros em dados 4G ou 5G, eliminando a necessidade de retransmissão. Como a transação de aceleração FEC não contém informações de estado da célula, ela pode ser facilmente virtualizada, permitindo benefícios de agrupamento e fácil migração de células.

Historicamente, a Intel fornecia a placa aceleradora vRAN ACC100 para executar rapidamente algoritmos FEC de Camada 1, liberando poder de processamento do host para a CPU principal. Desde então, a Intel integrou essa tecnologia diretamente em CPUs mais novas, começando com Sapphire Rapids, sob o nome Intel vRAN Boost (VRB). O Intel vRAN Boost atua como um acelerador de descarregamento na própria CPU, eliminando a necessidade de uma placa de hardware separada. Esta seção detalha a configuração do SUSE Telco Cloud para que as cargas de trabalho aproveitem o ACC100 ou o Intel vRAN Boost.

41.1 Parâmetros kernel

Para habilitar a aceleração vRAN, precisamos habilitar os seguintes parâmetros do kernel (se ainda não estiverem presentes):

parametervaluedescrição

iommu

pt

Esta opção habilita o uso de vfio para as interfaces DPDK.

intel_iommu or amd_iommu

on

Esta opção habilita o uso de vfio para VFs.

Modifique o arquivo GRUB /etc/default/grub para adicioná-los à linha de comando do kernel:

GRUB_CMDLINE_LINUX="BOOT_IMAGE=/boot/vmlinuz-6.4.0-9-rt root=UUID=77b713de-5cc7-4d4c-8fc6-f5eca0a43cf9 skew_tick=1 rd.timeout=60 rd.retry=45 console=ttyS1,115200 console=tty0 default_hugepagesz=1G hugepagesz=1G hugepages=40 hugepagesz=2M hugepages=0 ignition.platform.id=openstack net.ifnames=1 intel_iommu=on iommu=pt irqaffinity=0,31,32,63 isolcpus=domain,nohz,managed_irq,1-30,33-62 nohz_full=1-30,33-62 nohz=on mce=off nosoftlockup nowatchdog nmi_watchdog=0 quiet rcu_nocb_poll rcu_nocbs=1-30,33-62 rcupdate.rcu_cpu_stall_suppress=1 rcupdate.rcu_expedited=1 rcupdate.rcu_normal_after_boot=1 rcupdate.rcu_task_stall_timeout=0 rcutree.kthread_prio=99 security=selinux selinux=1 idle=poll"

Atualize a configuração do GRUB e reinicie o sistema para aplicar as alterações:

$ transactional-update grub.cfg
$ reboot

Para verificar se os parâmetros foram aplicados após a reinicialização, verifique a linha de comando:

$ cat /proc/cmdline

41.2 Configure SR-IOV em aceleradores FEC

  • Carregue o módulo do kernel vfio-pci para habilitar a aceleração vRAN. O primeiro argumento indica o módulo vfio-pci para suportar SR-IOV, e o segundo argumento impede que o dispositivo PCI entre em um estado de baixo consumo de energia quando estiver ocioso.

$ modprobe vfio-pci enable_sriov=1 disable_idle_d3=1
  • Recupere o endereço do dispositivo PCI do acelerador FEC:

$ lspci -DPPnn | grep -i acc
0000:07:00.0 Processing accelerators [1200]: Intel Corporation Device [8086:57c2]
0000:0a:00.0 Processing accelerators [1200]: Intel Corporation Device [8086:57c2]
  • Vincule a interface física (PF) ao driver vfio-pci:

$ dpdk-devbind.py -b vfio-pci 0000:07:00.0
  • Crie as funções virtuais (VFs) a partir da interface física (PF).

Verifique a capacidade máxima VF da placa aceleradora. Em seguida, configure a placa para expor o número desejado de VFs, sem exceder o número máximo. Neste exemplo, configuramos a placa para sua capacidade total de 16 VFs:

$ cat /sys/bus/pci/devices/0000:07:00.0/sriov_totalvfs
64
$ echo 16 > /sys/bus/pci/devices/0000:07:00.0/sriov_numvfs
  • Configure a placa aceleradora e suas funções virtuais com um arquivo de controle 4G ou 5G, selecionando o tipo de dispositivo vRAN Boost correto dependendo da geração exata do processador Intel: VRB1 (anteriormente conhecido como ACC200) se for Sapphire Rapids Edge Enhanced (SPR-EE), VRB2 para Granite Rapids-D (GNR-D). Um token de VF exclusivo (UUID) deve ser fornecido (a carga de trabalho consumirá este token de VF para utilizar os recursos de aceleração FEC da placa).

Atenção
Atenção

Descontinuação a partir de pf-bb-config: a nova versão do RPM que oferece suporte ao tipo de dispositivo VRB2 agora está instalando os arquivos de exemplo de configuração no local /usr/share/pf-bb-config/examples; o caminho antigo /opt/pf-bb-config/ ainda é suportado, mas será removido em versões futuras. Por favor, atualize seus scripts e documentação para refletir o novo caminho (como feito no exemplo abaixo).

$ pf_bb_config VRB2 -c /usr/share/pf-bb-config/examples/vrb2/vrb2_config_vf_5g.cfg -f /usr/share/pf-bb-config/examples/vrb2/srs_fft_windows_coefficient.bin -v 00112233-4455-6677-8899-aabbccddeeff -p 0000:07:00.0
== pf_bb_config Version 25.11 ==
VRB2 PF [0000:07:00.0] configuration complete!
Log file = /var/log/pf_bb_cfg_0000:07:00.0.log
  • Verifique as novas VFs criadas a partir da PF FEC. Observe que as VFs obtiveram o ID de dispositivo 0d5d. Esta informação é necessária na próxima etapa para expor essas VFs como recurso do Kubernetes:

$ # dpdk-devbind.py -s | grep -A18 Baseband
Baseband devices using DPDK-compatible driver
=============================================
0000:07:00.0 'Device 57c2' numa_node=0 drv=vfio-pci unused=
0000:07:00.1 'Device 57c3' numa_node=0 drv=vfio-pci unused=
0000:07:00.2 'Device 57c3' numa_node=0 drv=vfio-pci unused=
0000:07:00.3 'Device 57c3' numa_node=0 drv=vfio-pci unused=
0000:07:00.4 'Device 57c3' numa_node=0 drv=vfio-pci unused=
0000:07:00.5 'Device 57c3' numa_node=0 drv=vfio-pci unused=
0000:07:00.6 'Device 57c3' numa_node=0 drv=vfio-pci unused=
0000:07:00.7 'Device 57c3' numa_node=0 drv=vfio-pci unused=
0000:07:01.0 'Device 57c3' numa_node=0 drv=vfio-pci unused=
0000:07:01.1 'Device 57c3' numa_node=0 drv=vfio-pci unused=
0000:07:01.2 'Device 57c3' numa_node=0 drv=vfio-pci unused=
0000:07:01.3 'Device 57c3' numa_node=0 drv=vfio-pci unused=
0000:07:01.4 'Device 57c3' numa_node=0 drv=vfio-pci unused=
0000:07:01.5 'Device 57c3' numa_node=0 drv=vfio-pci unused=
0000:07:01.6 'Device 57c3' numa_node=0 drv=vfio-pci unused=
0000:07:01.7 'Device 57c3' numa_node=0 drv=vfio-pci unused=
0000:07:02.0 'Device 57c3' numa_node=0 drv=vfio-pci unused=
--
Other Baseband devices
======================
0000:0a:00.0 'Device 57c2' numa_node=0 unused=vfio-pci

Other Crypto devices
====================
0000:01:00.0 '420xx Series QAT 4946' numa_node=0 unused=vfio-pci
0000:03:00.0 'Device 2714' numa_node=0 unused=vfio-pci

DMA devices using kernel driver
===============================
0000:00:01.0 'Device 11fb' numa_node=0 drv=idxd unused=vfio-pci

Other Eventdev devices
======================
0000:03:00.0 'Device 2714' numa_node=0 unused=vfio-pci

No 'Mempool' devices detected
=============================

41.3 Configurar o Kubernetes para Aceleração FEC

A etapa final é expor as VFs ao Kubernetes com a ajuda do plugin de dispositivo SR-IOV. Crie um ConfigMap usando o deviceID das VFs coletado na etapa anterior e instale o plugin de dispositivo SR-IOV. Assim que os nós do Kubernetes exibirem as VFs FEC como recursos Allocatable, o cluster estará pronto para que as cargas de trabalho aproveitem a aceleração FEC.

Siga as etapas da Opção 1 no capítulo Capítulo 39, SR-IOV. O SRIOV Network Operator não é aplicável para o Acelerador FEC, portanto, a Opção 2 não é aplicável.

42 Huge pages

Quando um processo usa RAM, o CPU marca-o como usado por esse processo. Para eficiência, o CPU aloca RAM em blocos; 4K bytes é o valor padrão em muitas plataformas. Esses blocos são chamados de páginas. As páginas podem ser trocadas para o disco, etc.

Como o espaço de endereçamento do processo é virtual, o CPU e o sistema operacional precisam lembrar quais páginas pertencem a qual processo e onde cada página está armazenada. Quanto maior o número de páginas, mais longa é a busca pelo mapeamento de memória. Quando um processo usa 1 GB de memória, isso representa 262144 entradas para consultar (1 GB / 4 K). Se uma entrada da tabela de páginas consome 8 bytes, isso representa 2 MB (262144 * 8) para consultar.

A maioria das arquiteturas CPU atuais suportam páginas maiores que o padrão, o que dá ao CPU/OS menos entradas para consultar.

  • Parâmetros kernel

Para habilitar as huge pages, devemos adicionar os seguintes parâmetros do kernel. Neste exemplo, configuramos 40 páginas de 1G, embora o tamanho das huge pages e o número exato devam ser adaptados aos requisitos de memória da sua aplicação:

parametervaluedescrição

hugepagesz

1G

Esta opção permite definir o tamanho das huge pages para 1 G

hugepages

40

Este é o número de huge pages definido anteriormente

default_hugepagesz

1G

Este é o valor padrão para obter as huge pages

Modifique o arquivo GRUB /etc/default/grub para adicionar estes parâmetros em GRUB_CMDLINE_LINUX:

default_hugepagesz=1G hugepagesz=1G hugepages=40 hugepagesz=2M hugepages=0

Atualize a configuração do GRUB e reinicie o sistema para aplicar as alterações:

$ transactional-update grub.cfg
$ reboot

Para validar que os parâmetros foram aplicados após a reinicialização, você pode verificar a linha de comando:

$ cat /proc/cmdline
  • Usando huge pages

Para usar as huge pages, precisamos montá-las:

$ mkdir -p /hugepages
$ mount -t hugetlbfs nodev /hugepages

Implante uma carga de trabalho do Kubernetes, criando os recursos e os volumes:

...
 resources:
   requests:
     memory: "24Gi"
     hugepages-1Gi: 16Gi
     intel.com/intel_sriov_oru: '4'
   limits:
     memory: "24Gi"
     hugepages-1Gi: 16Gi
     intel.com/intel_sriov_oru: '4'
...
...
volumeMounts:
  - name: hugepage
    mountPath: /hugepages
...
volumes:
  - name: hugepage
    emptyDir:
      medium: HugePages
...

43 Agendamento com reconhecimento de NUMA

O acesso não uniforme à memória ou a arquitetura de memória não uniforme (NUMA) é um design de memória física usado na arquitetura SMP (multiprocessadores), em que o tempo de acesso à memória depende da sua localização em relação a um processador. Sob NUMA, um processador pode acessar sua própria memória local mais rapidamente do que a memória não local, ou seja, memória local para outro processador ou memória compartilhada entre processadores.

43.1 Identificando nós NUMA

Para identificar os nós NUMA, em seu sistema use o seguinte comando:

$ lscpu | grep NUMA
NUMA node(s):                       1
NUMA node0 CPU(s):                  0-63
Nota
Nota

Para este exemplo, temos apenas um nó NUMA mostrando 64 CPUs.

NUMA precisa ser habilitado no BIOS. Se dmesg não tiver registros da inicialização NUMA durante a inicialização, as mensagens relacionadas a NUMA no buffer de anel do kernel podem ter sido sobrescritas.

44 Metal LB

MetalLB é uma implementação de balanceador de carga para clusters Kubernetes bare metal, usando protocolos de roteamento padrão como L2 e BGP como protocolos de anúncio. É um balanceador de carga de rede que pode ser usado para expor serviços em um cluster Kubernetes para o mundo exterior devido à necessidade de usar Serviços do Kubernetes do tipo LoadBalancer com bare metal.

Para habilitar MetalLB no cluster RKE2, as seguintes etapas são necessárias:

  • Instale MetalLB usando o seguinte comando:

$ kubectl apply <<EOF -f
apiVersion: helm.cattle.io/v1
kind: HelmChart
metadata:
  name: metallb
  namespace: kube-system
spec:
  chart: oci://registry.suse.com/edge/charts/metallb
  targetNamespace: metallb-system
  version: 306.0.2+up0.15.3
  createNamespace: true
---
apiVersion: helm.cattle.io/v1
kind: HelmChart
metadata:
  name: endpoint-copier-operator
  namespace: kube-system
spec:
  chart: oci://registry.suse.com/edge/charts/endpoint-copier-operator
  targetNamespace: endpoint-copier-operator
  version: 306.0.1+up0.3.0
  createNamespace: true
EOF
  • Crie as configurações de IpAddressPool e L2advertisement:

apiVersion: metallb.io/v1beta1
kind: IPAddressPool
metadata:
  name: kubernetes-vip-ip-pool
  namespace: metallb-system
spec:
  addresses:
    - 10.168.200.98/32
  serviceAllocation:
    priority: 100
    namespaces:
      - default
---
apiVersion: metallb.io/v1beta1
kind: L2Advertisement
metadata:
  name: ip-pool-l2-adv
  namespace: metallb-system
spec:
  ipAddressPools:
    - kubernetes-vip-ip-pool
  • Crie o serviço de endpoint para expor o VIP:

apiVersion: v1
kind: Service
metadata:
  name: kubernetes-vip
  namespace: default
spec:
  internalTrafficPolicy: Cluster
  ipFamilies:
  - IPv4
  ipFamilyPolicy: SingleStack
  ports:
  - name: rke2-api
    port: 9345
    protocol: TCP
    targetPort: 9345
  - name: k8s-api
    port: 6443
    protocol: TCP
    targetPort: 6443
  sessionAffinity: None
  type: LoadBalancer
  • Verifique se o VIP foi criado e se os pods MetalLB estão em execução:

$ kubectl get svc -n default
$ kubectl get pods -n default

45 Configuração de registro privado

Containerd pode ser configurado para se conectar a registros privados e usá-los para extrair imagens privadas em cada nó.

Na inicialização, RKE2 verifica se um arquivo registries.yaml existe em /etc/rancher/rke2/ e instrui containerd a usar quaisquer registros definidos no arquivo. Se você deseja usar um registro privado, crie este arquivo como root em cada nó que usará o registro.

Para adicionar o registro privado, crie o arquivo /etc/rancher/rke2/registries.yaml com o seguinte conteúdo:

mirrors:
  docker.io:
    endpoint:
      - "https://registry.example.com:5000"
configs:
  "registry.example.com:5000":
    auth:
      username: xxxxxx # this is the registry username
      password: xxxxxx # this is the registry password
    tls:
      cert_file:            # path to the cert file used to authenticate to the registry
      key_file:             # path to the key file for the certificate used to authenticate to the registry
      ca_file:              # path to the ca file used to verify the registry's certificate
      insecure_skip_verify: # may be set to true to skip verifying the registry's certificate

ou sem autenticação:

mirrors:
  docker.io:
    endpoint:
      - "https://registry.example.com:5000"
configs:
  "registry.example.com:5000":
    tls:
      cert_file:            # path to the cert file used to authenticate to the registry
      key_file:             # path to the key file for the certificate used to authenticate to the registry
      ca_file:              # path to the ca file used to verify the registry's certificate
      insecure_skip_verify: # may be set to true to skip verifying the registry's certificate

Para que as alterações no registro entrem em vigor, você precisa realizar a configuração deste arquivo antes de iniciar o RKE2 no nó ou reiniciar o RKE2 em cada nó configurado.

Nota
Nota

Para obter mais informações sobre isso, verifique configuração do registro do containerd rke2.

46 Precision Time Protocol

O Precision Time Protocol (PTP) é um protocolo de rede desenvolvido pelo Institute of Electrical and Electronics Engineers (IEEE) para permitir a sincronização de tempo em sub-microssegundos em uma rede de computadores. Desde a sua criação e há algumas décadas, o PTP tem sido usado em muitas indústrias. Recentemente, ele tem visto uma adoção crescente nas redes de telecomunicações como um elemento vital para redes 5G. Embora seja um protocolo relativamente simples, sua configuração pode mudar significativamente dependendo da aplicação. Por esse motivo, vários perfis foram definidos e padronizados.

Nesta seção, apenas perfis específicos de telecomunicações serão abordados. Consequentemente, a capacidade de carimbo de data/hora e um relógio de hardware PTP (PHC) na NIC serão assumidos. Atualmente, todos os adaptadores de rede de nível de telecomunicações vêm com suporte a PTP em hardware, mas você pode verificar tais capacidades com o seguinte comando:

# ethtool -T p1p1
Time stamping parameters for p1p1:
Capabilities:
        hardware-transmit
        software-transmit
        hardware-receive
        software-receive
        software-system-clock
        hardware-raw-clock
PTP Hardware Clock: 0
Hardware Transmit Timestamp Modes:
        off
        on
Hardware Receive Filter Modes:
        none
        all

Substitua p1p1 pelo nome da interface a ser usada para PTP.

As seções a seguir fornecerão orientações sobre como instalar e configurar o PTP especificamente no SUSE Telco Cloud, mas espera-se familiaridade com conceitos básicos de PTP. Para uma breve visão geral do PTP e da implementação incluída no SUSE Telco Cloud, consulte a documentação do SLES Precision Time Protocol.

46.1 Instalar componentes de software PTP

No SUSE Telco Cloud, a implementação do PTP é fornecida pelo pacote linuxptp, que inclui dois componentes:

  • ptp4l: um daemon que controla o PHC na NIC e executa o protocolo PTP

  • phc2sys: um daemon que mantém o relógio do sistema sincronizado com o PHC sincronizado por PTP na NIC

Ambos os daemons são necessários para que a sincronização do sistema funcione plenamente e devem ser configurados corretamente de acordo com sua configuração. Isso é abordado em Seção 46.2, “Configure o PTP para implantações de telecomunicações”.

A maneira mais fácil e melhor de integrar o PTP em seu cluster downstream é adicionar o pacote linuxptp em packageList no arquivo de definição do Edge Image Builder (EIB). Dessa forma, o software do plano de controle PTP será instalado automaticamente durante o provisionamento do cluster. Veja a documentação do EIB (Seção 5.3.6, “Configurando pacotes RPM”) para obter mais informações sobre a instalação de pacotes.

Abaixo, encontre um exemplo de manifesto EIB com linuxptp:

apiVersion: 1.3
image:
  imageType: RAW
  arch: x86_64
  baseImage: SL-Micro.x86_64-6.2-Base-RT-GM.raw
  outputImageName: eibimage-slmicrort-telco.raw
operatingSystem:
  time:
    timezone: America/New_York
  kernelArgs:
    - ignition.platform.id=openstack
  systemd:
    disable:
      - rebootmgr
      - transactional-update.timer
      - transactional-update-cleanup.timer
      - fstrim
      - time-sync.target
    enable:
      - ptp4l
      - phc2sys
  users:
    - username: root
      encryptedPassword: $ROOT_PASSWORD
  packages:
    packageList:
      - jq            # Non Telco specific - category: testing/utils
      - dpdk          # TelCo Core-Network UserPlane (5G UPF) and RAN UserPlane (gNB: DU and CU-UP) - category: runtime
      - dpdk-tools    # TelCo Core-Network UserPlane (5G UPF) and RAN UserPlane (gNB: DU and CU-UP) - category: testing/utils
      - libdpdk-25    # TelCo Core-Network UserPlane (5G UPF) and RAN UserPlane (gNB: DU and CU-UP) - category: runtime
      - pf-bb-config  # TelCo RAN (gNB: DU) - category: config.
      - open-iscsi    # Non Telco specific (required by SUSE Storage/Longhorn) - category: runtime
      - tuned         # Non Telco specific (linux tuning) - category: config.
      - cpupower      # Non Telco specific (linux tuning - CPU power related settings) - category: config.
      - rt-tests      # Non Telco specific (RT scheduler-latency testing) - category: testing/utils
      - linuxptp      # TelCo RAN; time sync (gNB: DU) - category: runtime
      - synce4l       # TelCo RAN; time sync (gNN: DU) - category: runtime
      - pciutils      # Non Telco specific (provides "lspci" command) - category: testing/utils
      - numactl       # Non Telco specific (provides "numatcl" command) - category: testing/utils
    sccRegistrationCode: $SCC_REGISTRATION_CODE
Nota
Nota

O pacote linuxptp incluído no SUSE Telco Cloud não habilita ptp4l e phc2sys por padrão. Se os arquivos de configuração específicos do sistema forem implantados no momento do provisionamento (veja Seção 46.3, “Integração com Cluster API”), eles deverão ser habilitados. Faça isso adicionando-os à seção systemd do manifesto, como no exemplo acima.

Siga o processo habitual para criar a imagem conforme descrito na Documentação do EIB (Seção 5.4, “Criando a imagem”) e use-a para implantar seu cluster. Se você é novo no EIB, comece pelo Capítulo 12, Edge Image Builder em vez disso.

46.2 Configure o PTP para implantações de telecomunicações

Muitas aplicações de telecomunicações exigem sincronização rigorosa de fase e tempo com pouco desvio, o que resultou na definição de dois perfis orientados a telecomunicações: o ITU-T G.8275.1 e o ITU-T G.8275.2. Ambos possuem uma alta taxa de mensagens de sincronização e outras características distintas, como o uso de um algoritmo Best Master Clock (BMCA) alternativo. Tal comportamento exige configurações específicas no arquivo de configuração consumido pelo ptp4l, fornecido nas seções a seguir como referência.

Nota
Nota
  • Ambas as seções cobrem apenas o caso de um relógio comum na configuração de Receptor de Tempo.

  • Qualquer perfil desse tipo deve ser usado em uma infraestrutura PTP bem planejada.

  • Sua rede PTP específica pode exigir ajustes adicionais de configuração; certifique-se de revisar e adaptar os exemplos fornecidos, se necessário.

46.2.1 Perfil PTP ITU-T G.8275.1

O perfil G.8275.1 apresenta as seguintes características:

  • Executa diretamente sobre Ethernet e requer suporte total da rede (nós/switches adjacentes devem suportar PTP).

  • A configuração de domínio padrão é 24.

  • A comparação de conjuntos de dados é baseada no algoritmo G.8275.x e seus valores localPriority após priority2.

Copie o seguinte conteúdo para um arquivo chamado /etc/ptp4l-G.8275.1.conf:

# Telecom G.8275.1 example configuration
[global]
domainNumber                    24
priority2            255
dataset_comparison              G.8275.x
G.8275.portDS.localPriority     128
G.8275.defaultDS.localPriority  128
maxStepsRemoved                 255
logAnnounceInterval             -3
logSyncInterval                 -4
logMinDelayReqInterval          -4
announceReceiptTimeout        3
serverOnly                      0
ptp_dst_mac                     01:80:C2:00:00:0E
network_transport               L2

Uma vez que o arquivo tenha sido criado, ele deve ser referenciado em /etc/sysconfig/ptp4l para que o daemon inicie corretamente. Isso pode ser feito alterando a linha OPTIONS= para:

OPTIONS="-f /etc/ptp4l-G.8275.1.conf -i $IFNAME --message_tag ptp-8275.1"

Mais precisamente:

  • -f requer o nome do arquivo de configuração a ser usado, sendo /etc/ptp4l-G.8275.1.conf o valor utilizado neste caso.

  • O -i requer o nome da interface a ser usada; substitua $IFNAME por um nome de interface real.

  • O --message_tag permite identificar melhor a saída do ptp4l nos logs do sistema e é opcional.

Uma vez que as etapas acima estejam concluídas, o daemon ptp4l deve ser (re)iniciado:

# systemctl restart ptp4l

Verifique o status da sincronização observando os logs com:

# journalctl -e -u ptp4l

46.2.2 Arquivo de controle PTP ITU-T G.8275.2

O arquivo de controle G.8275.2 tem as seguintes especificidades:

  • Executa sobre IP e não requer suporte total da rede (nós/switches adjacentes podem não suportar PTP).

  • A configuração de domínio padrão é 44.

  • A comparação de conjuntos de dados é baseada no algoritmo G.8275.x e seus valores localPriority após priority2.

Copie o seguinte conteúdo para um arquivo chamado /etc/ptp4l-G.8275.2.conf:

# Telecom G.8275.2 example configuration
[global]
domainNumber                    44
priority2            255
dataset_comparison              G.8275.x
G.8275.portDS.localPriority     128
G.8275.defaultDS.localPriority  128
maxStepsRemoved                 255
logAnnounceInterval             0
serverOnly                      0
hybrid_e2e                      1
inhibit_multicast_service       1
unicast_listen                  1
unicast_req_duration            60
logSyncInterval                 -5
logMinDelayReqInterval          -4
announceReceiptTimeout        2
#
# Customize the following for slave operation:
#
[unicast_master_table]
table_id                        1
logQueryInterval                2
UDPv4                           $PEER_IP_ADDRESS
[$IFNAME]
unicast_master_table            1

Certifique-se de substituir os seguintes espaços reservados:

  • $PEER_IP_ADDRESS - o endereço IP do próximo nó PTP com o qual se comunicar, como o master ou boundary clock que fornecerá a sincronização.

  • $IFNAME - informa a ptp4l qual interface usar para PTP.

Uma vez que o arquivo tenha sido criado, ele deve ser referenciado, juntamente com o nome da interface a ser usada para PTP, em /etc/sysconfig/ptp4l para que o daemon inicie corretamente. Isso pode ser feito alterando a linha OPTIONS= para:

OPTIONS="-f /etc/ptp4l-G.8275.2.conf --message_tag ptp-8275.2"

Mais precisamente:

  • O -f requer o nome do arquivo de configuração a ser usado. Neste caso, é /etc/ptp4l-G.8275.2.conf.

  • O --message_tag permite identificar melhor a saída do ptp4l nos logs do sistema e é opcional.

Uma vez que as etapas acima estejam concluídas, o daemon ptp4l deve ser (re)iniciado:

# systemctl restart ptp4l

Verifique o status da sincronização observando os logs com:

# journalctl -e -u ptp4l

46.2.3 Configuração PTP de um Boundary Clock

As seções anteriores abordaram a configuração de um relógio comum, mas implantações de Telco podem exigir que o nó atue como um Boundary Clock. Em tal cenário, o tempo de referência deve ser propagado de um Grand Master para um ou mais Time Receivers downstream, o que requer uma NIC com duas ou mais portas. Neste caso, uma porta assumirá a função de Time Receiver, que está conduzindo as atualizações do PTP Hardware Clock (PHC) na NIC, enquanto as restantes funcionarão como Time Transmitters. Uma única instância de ptp4l é suficiente para uma única NIC multiporta, mas cada interface de kernel envolvida na distribuição de tempo deve ser fornecida, como parte de sua configuração. Por exemplo, atualize o arquivo /etc/sysconfig/ptp4l para incluir quatro portas, apenas substitua as variáveis pelos nomes reais das interfaces ou ajuste conforme necessário:

OPTIONS="-f /etc/ptp4l-G.8275.1.conf --message_tag ptp-8275.1 -i $IFNAME1 -i $IFNAME2 -i $IFNAME3 -i $IFNAME4"
Nota
Nota

Não há necessidade de definir clock_type como BC, pois isso será automaticamente implícito se mais de uma porta for fornecida.

Uma vez feito, o daemon ptp4l pode ser (re)iniciado com:

# systemctl restart ptp4l

Sem qualquer configuração de porta específica, o ptp4l executará o BMCA para determinar através de qual porta o GM pode ser alcançado. Se uma configuração estática for preferida, anexe uma seção para cada porta com a função prescrita no arquivo de configuração. Por exemplo:

# Telecom G.8275.1 example configuration
[global]
domainNumber                    24
priority2                       255
dataset_comparison              G.8275.x
G.8275.portDS.localPriority     128
G.8275.defaultDS.localPriority  128
maxStepsRemoved                 255
logAnnounceInterval             -3
logSyncInterval                 -4
logMinDelayReqInterval          -4
announceReceiptTimeout          3
ptp_dst_mac                     01:80:C2:00:00:0E
network_transport               L2

[$IFNAME1]
# Time Receiver by default

[$IFNAME2]
serverOnly                      1

[$IFNAME3]
serverOnly                      1

[$IFNAME4]
serverOnly                      1

No entanto, certifique-se de determinar a conexão correta com o GM antes de iniciar o daemon.

46.2.4 Sincronização do relógio do sistema a partir do PTP

É importante ter em mente que o PTP funciona sincronizando os relógios de hardware locais da NIC. Isso não alinha automaticamente o relógio do sistema com o GM, já que o relógio do sistema é derivado de um relógio de hardware diferente. Para manter o relógio do sistema sincronizado com o PTP, o phc2sys deve ser executado. Recomenda-se que você conclua totalmente a configuração de ptp4l antes de passar para phc2sys. phc2sys não requer um arquivo de configuração por padrão e seus parâmetros de execução podem ser controlados exclusivamente através da variável OPTIONS= presente em /etc/sysconfig/ptp4l, de maneira semelhante a ptp4l:

OPTIONS="-s $IFNAME -w"

Onde $IFNAME é o nome da interface já configurada no ptp4l que será usada como fonte para o relógio do sistema. Isso é usado para identificar o PHC de origem.

No entanto, se um perfil PTP específico ou número de domínio for usado, pode ser necessário fornecer ao phc2sys um arquivo de configuração de acordo com aquele fornecido ao ptp4l. Na maioria dos casos, ele também pode ser reutilizado diretamente com o phc2sys:

OPTIONS="-f /etc/ptp4l-G.8275.1.conf -s $IFNAME -w"

46.3 Integração com Cluster API

Sempre que um cluster é implantado por meio de um cluster de gerenciamento e provisionamento de rede direcionado, tanto o arquivo de configuração quanto as duas variáveis de configuração em /etc/sysconfig podem ser implantados no host no momento do provisionamento. Abaixo está um trecho de uma definição de cluster, com foco em um objeto RKE2ControlPlane modificado que implanta o mesmo arquivo de configuração G.8275.1 em todos os hosts:

apiVersion: controlplane.cluster.x-k8s.io/v1beta2
kind: RKE2ControlPlane
metadata:
  name: single-node-cluster
  namespace: default
spec:
  infrastructureRef:
    apiGroup: infrastructure.cluster.x-k8s.io
    kind: Metal3MachineTemplate
    name: single-node-cluster-controlplane
  replicas: 1
  version: ${RKE2_VERSION}
  rolloutStrategy:
    type: "RollingUpdate"
    rollingUpdate:
      maxSurge: 0
  registrationMethod: "control-plane-endpoint"
  serverConfig:
    cni: canal
  agentConfig:
    format: ignition
    cisProfile: cis
    additionalUserData:
      config: |
        variant: fcos
        version: 1.4.0
        systemd:
          units:
            - name: rke2-preinstall.service
              enabled: true
              contents: |
                [Unit]
                Description=rke2-preinstall
                Wants=network-online.target
                Before=rke2-install.service
                ConditionPathExists=!/run/cluster-api/bootstrap-success.complete
                [Service]
                Type=oneshot
                User=root
                ExecStartPre=/bin/sh -c "mount -L config-2 /mnt"
                ExecStart=/bin/sh -c "sed -i \"s/BAREMETALHOST_UUID/$(jq -r .uuid /mnt/openstack/latest/meta_data.json)/\" /etc/rancher/rke2/config.yaml"
                ExecStart=/bin/sh -c "echo \"node-name: $(jq -r .name /mnt/openstack/latest/meta_data.json)\" >> /etc/rancher/rke2/config.yaml"
                ExecStart=/bin/sh -c "echo \"node-label:\" >> /etc/rancher/rke2/config.yaml"
                ExecStart=/bin/sh -c "echo \"  - metal3.io/uuid=$(jq -r .uuid /mnt/openstack/latest/meta_data.json)\" >> /etc/rancher/rke2/config.yaml"
                ExecStartPost=/bin/sh -c "umount /mnt"
                [Install]
                WantedBy=multi-user.target
        storage:
          files:
            - path: /etc/ptp4l-G.8275.1.conf
              overwrite: true
              contents:
                inline: |
                  # Telecom G.8275.1 example configuration
                  [global]
                  domainNumber                    24
                  priority2                       255
                  dataset_comparison              G.8275.x
                  G.8275.portDS.localPriority     128
                  G.8275.defaultDS.localPriority  128
                  maxStepsRemoved                 255
                  logAnnounceInterval             -3
                  logSyncInterval                 -4
                  logMinDelayReqInterval          -4
                  announceReceiptTimeout          3
                  serverOnly                      0
                  ptp_dst_mac                     01:80:C2:00:00:0E
                  network_transport               L2
              mode: 0644
              user:
                name: root
              group:
                name: root
            - path: /etc/sysconfig/ptp4l
              overwrite: true
              contents:
                inline: |
                  ## Path:           Network/LinuxPTP
                  ## Description:    Precision Time Protocol (PTP): ptp4l settings
                  ## Type:           string
                  ## Default:        "-i eth0 -f /etc/ptp4l.conf"
                  ## ServiceRestart: ptp4l
                  #
                  # Arguments when starting ptp4l(8).
                  #
                  OPTIONS="-f /etc/ptp4l-G.8275.1.conf -i $IFNAME --message_tag ptp-8275.1"
              mode: 0644
              user:
                name: root
              group:
                name: root
            - path: /etc/sysconfig/phc2sys
              overwrite: true
              contents:
                inline: |
                  ## Path:           Network/LinuxPTP
                  ## Description:    Precision Time Protocol (PTP): phc2sys settings
                  ## Type:           string
                  ## Default:        "-s eth0 -w"
                  ## ServiceRestart: phc2sys
                  #
                  # Arguments when starting phc2sys(8).
                  #
                  OPTIONS="-s $IFNAME -w"
              mode: 0644
              user:
                name: root
              group:
                name: root
    kubelet:
      extraArgs:
        - provider-id=metal3://BAREMETALHOST_UUID
    nodeName: "localhost.localdomain"

Além de outras variáveis, a definição acima deve ser completada com o nome da interface e com os outros objetos do Cluster API, conforme descrito em Parte VII, “Provisionamento de rede direcionado totalmente automatizado”.

Nota
Nota
  • Essa abordagem é conveniente apenas se o hardware no cluster for uniforme e a mesma configuração for necessária em todos os hosts, incluindo o nome da interface.

  • Abordagens alternativas são possíveis e serão abordadas em versões futuras.

Neste ponto, seus hosts devem ter uma pilha PTP funcionando e em execução e começarão a negociar sua função PTP.

46.4 PTP em plataformas Intel Granite Rapids-D

O SUSE Telco Cloud suporta temporização precisa em uma variedade de plataformas diferentes, incluindo os projetos mais recentes baseados em Intel Granite Rapids-D (GNR-D). Esses novos servidores normalmente incluem um controlador Ethernet de alta velocidade integrado e uma ou mais placas adicionais com um controlador Ethernet para portas extras. Ao contrário das gerações de plataforma anteriores, eles também são equipados com um DPLL dedicado que permite o roteamento dos sinais de temporização através do sistema e das diferentes NIC, e não requer mais cabeamento externo. A implantação geral é, portanto, simplificada, mas etapas e componentes de software específicos são necessários, como o DPLL no momento da inicialização e a configuração do sinal interno.

Antes de seguir as etapas de configuração, baixe e instale o driver de kernel mais recente para os Intel 800 Series Network Devices a partir do site da Intel. Selecione o arquivo zip contendo os \"ice_RPM_Files\" e descompacte o arquivo, então instale o RPM ice-kmp-default-*sles16sp0.x86_64.rpm contido nele, por exemplo, o arquivo ice-kmp-default-2.4.5_k6.12.0_160000.5-1.sles16sp0.x86_64.rpm:

# transactional-update pkg install ice-kmp-default-2.4.5_k6.12.0_160000.5-1.sles16sp0.x86_64.rpm

Reinicie o servidor para tornar a alteração persistente e efetiva.

Nota
Nota
  • Um sistema Dell PowerEdge XR8720t será usado como sistema de referência nos exemplos; as interfaces de kernel e a configuração de porta podem ser diferentes em um servidor GNR-D diferente.

  • Assume-se uma implantação de Telco e o perfil Telco G.8275.1 é usado nas seções a seguir para PTP.

46.4.1 PTP Boundary Clock

Esta seção descreve o processo de configuração de um Boundary Clock (BC) em um sistema GNR-D, onde uma porta na NIC integrada recebe os timestamps PTP de um GM e todas as portas restantes no sistema atuam como Transmissores de Tempo para outros nós da rede.

Nota
Nota

A configuração descrita aqui é completamente estática. Se o GM ficar indisponível, a sincronização downstream dependerá exclusivamente das capacidades de holdover do host; nenhuma alternância automática para uma fonte diferente de referência de tempo será realizada.

Para habilitar o comportamento de BC, execute as seguintes etapas na mesma ordem toda vez que o sistema for inicializado:

  1. Verifique se os dispositivos PTP esperados que controlam os PHCs estão presentes:

    # ls -l /sys/class/ptp/
    total 0
    lrwxrwxrwx. 1 root root 0 Apr 27 20:21 ptp1 -> ../../devices/pci0000:12/0000:12:04.0/0000:13:00.0/ptp/ptp1
    lrwxrwxrwx. 1 root root 0 Apr 27 20:21 ptp2 -> ../../devices/pci0000:6b/0000:6b:02.0/0000:6c:00.0/ptp/ptp2
    lrwxrwxrwx. 1 root root 0 Apr 27 20:21 ptp3 -> ../../devices/pci0000:6b/0000:6b:06.0/0000:6e:00.0/ptp/ptp3
    Nota
    Nota

    Ajuste os comandos subsequentes de acordo com os nomes reais encontrados no sistema que está sendo configurado.

  2. Identifique o controlador integrado, pois ele exigirá uma configuração específica:

    A saída anterior deve indicar o dispositivo ao qual eles estão vinculados por meio do endereço PCI e você pode usar lspci para consultar o tipo de dispositivo:

    # lspci -s 0000:13:00.0
    13:00.0 Ethernet controller: Intel Corporation Ethernet Connection E825-C for SFP (rev 04)
    # lspci -s 0000:6c:00.0
    6c:00.0 Ethernet controller: Intel Corporation Ethernet Controller E830-CC for SFP
    # lspci -s 0000:6e:00.0
    6e:00.0 Ethernet controller: Intel Corporation Ethernet Controller E830-CC for SFP

    Este servidor específico está equipado com um controlador integrado Intel E825-C e duas placas adicionais E830-CC.

    Alternativamente, você pode encontrar mais informações sobre o controlador consultando a primeira porta de rede do controlador que expõe esse PHC:

    # ls -l /sys/class/ptp/ptp0/device/net/
    total 0
    drwxr-xr-x. 5 root root 0 Apr 30 15:16 em5
    # ethtool -i em5
    driver: ice
    version: 2.4.5
    firmware-version: 4.03 0x80007f91 1.3881.0
    expansion-rom-version:
    bus-info: 0000:13:00.0
    [...]

    Observe que em5 é a primeira porta do controlador Ethernet integrado neste sistema.

  3. Configure os sinais entre o PHC no controlador Ethernet integrado e o DPLL de temporização do sistema:

    1. Deixe o DPLL controlar o clock Ethernet no controlador integrado:

      # echo 4 1 > /sys/class/net/em5/device/tspll_cfg
    2. Habilite um pulso a cada início de segundo (Pulse Per Second, PPS) do PHC para o DPLL através do pino SDP2 (sinal de 1kHz):

      # echo 2 1 > /sys/class/ptp/ptp1/pins/SDP2
      # echo 1 0 0 0 1000000 > /sys/class/ptp/ptp1/period
    3. Opcionalmente, o pino SPD0 (sinal de 1Hz) também pode ser habilitado:

      # echo 2 2 > /sys/class/ptp/ptp1/pins/SDP0
      # echo 2 0 0 1 0 > /sys/class/ptp/ptp1/period
    4. Habilite o sinal de 1 PPS para ser propagado do DPLL do sistema de temporização para as placas adicionais:

      # echo 1 1 > /sys/class/ptp/ptp2/pins/SDP1
      # echo 1 1 > /sys/class/ptp/ptp3/pins/SDP1
  4. Execute ts2phc para manter os PHCs das placas adicionais sincronizados com o mesmo timestamp do PHC /dev/ptp1:

    # ts2phc -f ts2phc-aic-all.cfg -s /dev/ptp1

    Consulte Seção 46.4.2.3, “Arquivo de configuração do ts2phc para placas adicionais” para o conteúdo de ts2phc-aic-all.cfg.

  5. Execute uma instância do ptp4l para o controlador integrado (/dev/ptp1):

    # ptp4l -f ptp4l-G.8275.1-nac.conf

    Consulte Seção 46.4.2.1, “Arquivo de configuração do ptp4l para o controlador integrado (/dev/ptp1)” para o conteúdo de ptp4l-G.8275.1-nac.conf.

  6. Execute uma instância do ptp4l para cada placa adicional (/dev/ptp3 e/ou /dev/ptp2):

    # ptp4l -f ptp4l-G.8275.1-aic1.conf
    # ptp4l -f ptp4l-G.8275.1-aic2.conf

    Consulte Seção 46.4.2.2, “Arquivo de configuração do ptp4l para placas adicionais (/dev/ptp2 ou /dev/ptp3)” para o conteúdo dos arquivos de configuração.

    Nota
    Nota

    Para evitar conflitos e permitir a próxima etapa, cada uma dessas instâncias deve usar soquetes de controle e de somente leitura diferentes.

  7. Sincronize os parâmetros de runtime PTP e os valores das instâncias do ptp4l das AICs com o pmc:

    Espera-se que um BC encaminhe não apenas o horário de um GM ao qual está conectado, mas também parâmetros auxiliares, como sua classe de relógio e nível de precisão. Isso acontece automaticamente dentro de um grupo de interfaces gerenciadas pela mesma instância do ptp4l, mas não entre instâncias diferentes do ptp4l, lidando com PHCs e portas diferentes.

    Uma vez que o sistema esteja sincronizado com um GM, consulte a instância do ptp4l no controlador integrado e defina os valores nas instâncias restantes do ptp4l via comandos pmc. Por exemplo:

    # pmc -f /etc/ptp4l-G.8275.1-nac-bmca.conf -u -b 0 'GET PARENT_DATA_SET' | grep gm
                    gm.ClockClass                         8
                    gm.ClockAccuracy                      0xfe
                    gm.OffsetScaledLogVariance            0xffff
    # pmc -f /etc/ptp4l-G.8275.1-nac-bmca.conf -u -b 0 'GET TIME_PROPERTIES_DATA_SET' | grep -v PROPERTIES
                    currentUtcOffset      37
                    leap61                0
                    leap59                0
                    currentUtcOffsetValid 0
                    ptpTimescale          1
                    timeTraceable         0
                    frequencyTraceable    0
                    timeSource            0xa0
    pmc -f /etc/ptp4l-G.8275.1-aic1-static.conf -u -b 0 'SET GRANDMASTER_SETTINGS_NP
                    clockClass              8
                    clockAccuracy           0xfe
                    offsetScaledLogVariance 0xffff
                    currentUtcOffset        37
                    leap61                  0
                    leap59                  0
                    currentUtcOffsetValid   0
                    ptpTimescale            1
                    timeTraceable           0
                    frequencyTraceable      0
                    timeSource              0xa0

    Consulte Seção 46.4.2.4, “Script de encaminhamento de parâmetros GM” para automatizar este processo e evitar etapas manuais.

  8. Opcionalmente, execute o phc2sys para derivar o horário do sistema a partir da sincronização PTP:

    # phc2sys -f /etc/ptp4l-G.8275.1-nac.conf -s /dev/ptp1 -c CLOCK_REALTIME -w

    O arquivo de entrada é o mesmo arquivo de configuração usado para o ptp4l e o controlador integrado. Consulte Seção 46.2.4, “Sincronização do relógio do sistema a partir do PTP” para permitir que o systemd gerencie sua execução.

46.4.2 Arquivos de configuração

Esta seção fornece exemplos de arquivos de configuração e scripts que podem ser usados em conjunto com as etapas acima para configurar rapidamente um BC funcional no GNR-D. Os arquivos de configuração do ptp4l contêm todas as definições necessárias, sem a necessidade de sinalizadores de execução externos adicionais, e são todos baseados no perfil Telco G.8275.1. Mais detalhes são fornecidos para cada arquivo em suas respectivas seções.

46.4.2.1 Arquivo de configuração do ptp4l para o controlador integrado (/dev/ptp1)

[global]
domainNumber                    24
priority2                       255
dataset_comparison              G.8275.x
G.8275.portDS.localPriority     128
G.8275.defaultDS.localPriority  128
maxStepsRemoved                 255
logAnnounceInterval             -3
logSyncInterval                 -4
logMinDelayReqInterval          -4
announceReceiptTimeout          3
ptp_dst_mac                     01:1b:19:00:00:00
network_transport               L2
summary_interval                3
message_tag                     "ptp4l-nac"
uds_address                     /var/run/ptp4l-nac
uds_ro_address                  /var/run/ptp4lro-nac

[em1]

[em2]

[em3]

[em4]

A configuração acima aproveita o BMCA para determinar a função da porta, assumindo que um GM esteja disponível através de uma delas. Se um controle mais rigoroso for necessário, adicione o sinalizador serverOnly sob cada definição de interface. Para mais detalhes, consulte Seção 46.2.3, “Configuração PTP de um Boundary Clock” ou a configuração das placas adicionais abaixo como exemplo. Por uma questão de brevidade, apenas quatro interfaces estão listadas; você precisa ajustar de acordo com seus requisitos.

46.4.2.2 Arquivo de configuração do ptp4l para placas adicionais (/dev/ptp2 ou /dev/ptp3)

# Telecom G.8275.1 example configuration
[global]
domainNumber                    24
priority2                       255
dataset_comparison              G.8275.x
G.8275.portDS.localPriority     250
G.8275.defaultDS.localPriority  250
maxStepsRemoved                 255
logAnnounceInterval             -3
logSyncInterval                 -4
logMinDelayReqInterval          -4
announceReceiptTimeout          3
ptp_dst_mac                     01:1b:19:00:00:00
network_transport               L2
summary_interval                3
message_tag                     "ptp4l-iac1"
uds_address                     /var/run/ptp4l-aic1
uds_ro_address                  /var/run/ptp4lro-aic1

[p1p1]
serverOnly                      1

[p1p2]
serverOnly                      1

[p1p3]
serverOnly                      1

[p1p4]
serverOnly                      1

Por uma questão de brevidade, apenas quatro interfaces estão listadas. Você precisa ajustar de acordo com seus requisitos. Todas as interfaces foram definidas estaticamente para a função TimeTransmitter.

46.4.2.3 Arquivo de configuração do ts2phc para placas adicionais

[global]
use_syslog              0
verbose                 1
logging_level           7
ts2phc.pulsewidth       100000000

[p1p1]
ts2phc.channel          1
ts2phc.extts_polarity   rising
ts2phc.pin_index        1

[p2p1]
ts2phc.channel          1
ts2phc.extts_polarity   rising
ts2phc.pin_index        1

Esta configuração cobre a sincronização de duas placas adicionais (referenciadas por sua primeira porta, p1p1 e p2p1) via o SDP1 em cada controlador.

46.4.2.4 Script de encaminhamento de parâmetros GM

O script abaixo pode ser aproveitado para encaminhar os valores e parâmetros do GM para Time Receivers em portas gerenciadas por instâncias ptp4l diferentes daquela onde o GM reside. Não se esqueça de editar a seção Input variables para ajustar os nomes dos arquivos e executá-lo assim que o sistema estiver sincronizado com um GM.

#!/bin/bash

set -euo pipefail

################## Variáveis de entrada ##################
VERBOSE=1

CONFIG_FILE_NAC=/etc/ptp4l-G.8275.1-nac-bmca.conf
CONFIG_FILES_AICS=(/etc/ptp4l-G.8275.1-aic1-static.conf /etc/ptp4l-G.8275.1-aic2-static.conf)

#####################################################


# Verifique se o sistema está sincronizado com um GM
GM_PRESENT=$(pmc -f ${CONFIG_FILE_NAC} -u -b 0 'GET TIME_STATUS_NP' | awk '/gmPresent/ {print $2}')

if [ \"${GM_PRESENT}\" != \"true\" ]; then
    echo \"Nenhum GM presente, saindo...\"
    exit 1
fi

# Obtenha os valores do Grand Master \"upstream\"

PDS_GM_VALUES=$(pmc -f ${CONFIG_FILE_NAC} -u -b 0 'GET PARENT_DATA_SET' | awk 'BEGIN {ORS=" "} /gm./ {print $2}')
TPDS_GM_VALUES=$(pmc -f ${CONFIG_FILE_NAC} -u -b 0 'GET TIME_PROPERTIES_DATA_SET' | awk 'BEGIN {ORS=" "} NR>2 {print $2}')

if [ -z \"$PDS_GM_VALUES\" ]; then
    echo \"Nenhum valor de PARENT_DATA_SET recuperado\"
    exit 2
elif [ -z \"$TPDS_GM_VALUES\" ]; then
    echo \"Nenhum valor de TIME_PROPERTIES_DATA_SET recuperado\"
    exit 2
fi

# Descompactar de PARENT_DATA_SET
read CLOCK_CLASS CLOCK_ACCURACY VARIANCE <<< $PDS_GM_VALUES

# Descompactar de TIME_PROPERTIES_DATA_SET
read UTC_OFFSET LEAP_61 LEAP_59 UTC_OFFSET_VALID PTP_TIMESCALE T_TRACEABLE F_TRACEABLE T_SOURCE <<< $TPDS_GM_VALUES

if [ \"$VERBOSE\" -eq 1 ]; then +
    echo \"Lido de PARENT_DATA_SET: clockClass=${CLOCK_CLASS} clockAccuracy=${CLOCK_ACCURACY} offsetScaledLogVariance=${VARIANCE}\" +
    echo \"Lido de TIME_PROPERTIES_DATA_SET: currentUtcOffset=${UTC_OFFSET} leap61=${LEAP_61} leap59=${LEAP_59}\" \\ +
         \"currentUtcOffsetValid=${UTC_OFFSET_VALID} ptpTimescale=${PTP_TIMESCALE} timeTraceable=${T_TRACEABLE}\" \\ +
         \"frequencyTraceable=${F_TRACEABLE} timeSource=${T_SOURCE}\" +
fi


# Encaminhe esses valores para os receptores de tempo "downstream" atualizando as instâncias ptp4l

for FILE in \"${CONFIG_FILES_AICS[@]}\"; do +
    if [ \"$VERBOSE\" -eq 1 ]; then +
        echo \"Atualizando GRANDMASTER_SETTINGS_NP (${FILE})\" +
    fi

    pmc -f ${FILE} -u -b 0 'SET GRANDMASTER_SETTINGS_NP
       clockClass              '${CLOCK_CLASS}'
       clockAccuracy           '${CLOCK_ACCURACY}'
       offsetScaledLogVariance '${VARIANCE}'
       currentUtcOffset        '${UTC_OFFSET}'
       leap61                  '${LEAP_61}'
       leap59                  '${LEAP_59}'
       currentUtcOffsetValid   '${UTC_OFFSET_VALID}'
       ptpTimescale            '${PTP_TIMESCALE}'
       timeTraceable           '${T_TRACEABLE}'
       frequencyTraceable      '${F_TRACEABLE}'
       timeSource              '${T_SOURCE}'' &> /dev/null

    if [ $? -ne 0 ]; then +
        echo \"Falha ao atualizar ${FILE}\" +
    fi +
done
Nota
Nota

O script deve ser executado toda vez que o GM mudar.

47 SCTP - Stream Control Transmission Protocol

De Stream Control Transmission Protocol - Wikipedia

O Stream Control Transmission Protocol (SCTP) é um protocolo de comunicação de rede de computadores na camada de transporte do conjunto de protocolos da Internet. Originalmente destinado ao transporte de mensagens do Signaling System 7 (SS7) em telecomunicações, o protocolo fornece o recurso orientado a mensagens do User Datagram Protocol (UDP), garantindo ao mesmo tempo o transporte confiável e em sequência de mensagens com controle de congestionamento, como o Transmission Control Protocol (TCP). Ao contrário do UDP e do TCP, o protocolo suporta multihoming e caminhos redundantes para aumentar a resiliência e a confiabilidade.

O SCTP é padronizado pela Internet Engineering Task Force (IETF) no RFC 9260. A implementação de referência do SCTP foi lançada como parte da versão 7 do FreeBSD e, desde então, foi amplamente portada para outras plataformas.

Nas especificações 3GPP 4G (LTE), o SCTP (Stream Control Transmission Protocol) atua como o transporte fundamental da Camada 4 para mensagens de sinalização do plano de controle em todo o Evolved Packet Core (EPC), incluindo a conexão de sinalização com o domínio da Radio Access Network (RAN). As especificações 3GPP 5G, por outro lado, removeram a necessidade de SCTP dentro da Core Network através da introdução da Service Based Architecture (SBA), que substitui todas as interfaces de sinalização baseadas em Diameter-over-SCTP por HTTP/2. No entanto, ele ainda é necessário dentro do domínio 5G RAN:

  • nas interfaces de sinalização entre os elementos de rede que compõem uma instância gNodeB "desagregada" (interface F1-C entre DU e CU-CP e interface E1 entre CU-CP e CU-UP).

  • na interface Xn-C que conecta instâncias gNodeB para fins de sinalização.

  • no ponto de referência N2 (também conhecido como NG-C) usado para conectar instâncias gNodeB (domínio RAN) com instâncias AMF (domínio Core Network) para fins de sinalização.

Em seguida, você deve habilitar o módulo do kernel sctp do Linux (lksctp) nos nós de cluster downstream que hospedam as cargas de trabalho de telecomunicações compatíveis com SCTP que o utilizam:

  • Para carregar manualmente o módulo do kernel sctp em um nó Linux:

$ sudo modprobe sctp
  • Para automatizar o carregamento do módulo do kernel sctp a cada inicialização do nó, crie um arquivo chamado sctp.conf no diretório /etc/modules-load.d/ que contenha simplesmente a string sctp (ou seja, o nome do módulo do kernel que a unidade systemd-modules-load.service deve carregar na inicialização).

$ echo "sctp" > /etc/modules-load.d/sctp.conf
$ reboot

A maneira mais fácil e melhor de garantir que o módulo do kernel sctp seja carregado a cada inicialização do nó é adicionar esse arquivo /etc/modules-load.d/sctp.conf à imagem bruta criada com o Edge Image Builder (EIB) usada para provisionar nós downstream; consulte a documentação do Edge Image Builder (EIB) (Seção 5.3.5, “Adicionando Arquivos de sistema operacional”) para obter mais informações sobre como fazer isso.

Parte VII Provisionamento de rede direcionado totalmente automatizado

48 Introdução

Este capítulo descreve como provisionar clusters downstream usando o Provisionamento de Rede Direcionado, o método de provisionamento suportado para o SUSE Telco Cloud. Ao contrário do Provisionamento baseado em imagem, este fluxo de trabalho mantém a imagem do SO genérica e direciona toda a configuração específica do cluster a partir do cluster de gerenciamento, permitindo implantações consistentes e totalmente automatizadas em escala em locais distribuídos.

O Provisionamento de Rede Direcionado é um fluxo de trabalho totalmente automatizado e zero-touch, conduzido pelo cluster de gerenciamento. Cada host bare-metal é primeiro pré-registrado no Metal3 a partir do cluster de gerenciamento, registrando suas credenciais de BMC e detalhes de hardware. Uma vez que o host esteja instalado no rack, conectado às redes necessárias e ligado, o cluster de gerenciamento assume o controle: ele provisiona o SO usando uma imagem base gerada pelo EIB via interface de gerenciamento fora de banda e implanta a pilha completa do Kubernetes com todos os perfis de telecomunicações aplicados, sem qualquer intervenção manual adicional.

O cluster de gerenciamento automatiza a implantação dos seguintes componentes em cada nó de cluster downstream:

  • SUSE Linux Micro (Capítulo 10, SUSE Linux Micro) (ou SUSE Linux Micro RT para kernel de tempo real) como sistema operacional. Rede, armazenamento, usuários e argumentos de kernel podem ser personalizados dependendo do caso de uso.

  • RKE2 (Capítulo 14, RKE2) como a distribuição Kubernetes. O plug-in CNI padrão é Cilium. Outras combinações de CNI, como Cilium+Multus, podem ser usadas dependendo do caso de uso.

  • (Opcional) SUSE Storage (Capítulo 15, SUSE Storage)

  • (Opcional) SUSE Security (Capítulo 16, SUSE Security)

  • (Opcional) MetalLB como balanceador de carga para clusters de vários nós de alta disponibilidade.

As seções a seguir descrevem os diferentes fluxos de trabalho de provisionamento de rede direcionado e alguns recursos adicionais que podem ser adicionados ao processo de provisionamento:

Nota
Nota

As seções a seguir mostram como preparar os diferentes cenários para o fluxo de trabalho de provisionamento de rede direcionado usando o SUSE Telco Cloud. Para exemplos das diferentes opções de configuração para implantação (incl. ambientes air-gapped, redes DHCP e sem DHCP, registros de contêiner privados, etc.), consulte o repositório do SUSE Telco Cloud.

49 Preparar a imagem do cluster downstream para cenários conectados

O Edge Image Builder (Capítulo 12, Edge Image Builder) é usado para preparar uma imagem base SLEMicro modificada que é provisionada nos hosts do cluster downstream.

Grande parte da configuração via Edge Image Builder é possível, mas neste guia, cobrimos as configurações mínimas necessárias para configurar o cluster downstream.

49.1 Pré-requisitos para cenários conectados

Nota
Nota

É necessário usar um host de compilação com a mesma arquitetura das imagens que estão sendo criadas. Em outras palavras, para criar uma imagem aarch64, é necessário usar um host de compilação aarch64, e vice-versa para x86-64 (compilações cruzadas não são suportadas neste momento).

49.2 Configuração de imagem para cenários conectados

Ao executar o Edge Image Builder, um diretório é montado a partir do 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 é o arquivo de definição de imagem, veja Capítulo 5, Clusters autônomos com o Edge Image Builder para mais detalhes.

  • A pasta da imagem base conterá a imagem bruta de saída gerada seguindo o guia Capítulo 64, Criando imagens atualizadas do SUSE Linux Micro com o Kiwi com o perfil Base (ou Base-RT para o kernel de tempo real) deve ser copiada/movida para a pasta base-images.

  • O diretório custom/files contém os arquivos performance-settings.sh e sriov-auto-filler.sh a serem copiados para a imagem durante o processo de criação da imagem.

  • O diretório custom/scripts contém scripts a serem executados na primeira inicialização:

    1. O script 01-fix-growfs.sh é necessário para redimensionar a partição raiz do SO na implantação

    2. O script 02-performance.sh é opcional e pode ser usado para configurar o sistema para ajuste de desempenho.

    3. O script 03-sriov.sh é opcional e pode ser usado para configurar o sistema para SR-IOV.

  • A pasta network é opcional, veja Seção 49.2.6, “Script adicional para Configuração de Rede Avançada” para mais detalhes.

  • A pasta os-files contém os arquivos de configuração necessários para carregar, a cada inicialização de nó, os módulos do kernel sctp e vfio-pci com as opções necessárias.

├── downstream-cluster-config.yaml
├── base-images
│   └── SL-Micro.x86_64-6.2-Base-GM.raw
├── custom
│   ├── files
│   │   ├── performance-settings.sh
│   │   └── sriov-auto-filler.sh
│   └── scripts
│       ├── 01-fix-growfs.sh
│       ├── 02-performance.sh
│       └── 03-sriov.sh
├── network
│   └── configure-network.sh
└── os-files
    └── etc
        ├── modprobe.d
        │   └── vfio-pci-options.conf
        └── modules-load.d
            ├── sctp.conf
            └── vfio-pci.conf

49.2.1 Arquivo de definição de imagem de cluster downstream

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

apiVersion: 1.3
image:
  imageType: raw
  arch: x86_64
  baseImage: SL-Micro.x86_64-6.2-Base-GM.raw
  outputImageName: eibimage-output-telco.raw
operatingSystem:
  kernelArgs:
    - ignition.platform.id=openstack
  systemd:
    disable:
      - rebootmgr
      - transactional-update.timer
      - transactional-update-cleanup.timer
      - fstrim
      - time-sync.target
  users:
    - username: root
      encryptedPassword: $ROOT_PASSWORD
      sshKeys:
      - $USERKEY1
      createHomeDir: true
  packages:
    packageList:
      - jq
    sccRegistrationCode: $SCC_REGISTRATION_CODE

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

$ROOT_PASSWORD é a senha criptografada para o usuário root, o que pode ser útil para teste/depuração. Ele pode ser gerado com o comando openssl passwd -6 PASSWORD

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

Nota
Nota

arch: x86_64 é a arquitetura da imagem. Para a arquitetura arm64, use arch: aarch64.

Observe que ignition.platform.id=openstack é obrigatório; sem este argumento, a configuração do SLEMicro via ignition falhará no fluxo automatizado do Metal3.

Para versões do SUSE Linux Micro anteriores à 6.2, net.ifnames=1 deve ser definido explicitamente como um argumento de kernel para habilitar Predictable Network Interface Naming. Isso é aplicado por padrão a partir da versão 6.2 em diante e a configuração explícita não é necessária. Isso está alinhado com a configuração predictableNicNames no gráfico Helm do Metal3 do Cluster de Gerenciamento, que é necessária para que o Provisionamento de Rede Direcionado funcione corretamente. A nomenclatura consistente de interfaces também é crítica quando o SR-IOV é utilizado.

49.2.2 Script Growfs

Atualmente, um script personalizado (custom/scripts/01-fix-growfs.sh) é necessário para expandir o sistema de arquivos para corresponder ao 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 /

49.2.3 Script de desempenho

O script opcional a seguir (custom/scripts/02-performance.sh) pode ser usado para configurar o sistema para ajuste de desempenho:

#!/bin/bash

# create the folder to extract the artifacts there
mkdir -p /opt/performance-settings

# copy the artifacts
cp performance-settings.sh /opt/performance-settings/

O conteúdo de custom/files/performance-settings.sh é um script que pode ser usado para configurar o sistema para ajuste de desempenho e pode ser baixado do seguinte link.

49.2.4 Script SR-IOV

O script opcional a seguir (custom/scripts/03-sriov.sh) pode ser usado para configurar o sistema para SR-IOV:

#!/bin/bash

# create the folder to extract the artifacts there
mkdir -p /opt/sriov
# copy the artifacts
cp sriov-auto-filler.sh /opt/sriov/sriov-auto-filler.sh

O conteúdo de custom/files/sriov-auto-filler.sh é um script que pode ser usado para configurar o sistema para SR-IOV e pode ser baixado do seguinte link.

Nota
Nota

Adicione seus próprios scripts personalizados para serem executados durante o processo de provisionamento usando a mesma abordagem. Para obter mais informações, consulte Capítulo 5, Clusters autônomos com o Edge Image Builder.

49.2.5 Configuração adicional para cargas de trabalho Telco

Para habilitar recursos de Telco como dpdk, sr-iov ou FEC, pacotes adicionais podem ser necessários, conforme mostrado no exemplo a seguir.

apiVersion: 1.3
image:
  imageType: raw
  arch: x86_64
  baseImage: SL-Micro.x86_64-6.2-Base-GM.raw
  outputImageName: eibimage-output-telco.raw
operatingSystem:
  kernelArgs:
    - ignition.platform.id=openstack
  systemd:
    disable:
      - rebootmgr
      - transactional-update.timer
      - transactional-update-cleanup.timer
      - fstrim
      - time-sync.target
  users:
    - username: root
      encryptedPassword: $ROOT_PASSWORD
      sshKeys:
      - $user1Key1
      createHomeDir: true
  packages:
    packageList:
      - jq            # Non Telco specific - category: testing/utils
      - dpdk          # TelCo Core-Network UserPlane (5G UPF) and RAN UserPlane (gNB: DU and CU-UP) - category: runtime
      - dpdk-tools    # TelCo Core-Network UserPlane (5G UPF) and RAN UserPlane (gNB: DU and CU-UP) - category: testing/utils
      - libdpdk-25    # TelCo Core-Network UserPlane (5G UPF) and RAN UserPlane (gNB: DU and CU-UP) - category: runtime
      - pf-bb-config  # TelCo RAN (gNB: DU) - category: config.
      - open-iscsi    # Non Telco specific (required by SUSE Storage/Longhorn) - category: runtime
      - tuned         # Non Telco specific (linux tuning) - category: config.
      - cpupower      # Non Telco specific (linux tuning - CPU power related settings) - category: config.
      - rt-tests      # Non Telco specific (RT scheduler-latency testing) - category: testing/utils
      - linuxptp      # TelCo RAN; time sync (gNB: DU) - category: runtime
      - synce4l       # TelCo RAN; time sync (gNN: DU) - category: runtime
      - pciutils      # Non Telco specific (provides "lspci" command) - category: testing/utils
      - numactl       # Non Telco specific (provides "numactl" command) - category: testing/utils
    sccRegistrationCode: $SCC_REGISTRATION_CODE

Onde $SCC_REGISTRATION_CODE é o código de registro copiado do SUSE Customer Center, e a lista de pacotes contém os pacotes mínimos a serem usados para os perfis de Telco.

Nota
Nota

arch: x86_64 é a arquitetura da imagem. Para a arquitetura arm64, use arch: aarch64.

49.2.6 Script adicional para Configuração de Rede Avançada

Se você precisar configurar IPs estáticos ou cenários de rede mais avançados conforme descrito em Capítulo 53, Configuração de rede avançada, a configuração adicional a seguir é necessária.

Na pasta network, crie o seguinte arquivo configure-network.sh - isso consome 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

META_DATA_FILE="/mnt/openstack/latest/meta_data.json"
if [ ! -f "${META_DATA_FILE}" ]; then
  umount /mnt
  echo "No meta_data.json found, skipping hostname 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

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

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

49.2.7 Módulos de kernel necessários para Telco

Para garantir que os módulos de kernel necessários para cargas de trabalho de telecomunicações sejam carregados na inicialização de cada nó, os seguintes arquivos de configuração devem ser adicionados à os-files pasta EIB:

49.2.7.1 sctp.conf

Para ser colocado no caminho os-files/etc/modules-load.d/, instruindo o systemd-modules-load.service a carregar o módulo do kernel sctp na inicialização do nó.

$ cat os-files/etc/modules-load.d/sctp.conf
# Request "systemd-modules-load.service" to load sctp module at boot time
sctp

49.2.7.2 vfio-pci.conf

Para ser colocado no caminho os-files/etc/modules-load.d/, instruindo o systemd-modules-load.service a carregar o módulo do kernel vfio-pci na inicialização do nó.

$ cat os-files/etc/modules-load.d/vfio-pci.conf
# Request "systemd-modules-load.service" to load vfio-pci module at boot time
# NOTE: The (SRIOV & DPDK related) required load-module options settings are defined in related "/etc/modprobe.d/vfio-pci-options.conf" file
vfio_pci

49.2.7.3 vfio-pci-options.conf

Para ser colocado no caminho os-files/etc/modprobe.d/, definindo os parâmetros necessários do módulo do kernel vfio-pci a serem aplicados quando o módulo do kernel for carregado.

$ cat os-files/etc/modprobe.d/vfio-pci-options.conf
# Enable SR-IOV and disable idle D3 state for vfio-pci driver
options vfio_pci enable_sriov=1 disable_idle_d3=1

49.3 Criação de imagem

Assim que a estrutura de diretórios estiver preparada seguindo 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.6/edge-image-builder:1.3.3.1 \
 build --definition-file downstream-cluster-config.yaml

Isso cria o arquivo de imagem ISO de saída chamado eibimage-output-telco.raw, com base na definição descrita acima.

A imagem de saída deve então ser disponibilizada via um servidor web, seja o contêiner media-server habilitado via a Documentação do Cluster de Gerenciamento (Nota) ou algum outro servidor acessível localmente. Nos exemplos abaixo, nos referimos a este servidor como imagecache.local:8080

50 Preparar imagem de cluster downstream para cenários de air gap

O Edge Image Builder (Capítulo 12, Edge Image Builder) é usado para preparar uma imagem base SLEMicro modificada que é provisionada nos hosts do cluster downstream.

Grande parte da configuração é possível com o Edge Image Builder, mas neste guia, cobrimos as configurações mínimas necessárias para configurar o cluster downstream para cenários de air gap.

50.1 Pré-requisitos para cenários de air gap

  • Um tempo de execução do contêiner, como Podman ou Rancher Desktop, é necessário para executar o Edge Image Builder.

  • A imagem base será criada usando o seguinte guia Capítulo 64, Criando imagens atualizadas do SUSE Linux Micro com o Kiwi com o arquivo de controle Base (ou Base-RT para o kernel de tempo real). O processo é o mesmo para ambas as arquiteturas (x86-64 e aarch64).

  • Se você quiser usar SR-IOV ou qualquer outra carga de trabalho que exija uma imagem de contêiner, um registro privado local deve ser implantado e já configurado (com/sem TLS e/ou autenticação). Este registro será usado para armazenar as imagens e as imagens OCI de helm chart.

Nota
Nota

É necessário usar um host de compilação com a mesma arquitetura das imagens que estão sendo criadas. Em outras palavras, para criar uma imagem aarch64, é necessário usar um host de compilação aarch64, e vice-versa para x86-64 (compilações cruzadas não são suportadas neste momento).

50.2 Configuração de imagem para cenários de air gap

Ao executar o Edge Image Builder, um diretório é montado a partir do 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-airgap-config.yaml é o arquivo de definição de imagem, veja Capítulo 5, Clusters autônomos com o Edge Image Builder para mais detalhes.

  • A pasta da imagem base conterá a imagem bruta de saída gerada seguindo o guia Capítulo 64, Criando imagens atualizadas do SUSE Linux Micro com o Kiwi com o perfil Base (ou Base-RT para o kernel de tempo real) deve ser copiada/movida para a pasta base-images.

  • A pasta network é opcional, veja Seção 49.2.6, “Script adicional para Configuração de Rede Avançada” para mais detalhes.

  • O diretório custom/scripts contém scripts a serem executados na primeira inicialização:

    1. O script 01-fix-growfs.sh é necessário para redimensionar a partição raiz do SO na implantação.

    2. O script 02-airgap.sh é necessário para copiar as imagens para o local correto durante o processo de criação da imagem para ambientes air-gapped.

    3. O script 03-performance.sh é opcional e pode ser usado para configurar o sistema para ajuste de desempenho.

    4. O script 04-sriov.sh é opcional e pode ser usado para configurar o sistema para SR-IOV.

  • O diretório custom/files contém as imagens rke2 e cni a serem copiadas para a imagem durante o processo de criação da imagem. Além disso, os arquivos opcionais performance-settings.sh e sriov-auto-filler.sh podem ser incluídos.

  • O diretório os-files contém os arquivos de configuração necessários para carregar, a cada inicialização de nó, os módulos do kernel sctp e vfio-pci com as opções necessárias.

├── downstream-cluster-airgap-config.yaml
├── base-images
│   └── SL-Micro.x86_64-6.2-Base-GM.raw
├── custom
│   ├── files
│   │   ├── install.sh
│   │   ├── rke2-images-cilium.linux-amd64.tar.zst
│   │   ├── rke2-images-core.linux-amd64.tar.zst
│   │   ├── rke2-images-multus.linux-amd64.tar.zst
│   │   ├── rke2-images.linux-amd64.tar.zst
│   │   ├── rke2-images-traefik.linux-amd64.tar.zst
│   │   ├── rke2.linux-amd64.tar.zst
│   │   ├── sha256sum-amd64.txt
│   │   ├── performance-settings.sh
│   │   └── sriov-auto-filler.sh
│   └── scripts
│       ├── 01-fix-growfs.sh
│       ├── 02-airgap.sh
│       ├── 03-performance.sh
│       └── 04-sriov.sh
├── network
│   └── configure-network.sh
└── os-files
    └── etc
        ├── modprobe.d
        │   └── vfio-pci-options.conf
        └── modules-load.d
            ├── sctp.conf
            └── vfio-pci.conf

50.2.1 Arquivo de definição de imagem de cluster downstream

O arquivo downstream-cluster-airgap-config.yaml é o arquivo de configuração principal para a imagem do cluster downstream e o conteúdo foi descrito na seção (Seção 49.2.5, “Configuração adicional para cargas de trabalho Telco”) anterior.

50.2.2 Script Growfs

Atualmente, um script personalizado (custom/scripts/01-fix-growfs.sh) é necessário para expandir o sistema de arquivos para corresponder ao 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 /

50.2.3 Script de air-gap

O script a seguir (custom/scripts/02-airgap.sh) é necessário para copiar as imagens para o local correto durante o processo de criação da imagem:

#!/bin/bash

# create the folder to extract the artifacts there
mkdir -p /opt/rke2-artifacts
mkdir -p /var/lib/rancher/rke2/agent/images

# copy the artifacts
cp install.sh /opt/
cp rke2-images*.tar.zst rke2.linux-amd64.tar.gz sha256sum-amd64.txt /opt/rke2-artifacts/

50.2.4 Script de desempenho

O script opcional a seguir (custom/scripts/03-performance.sh) pode ser usado para configurar o sistema para ajuste de desempenho:

#!/bin/bash

# create the folder to extract the artifacts there
mkdir -p /opt/performance-settings

# copy the artifacts
cp performance-settings.sh /opt/performance-settings/

O conteúdo de custom/files/performance-settings.sh é um script que pode ser usado para configurar o sistema para ajuste de desempenho e pode ser baixado do seguinte link.

50.2.5 Script SR-IOV

O script opcional a seguir (custom/scripts/04-sriov.sh) pode ser usado para configurar o sistema para SR-IOV:

#!/bin/bash

# create the folder to extract the artifacts there
mkdir -p /opt/sriov
# copy the artifacts
cp sriov-auto-filler.sh /opt/sriov/sriov-auto-filler.sh

O conteúdo de custom/files/sriov-auto-filler.sh é um script que pode ser usado para configurar o sistema para SR-IOV e pode ser baixado do seguinte link.

50.2.6 Módulos de kernel necessários para Telco

Conforme descrito para o cenário sem air-gap na seção (Seção 49.2.7, “Módulos de kernel necessários para Telco”).

50.2.7 Preparando os artefatos de air-gap

As etapas a seguir são necessárias para preparar os artefatos de air-gap usando a imagem do contêiner de lançamento para popular um registro com os artefatos da versão específica. Ele lida com a geração de tarball do RKE2, espelhamento OCI de Helm chart e espelhamento de imagem de contêiner em um único comando — não são necessários scripts separados.

  1. Se o seu registro privado exigir autenticação, crie um arquivo de autenticação de registro com credenciais codificadas em base64:

    $ echo -n "$(echo -n 'myusername' | base64 -w 0):$(echo -n 'mypassword' | base64 -w 0)" > registry-auth.txt
  2. Se você usar um repositório de charts do Rancher Apps (necessário para charts do Longhorn e de origem Rancher), crie um arquivo de autenticação do Rancher Apps:

    $ echo -n "$(echo -n 'myusername@apps.rancher.io' | base64 -w 0):$(echo -n 'mypassword' | base64 -w 0)" > rancher-apps-auth.txt
  3. (Opcional) Se você quiser espelhar artefatos do SUSE Private Registry (charts/imagens do Harbor), crie um arquivo de autenticação do SUSE Private Registry usando seu SCC mirroring credentials recuperado seguindo a documentação do SUSE Private Registry:

    $ echo -n "$(echo -n 'SUSE_REGISTRY_USERNAME' | base64 -w 0):$(echo -n 'SUSE_REGISTRY_PASSWORD' | base64 -w 0)" > suse-private-registry-auth.txt
  4. Execute o comando mirror usando a imagem do contêiner de release para popular seu registro privado com todos os artefatos necessários para uma versão de release específica (imagens RKE2, imagens OCI de Helm chart e imagens de contêiner). Coloque quaisquer arquivos de autenticação e certificados no diretório atual para que fiquem acessíveis dentro do contêiner via bind mount -v ./:/opt:z.

    Sem o SUSE Private Registry (charts/imagens do Harbor serão ignorados):

    $ podman run --rm \
      -v ./:/opt:z \
      registry.suse.com/edge/3.6/release-manifest:3.6 \
      mirror \
      -o /opt/output \
      -a /opt/registry-auth.txt \
      -c /opt/cert.pem \
      -r ${REGISTRY_IP}:5000 \
      --rancher-apps-authfile /opt/rancher-apps-auth.txt \
      --debug

    onde ${REGISTRY_IP} é o endereço IP da instância de registro a ser populada.

    Com o SUSE Private Registry:

    $ podman run --rm \
      -v ./:/opt:z \
      registry.suse.com/edge/3.6/release-manifest:3.6 \
      mirror \
      -o /opt/output \
      -a /opt/registry-auth.txt \
      -c /opt/cert.pem \
      -r ${MGMT_CLUSTER_REGISTRY_IP}:5000 \
      --rancher-apps-authfile /opt/rancher-apps-auth.txt \
      --suse-private-registry-authfile /opt/suse-private-registry-auth.txt \
      --debug

    onde ${MGMT_CLUSTER_REGISTRY_IP} é o endereço IP estático reservado fornecido à instância do SUSE Private Registry implantada no cluster de Gerenciamento, conforme descrito na seção (Seção 30.3, “Modificações na pasta kubernetes”) anterior.

  5. Copie os artefatos RKE2 gerados do diretório de saída (/opt/output`no exemplo) para a pasta `custom/files para que o EIB os consuma em clusters downstream durante o processo de build:

    $ cp output/rke2-images*.tar.zst custom/files/
    $ cp output/rke2.linux-amd64.tar.gz custom/files/
    $ cp output/sha256sum-amd64.txt custom/files/
Nota
Nota

A imagem do contêiner de release já inclui /release_manifest.yaml e /release_images.yaml internamente, portanto, não é necessário fornecer arquivos de manifesto adicionais. Para referência completa de flags e uso avançado, consulte a documentação do seactl.

50.3 Criação de imagem para cenários de air gap

Assim que a estrutura de diretórios estiver preparada seguindo 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.6/edge-image-builder:1.3.3.1 \
 build --definition-file downstream-cluster-airgap-config.yaml

Isso cria o arquivo de imagem ISO de saída chamado eibimage-output-telco.raw, com base na definição descrita acima.

A imagem de saída deve então ser disponibilizada via um servidor web, seja o contêiner media-server habilitado via a Documentação do Cluster de Gerenciamento (Nota) ou algum outro servidor acessível localmente. Nos exemplos abaixo, nos referimos a este servidor como imagecache.local:8080.

51 Provisionamento de cluster downstream com provisionamento de rede direcionado (nó único)

Esta seção descreve o fluxo de trabalho usado para automatizar o provisionamento de um cluster downstream de nó único usando provisionamento de rede direcionado. Esta é a maneira mais simples de automatizar o provisionamento de um cluster downstream.

Requisitos

Fluxo de trabalho

O diagrama a seguir mostra o fluxo de trabalho usado para automatizar o provisionamento de um cluster downstream de nó único usando provisionamento de rede direcionado:

atip automated singlenode1

Existem duas etapas diferentes para automatizar o provisionamento de um cluster downstream de nó único usando provisionamento de rede direcionado:

  1. Registre o host bare-metal para torná-lo disponível para o processo de provisionamento.

  2. Provisione o host bare-metal para instalar e configurar o sistema operacional e o cluster Kubernetes.

Registre o host bare-metal

A primeira etapa é registrar o novo host bare-metal no cluster de gerenciamento para torná-lo disponível para ser provisionado. Para fazer isso, o arquivo a seguir (bmh-example.yaml) deve ser criado no cluster de gerenciamento, para especificar as credenciais BMC a serem usadas e o objeto BaremetalHost a ser inscrito:

apiVersion: v1
kind: Secret
metadata:
  name: example-demo-credentials
type: Opaque
data:
  username: ${BMC_USERNAME}
  password: ${BMC_PASSWORD}
---
apiVersion: metal3.io/v1alpha1
kind: BareMetalHost
metadata:
  name: example-demo
  labels:
    cluster-role: control-plane
spec:
  architecture: x86_64
  online: true
  bootMACAddress: ${BMC_MAC}
  rootDeviceHints:
    deviceName: /dev/nvme0n1
  bmc:
    address: ${BMC_ADDRESS}
    disableCertificateVerification: true
    credentialsName: example-demo-credentials

em que:

  • ${BMC_USERNAME} — O nome de usuário para o BMC do novo host bare-metal.

  • ${BMC_PASSWORD} — A senha para o BMC do novo host bare-metal.

  • ${BMC_MAC} — O endereço MAC do novo host bare-metal a ser usado.

  • ${BMC_ADDRESS} — O URL para o host bare-metal BMC (por exemplo, redfish-virtualmedia://192.168.200.75/redfish/v1/Systems/1/). Para saber mais sobre as diferentes opções disponíveis dependendo do seu provedor de hardware, verifique o seguinte link.

Nota
Nota
  • A arquitetura deve ser x86_64 ou aarch64, dependendo da arquitetura do host bare-metal a ser inscrito.

  • Se nenhuma configuração de rede para o host tiver sido especificada, seja no momento da criação da imagem ou por meio da definição BareMetalHost, um mecanismo de autoconfiguração (DHCP, DHCPv6, SLAAC) será usado. Para mais detalhes ou configurações complexas, verifique o Capítulo 53, Configuração de rede avançada.

Assim que o arquivo for criado, o comando a seguir deve ser executado no cluster de gerenciamento para iniciar a inscrição do novo host bare-metal no cluster de gerenciamento:

$ kubectl apply -f bmh-example.yaml

O novo objeto de host bare-metal será inscrito, alterando seu estado de registering para inspecting e available. As alterações podem ser verificadas usando o seguinte comando:

$ kubectl get bmh
Nota
Nota

O objeto BaremetalHost fica no estado registering até que as credenciais BMC sejam validadas. Assim que as credenciais forem validadas, o objeto BaremetalHost altera seu estado para inspecting, e esta etapa pode levar algum tempo dependendo do hardware (até 20 minutos). Durante a fase de inspeção, as informações de hardware são recuperadas e o objeto Kubernetes é atualizado. Verifique as informações usando o seguinte comando: kubectl get bmh -o yaml.

Etapa de provisionamento

Uma vez que o host bare-metal esteja inscrito e disponível, a próxima etapa é provisionar o host bare-metal para instalar e configurar o sistema operacional e o cluster Kubernetes. Para fazer isso, o seguinte arquivo (capi-provisioning-example.yaml) deve ser criado no cluster de gerenciamento com as seguintes informações (o capi-provisioning-example.yaml pode ser gerado unindo os seguintes blocos).

Nota
Nota

Apenas valores entre $\{…​\} devem ser substituídos pelos valores reais.

O bloco a seguir é a definição do cluster, onde a rede pode ser configurada usando os blocos pods e services. Além disso, ele contém as referências aos objetos do plano de controle e da infraestrutura (usando o provedor Metal3) a serem usados.

apiVersion: cluster.x-k8s.io/v1beta2
kind: Cluster
metadata:
  name: single-node-cluster
  namespace: default
  labels:
    cluster-api.cattle.io/rancher-auto-import: "true"
spec:
  clusterNetwork:
    pods:
      cidrBlocks:
        - 192.168.0.0/18
        - fd00:bad:cafe::/48
    services:
      cidrBlocks:
        - 10.96.0.0/12
        - fd00:bad:bad:cafe::/112
  controlPlaneRef:
    apiGroup: controlplane.cluster.x-k8s.io
    kind: RKE2ControlPlane
    name: single-node-cluster
  infrastructureRef:
    apiGroup: infrastructure.cluster.x-k8s.io
    kind: Metal3Cluster
    name: single-node-cluster
Nota
Nota
  • Implantações de pilha única e pilha dupla são possíveis; remova os CIDRs IPv6 da definição acima para um cluster apenas IPv4.

  • Implantações de pilha única IPv6 estão em status de prévia técnica e ainda não são oficialmente suportadas.

  • Adicionar o rótulo cluster-api.cattle.io/rancher-auto-import: "true" aos objetos cluster.x-k8s.io importará o cluster para o Rancher (criando um objeto clusters.management.cattle.io correspondente). Consulte a documentação da API de Cluster para obter mais informações.

O objeto Metal3Cluster especifica o endpoint do plano de controle (substituindo o ${DOWNSTREAM_CONTROL_PLANE_IPV4}) a ser configurado e o noCloudProvider porque um nó bare-metal é usado.

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

O objeto RKE2ControlPlane especifica a configuração do plano de controle a ser usada e o objeto Metal3MachineTemplate especifica a imagem do plano de controle a ser usada. Além disso, ele contém as informações sobre o número de réplicas a serem usadas (neste caso, uma) e o plug-in CNI a ser usado (neste caso, Cilium). O bloco agentConfig contém o formato Ignition a ser usado e o additionalUserData a ser usado para configurar o nó RKE2 com informações como um systemd chamado rke2-preinstall.service para substituir automaticamente o BAREMETALHOST_UUID e node-name durante o processo de provisionamento usando as informações do Ironic. Para habilitar o multus com cilium, um arquivo é criado no diretório de manifestos do servidor rke2 chamado rke2-cilium-config.yaml com a configuração a ser usada. O último bloco de informações contém a versão do Kubernetes a ser usada. ${RKE2_VERSION} é a versão do RKE2 a ser usada substituindo este valor (por exemplo, v1.35.4+rke2r1).

apiVersion: controlplane.cluster.x-k8s.io/v1beta2
kind: RKE2ControlPlane
metadata:
  name: single-node-cluster
  namespace: default
  annotations: {
    rke2.controlplane.cluster.x-k8s.io/load-balancer-exclusion: "true"
  }
spec:
  machineTemplate:
  infrastructureRef:
    apiGroup: infrastructure.cluster.x-k8s.io
    kind: Metal3MachineTemplate
    name: single-node-cluster-controlplane
  replicas: 1
  version: ${RKE2_VERSION}
  rolloutStrategy:
    type: "RollingUpdate"
    rollingUpdate:
      maxSurge: 0
  serverConfig:
    cni: cilium
  agentConfig:
    format: ignition
    additionalUserData:
      config: |
        variant: fcos
        version: 1.4.0
        systemd:
          units:
          - name: rke2-preinstall.service
            enabled: true
            contents: |
              [Unit]
              Description=rke2-preinstall
              Wants=network-online.target
              Before=rke2-install.service
              ConditionPathExists=!/run/cluster-api/bootstrap-success.complete
              [Service]
              Type=oneshot
              User=root
              ExecStartPre=/bin/sh -c "mount -L config-2 /mnt"
              ExecStart=/bin/sh -c "sed -i \"s/BAREMETALHOST_UUID/$(jq -r .uuid /mnt/openstack/latest/meta_data.json)/\" /etc/rancher/rke2/config.yaml"
              ExecStart=/bin/sh -c "echo \"node-name: $(jq -r .name /mnt/openstack/latest/meta_data.json)\" >> /etc/rancher/rke2/config.yaml"
              ExecStart=/bin/sh -c "echo \"node-label:\" >> /etc/rancher/rke2/config.yaml"
              ExecStart=/bin/sh -c "echo \"  - metal3.io/uuid=$(jq -r .uuid /mnt/openstack/latest/meta_data.json)\" >> /etc/rancher/rke2/config.yaml"
              ExecStartPost=/bin/sh -c "umount /mnt"
              [Install]
              WantedBy=multi-user.target
          # rke2-traefik-deployment.service unit to be removed once "traefik" being the default ingress controller (starting with RKE2 v1.36)
          - name: rke2-traefik-deployment.service
            enabled: true
            contents: |
              [Unit]
              Description=rke2-traefik-deployment
              Wants=rke2-preinstall.service
              Before=rke2-install.service
              ConditionPathExists=!/run/cluster-api/bootstrap-success.complete
              [Service]
              Type=oneshot
              User=root
              ExecStart=/bin/sh -c "echo \"ingress-controller: traefik\" >> /etc/rancher/rke2/config.yaml"
              [Install]
              WantedBy=multi-user.target
        storage:
          directories:
          - path: /var/lib/rancher/rke2/server/manifests
            overwrite: true
          files:
          # https://docs.rke2.io/networking/multus_sriov#using-multus-with-cilium
          - path: /var/lib/rancher/rke2/server/manifests/rke2-cilium-config.yaml
            overwrite: true
            contents:
              inline: |
                apiVersion: helm.cattle.io/v1
                kind: HelmChartConfig
                metadata:
                  name: rke2-cilium
                  namespace: kube-system
                spec:
                  valuesContent: |-
                    cni:
                      exclusive: false
            mode: 0644
            user:
              name: root
            group:
              name: root
          - path: /var/lib/rancher/rke2/server/manifests/rke2-traefik-config.yaml
            overwrite: true
            contents:
              inline: |
                apiVersion: helm.cattle.io/v1
                kind: HelmChartConfig
                metadata:
                  name: rke2-traefik
                  namespace: kube-system
                spec:
                  valuesContent: |-
                    ingressClass:
                      isDefaultClass: true
                    ports:
                      web:
                        hostPort: null    # disallow hostPort
                        exposedPort: 80
                      websecure:
                        hostPort: null    # disallow hostPort
                        exposedPort: 443
                    service:
                      enabled: true
                      type: LoadBalancer
                      spec:
                        externalTrafficPolicy: Local
                        allocateLoadBalancerNodePorts: false  # k8s GA from 1.24; supported by MetalLB
            mode: 0644
            user:
              name: root
            group:
              name: root
    kubelet:
      extraArgs:
      - provider-id=metal3://BAREMETALHOST_UUID
    nodeName: "localhost.localdomain"

O objeto Metal3MachineTemplate especifica as seguintes informações:

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

O objeto Metal3DataTemplate especifica o metaData para o cluster downstream.

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

Uma vez que o arquivo seja criado juntando os blocos anteriores, o seguinte comando deve ser executado no cluster de gerenciamento para iniciar o provisionamento do novo host bare-metal:

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

52 Provisionamento de cluster downstream com provisionamento de rede direcionado (multi-nó)

Esta seção descreve o fluxo de trabalho usado para automatizar o provisionamento de um cluster downstream multi-nó usando provisionamento de rede direcionado e MetalLB como estratégia de balanceador de carga. Esta é a maneira mais simples de automatizar o provisionamento de um cluster downstream. O diagrama a seguir mostra o fluxo de trabalho usado para automatizar o provisionamento de um cluster downstream multi-nó usando provisionamento de rede direcionado e MetalLB.

Requisitos

Fluxo de trabalho

O diagrama a seguir mostra o fluxo de trabalho usado para automatizar o provisionamento de um cluster downstream multi-nó usando provisionamento de rede direcionado:

atip automate multinode1
  1. Registre os três hosts bare-metal para torná-los disponíveis para o processo de provisionamento.

  2. Provisione os três hosts bare-metal para instalar e configurar o sistema operacional e o cluster Kubernetes usando MetalLB.

Registre os hosts bare-metal

O primeiro passo é inscrever os três hosts bare-metal no cluster de gerenciamento para torná-los disponíveis para serem provisionados. Para fazer isso, os seguintes arquivos (bmh-example-node1.yaml, bmh-example-node2.yaml e bmh-example-node3.yaml) devem ser criados no cluster de gerenciamento, para especificar as credenciais BMC a serem usadas e o objeto BaremetalHost a ser inscrito no cluster de gerenciamento.

Nota
Nota
  • Apenas os valores entre $\{…​\} devem ser substituídos pelos valores reais.

  • Nós o guiaremos pelo processo para apenas um host. As mesmas etapas se aplicam aos outros dois nós.

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

Onde:

  • ${BMC_NODE1_USERNAME} — O nome de usuário para o BMC do primeiro host bare-metal.

  • ${BMC_NODE1_PASSWORD} — A senha para o BMC do primeiro host bare-metal.

  • ${BMC_NODE1_MAC} — O endereço MAC do primeiro host bare-metal a ser usado.

  • ${BMC_NODE1_ADDRESS} — A URL para o BMC do primeiro host bare-metal (por exemplo, redfish-virtualmedia://192.168.200.75/redfish/v1/Systems/1/). A parte do host da URL pode ser um endereço IP (v4 ou v6) ou um nome de domínio, onde a infraestrutura existente permita. Para saber mais sobre as diferentes opções disponíveis dependendo do seu provedor de hardware, verifique o seguinte link.

Nota
Nota
  • Se nenhuma configuração de rede para o host tiver sido especificada, seja no momento da criação da imagem ou por meio da definição BareMetalHost, um mecanismo de autoconfiguração (DHCP, DHCPv6, SLAAC) será usado. Para mais detalhes ou configurações complexas, verifique o Capítulo 53, Configuração de rede avançada.

  • Clusters IPv6 de pilha única estão em status de prévia técnica e ainda não são oficialmente suportados.

  • A arquitetura deve ser x86_64 ou aarch64, dependendo da arquitetura do host bare-metal a ser inscrito.

  • Todos os servidores modernos vêm com um BMC capaz de dual-stack; no entanto, o suporte a IPv6 (e possivelmente a opção de usar nomes de host para a capacidade VirtualMedia) deve ser verificado antes do uso em produção em um ambiente dual-stack.

Uma vez que o arquivo seja criado, o seguinte comando deve ser executado no cluster de gerenciamento para começar a inscrever os hosts bare-metal no cluster de gerenciamento:

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

Os novos objetos de host bare-metal são inscritos, alterando seu estado de registering para inspecting e available. As alterações podem ser verificadas usando o seguinte comando:

$ kubectl get bmh -o wide
Nota
Nota

O objeto BaremetalHost fica no estado registering até que as credenciais BMC sejam validadas. Assim que as credenciais forem validadas, o objeto BaremetalHost altera seu estado para inspecting, e esta etapa pode levar algum tempo dependendo do hardware (até 20 minutos). Durante a fase de inspeção, as informações de hardware são recuperadas e o objeto Kubernetes é atualizado. Verifique as informações usando o seguinte comando: kubectl get bmh -o yaml.

Etapa de provisionamento

Uma vez que os três hosts bare-metal estejam inscritos e disponíveis, o próximo passo é provisionar os hosts bare-metal para instalar e configurar o sistema operacional e o cluster Kubernetes, criando um balanceador de carga para gerenciá-los. Para fazer isso, o seguinte arquivo (capi-provisioning-example.yaml) deve ser criado no cluster de gerenciamento com as seguintes informações (o `capi-provisioning-example.yaml pode ser gerado unindo os seguintes blocos).

Nota
Nota
  • Apenas valores entre $\{…​\} devem ser substituídos pelos valores reais.

  • O endereço VIP é um endereço IP reservado que não é atribuído a nenhum nó e é usado para configurar o balanceador de carga. Em um cluster dual-stack, tanto um IPv4 quanto um IPv6 podem ser especificados, mas nos exemplos a seguir será dada prioridade ao endereço IPv4.

Abaixo está a definição do cluster, onde a rede do cluster pode ser configurada usando os blocos pods e services. Além disso, ele contém as referências aos objetos do plano de controle e da infraestrutura (usando o provedor Metal3) a serem usados.

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
  • Ambas as implantações single-stack e dual-stack são possíveis. Remova os CIDRs IPv6 e os endereços VIP IPv6 (nas seções subsequentes) para um cluster apenas IPv4.

  • Adicionar o rótulo cluster-api.cattle.io/rancher-auto-import: "true" aos objetos cluster.x-k8s.io importará o cluster para o Rancher (criando um objeto clusters.management.cattle.io correspondente). Consulte a documentação da API de Cluster para obter mais informações.

O objeto Metal3Cluster especifica o endpoint do plano de controle que usa o endereço VIP já reservado (substituindo o ${EDGE_VIP_ADDRESS_IPV4}) a ser configurado e o noCloudProvider porque os três nós bare-metal são usados.

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

O objeto RKE2ControlPlane especifica a configuração do plano de controle a ser usada, e o objeto Metal3MachineTemplate especifica a imagem do plano de controle a ser usada.

  • Uma anotação de exclusão de balanceador de carga que informa aos balanceadores de carga externos, como o MetalLB, que um nó será drenado durante operações de ciclo de vida, como fazer upgrade de clusters downstream. Para obter os detalhes, consulte: Seção 59.1, “Exclusão de balanceador de carga”

  • O número de réplicas a ser usado (neste caso, três).

  • O modo de anúncio a ser usado pelo Balanceador de Carga (address usa a implementação L2), bem como o endereço a ser usado (substituindo o ${EDGE_VIP_ADDRESS} pelo endereço VIP).

  • O serverConfig com o plug-in CNI a ser usado (neste caso, Cilium), e o(s) endereço(s) e nome(s) VIP adicionais a serem listados em tlsSan.

  • O bloco agentConfig contém o Ignition formato a ser usado e o additionalUserData a ser usado para configurar o RKE2 nó com informações como:

    • O serviço systemd chamado rke2-preinstall.service para substituir automaticamente o BAREMETALHOST_UUID e o node-name durante o processo de provisionamento usando as informações do Ironic, além de adicionar o rótulo metal3.io/uuid aos objetos Node com o UUID BareMetalHost.

    • O serviço systemd chamado rke2-traefik-deployment.service para definir a opção de configuração server do RKE2 ingress-controller no arquivo /etc/rancher/rke2/config.yaml como traefik.

    • O bloco storage que contém os Helm charts a serem usados para instalar o MetalLB e o endpoint-copier-operator.

    • O arquivo de recurso personalizado metalLB com o IPaddressPool e o L2Advertisement a serem usados (substituindo ${EDGE_VIP_ADDRESS_IPV4} pelo endereço VIP).

    • O arquivo endpoint-svc.yaml a ser usado para configurar o serviço kubernetes-vip a ser usado pelo MetalLB para gerenciar o endereço VIP.

  • O último bloco de informações contém a versão do Kubernetes a ser usada. O ${RKE2_VERSION} é a versão do RKE2 a ser usada substituindo este valor (por exemplo, v1.35.4+rke2r1).

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

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

O objeto Metal3MachineTemplate especifica as seguintes informações:

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

O objeto Metal3DataTemplate especifica o metaData para o cluster downstream.

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

Os arquivos yaml a seguir são um exemplo de configuração para os nós de trabalho.

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}

O objeto RKE2ConfigTemplate especifica o modelo de configuração a ser usado para nós de trabalho de cluster com vários nós.

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

O objeto Metal3MachineTemplate contém referências a dataTemplate, hostSelector e image para os nós de trabalho:

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

O objeto Metal3DataTemplate especifica o metaData para o cluster downstream para os nós de trabalho:

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

Assim que o arquivo for criado juntando os blocos anteriores, execute o seguinte comando no cluster de gerenciamento para iniciar o provisionamento dos três novos hosts bare-metal:

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

53 Configuração de rede avançada

O fluxo de trabalho de provisionamento de rede direcionado permite configurações de rede específicas em clusters downstream, como IPs estáticos, vínculo, VLANs, IPv6, etc.

As seções a seguir descrevem as etapas adicionais necessárias para habilitar o provisionamento de clusters downstream usando configuração de rede avançada.

Requisitos

Configuração

Antes de prosseguir, consulte uma das seções a seguir para obter orientação sobre as etapas necessárias para registrar e provisionar o(s) host(s):

Qualquer configuração de rede avançada deve ser aplicada no momento da inscrição por meio da definição de host BareMetalHost e um Secret associado contendo um bloco nmstate formatado como networkData. O arquivo de exemplo a seguir define um secret contendo o networkData necessário que solicita um IP estático e VLAN para o host do cluster downstream:

apiVersion: v1
kind: Secret
metadata:
  name: controlplane-0-networkdata
type: Opaque
stringData:
  networkData: |
    interfaces:
    - name: ${CONTROLPLANE_INTERFACE}
      type: ethernet
      state: up
      mtu: 1500
      identifier: mac-address
      mac-address: "${CONTROLPLANE_MAC}"
      ipv4:
        address:
        - ip:  "${CONTROLPLANE_IP}"
          prefix-length: "${CONTROLPLANE_PREFIX}"
        enabled: true
        dhcp: false
    - name: floating
      type: vlan
      state: up
      vlan:
        base-iface: ${CONTROLPLANE_INTERFACE}
        id: ${VLAN_ID}
    dns-resolver:
      config:
        server:
        - "${DNS_SERVER}"
    routes:
      config:
      - destination: 0.0.0.0/0
        next-hop-address: "${CONTROLPLANE_GATEWAY}"
        next-hop-interface: ${CONTROLPLANE_INTERFACE}

Como você pode ver, o exemplo mostra a configuração para habilitar a interface com IPs estáticos, bem como a configuração para habilitar a VLAN usando a interface base, uma vez que as seguintes variáveis sejam substituídas pelos valores reais, de acordo com sua infraestrutura:

  • ${CONTROLPLANE_INTERFACE} — A interface do plano de controle a ser usada para o cluster downstream (por exemplo, eth0). Incluindo identifier: mac-address, a nomenclatura é inspecionada automaticamente pelo endereço MAC, portanto, qualquer nome de interface pode ser usado.

  • ${CONTROLPLANE_IP} — O endereço IP a ser usado como um endpoint para o cluster downstream (deve corresponder ao endpoint do kubeapi-server).

  • ${CONTROLPLANE_PREFIX} — O CIDR a ser usado para o cluster downstream (por exemplo, 24 se você quiser /24 ou 255.255.255.0).

  • ${CONTROLPLANE_GATEWAY} — O gateway a ser usado para o cluster downstream (por exemplo, 192.168.100.1).

  • ${CONTROLPLANE_MAC} — O endereço MAC a ser usado para a interface do plano de controle (por exemplo, 00:0c:29:3e:3e:3e).

  • ${DNS_SERVER} — O DNS a ser usado para o cluster downstream (por exemplo, 192.168.100.2).

  • ${VLAN_ID} — O ID da VLAN a ser usado para o cluster downstream (por exemplo, 100).

Qualquer outra definição compatível com nmstate pode ser usada para configurar a rede para o cluster downstream para se adaptar aos requisitos específicos. Por exemplo, é possível especificar uma configuração de pilha dupla estática:

apiVersion: v1
kind: Secret
metadata:
  name: controlplane-0-networkdata
type: Opaque
stringData:
  networkData: |
    interfaces:
    - name: ${CONTROLPLANE_INTERFACE}
      type: ethernet
      state: up
      mac-address: ${CONTROLPLANE_MAC}
      ipv4:
        enabled: true
        dhcp: false
        address:
        - ip: ${CONTROLPLANE_IP_V4}
          prefix-length: ${CONTROLPLANE_PREFIX_V4}
      ipv6:
        enabled: true
        dhcp: false
        autoconf: false
        address:
        - ip: ${CONTROLPLANE_IP_V6}
          prefix-length: ${CONTROLPLANE_PREFIX_V6}
    routes:
      config:
      - destination: 0.0.0.0/0
        next-hop-address: ${CONTROLPLANE_GATEWAY_V4}
        next-hop-interface: ${CONTROLPLANE_INTERFACE}
      - destination: ::/0
        next-hop-address: ${CONTROLPLANE_GATEWAY_V6}
        next-hop-interface: ${CONTROLPLANE_INTERFACE}
    dns-resolver:
      config:
        server:
        - ${DNS_SERVER_V4}
        - ${DNS_SERVER_V6}

Quanto ao exemplo anterior, substitua as seguintes variáveis pelos valores reais, de acordo com sua infraestrutura:

  • ${CONTROLPLANE_IP_V4} - o endereço IPv4 a ser atribuído ao host

  • ${CONTROLPLANE_PREFIX_V4} - o prefixo IPv4 da rede à qual o IP do host pertence

  • ${CONTROLPLANE_IP_V6} - o endereço IPv6 a ser atribuído ao host

  • ${CONTROLPLANE_PREFIX_V6} - o prefixo IPv6 da rede à qual o IP do host pertence

  • ${CONTROLPLANE_GATEWAY_V4} - o endereço IPv4 do gateway para o tráfego que corresponde à rota padrão

  • ${CONTROLPLANE_GATEWAY_V6} - o endereço IPv6 do gateway para o tráfego que corresponde à rota padrão

  • ${CONTROLPLANE_INTERFACE} - o nome da interface para atribuir os endereços e para usar para tráfego de saída que corresponde à rota padrão, tanto para IPv4 quanto para IPv6

  • ${DNS_SERVER_V4} e/ou ${DNS_SERVER_V6} - o(s) endereço(s) IP do(s) servidor(es) DNS a ser(em) usado(s), que pode(m) ser especificado(s) como entrada única ou múltipla. Há suporte para endereços IPv4 e/ou IPv6

Nota
Nota
  • Você pode consultar o repositório de exemplos do SUSE Telco Cloud para exemplos mais complexos, incluindo configurações somente IPv6 e dual-stack.

  • Implantações de pilha única IPv6 estão em status de prévia técnica e ainda não são oficialmente suportadas.

Por fim, independentemente dos detalhes da configuração de rede, certifique-se de que o segredo seja referenciado anexando preprovisioningNetworkDataName ao objeto BaremetalHost para registrar o host com sucesso no cluster de gerenciamento.

apiVersion: v1
kind: Secret
metadata:
  name: example-demo-credentials
type: Opaque
data:
  username: ${BMC_USERNAME}
  password: ${BMC_PASSWORD}
---
apiVersion: metal3.io/v1alpha1
kind: BareMetalHost
metadata:
  name: example-demo
  labels:
    cluster-role: control-plane
spec:
  architecture: x86_64
  online: true
  bootMACAddress: ${BMC_MAC}
  rootDeviceHints:
    deviceName: /dev/nvme0n1
  bmc:
    address: ${BMC_ADDRESS}
    disableCertificateVerification: true
    credentialsName: example-demo-credentials
  preprovisioningNetworkDataName: controlplane-0-networkdata
Nota
Nota
  • Se você precisar implantar um cluster de vários nós, o mesmo processo deve ser feito para cada nó.

  • Metal3DataTemplate, networkData e Metal3 IPAM atualmente não são suportados; apenas a configuração via segredos estáticos é totalmente suportada.

  • A arquitetura deve ser x86_64 ou aarch64, dependendo da arquitetura do host bare-metal a ser registrado.

54 Recursos de Telco (DPDK, SR-IOV, isolamento de CPU, huge pages, NUMA, etc.)

O fluxo de trabalho de provisionamento de rede direcionado permite automatizar os recursos de Telco a serem usados nos clusters downstream para executar cargas de trabalho de Telco sobre esses servidores.

Requisitos

Configuração

Use as duas seções a seguir como base para registrar e provisionar os hosts:

Os recursos de Telco abordados nesta seção são os seguintes:

  • DPDK e criação de VFs

  • SR-IOV e alocação de VFs para serem usadas pelas cargas de trabalho

  • Isolamento de CPU e ajuste de desempenho

  • Configuração de páginas enormes

  • Ajuste de parâmetros do kernel

Nota
Nota

Para mais informações sobre os recursos de Telco, consulte Parte VI, “Configuração de recursos de Telco”.

As alterações necessárias para habilitar os recursos de Telco mostrados acima estão todas dentro do bloco RKE2ControlPlane no arquivo de provisionamento capi-provisioning-example.yaml. O restante das informações dentro do arquivo capi-provisioning-example.yaml é igual às informações fornecidas na seção de provisionamento (Capítulo 51, Provisionamento de cluster downstream com provisionamento de rede direcionado (nó único)).

Para tornar o processo claro, as alterações necessárias nesse bloco (RKE2ControlPlane) para habilitar os recursos de Telco são as seguintes:

  • O arquivo de ignição /var/lib/rancher/rke2/server/manifests/configmap-sriov-custom-auto.yaml a ser usado para definir as interfaces, drivers e o número de VFs a serem criados e expostos às cargas de trabalho.

    • Os valores dentro do config map sriov-custom-auto-config são os únicos valores a serem substituídos por valores reais.

      • ${RESOURCE_NAME1} — O nome do recurso a ser usado para a primeira interface PF (por exemplo, sriov-resource-du1). Ele é adicionado ao prefixo rancher.io para ser usado como um rótulo a ser utilizado pelas cargas de trabalho (por exemplo, rancher.io/sriov-resource-du1).

      • ${SRIOV-NIC-NAME1} — O nome da primeira interface PF a ser usada (por exemplo, eth0).

      • ${PF_NAME1} — O nome da primeira função física PF a ser usada. Gere filtros mais complexos usando isto (por exemplo, eth0#2-5).

      • ${DRIVER_NAME1} — O nome do driver a ser usado para a primeira interface VF (por exemplo, vfio-pci).

      • ${NUM_VFS1} — O número de VFs a serem criados para a primeira interface PF (por exemplo, 8).

  • O /var/sriov-auto-filler.sh a ser usado como um tradutor entre o config map de alto nível sriov-custom-auto-config e o sriovnetworknodepolicy que contém as informações de hardware de baixo nível. Este script foi criado para abstrair o usuário da complexidade de saber as informações de hardware com antecedência. Nenhuma alteração é necessária neste arquivo, mas ele deve estar presente se precisarmos habilitar sr-iov e criar VFs.

  • Os argumentos do kernel a serem usados para habilitar os seguintes recursos:

Parâmetro

Valor

Descrição

isolcpus

domain,nohz,managed_irq,1-30,33-62

Isole os núcleos 1-30 e 33-62.

skew_tick

1

Permite que o kernel desvie as interrupções do temporizador entre as CPUs isoladas.

nohz

on

Permite que o kernel execute o tick do temporizador em uma única CPU quando o sistema estiver ocioso.

nohz_full

1-30,33-62

o parâmetro de inicialização do kernel é a interface principal atual para configurar dynticks completos junto com o Isolamento de CPU.

rcu_nocbs

1-30,33-62

Permite que o kernel execute os callbacks RCU em uma única CPU quando o sistema estiver ocioso.

irqaffinity

0,31,32,63

Permite que o kernel execute as interrupções em uma única CPU quando o sistema estiver ocioso.

inativo

poll

Minimiza a latência de saída do estado ocioso.

iommu

pt

Permite usar vfio para as interfaces dpdk.

intel_iommu

on

Habilita o uso de vfio para VFs.

hugepagesz

1G

Permite definir o tamanho das huge pages para 1 G.

hugepages

40

Número de huge pages definido anteriormente.

default_hugepagesz

1G

Valor padrão para habilitar huge pages.

nowatchdog

 

Desabilita o watchdog.

nmi_watchdog

0

Desabilita o watchdog NMI.

  • Os seguintes serviços do systemd são usados para habilitar o seguinte:

    • rke2-preinstall.service para substituir automaticamente o BAREMETALHOST_UUID e node-name durante o processo de provisionamento usando as informações do Ironic.

    • cpu-partitioning.service para habilitar os núcleos de isolamento do CPU (por exemplo, 1-30,33-62).

    • performance-settings.service para habilitar o ajuste de desempenho da CPU.

    • sriov-custom-auto-vfs.service para instalar o Helm chart sriov, aguardar até que os recursos personalizados sejam criados e executar o /var/sriov-auto-filler.sh para substituir os valores no config map sriov-custom-auto-config e criar o sriovnetworknodepolicy a ser usado pelas cargas de trabalho.

  • O ${RKE2_VERSION} é a versão do RKE2 a ser usada substituindo este valor (por exemplo, v1.35.4+rke2r1).

Com todas essas alterações mencionadas, o bloco RKE2ControlPlane no capi-provisioning-example.yaml ficará da seguinte forma:

apiVersion: controlplane.cluster.x-k8s.io/v1beta2
kind: RKE2ControlPlane
metadata:
  name: single-node-cluster
  namespace: default
spec:
  infrastructureRef:
    apiGroup: infrastructure.cluster.x-k8s.io
    kind: Metal3MachineTemplate
    name: single-node-cluster-controlplane
  replicas: 1
  version: ${RKE2_VERSION}
  rolloutStrategy:
    type: "RollingUpdate"
    rollingUpdate:
      maxSurge: 0
  serverConfig:
    cni: calico
    cniMultusEnable: true
  agentConfig:
    format: ignition
    additionalUserData:
      config: |
        variant: fcos
        version: 1.4.0
        storage:
          files:
          - path: /var/lib/rancher/rke2/server/manifests/configmap-sriov-custom-auto.yaml
            overwrite: true
            contents:
              inline: |
                apiVersion: v1
                kind: ConfigMap
                metadata:
                  name: sriov-custom-auto-config
                  namespace: kube-system
                data:
                  config.json: |
                    [
                        {
                          "resourceName": "${RESOURCE_NAME1}",
                          "interface": "${SRIOV-NIC-NAME1}",
                          "pfname": "${PF_NAME1}",
                          "driver": "${DRIVER_NAME1}",
                          "numVFsToCreate": ${NUM_VFS1}
                        },
                        {
                          "resourceName": "${RESOURCE_NAME2}",
                          "interface": "${SRIOV-NIC-NAME2}",
                          "pfname": "${PF_NAME2}",
                          "driver": "${DRIVER_NAME2}",
                          "numVFsToCreate": ${NUM_VFS2}
                        }
                    ]
            mode: 0644
            user:
              name: root
            group:
              name: root
          - path: /var/lib/rancher/rke2/server/manifests/sriov-crd.yaml
            overwrite: true
            contents:
              inline: |
                apiVersion: helm.cattle.io/v1
                kind: HelmChart
                metadata:
                  name: sriov-crd
                  namespace: kube-system
                spec:
                  chart: oci://registry.suse.com/edge/charts/sriov-crd
                  targetNamespace: sriov-network-operator
                  version: 306.0.4+up1.6.0
                  createNamespace: true
          - path: /var/lib/rancher/rke2/server/manifests/sriov-network-operator.yaml
            overwrite: true
            contents:
              inline: |
                apiVersion: helm.cattle.io/v1
                kind: HelmChart
                metadata:
                  name: sriov-network-operator
                  namespace: kube-system
                spec:
                  chart: oci://registry.suse.com/edge/charts/sriov-network-operator
                  targetNamespace: sriov-network-operator
                  version: 306.0.4+up1.6.0
                  createNamespace: true
        kernel_arguments:
          should_exist:
            - intel_iommu=on
            - iommu=pt
            - idle=poll
            - mce=off
            - hugepagesz=1G hugepages=40
            - hugepagesz=2M hugepages=0
            - default_hugepagesz=1G
            - irqaffinity=${NON-ISOLATED_CPU_CORES}
            - isolcpus=domain,nohz,managed_irq,${ISOLATED_CPU_CORES}
            - nohz_full=${ISOLATED_CPU_CORES}
            - rcu_nocbs=${ISOLATED_CPU_CORES}
            - rcu_nocb_poll
            - nosoftlockup
            - nowatchdog
            - nohz=on
            - nmi_watchdog=0
            - skew_tick=1
            - quiet
        systemd:
          units:
          - name: rke2-preinstall.service
            enabled: true
            contents: |
              [Unit]
              Description=rke2-preinstall
              Wants=network-online.target
              Before=rke2-install.service
              ConditionPathExists=!/run/cluster-api/bootstrap-success.complete
              [Service]
              Type=oneshot
              User=root
              ExecStartPre=/bin/sh -c "mount -L config-2 /mnt"
              ExecStart=/bin/sh -c "sed -i \"s/BAREMETALHOST_UUID/$(jq -r .uuid /mnt/openstack/latest/meta_data.json)/\" /etc/rancher/rke2/config.yaml"
              ExecStart=/bin/sh -c "echo \"node-name: $(jq -r .name /mnt/openstack/latest/meta_data.json)\" >> /etc/rancher/rke2/config.yaml"
              ExecStart=/bin/sh -c "echo \"node-label:\" >> /etc/rancher/rke2/config.yaml"
              ExecStart=/bin/sh -c "echo \"  - metal3.io/uuid=$(jq -r .uuid /mnt/openstack/latest/meta_data.json)\" >> /etc/rancher/rke2/config.yaml"
              ExecStartPost=/bin/sh -c "umount /mnt"
              [Install]
              WantedBy=multi-user.target
          # rke2-traefik-deployment.service unit to be removed once "traefik" being the default ingress controller (starting with RKE2 v1.36)
          - name: rke2-traefik-deployment.service
            enabled: true
            contents: |
              [Unit]
              Description=rke2-traefik-deployment
              Wants=rke2-preinstall.service
              Before=rke2-install.service
              ConditionPathExists=!/run/cluster-api/bootstrap-success.complete
              [Service]
              Type=oneshot
              User=root
              ExecStart=/bin/sh -c "echo \"ingress-controller: traefik\" >> /etc/rancher/rke2/config.yaml"
              [Install]
              WantedBy=multi-user.target
          - name: cpu-partitioning.service
            enabled: true
            contents: |
              [Unit]
              Description=cpu-partitioning
              Wants=network-online.target
              After=network.target network-online.target
              [Service]
              Type=oneshot
              User=root
              ExecStart=/bin/sh -c "echo isolated_cores=${ISOLATED_CPU_CORES} > /etc/tuned/cpu-partitioning-variables.conf"
              ExecStartPost=/bin/sh -c "tuned-adm profile cpu-partitioning"
              ExecStartPost=/bin/sh -c "systemctl enable tuned.service"
              [Install]
              WantedBy=multi-user.target
          - name: performance-settings.service
            enabled: true
            contents: |
              [Unit]
              Description=performance-settings
              Wants=network-online.target
              After=network.target network-online.target cpu-partitioning.service
              [Service]
              Type=oneshot
              User=root
              ExecStart=/bin/sh -c "/opt/performance-settings/performance-settings.sh"
              [Install]
              WantedBy=multi-user.target
          - name: sriov-custom-auto-vfs.service
            enabled: true
            contents: |
              [Unit]
              Description=SRIOV Custom Auto VF Creation
              Wants=network-online.target  rke2-server.target
              After=network.target network-online.target rke2-server.target
              [Service]
              User=root
              Type=forking
              TimeoutStartSec=900
              ExecStart=/bin/sh -c "while ! /var/lib/rancher/rke2/bin/kubectl --kubeconfig=/etc/rancher/rke2/rke2.yaml wait --for condition=ready nodes --all ; do sleep 2 ; done"
              ExecStartPost=/bin/sh -c "while [ $(/var/lib/rancher/rke2/bin/kubectl --kubeconfig=/etc/rancher/rke2/rke2.yaml get sriovnetworknodestates.sriovnetwork.openshift.io --ignore-not-found --no-headers -A | wc -l) -eq 0 ]; do sleep 1; done"
              ExecStartPost=/bin/sh -c "/opt/sriov/sriov-auto-filler.sh"
              RemainAfterExit=yes
              KillMode=process
              [Install]
              WantedBy=multi-user.target
    kubelet:
      extraArgs:
      - provider-id=metal3://BAREMETALHOST_UUID
    nodeName: "localhost.localdomain"

Uma vez que o arquivo seja criado unindo os blocos anteriores, o seguinte comando deve ser executado no cluster de gerenciamento para iniciar o provisionamento do novo cluster downstream usando os recursos de Telco:

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

55 Registro privado

É possível configurar um registro privado como um espelho para imagens usadas pelas cargas de trabalho.

Para fazer isso, criamos o segredo contendo as informações sobre o registro privado a ser usado pelo cluster downstream.

apiVersion: v1
kind: Secret
metadata:
  name: private-registry-cert
  namespace: default
data:
  tls.crt: ${TLS_CERTIFICATE}
  tls.key: ${TLS_KEY}
  ca.crt: ${CA_CERTIFICATE}
type: kubernetes.io/tls
---
apiVersion: v1
kind: Secret
metadata:
  name: private-registry-auth
  namespace: default
data:
  username: ${REGISTRY_USERNAME}
  password: ${REGISTRY_PASSWORD}

tls.crt, tls.key e ca.crt são os certificados a serem usados para autenticar o registro privado. username e password são as credenciais a serem usadas para autenticar o registro privado.

Nota
Nota

tls.crt, tls.key, ca.crt, username e password devem ser codificados no formato base64 antes de serem usados no segredo.

Com todas essas alterações mencionadas, o bloco RKE2ControlPlane no capi-provisioning-example.yaml ficará da seguinte forma:

apiVersion: controlplane.cluster.x-k8s.io/v1beta2
kind: RKE2ControlPlane
metadata:
  name: single-node-cluster
  namespace: default
spec:
  infrastructureRef:
    apiGroup: infrastructure.cluster.x-k8s.io
    kind: Metal3MachineTemplate
    name: single-node-cluster-controlplane
  replicas: 1
  version: ${RKE2_VERSION}
  rolloutStrategy:
    type: "RollingUpdate"
    rollingUpdate:
      maxSurge: 0
  privateRegistriesConfig:
    mirrors:
      "registry.example.com":
        endpoint:
          - "https://registry.example.com:5000"
    configs:
      "registry.example.com":
        authSecret:
          apiVersion: v1
          kind: Secret
          namespace: default
          name: private-registry-auth
        tls:
          tlsConfigSecret:
            apiVersion: v1
            kind: Secret
            namespace: default
            name: private-registry-cert
  serverConfig:
    cni: calico
    cniMultusEnable: true
  agentConfig:
    format: ignition
    additionalUserData:
      config: |
        variant: fcos
        version: 1.4.0
        systemd:
          units:
          - name: rke2-preinstall.service
            enabled: true
            contents: |
              [Unit]
              Description=rke2-preinstall
              Wants=network-online.target
              Before=rke2-install.service
              ConditionPathExists=!/run/cluster-api/bootstrap-success.complete
              [Service]
              Type=oneshot
              User=root
              ExecStartPre=/bin/sh -c "mount -L config-2 /mnt"
              ExecStart=/bin/sh -c "sed -i \"s/BAREMETALHOST_UUID/$(jq -r .uuid /mnt/openstack/latest/meta_data.json)/\" /etc/rancher/rke2/config.yaml"
              ExecStart=/bin/sh -c "echo \"node-name: $(jq -r .name /mnt/openstack/latest/meta_data.json)\" >> /etc/rancher/rke2/config.yaml"
              ExecStart=/bin/sh -c "echo \"node-label:\" >> /etc/rancher/rke2/config.yaml"
              ExecStart=/bin/sh -c "echo \"  - metal3.io/uuid=$(jq -r .uuid /mnt/openstack/latest/meta_data.json)\" >> /etc/rancher/rke2/config.yaml"
              ExecStartPost=/bin/sh -c "umount /mnt"
              [Install]
              WantedBy=multi-user.target
          # rke2-traefik-deployment.service unit to be removed once "traefik" being the default ingress controller (starting with RKE2 v1.36)
          - name: rke2-traefik-deployment.service
            enabled: true
            contents: |
              [Unit]
              Description=rke2-traefik-deployment
              Wants=rke2-preinstall.service
              Before=rke2-install.service
              ConditionPathExists=!/run/cluster-api/bootstrap-success.complete
              [Service]
              Type=oneshot
              User=root
              ExecStart=/bin/sh -c "echo \"ingress-controller: traefik\" >> /etc/rancher/rke2/config.yaml"
              [Install]
              WantedBy=multi-user.target
    kubelet:
      extraArgs:
      - provider-id=metal3://BAREMETALHOST_UUID
    nodeName: "localhost.localdomain"

Onde registry.example.com é o nome de exemplo do registro privado a ser usado pelo cluster downstream, e ele deve ser substituído pelos valores reais.

56 Provisionamento de cluster downstream em cenários air-gapped

O fluxo de trabalho de provisionamento de rede direcionado permite automatizar o provisionamento de clusters downstream em cenários air-gapped.

56.1 Requisitos para cenários air-gapped

  1. A imagem raw gerada usando EIB deve incluir as imagens de contêiner específicas (OCI de helm-chart e imagens de contêiner) necessárias para executar o cluster downstream em um cenário air-gapped. Para obter mais informações, consulte esta seção (Capítulo 50, Preparar imagem de cluster downstream para cenários de air gap).

  2. No caso de usar SR-IOV ou qualquer outra carga de trabalho personalizada, as imagens necessárias para executar as cargas de trabalho devem ser pré-carregadas em seu registro privado seguindo a seção de pré-carregamento de registro privado (Seção 50.2.7, “Preparando os artefatos de air-gap”).

56.2 Registrar os hosts bare metal em cenários air-gapped

O processo para registrar os hosts bare metal no cluster de gerenciamento é o mesmo descrito na seção anterior (Capítulo 51, Provisionamento de cluster downstream com provisionamento de rede direcionado (nó único)).

56.3 Provisionar o cluster downstream em cenários air-gapped

Existem algumas alterações importantes necessárias para provisionar o cluster downstream em cenários air-gapped:

  1. O bloco RKE2ControlPlane no arquivo capi-provisioning-example.yaml deve incluir a diretiva spec.agentConfig.airGapped: true.

  2. A configuração do registro privado deve ser incluída no bloco RKE2ControlPlane no arquivo capi-provisioning-airgap-example.yaml seguindo a seção de registro privado (Capítulo 55, Registro privado).

  3. Se você estiver usando SR-IOV ou qualquer outra configuração AdditionalUserData (script de combustão) que exija a instalação do helm-chart, você deve modificar o conteúdo para referenciar o registro privado em vez de usar o registro público.

O exemplo a seguir mostra a configuração de SR-IOV no bloco AdditionalUserData no arquivo capi-provisioning-airgap-example.yaml com as modificações necessárias para referenciar o registro privado

  • Referências de segredos do Registro Privado

  • Definição de Helm-Chart usando o registro privado em vez das imagens OCI públicas.

# secret to include the private registry certificates
apiVersion: v1
kind: Secret
metadata:
  name: private-registry-cert
  namespace: default
data:
  tls.crt: ${TLS_BASE64_CERT}
  tls.key: ${TLS_BASE64_KEY}
  ca.crt: ${CA_BASE64_CERT}
type: kubernetes.io/tls
---
# secret to include the private registry auth credentials
apiVersion: v1
kind: Secret
metadata:
  name: private-registry-auth
  namespace: default
data:
  username: ${REGISTRY_USERNAME}
  password: ${REGISTRY_PASSWORD}
---
apiVersion: controlplane.cluster.x-k8s.io/v1beta2
kind: RKE2ControlPlane
metadata:
  name: single-node-cluster
  namespace: default
spec:
  infrastructureRef:
    apiGroup: infrastructure.cluster.x-k8s.io
    kind: Metal3MachineTemplate
    name: single-node-cluster-controlplane
  replicas: 1
  version: ${RKE2_VERSION}
  rolloutStrategy:
    type: "RollingUpdate"
    rollingUpdate:
      maxSurge: 0
  privateRegistriesConfig:       # Private registry configuration to add your own mirror and credentials
    mirrors:
      docker.io:
        endpoint:
          - "${PRIVATE_REGISTRY_URL}"
        rewrite:
          "^(.*)$": "mirror/$1"
      registry.suse.com:
        endpoint:
          - "${PRIVATE_REGISTRY_URL}"
        rewrite:
          "^(.*)$": "mirror/$1"
      registry.suse.de:
        endpoint:
          - "${PRIVATE_REGISTRY_URL}"
        rewrite:
          "^(.*)$": "mirror/$1"
      registry.opensuse.org:
        endpoint:
          - "${PRIVATE_REGISTRY_URL}"
        rewrite:
          "^(.*)$": "mirror/$1"
      registry.rancher.com:
        endpoint:
          - "${PRIVATE_REGISTRY_URL}"
        rewrite:
          "^(.*)$": "mirror/$1"
    configs:
      "192.168.100.22:5000":
        authSecret:
          apiVersion: v1
          kind: Secret
          namespace: default
          name: private-registry-auth
        tls:
          tlsConfigSecret:
            apiVersion: v1
            kind: Secret
            namespace: default
            name: private-registry-cert
          insecureSkipVerify: false
  serverConfig:
    cni: calico
    cniMultusEnable: true
  agentConfig:
    airGapped: true       # Airgap true to enable airgap mode
    format: ignition
    additionalUserData:
      config: |
        variant: fcos
        version: 1.4.0
        storage:
          files:
          - path: /var/lib/rancher/rke2/server/manifests/configmap-sriov-custom-auto.yaml
            overwrite: true
            contents:
              inline: |
                apiVersion: v1
                kind: ConfigMap
                metadata:
                  name: sriov-custom-auto-config
                  namespace: sriov-network-operator
                data:
                  config.json: |
                    [
                        {
                          "resourceName": "${RESOURCE_NAME1}",
                          "interface": "${SRIOV-NIC-NAME1}",
                          "pfname": "${PF_NAME1}",
                          "driver": "${DRIVER_NAME1}",
                          "numVFsToCreate": ${NUM_VFS1}
                        },
                        {
                          "resourceName": "${RESOURCE_NAME2}",
                          "interface": "${SRIOV-NIC-NAME2}",
                          "pfname": "${PF_NAME2}",
                          "driver": "${DRIVER_NAME2}",
                          "numVFsToCreate": ${NUM_VFS2}
                        }
                    ]
            mode: 0644
            user:
              name: root
            group:
              name: root
          - path: /var/lib/rancher/rke2/server/manifests/sriov.yaml
            overwrite: true
            contents:
              inline: |
                apiVersion: v1
                data:
                  .dockerconfigjson: ${REGISTRY_AUTH_DOCKERCONFIGJSON}
                kind: Secret
                metadata:
                  name: privregauth
                  namespace: kube-system
                type: kubernetes.io/dockerconfigjson
                ---
                apiVersion: v1
                kind: ConfigMap
                metadata:
                  namespace: kube-system
                  name: example-repo-ca
                data:
                  ca.crt: |-
                    -----BEGIN CERTIFICATE-----
                    ${CA_BASE64_CERT}
                    -----END CERTIFICATE-----
                ---
                apiVersion: helm.cattle.io/v1
                kind: HelmChart
                metadata:
                  name: sriov-crd
                  namespace: kube-system
                spec:
                  chart: oci://${PRIVATE_REGISTRY_URL}/mirror/sriov-crd
                  dockerRegistrySecret:
                    name: privregauth
                  repoCAConfigMap:
                    name: example-repo-ca
                  createNamespace: true
                  set:
                    global.clusterCIDR: 192.168.0.0/18
                    global.clusterCIDRv4: 192.168.0.0/18
                    global.clusterDNS: 10.96.0.10
                    global.clusterDomain: cluster.local
                    global.rke2DataDir: /var/lib/rancher/rke2
                    global.serviceCIDR: 10.96.0.0/12
                  targetNamespace: sriov-network-operator
                  version: 306.0.4+up1.6.0
                ---
                apiVersion: helm.cattle.io/v1
                kind: HelmChart
                metadata:
                  name: sriov-network-operator
                  namespace: kube-system
                spec:
                  chart: oci://${PRIVATE_REGISTRY_URL}/mirror/sriov-network-operator
                  dockerRegistrySecret:
                    name: privregauth
                  repoCAConfigMap:
                    name: example-repo-ca
                  createNamespace: true
                  set:
                    global.clusterCIDR: 192.168.0.0/18
                    global.clusterCIDRv4: 192.168.0.0/18
                    global.clusterDNS: 10.96.0.10
                    global.clusterDomain: cluster.local
                    global.rke2DataDir: /var/lib/rancher/rke2
                    global.serviceCIDR: 10.96.0.0/12
                  targetNamespace: sriov-network-operator
                  version: 306.0.4+up1.6.0
            mode: 0644
            user:
              name: root
            group:
              name: root
        kernel_arguments:
          should_exist:
            - intel_iommu=on
            - iommu=pt
            - idle=poll
            - mce=off
            - hugepagesz=1G hugepages=40
            - hugepagesz=2M hugepages=0
            - default_hugepagesz=1G
            - irqaffinity=${NON-ISOLATED_CPU_CORES}
            - isolcpus=domain,nohz,managed_irq,${ISOLATED_CPU_CORES}
            - nohz_full=${ISOLATED_CPU_CORES}
            - rcu_nocbs=${ISOLATED_CPU_CORES}
            - rcu_nocb_poll
            - nosoftlockup
            - nowatchdog
            - nohz=on
            - nmi_watchdog=0
            - skew_tick=1
            - quiet
        systemd:
          units:
          - name: rke2-preinstall.service
            enabled: true
            contents: |
              [Unit]
              Description=rke2-preinstall
              Wants=network-online.target
              Before=rke2-install.service
              ConditionPathExists=!/run/cluster-api/bootstrap-success.complete
              [Service]
              Type=oneshot
              User=root
              ExecStartPre=/bin/sh -c "mount -L config-2 /mnt"
              ExecStart=/bin/sh -c "sed -i \"s/BAREMETALHOST_UUID/$(jq -r .uuid /mnt/openstack/latest/meta_data.json)/\" /etc/rancher/rke2/config.yaml"
              ExecStart=/bin/sh -c "echo \"node-name: $(jq -r .name /mnt/openstack/latest/meta_data.json)\" >> /etc/rancher/rke2/config.yaml"
              ExecStart=/bin/sh -c "echo \"node-label:\" >> /etc/rancher/rke2/config.yaml"
              ExecStart=/bin/sh -c "echo \"  - metal3.io/uuid=$(jq -r .uuid /mnt/openstack/latest/meta_data.json)\" >> /etc/rancher/rke2/config.yaml"
              ExecStartPost=/bin/sh -c "umount /mnt"
              [Install]
              WantedBy=multi-user.target
          # rke2-traefik-deployment.service unit to be removed once "traefik" being the default ingress controller (starting with RKE2 v1.36)
          - name: rke2-traefik-deployment.service
            enabled: true
            contents: |
              [Unit]
              Description=rke2-traefik-deployment
              Wants=rke2-preinstall.service
              Before=rke2-install.service
              ConditionPathExists=!/run/cluster-api/bootstrap-success.complete
              [Service]
              Type=oneshot
              User=root
              ExecStart=/bin/sh -c "echo \"ingress-controller: traefik\" >> /etc/rancher/rke2/config.yaml"
              [Install]
              WantedBy=multi-user.target
          - name: cpu-partitioning.service
            enabled: true
            contents: |
              [Unit]
              Description=cpu-partitioning
              Wants=network-online.target
              After=network.target network-online.target
              [Service]
              Type=oneshot
              User=root
              ExecStart=/bin/sh -c "echo isolated_cores=${ISOLATED_CPU_CORES} > /etc/tuned/cpu-partitioning-variables.conf"
              ExecStartPost=/bin/sh -c "tuned-adm profile cpu-partitioning"
              ExecStartPost=/bin/sh -c "systemctl enable tuned.service"
              [Install]
              WantedBy=multi-user.target
          - name: performance-settings.service
            enabled: true
            contents: |
              [Unit]
              Description=performance-settings
              Wants=network-online.target
              After=network.target network-online.target cpu-partitioning.service
              [Service]
              Type=oneshot
              User=root
              ExecStart=/bin/sh -c "/opt/performance-settings/performance-settings.sh"
              [Install]
              WantedBy=multi-user.target
          - name: sriov-custom-auto-vfs.service
            enabled: true
            contents: |
              [Unit]
              Description=SRIOV Custom Auto VF Creation
              Wants=network-online.target  rke2-server.target
              After=network.target network-online.target rke2-server.target
              [Service]
              User=root
              Type=forking
              TimeoutStartSec=1800
              ExecStart=/bin/sh -c "while ! /var/lib/rancher/rke2/bin/kubectl --kubeconfig=/etc/rancher/rke2/rke2.yaml wait --for condition=ready nodes --timeout=30m --all ; do sleep 10 ; done"
              ExecStartPost=/bin/sh -c "/opt/sriov/sriov-auto-filler.sh"
              RemainAfterExit=yes
              KillMode=process
              [Install]
              WantedBy=multi-user.target
    kubelet:
      extraArgs:
      - provider-id=metal3://BAREMETALHOST_UUID
    nodeName: "localhost.localdomain"

Parte VIII Operações do Dia Dois

Esta seção explica como os administradores podem lidar com diferentes tarefas de operação do "Dia Dois", tanto no gerenciamento quanto nos clusters downstream.

  • 57 Migração Edge 3.6
  • Esta seção explica como migrar seus clusters management e downstream de SUSE Telco Cloud 3.5 para SUSE Telco Cloud 3.6.0.

  • 58 Cluster de gerenciamento
  • Atualmente, existem duas maneiras de realizar operações de \"Dia 2\" no seu cluster management:

  • 59 Ações de ciclo de vida
  • Esta seção aborda as ações de gerenciamento de ciclo de vida para clusters implantados via SUSE Telco Cloud.

57 Migração Edge 3.6

Esta seção explica como migrar seus clusters management e downstream de SUSE Telco Cloud 3.5 para SUSE Telco Cloud 3.6.0.

Importante
Importante

Sempre realize migrações de cluster a partir da latest Z-stream release do SUSE Telco Cloud 3.5.

Sempre migre para a SUSE Telco Cloud 3.6.0 release. Para upgrades pós-migração subsequentes, consulte as management (Capítulo 58, Cluster de gerenciamento) seções.

A tabela a seguir lista os diferentes tipos de clusters e os métodos para fazer upgrade dos clusters:

Tabela 57.1: Clusters e métodos para fazer upgrade de clusters downstream
Tipo de clusterMétodo

Clusters provisionados por EIB

Consulte Seção 57.1.3, “Fleet” para obter os detalhes.

Clusters provisionados por Metal3

Consulte atualizações de cluster downstream (Seção 59.3, “Upgrades de clusters downstream”) para obter detalhes.

57.1 Cluster de gerenciamento

Esta seção abrange os seguintes tópicos:

Seção 57.1.1, “Pré-requisitos” - etapas de pré-requisito a serem concluídas antes de iniciar a migração.

Seção 57.1.2, “Upgrade Controller” - como fazer uma migração de cluster management usando o Capítulo 21, Upgrade Controller.

Seção 57.1.3, “Fleet” - como fazer uma migração de cluster management usando Capítulo 9, Fleet.

57.1.1 Pré-requisitos

57.1.1.1 Atualize os CRDs do Bare Metal Operator

Nota
Nota

Aplica-se apenas a clusters de gerenciamento CAPI/Metal3 que exigem uma atualização de gráfico Capítulo 11, Metal3.

O gráfico Helm Metal3 inclui os CRDs Bare Metal Operator (BMO) aproveitando o diretório CRD do Helm.

No entanto, essa abordagem tem certas limitações, particularmente a incapacidade de atualizar CRDs neste diretório usando o Helm. Para obter mais informações, consulte a documentação do Helm.

Como resultado, antes de atualizar o Metal3 para uma versão compatível com SUSE Telco Cloud 3.6.0, os usuários devem atualizar manualmente os CRDs do BMO subjacentes.

Em uma máquina com Helm instalado e kubectl configurado para apontar para o seu cluster management:

  1. Aplique manualmente os CRDs do BMO:

    helm show crds oci://registry.suse.com/edge/charts/metal3 --version 306.0.29+up0.15.0 | kubectl apply -f -

57.1.1.2 Migrar a configuração do certificado de CA do Metal3

Nota
Nota

Aplica-se apenas a implantações do Metal3 que usam CAs confiáveis adicionais para servidores de mídia externos com TLS.

O gráfico Helm do Metal3 mudou a forma como os certificados de CA confiáveis são configurados. Anteriormente, as CAs adicionais eram fornecidas por meio de um Secret (tls-ca-additional) com o sinalizador booleano additionalTrustedCAs. A nova versão usa um ConfigMap contendo o pacote de CA completo referenciado pelo valor global.trustedCAs.

Se você configurou CAs confiáveis adicionais para o Metal3, você precisa migrar da abordagem baseada em Secret para a abordagem baseada em ConfigMap:

  1. Crie um ConfigMap contendo seu pacote de CA a partir do Secret existente:

    Extraia os certificados do Secret antigo:

    kubectl get secret tls-ca-additional -n metal3-system -o jsonpath='{.data}' | \
      jq -r 'to_entries[] | .value' | base64 -d > ca-bundle.pem

    Opcional - Inclua o pacote de CA do sistema: Se sua implantação do Metal3 também precisar confiar em CAs públicas (por exemplo, ao acessar recursos externos via HTTPS), você precisará incluir o pacote de CA do sistema além de suas CAs personalizadas. Extraia o pacote de CA do sistema de uma imagem de contêiner e adicione-o antes de suas CAs personalizadas:

    # Extract system CAs from a container image (using podman or docker)
    podman run --rm registry.suse.com/bci/bci-base:latest cat /etc/ssl/certs/ca-certificates.crt > system-cas.pem
    
    # Combine system CAs with your custom CAs
    cat system-cas.pem ca-bundle.pem > combined-ca-bundle.pem
    mv combined-ca-bundle.pem ca-bundle.pem
    Importante
    Importante

    Se você incluir o pacote de CA do sistema, torna-se sua responsabilidade mantê-lo atualizado. As CAs do sistema na imagem do contêiner podem ficar obsoletas com o tempo, à medida que os certificados de CA expiram ou são revogados. Você deve atualizar periodicamente o pacote de CA do sistema extraindo-o novamente de uma imagem de contêiner atualizada.

    Crie o ConfigMap com o pacote de CA final:

    kubectl create configmap tls-ca-bundle -n metal3-system --from-file=ca-bundle.pem=ca-bundle.pem
  2. Atualize seus valores de Helm do Metal3 para usar a nova referência do ConfigMap:

    Altere de:

    global:
      additionalTrustedCAs: true

    Para:

    global:
      trustedCAs: tls-ca-bundle
  3. Após atualizar o gráfico Helm do Metal3 com a nova configuração, você pode excluir o Secret antigo:

    kubectl delete secret tls-ca-additional -n metal3-system

57.1.2 Upgrade Controller

Importante
Importante

O Upgrade Controller atualmente suporta migrações de versão SUSE Telco Cloud apenas para clusters de gerenciamento que não são air-gapped.

Os tópicos a seguir são abordados como parte desta seção:

Seção 57.1.2.1, “Pré-requisitos” - pré-requisitos específicos para o Upgrade Controller.

Seção 57.1.2.2, “Etapas de migração” - etapas para migrar um cluster management para uma nova versão SUSE Telco Cloud usando o Upgrade Controller.

57.1.2.1 Pré-requisitos

57.1.2.1.1 SUSE Telco Cloud 3.6 Upgrade Controller

Antes de usar o Upgrade Controller, você deve primeiro garantir que ele esteja executando uma versão capaz de migrar para a versão SUSE Telco Cloud desejada.

Para fazer isso:

  1. Se você já tiver o Upgrade Controller implantado a partir de uma versão SUSE Telco Cloud anterior, atualize seu gráfico:

    helm upgrade upgrade-controller -n upgrade-controller-system oci://registry.suse.com/edge/charts/upgrade-controller --version 306.0.4+up0.1.3
  2. Se você não tiver Upgrade Controller implantado, siga Seção 21.3, “Instalando o Upgrade Controller”.

57.1.2.2 Etapas de migração

Realizar uma migração de cluster management com o Upgrade Controller é fundamentalmente semelhante à execução de um upgrade.

A única diferença é que seu UpgradePlan deve especificar a versão de lançamento 3.6.0:

apiVersion: lifecycle.suse.com/v1alpha1
kind: UpgradePlan
metadata:
  name: upgrade-plan-mgmt
  # Change to the namespace of your Upgrade Controller
  namespace: CHANGE_ME
spec:
  releaseVersion: 3.6.0

Para obter informações sobre como usar o UpgradePlan acima para realizar uma migração, consulte processo de upgrade do Upgrade Controller (Seção 58.1, “Upgrade Controller”).

57.1.3 Fleet

Nota
Nota

Sempre que possível, use o Seção 57.1.2, “Upgrade Controller” para migração.

Consulte esta seção apenas para casos de uso não cobertos pelo Upgrade Controller.

Realizar uma migração de cluster management com Fleet é fundamentalmente semelhante à execução de um upgrade.

As principais diferenças são:

  1. As frotas devem ser usadas a partir da versão release-3.6.0 do repositório suse-edge/fleet-examples.

  2. Os gráficos agendados para um upgrade devem ser atualizados para versões compatíveis com a versão SUSE Telco Cloud 3.6.0. Para obter uma lista dos componentes SUSE Telco Cloud 3.6.0, consulte Seção 75.4, “Release 3.6.0”.

Importante
Importante

Para garantir uma migração SUSE Telco Cloud 3.6.0 bem-sucedida, é importante que os usuários cumpram os pontos descritos acima.

57.2 Clusters downstream

Seção 57.2.1, “Fleet” - como fazer uma migração de cluster downstream usando Capítulo 9, Fleet.

57.2.1 Fleet

Realizar uma migração de cluster downstream com Fleet é fundamentalmente semelhante à execução de um upgrade.

As principais diferenças são:

  1. As Fleet devem ser usadas a partir da versão release-3.6.0 do repositório suse-edge/fleet-examples.

  2. Os gráficos agendados para um upgrade devem ser atualizados para versões compatíveis com a versão SUSE Telco Cloud 3.6.0. Para obter uma lista dos componentes SUSE Telco Cloud 3.6.0, consulte Seção 75.4, “Release 3.6.0”.

Importante
Importante

Para garantir uma migração SUSE Telco Cloud 3.6.0 bem-sucedida, é importante que os usuários cumpram os pontos descritos acima.

58 Cluster de gerenciamento

Atualmente, existem duas maneiras de realizar operações de \"Dia 2\" no seu cluster management:

58.1 Upgrade Controller

Importante
Importante

O Upgrade Controller atualmente suporta apenas operações Day 2 para clusters não air-gapped.

Esta seção aborda como realizar as várias operações Day 2 relacionadas a fazer upgrade do seu cluster management de uma versão de plataforma SUSE Telco Cloud para outra.

As operações Day 2 são automatizadas pelo Upgrade Controller (Capítulo 21, Upgrade Controller) e incluem:

58.1.1 Pré-requisitos

Antes de fazer upgrade do seu cluster management, os seguintes pré-requisitos devem ser atendidos:

  1. SCC registered nodes - certifique-se de que o SO dos nós do seu cluster esteja registrado com uma chave de assinatura que suporte a versão do SO especificada na SUSE Telco Cloud release (Capítulo 75, Notas de versão) para a qual você pretende fazer upgrade.

  2. Upgrade Controller - certifique-se de que o Upgrade Controller tenha sido implantado em seu cluster management. Para as etapas de instalação, consulte Seção 21.3, “Instalando o Upgrade Controller”.

58.1.2 Upgrade

  1. Determine a versão de SUSE Telco Cloud release (Capítulo 75, Notas de versão) para a qual você deseja fazer upgrade do seu cluster management.

  2. No cluster management, implante um UpgradePlan que especifique o release version desejado. O UpgradePlan deve ser implantado no namespace do Upgrade Controller.

    kubectl apply -n <upgrade_controller_namespace> -f - <<EOF
    apiVersion: lifecycle.suse.com/v1alpha1
    kind: UpgradePlan
    metadata:
      name: upgrade-plan-mgmt
    spec:
      # Version retrieved from release notes
      releaseVersion: 3.X.Y
    EOF
    Nota
    Nota

    Podem existir casos de uso em que você deseje fazer configurações adicionais sobre o UpgradePlan. Para todas as configurações possíveis, consulte Seção 21.6.1, “UpgradePlan”.

  3. A implantação do UpgradePlan no namespace do Upgrade Controller’s iniciará o upgrade process.

    Nota
    Nota

    Para obter mais informações sobre o upgrade process real, consulte Seção 21.5, “Como funciona o Upgrade Controller?”.

    Para obter informações sobre como rastrear o upgrade process, consulte Seção 21.7, “Acompanhando o processo de atualização”.

58.1.3 Tarefas pós-upgrade

Fazer upgrade do SUSE Telco Cloud do z-stream 3.5 mais recente para 3.6.0 pode exigir algumas etapas manuais finais a serem executadas após o Upgrade Controller ter concluído o processo de fazer upgrade. Essas estão relacionadas à substituição do Ingress-NGINX pelo Traefik como o único controlador de ingresso suportado no SUSE Telco Cloud a partir da versão 3.6.

Nota
Nota

O provedor de ingresso Traefik integrado ao RKE2/K3s é o único controlador de ingresso suportado na versão SUSE Telco Cloud 3.6, sendo ainda possível executar temporariamente o Ingress-NGINX junto com o Traefik para oferecer suporte a cenários complexos de migração de ingresso, mas apenas após os clusters de Gerenciamento e/ou Downstream SUSE Telco Cloud terem feito upgrade para a versão 3.6 e pelo tempo necessário para realizar essa migração.

O guia Migração de Ingress NGINX para Traefik fornece detalhes sobre os caminhos de migração de ingresso disponíveis assim que o controlador de ingresso Traefik substituir o Ingress-NGINX descontinuado.

Caso o cluster de Gerenciamento recém-fez upgrade não estivesse executando o controlador de ingresso Traefik (mas o padrão Ingress-NGINX) antes de iniciar o upgrade, agora é necessário implantar manualmente o Traefik.

Primeiro, vamos garantir que a instância do ingress-NGINX implantada esteja configurada corretamente (por exemplo, para evitar colisões desnecessárias de hostPort entre os pods dos dois controladores de ingresso):

kubectl apply -f - <<- EOF
apiVersion: helm.cattle.io/v1
kind: HelmChartConfig
metadata:
  name: rke2-ingress-nginx
  namespace: kube-system
spec:
  valuesContent: |-
    controller:
      hostPort:
        enabled: false  # not needed when exposing through a type:LoadBalancer service
      config:
        use-forwarded-headers: "true"
        enable-real-ip: "true"
      publishService:
        enabled: true
      service:
        enabled: true
        type: LoadBalancer
        externalTrafficPolicy: Local
EOF

Agora podemos prosseguir com a implantação do Traefik, por meio da instalação dos gráficos Helm rke2-traefik-crd e rke2-traefik.

Nota
Nota

Implante esses gráficos Helm por meio de manifestos HelmChart, conforme mostrado abaixo, para garantir que o Upgrade Controller também cuide de fazer upgrade desses gráficos Helm em futuros processos de fazer upgrade do cluster de Gerenciamento.

kubectl apply -f - <<- EOF
apiVersion: helm.cattle.io/v1
kind: HelmChart
metadata:
  name: rke2-traefik-crd
  namespace: kube-system
spec:
  chart: rke2-traefik-crd
  version: {rke2-traefik-crd Helm chart version}
  repo: https://rke2-charts.rancher.io
  bootstrap: false
  failurePolicy: reinstall
  backOffLimit: 20
  targetNamespace: kube-system
  set:
    global.cattle.systemDefaultRegistry: registry.rancher.com
    global.rke2DataDir: /var/lib/rancher/rke2
    global.systemDefaultRegistry: registry.rancher.com
---
apiVersion: helm.cattle.io/v1
kind: HelmChart
metadata:
  name: rke2-traefik
  namespace: kube-system
spec:
  chart: rke2-traefik
  version: {rke2-traefik Helm chart version}
  repo: https://rke2-charts.rancher.io
  bootstrap: false
  failurePolicy: reinstall
  backOffLimit: 20
  targetNamespace: kube-system
  set:
    global.cattle.systemDefaultRegistry: registry.rancher.com
    global.rke2DataDir: /var/lib/rancher/rke2
    global.systemDefaultRegistry: registry.rancher.com
  valuesContent: |-
    ingressClass:
      isDefaultClass: false  # if traefik deployed alongside ingress-nginx
    ports:
      web:
        hostPort: null    # disallow hostPort
        exposedPort: 80
      websecure:
        hostPort: null    # disallow hostPort
        exposedPort: 443
    service:
      enabled: true
      type: LoadBalancer
      spec:
        externalTrafficPolicy: Local
        allocateLoadBalancerNodePorts: false  # k8s GA from 1.24; supported by MetalLB
    providers:
      kubernetesIngressNginx:  # this provider allows traefik to "understand" most of the ingress-nginx annotations
        enabled: true
        ingressClass: "rke2-ingress-nginx-migration"
        controllerClass: "rke2.​cattle.​io/ingress-nginx-migration"
EOF

O {rke2-traefik-crd Helm chart version} e o {rke2-traefik-crd Helm chart version} são aqueles ditados pela versão do RKE2/k3s para a qual fizemos upgrade.

Na última etapa, finalmente criamos os objetos necessários do MetalLB para expor o serviço Traefik por meio de um serviço do tipo LoadBalancer:

kubectl apply -f - <<- EOF
apiVersion: metallb.io/v1beta1
kind: IPAddressPool
metadata:
  name: ingress-ippool-traefik
  namespace: metallb-system
spec:
  addresses:
  - {EXTERNAL_IP_FOR_TRAEFIK_SERVICE}/32
  serviceAllocation:
    priority: 100
    serviceSelectors:
    - matchExpressions:
      - {key: app.kubernetes.io/name, operator: In, values: [rke2-traefik]}
---
apiVersion: metallb.io/v1beta1
kind: L2Advertisement
metadata:
  name: ingress-l2-adv-traefik
  namespace: metallb-system
spec:
  ipAddressPools:
  - ingress-ippool-traefik
EOF

Agora, tanto o Traefik quanto o Ingress-NGINX estão sendo executados lado a lado, permitindo que você execute com segurança a migração necessária de seus ingresses de um para o outro.

Importante
Importante

Assim que todos os ingresses tiverem sido migrados e você não precisar mais do Ingress-NGINX, certifique-se de desinstalá-lo e limpar todos os recursos relacionados para evitar qualquer consumo desnecessário de recursos em seu cluster.

58.2 Fleet

Esta seção oferece informações sobre como realizar operações de "Dia 2" usando o componente Fleet (Capítulo 9, Fleet).

Os tópicos a seguir são abordados como parte desta seção:

  1. Seção 58.2.1, “Componentes” - componentes padrão usados para todas as operações de "Dia 2".

  2. Seção 58.2.2, “Determine seu caso de uso” - fornece uma visão geral dos recursos personalizados do Fleet que serão usados e sua adequação para diferentes casos de uso de operações de "Dia 2".

  3. Seção 58.2.3, “Fluxo de trabalho de Dia 2” - fornece um guia de fluxo de trabalho para a execução de operações de "Dia 2" com o Fleet.

  4. Seção 58.2.4, “Fazer upgrade do SO” - descreve como fazer upgrade do SO usando o Fleet.

  5. Seção 58.2.5, “Atualização da versão do Kubernetes” - descreve como fazer upgrade da versão do Kubernetes usando o Fleet.

  6. Seção 58.2.6, “Fazer upgrade do Helm chart” - descreve como fazer upgrade do Helm chart usando o Fleet.

58.2.1 Componentes

Abaixo, você pode encontrar uma descrição dos componentes padrão que devem ser configurados em seu cluster management para que você possa realizar com sucesso as operações de "Dia 2" usando o Fleet.

58.2.1.1 Rancher

Opcional; Responsável por gerenciar o downstream clusters e implantar o System Upgrade Controller em seu management cluster.

Para obter mais informações, consulte Capítulo 6, Rancher.

58.2.1.2 System Upgrade Controller (SUC)

O System Upgrade Controller é responsável por executar tarefas em nós especificados com base em dados de configuração fornecidos por meio de um recurso personalizado, chamado de Plan.

O SUC é utilizado ativamente para fazer upgrade do sistema operacional e da distribuição do Kubernetes.

Para obter mais informações sobre o componente SUC e como ele se encaixa na pilha Edge, consulte Capítulo 20, Upgrade Controller do Sistema.

58.2.2 Determine seu caso de uso

O Fleet usa dois tipos de recursos personalizados para permitir o gerenciamento de recursos do Kubernetes e do Helm.

Abaixo, você pode encontrar informações sobre o propósito desses recursos e os casos de uso para os quais eles são mais adequados no contexto de operações de "Dia 2".

58.2.2.1 GitRepo

Um GitRepo é um recurso Fleet (Capítulo 9, Fleet) que representa um repositório Git a partir do qual o Fleet pode criar Bundles. Cada Bundle é criado com base em caminhos de configuração definidos dentro do recurso GitRepo. Para obter mais informações, consulte a documentação do GitRepo.

No contexto de operações de "Dia 2", os recursos GitRepo são normalmente usados para implantar SUC ou SUC Plans em ambientes não air-gapped que utilizam uma abordagem de Fleet GitOps.

Alternativamente, os recursos GitRepo também podem ser usados para implantar SUC ou SUC Plans em ambientes air-gapped, desde que você espelhe a configuração do seu repositório por meio de um servidor git local.

58.2.2.2 Pacote

Bundles contêm recursos raw do Kubernetes que serão implantados no cluster de destino. Geralmente, eles são criados a partir de um recurso GitRepo, mas existem casos de uso em que podem ser implantados manualmente. Para obter mais informações, consulte a documentação do Bundle.

No contexto de operações de "Dia 2", os recursos Bundle são normalmente usados para implantar SUC ou SUC Plans em ambientes air-gapped que não utilizam alguma forma de procedimento de GitOps local (por exemplo, um servidor git local).

Alternativamente, se o seu caso de uso não permitir um fluxo de trabalho GitOps (por exemplo, usando um repositório Git), os recursos Bundle também podem ser usados para implantar SUC ou SUC Plans em ambientes não air-gapped.

58.2.3 Fluxo de trabalho de Dia 2

O que se segue é um fluxo de trabalho de "Dia 2" que deve ser seguido ao fazer upgrade de um cluster management para uma versão específica do Edge.

58.2.4 Fazer upgrade do SO

Esta seção descreve como fazer upgrade do sistema operacional usando Capítulo 9, Fleet e o Capítulo 20, Upgrade Controller do Sistema.

Os tópicos a seguir são abordados como parte desta seção:

  1. Seção 58.2.4.1, “Componentes” - componentes adicionais usados pelo processo de upgrade.

  2. Seção 58.2.4.2, “Visão geral” - visão geral do processo de upgrade.

  3. Seção 58.2.4.3, “Requisitos” - requisitos do processo de upgrade.

  4. Seção 58.2.4.4, “Upgrade do SO - implantação do plano SUC” - informações sobre como implantar o SUC plans, responsável por acionar o processo de upgrade.

58.2.4.1 Componentes

Esta seção aborda os componentes personalizados que o processo de OS upgrade usa em relação aos componentes (Seção 58.2.1, “Componentes”) padrão de "Day 2".

58.2.4.1.1 systemd.service

O upgrade do SO em um nó específico é gerenciado por um systemd.service.

Um serviço diferente é criado dependendo do tipo de upgrade que o SO requer de uma versão do Edge para outra:

  • Para versões do Edge que requerem a mesma versão do SO (por exemplo, 6.1), o os-pkg-update.service será criado. Ele usa transactional-update para realizar um upgrade normal de pacotes.

  • Para versões do Edge que requerem uma migração de versão do SO (por exemplo, 6.1 → 6.2), o os-migration.service será criado. Ele usa transactional-update para realizar:

    1. Um upgrade normal de pacotes que garante que todos os pacotes estejam atualizados para mitigar quaisquer falhas na migração relacionadas a versões antigas de pacotes.

    2. Uma migração de SO utilizando o comando zypper migration.

Os serviços mencionados acima são fornecidos em cada nó por meio de um SUC plan que deve estar localizado no cluster management que precisa de upgrade do SO.

58.2.4.2 Visão geral

O upgrade do sistema operacional para nós de cluster management é feito utilizando Fleet e o System Upgrade Controller (SUC).

Fleet é usado para implantar e gerenciar SUC plans no cluster desejado.

Nota
Nota

SUC plans são recursos personalizados que descrevem as etapas que o SUC precisa seguir para que uma tarefa específica seja executada em um conjunto de nós. Para um exemplo de como um SUC plan se parece, consulte o repositório upstream.

Os OS SUC plans são enviados para cada cluster implantando um recurso GitRepo ou Bundle em um workspace específico do Fleet. O Fleet recupera os GitRepo/Bundle implantados e implanta seu conteúdo (o OS SUC plans) no(s) cluster(es) desejado(s).

Nota
Nota

Os recursos GitRepo/Bundle são sempre implantados no management cluster. Se usar um recurso GitRepo ou Bundle depende do seu caso de uso, verifique Seção 58.2.2, “Determine seu caso de uso” para mais informações.

OS SUC plans descrevem o seguinte fluxo de trabalho:

  1. Sempre cordon os nós antes de upgrades do SO.

  2. Sempre faça upgrade dos nós control-plane antes dos nós worker.

  3. Sempre faça upgrade do cluster, um nó por vez.

Uma vez que os OS SUC plans são implantados, o fluxo de trabalho é o seguinte:

  1. O SUC reconcilia os OS SUC plans implantados e cria um Kubernetes Job em cada nó.

  2. O Kubernetes Job cria um systemd.service (Seção 58.2.4.1.1, “systemd.service”) para upgrade de pacote ou migração de SO.

  3. O systemd.service criado aciona o processo de upgrade do SO no nó específico.

    Importante
    Importante

    Assim que o processo de upgrade do SO terminar, o nó correspondente será rebooted para aplicar as atualizações no sistema.

Abaixo você pode encontrar um diagrama da descrição acima:

fleet day2 management os upgrade

58.2.4.3 Requisitos

Geral:

  1. Máquina registrada no SCC - Todos os management nós do cluster devem estar registrados no https://scc.suse.com/, o que é necessário para que o respectivo systemd.service possa se conectar com sucesso ao repositório RPM desejado.

    Importante
    Importante

    Para versões Edge que exigem uma migração de versão de SO (por exemplo, 6.1 → 6.2), certifique-se de que sua chave SCC suporte a migração para a nova versão.

  2. Certifique-se de que as tolerâncias do Plano SUC correspondam às tolerâncias do nó - Se os nós do seu cluster Kubernetes tiverem taints personalizados, certifique-se de adicionar tolerâncias para esses taints nos Planos SUC. Por padrão, SUC Plans possuem tolerâncias apenas para nós control-plane. As tolerâncias padrão incluem:

    • CriticalAddonsOnly=true:NoExecute

    • node-role.kubernetes.io/control-plane:NoSchedule

    • node-role.kubernetes.io/etcd:NoExecute

      Nota
      Nota

      Quaisquer tolerâncias adicionais devem ser adicionadas na seção .spec.tolerations de cada Plano. SUC Plans relacionados ao upgrade do SO podem ser encontrados no repositório suse-edge/fleet-examples em fleets/day2/system-upgrade-controller-plans/os-upgrade. Certifique-se de usar os Planos de uma tag de release de repositório válida.

      Um exemplo de definição de tolerâncias personalizadas para o plano SUC control-plane seria assim:

      apiVersion: upgrade.cattle.io/v1
      kind: Plan
      metadata:
        name: os-upgrade-control-plane
      spec:
        ...
        tolerations:
        # default tolerations
        - key: "CriticalAddonsOnly"
          operator: "Equal"
          value: "true"
          effect: "NoExecute"
        - key: "node-role.kubernetes.io/control-plane"
          operator: "Equal"
          effect: "NoSchedule"
        - key: "node-role.kubernetes.io/etcd"
          operator: "Equal"
          effect: "NoExecute"
        # custom toleration
        - key: "foo"
          operator: "Equal"
          value: "bar"
          effect: "NoSchedule"
      ...

Air-gapped:

  1. Espelhar repositórios RPM da SUSE - Os repositórios RPM do SO devem ser espelhados localmente para que o systemd.service possa ter acesso a eles. Isso pode ser alcançado usando RMT ou SUMA.

58.2.4.4 Upgrade do SO - implantação do plano SUC

Importante
Importante

Para ambientes atualizados anteriormente usando este procedimento, os usuários devem garantir que uma das seguintes etapas seja concluída:

  • Remove any previously deployed SUC Plans related to older Edge release versions from the management cluster - pode ser feito removendo o cluster desejado da GitRepo/Bundle target configuration existente, ou removendo o recurso GitRepo/Bundle por completo.

  • Reuse the existing GitRepo/Bundle resource - pode ser feito apontando a revisão do recurso para uma nova tag que contenha as frotas corretas para o suse-edge/fleet-examples release desejado.

Isso é feito para evitar conflitos entre SUC Plans para versões de release do Edge mais antigas.

Se os usuários tentarem fazer upgrade enquanto houver SUC Plans existentes no cluster management, eles verão o seguinte erro do Fleet:

Not installed: Unable to continue with install: Plan <plan_name> in namespace <plan_namespace> exists and cannot be imported into the current release: invalid ownership metadata; annotation validation error..

Como mencionado em Seção 58.2.4.2, “Visão geral”, os upgrades do SO são feitos enviando SUC plans para o cluster desejado por meio de uma das seguintes maneiras:

Para determinar qual recurso você deve usar, consulte Seção 58.2.2, “Determine seu caso de uso”.

Para casos de uso em que você deseja implantar o OS SUC plans a partir de uma ferramenta GitOps de terceiros, consulte Seção 58.2.4.4.3, “Implantação do plano SUC - fluxo de trabalho GitOps de terceiros”

58.2.4.4.1 Implantação do plano SUC - recurso GitRepo

Um recurso GitRepo, que implanta o OS SUC plans necessário, pode ser implantado de uma das seguintes maneiras:

  1. Através do Rancher UI - Seção 58.2.4.4.1.1, “Criação de GitRepo - UI do Rancher” (quando Rancher estiver disponível).

  2. Ao implantar manualmente (Seção 58.2.4.4.1.2, “Criação de GitRepo - manual”) o recurso no seu management cluster.

Uma vez implantado, para monitorar o processo de upgrade do SO dos nós do seu cluster alvo, consulte Seção 20.3, “Monitoramento de Planos do Upgrade Controller do Sistema”.

58.2.4.4.1.1 Criação de GitRepo - UI do Rancher

Para criar um recurso GitRepo através da UI do Rancher, siga a documentação oficial deles.

A equipe Edge mantém um fleet pronto para uso. Dependendo do seu ambiente, este fleet pode ser usado diretamente ou como um modelo.

Importante
Importante

Sempre use este fleet a partir de uma tag de release válida do Edge.

Para casos de uso onde nenhuma alteração personalizada precisa ser incluída no SUC plans que o fleet entrega, os usuários podem referenciar diretamente o fleet os-upgrade do repositório suse-edge/fleet-examples.

Em casos onde alterações personalizadas são necessárias (por exemplo, para adicionar tolerâncias personalizadas), os usuários devem referenciar o fleet os-upgrade de um repositório separado, permitindo que adicionem as alterações aos planos SUC conforme necessário.

Um exemplo de como um GitRepo pode ser configurado para usar o fleet do repositório suse-edge/fleet-examples, pode ser visto aqui.

58.2.4.4.1.2 Criação de GitRepo - manual
  1. Puxe o recurso GitRepo:

    curl -o os-upgrade-gitrepo.yaml https://raw.githubusercontent.com/suse-edge/fleet-examples/refs/tags/release-3.6.1/gitrepos/day2/os-upgrade-gitrepo.yaml
  2. Edite a configuração do GitRepo:

    • Remova a seção spec.targets - necessária apenas para clusters downstream.

      # Example using sed
      sed -i.bak '/^  targets:/,$d' os-upgrade-gitrepo.yaml && rm -f os-upgrade-gitrepo.yaml.bak
      
      # Example using yq (v4+)
      yq eval 'del(.spec.targets)' -i os-upgrade-gitrepo.yaml
    • Aponte o namespace do GitRepo para o namespace fleet-local - feito para implantar o recurso no cluster de gerenciamento.

      # Example using sed
      sed -i.bak 's/namespace: fleet-default/namespace: fleet-local/' os-upgrade-gitrepo.yaml && rm -f os-upgrade-gitrepo.yaml.bak
      
      # Example using yq (v4+)
      yq eval '.metadata.namespace = "fleet-local"' -i os-upgrade-gitrepo.yaml
  3. Aplique o recurso GitRepo ao seu management cluster:

    kubectl apply -f os-upgrade-gitrepo.yaml
  4. Visualize o recurso GitRepo criado no namespace fleet-local:

    kubectl get gitrepo os-upgrade -n fleet-local
    
    # Example output
    NAME            REPO                                              COMMIT         BUNDLEDEPLOYMENTS-READY   STATUS
    os-upgrade      https://github.com/suse-edge/fleet-examples.git   release-3.6.1  0/0
58.2.4.4.2 Implantação do plano SUC - Recurso de Bundle

Um recurso Bundle, que inclui os OS SUC Plans necessários, pode ser implantado de uma das seguintes maneiras:

  1. Através do Rancher UI - Seção 58.2.4.4.2.1, “Criação de Bundle - Interface do Rancher” (quando Rancher estiver disponível).

  2. Ao implantar manualmente (Seção 58.2.4.4.2.2, “Criação de Bundle - manual”) o recurso no seu management cluster.

Uma vez implantado, para monitorar o processo de fazer upgrade do SO dos nós do seu cluster alvo, consulte Seção 20.3, “Monitoramento de Planos do Upgrade Controller do Sistema”.

58.2.4.4.2.1 Criação de Bundle - Interface do Rancher

A equipe Edge mantém um bundle pronto para uso que pode ser usado nas etapas abaixo.

Importante
Importante

Sempre use este bundle a partir de uma tag de release Edge válida.

Para criar um bundle através da interface do Rancher:

  1. No canto superior esquerdo, clique em ☰ → Continuous Delivery

  2. Vá para Avançado > Bundles

  3. Selecione Criar a partir de YAML

  4. A partir daqui, você pode criar o Bundle de uma das seguintes maneiras:

    Nota
    Nota

    Pode haver casos de uso em que você precise incluir alterações personalizadas no SUC plans que o bundle inclui (por exemplo, para adicionar tolerâncias personalizadas). Certifique-se de incluir essas alterações no bundle que será gerado pelas etapas abaixo.

    1. Copiando manualmente o conteúdo do bundle de suse-edge/fleet-examples para a página Criar a partir de YAML.

    2. Clonando o repositório suse-edge/fleet-examples da release desejada e selecionando a opção Ler a partir de arquivo na página Criar a partir de YAML. A partir daí, navegue até o local do bundle (bundles/day2/system-upgrade-controller-plans/os-upgrade) e selecione o arquivo do bundle. Isso preencherá automaticamente a página Criar a partir de YAML com o conteúdo do bundle.

  5. Edite o Bundle na interface do usuário do Rancher:

    • Altere o namespace do Bundle para apontar para o namespace fleet-local.

      # Example
      kind: Bundle
      apiVersion: fleet.cattle.io/v1alpha1
      metadata:
        name: os-upgrade
        namespace: fleet-local
      ...
    • Altere os clusters target para o Bundle apontar para o seu cluster local(gerenciamento):

      spec:
        targets:
        - clusterName: local
      Nota
      Nota

      Existem alguns casos de uso em que seu cluster local pode ter um nome diferente.

      Para recuperar o nome do seu cluster local, execute o comando abaixo:

      kubectl get clusters.fleet.cattle.io -n fleet-local
  6. Selecione Criar

58.2.4.4.2.2 Criação de Bundle - manual
  1. Obtenha o recurso Bundle:

    curl -o os-upgrade-bundle.yaml https://raw.githubusercontent.com/suse-edge/fleet-examples/refs/tags/release-3.6.1/bundles/day2/system-upgrade-controller-plans/os-upgrade/os-upgrade-bundle.yaml
  2. Edite a configuração do Bundle:

    • Altere os clusters target para o Bundle apontar para o seu cluster local(gerenciamento):

      spec:
        targets:
        - clusterName: local
      Nota
      Nota

      Existem alguns casos de uso em que seu cluster local pode ter um nome diferente.

      Para recuperar o nome do seu cluster local, execute o comando abaixo:

      kubectl get clusters.fleet.cattle.io -n fleet-local
    • Altere o namespace do Bundle para apontar para o namespace fleet-local.

      # Example
      kind: Bundle
      apiVersion: fleet.cattle.io/v1alpha1
      metadata:
        name: os-upgrade
        namespace: fleet-local
      ...
  3. Aplique o recurso Bundle ao seu management cluster:

    kubectl apply -f os-upgrade-bundle.yaml
  4. Visualize o recurso Bundle criado no namespace fleet-local:

    kubectl get bundles -n fleet-local
58.2.4.4.3 Implantação do plano SUC - fluxo de trabalho GitOps de terceiros

Pode haver casos de uso em que os usuários desejem incorporar o OS SUC plans ao seu próprio fluxo de trabalho GitOps de terceiros (por exemplo, Flux).

Para obter os recursos de fazer upgrade do SO de que você precisa, primeiro determine a tag de release do Edge do repositório suse-edge/fleet-examples que você deseja usar.

Depois disso, os recursos podem ser encontrados em fleets/day2/system-upgrade-controller-plans/os-upgrade, onde:

  • plan-control-plane.yaml é um recurso de plano SUC para nós de control-plane.

  • plan-worker.yaml é um recurso de plano SUC para nós de worker.

  • secret.yaml é um Secret que contém o script upgrade.sh, que é responsável por criar o systemd.service (Seção 58.2.4.1.1, “systemd.service”).

  • config-map.yaml é um ConfigMap que contém configurações que são consumidas pelo script upgrade.sh.

Importante
Importante

Estes recursos Plan são interpretados pelo System Upgrade Controller e devem ser implantados em cada cluster downstream que você deseja fazer upgrade. Para informações sobre a implantação do SUC, consulte Seção 20.2, “Instalando o Upgrade Controller do Sistema”.

Para entender melhor como seu fluxo de trabalho GitOps pode ser usado para implantar os SUC Plans para fazer upgrade do SO, pode ser útil dar uma olhada na visão geral (Seção 58.2.4.2, “Visão geral”).

58.2.5 Atualização da versão do Kubernetes

Esta seção descreve como realizar uma atualização do Kubernetes usando o Capítulo 9, Fleet e o Capítulo 20, Upgrade Controller do Sistema.

Os tópicos a seguir são abordados como parte desta seção:

  1. Seção 58.2.5.1, “Componentes” - componentes adicionais usados pelo processo de atualização.

  2. Seção 58.2.5.2, “Visão geral” - visão geral do processo de atualização.

  3. Seção 58.2.5.3, “Requisitos” - requisitos do processo de atualização.

  4. Seção 58.2.5.4, “Atualização do K8s - implantação do plano SUC” - informações sobre como implantar o SUC plans, responsável por acionar o processo de atualização.

58.2.5.1 Componentes

Esta seção aborda os componentes personalizados que o processo K8s upgrade usa em vez dos componentes (Seção 58.2.1, “Componentes”) padrão de "Dia 2".

58.2.5.1.1 rke2-upgrade

Imagem de contêiner responsável por atualizar a versão do RKE2 de um nó específico.

Distribuída por meio de um Pod criado pelo SUC com base em um Plano SUC. O Plano deve estar localizado em cada cluster que precise de uma atualização do RKE2.

Para obter mais informações sobre como a imagem rke2-upgrade realiza a atualização, consulte a documentação upstream.

58.2.5.1.2 k3s-upgrade

Imagem de contêiner responsável por atualizar a versão do K3s de um nó específico.

Distribuída por meio de um Pod criado pelo SUC com base em um Plano SUC. O Plano deve estar localizado em cada cluster que precise de um upgrade do K3s.

Para obter mais informações sobre como a imagem k3s-upgrade realiza a atualização, consulte a documentação upstream.

58.2.5.2 Visão geral

O upgrade da distribuição Kubernetes para nós de cluster management é feito utilizando Fleet e o System Upgrade Controller (SUC).

Fleet é usado para implantar e gerenciar SUC plans no cluster desejado.

Nota
Nota

SUC plans são recursos personalizados que descrevem as etapas que o SUC precisa seguir para que uma tarefa específica seja executada em um conjunto de nós. Para um exemplo de como um SUC plan se parece, consulte o repositório upstream.

Os K8s SUC plans são enviados em cada cluster implantando um recurso GitRepo ou Bundle em um workspace específico do Fleet. O Fleet recupera o GitRepo/Bundle implantado e implanta seu conteúdo (o K8s SUC plans) no(s) cluster(es) desejado(s).

Nota
Nota

Recursos GitRepo/Bundle são sempre implantados no management cluster. Se usar um recurso GitRepo ou Bundle depende do seu caso de uso, verifique Seção 58.2.2, “Determine seu caso de uso” para mais informações.

K8s SUC plans descrevem o seguinte fluxo de trabalho:

  1. Sempre cordon os nós antes de fazer upgrade do K8s.

  2. Sempre atualize os nós control-plane antes dos nós worker.

  3. Sempre atualize os nós control-plane um nó por vez e os nós worker dois nós por vez.

Uma vez que os K8s SUC plans são implantados, o fluxo de trabalho parece com isto:

  1. O SUC reconcilia os K8s SUC plans implantados e cria um Kubernetes Job em cada nó.

  2. Dependendo da distribuição do Kubernetes, o Job criará um Pod que executa a imagem de contêiner rke2-upgrade (Seção 58.2.5.1.1, “rke2-upgrade”) ou k3s-upgrade (Seção 58.2.5.1.2, “k3s-upgrade”).

  3. O Pod criado passará pelo seguinte fluxo de trabalho:

    1. Substitua o binário rke2/k3s existente no nó pelo da imagem rke2-upgrade/k3s-upgrade.

    2. Encerre o processo rke2/k3s em execução.

  4. Encerrar o processo rke2/k3s aciona uma reinicialização, iniciando um novo processo que executa o binário atualizado, resultando em uma versão de distribuição do Kubernetes atualizada.

Abaixo você pode encontrar um diagrama da descrição acima:

fleet day2 management k8s upgrade

58.2.5.3 Requisitos

  1. Faça backup da sua distribuição Kubernetes:

    1. Para clusters RKE2, consulte a documentação de Backup e Restauração do RKE2.

    2. Para clusters K3s, consulte a documentação de Backup e Restauração do K3s.

  2. Certifique-se de que as tolerâncias do Plano SUC correspondam às tolerâncias do nó - Se os nós do seu cluster Kubernetes tiverem taints personalizados, certifique-se de adicionar tolerâncias para esses taints nos Planos SUC. Por padrão, os Planos SUC possuem tolerâncias apenas para nós de plano de controle. As tolerâncias padrão incluem:

    • CriticalAddonsOnly=true:NoExecute

    • node-role.kubernetes.io/control-plane:NoSchedule

    • node-role.kubernetes.io/etcd:NoExecute

      Nota
      Nota

      Quaisquer tolerâncias adicionais devem ser adicionadas na seção .spec.tolerations de cada Plano. Os Planos SUC relacionados à atualização da versão do Kubernetes podem ser encontrados no repositório suse-edge/fleet-examples em:

      • Para RKE2 - fleets/day2/system-upgrade-controller-plans/rke2-upgrade

      • Para K3s - fleets/day2/system-upgrade-controller-plans/k3s-upgrade

      Certifique-se de usar os Planos de uma tag de lançamento de repositório válida.

      Um exemplo de definição de tolerâncias personalizadas para o Plano SUC do plano de controle do RKE2 seria assim:

      apiVersion: upgrade.cattle.io/v1
      kind: Plan
      metadata:
        name: rke2-upgrade-control-plane
      spec:
        ...
        tolerations:
        # default tolerations
        - key: "CriticalAddonsOnly"
          operator: "Equal"
          value: "true"
          effect: "NoExecute"
        - key: "node-role.kubernetes.io/control-plane"
          operator: "Equal"
          effect: "NoSchedule"
        - key: "node-role.kubernetes.io/etcd"
          operator: "Equal"
          effect: "NoExecute"
        # custom toleration
        - key: "foo"
          operator: "Equal"
          value: "bar"
          effect: "NoSchedule"
      ...

58.2.5.4 Atualização do K8s - implantação do plano SUC

Importante
Importante

Para ambientes previamente atualizados usando este procedimento, os usuários devem garantir que um das seguintes etapas seja concluído:

  • Remove any previously deployed SUC Plans related to older Edge release versions from the management cluster - pode ser feito removendo o cluster desejado da GitRepo/Bundle configuração de destino existente, ou removendo o recurso GitRepo/Bundle por completo.

  • Reuse the existing GitRepo/Bundle resource - pode ser feito apontando a revisão do recurso para uma nova tag que contenha os Fleet corretos para o suse-edge/fleet-examples lançamento desejado.

Isso é feito para evitar conflitos entre SUC Plans para versões de lançamento do Edge mais antigas.

Se os usuários tentarem fazer upgrade enquanto houver SUC Plans existentes no cluster management, eles verão o seguinte erro do Fleet:

Not installed: Unable to continue with install: Plan <plan_name> in namespace <plan_namespace> exists and cannot be imported into the current release: invalid ownership metadata; annotation validation error..

Como mencionado em Seção 58.2.5.2, “Visão geral”, as atualizações do Kubernetes são feitas enviando SUC plans para o cluster desejado através de uma das seguintes maneiras:

Para determinar qual recurso você deve usar, consulte Seção 58.2.2, “Determine seu caso de uso”.

Para casos de uso onde você deseja implantar o K8s SUC plans a partir de uma ferramenta GitOps de terceiros, consulte Seção 58.2.5.4.3, “Implantação do plano SUC - fluxo de trabalho GitOps de terceiros”

58.2.5.4.1 Implantação de plano SUC - recurso GitRepo

Um recurso GitRepo, que envia o K8s SUC plans necessário, pode ser implantado de uma das seguintes maneiras:

  1. Através do Rancher UI - Seção 58.2.5.4.1.1, “Criação de GitRepo - IU do Rancher” (quando Rancher estiver disponível).

  2. Por implantação manual (Seção 58.2.5.4.1.2, “Criação de GitRepo - manual”) do recurso no seu management cluster.

Uma vez implantado, para monitorar o processo de fazer upgrade do Kubernetes dos nós do seu cluster de destino, consulte Seção 20.3, “Monitoramento de Planos do Upgrade Controller do Sistema”.

58.2.5.4.1.1 Criação de GitRepo - IU do Rancher

Para criar um recurso GitRepo através da IU do Rancher, siga a documentação oficial deles.

A equipe Edge mantém fleets prontos para uso para as distribuições Kubernetes rke2 e k3s. Dependendo do seu ambiente, este fleet pode ser usado diretamente ou como um modelo.

Importante
Importante

Sempre use esses fleets a partir de uma tag de release válida do Edge.

Para casos de uso onde não é necessário incluir alterações personalizadas no SUC plans que esses fleets enviam, os usuários podem referenciar diretamente os fleets do repositório suse-edge/fleet-examples.

Em casos onde alterações personalizadas são necessárias (por exemplo, para adicionar tolerations personalizadas), os usuários devem referenciar os fleets de um repositório separado, permitindo-lhes adicionar as alterações aos planos SUC conforme necessário.

Exemplos de configuração para um recurso GitRepo usando os fleets do repositório suse-edge/fleet-examples:

58.2.5.4.1.2 Criação de GitRepo - manual
  1. Puxe o recurso GitRepo:

    • Para clusters RKE2:

      curl -o rke2-upgrade-gitrepo.yaml https://raw.githubusercontent.com/suse-edge/fleet-examples/refs/tags/release-3.6.1/gitrepos/day2/rke2-upgrade-gitrepo.yaml
    • Para clusters K3s:

      curl -o k3s-upgrade-gitrepo.yaml https://raw.githubusercontent.com/suse-edge/fleet-examples/refs/tags/release-3.6.1/gitrepos/day2/k3s-upgrade-gitrepo.yaml
  2. Edite a configuração do GitRepo:

    • Remova a seção spec.targets - necessária apenas para clusters downstream.

      • Para RKE2:

        # Example using sed
        sed -i.bak '/^  targets:/,$d' rke2-upgrade-gitrepo.yaml && rm -f rke2-upgrade-gitrepo.yaml.bak
        
        # Example using yq (v4+)
        yq eval 'del(.spec.targets)' -i rke2-upgrade-gitrepo.yaml
      • Para K3s:

        # Example using sed
        sed -i.bak '/^  targets:/,$d' k3s-upgrade-gitrepo.yaml && rm -f k3s-upgrade-gitrepo.yaml.bak
        
        # Example using yq (v4+)
        yq eval 'del(.spec.targets)' -i k3s-upgrade-gitrepo.yaml
    • Aponte o namespace do GitRepo para o namespace fleet-local - feito para implantar o recurso no cluster de gerenciamento.

      • Para RKE2:

        # Example using sed
        sed -i.bak 's/namespace: fleet-default/namespace: fleet-local/' rke2-upgrade-gitrepo.yaml && rm -f rke2-upgrade-gitrepo.yaml.bak
        
        # Example using yq (v4+)
        yq eval '.metadata.namespace = "fleet-local"' -i rke2-upgrade-gitrepo.yaml
      • Para K3s:

        # Example using sed
        sed -i.bak 's/namespace: fleet-default/namespace: fleet-local/' k3s-upgrade-gitrepo.yaml && rm -f k3s-upgrade-gitrepo.yaml.bak
        
        # Example using yq (v4+)
        yq eval '.metadata.namespace = "fleet-local"' -i k3s-upgrade-gitrepo.yaml
  3. Aplique os recursos GitRepo ao seu management cluster:

    # RKE2
    kubectl apply -f rke2-upgrade-gitrepo.yaml
    
    # K3s
    kubectl apply -f k3s-upgrade-gitrepo.yaml
  4. Visualize o recurso GitRepo criado no namespace fleet-local:

    # RKE2
    kubectl get gitrepo rke2-upgrade -n fleet-local
    
    # K3s
    kubectl get gitrepo k3s-upgrade -n fleet-local
    
    # Example output
    NAME           REPO                                              COMMIT          BUNDLEDEPLOYMENTS-READY   STATUS
    k3s-upgrade    https://github.com/suse-edge/fleet-examples.git   fleet-local   0/0
    rke2-upgrade   https://github.com/suse-edge/fleet-examples.git   fleet-local   0/0
58.2.5.4.2 Implantação do plano SUC - Recurso Bundle

Um recurso Bundle, que fornece os Kubernetes upgrade SUC Plans necessários, pode ser implantado de uma das seguintes maneiras:

  1. Através do Rancher UI - Seção 58.2.5.4.2.1, “Criação de Bundle - Interface do Rancher” (quando Rancher estiver disponível).

  2. Implantando manualmente (Seção 58.2.5.4.2.2, “Criação de Bundle - manual”) o recurso no seu management cluster.

Uma vez implantado, para monitorar o processo de atualização do Kubernetes dos nós do seu cluster de destino, consulte Seção 20.3, “Monitoramento de Planos do Upgrade Controller do Sistema”.

58.2.5.4.2.1 Criação de Bundle - Interface do Rancher

A equipe Edge mantém bundles prontos para uso para as distribuições Kubernetes rke2 e k3s. Dependendo do seu ambiente, esses bundles podem ser usados diretamente ou como um modelo.

Importante
Importante

Sempre use este bundle a partir de uma tag de release Edge válida.

Para criar um Bundle através da interface do Rancher:

  1. No canto superior esquerdo, clique em ☰ → Entrega contínua

  2. Vá para Avançado > Bundle

  3. Selecione Criar a partir de YAML

  4. A partir daqui, você pode criar o Bundle de uma das seguintes maneiras:

    Nota
    Nota

    Pode haver casos de uso em que você precise incluir alterações personalizadas no SUC plans que o Bundle fornece (por exemplo, para adicionar tolerâncias personalizadas). Certifique-se de incluir essas alterações no Bundle que será gerado pelas etapas abaixo.

    1. Copiando manualmente o conteúdo do Bundle para RKE2 ou K3s de suse-edge/fleet-examples para a página Criar a partir de YAML.

    2. Clonando o repositório suse-edge/fleet-examples da tag de release desejada e selecionando a opção Ler de Arquivo na página Criar a partir de YAML. A partir daí, navegue até o Bundle que você precisa (bundles/day2/system-upgrade-controller-plans/rke2-upgrade/plan-bundle.yaml para RKE2 e bundles/day2/system-upgrade-controller-plans/k3s-upgrade/plan-bundle.yaml para K3s). Isso preencherá automaticamente a página Criar a partir de YAML com o conteúdo do Bundle.

  5. Edite o Bundle na interface do Rancher:

    • Altere o namespace do Bundle para apontar para o namespace fleet-local.

      # Example
      kind: Bundle
      apiVersion: fleet.cattle.io/v1alpha1
      metadata:
        name: rke2-upgrade
        namespace: fleet-local
      ...
    • Altere os clusters de destino para o Bundle para apontar para o seu cluster local (gerenciamento):

      spec:
        targets:
        - clusterName: local
      Nota
      Nota

      Existem alguns casos de uso em que seu cluster local pode ter um nome diferente.

      Para recuperar o nome do seu cluster local, execute o comando abaixo:

      kubectl get clusters.fleet.cattle.io -n fleet-local
  6. Selecione Criar

58.2.5.4.2.2 Criação de Bundle - manual
  1. Puxe os recursos do Bundle:

    • Para clusters RKE2:

      curl -o rke2-plan-bundle.yaml https://raw.githubusercontent.com/suse-edge/fleet-examples/refs/tags/release-3.6.1/bundles/day2/system-upgrade-controller-plans/rke2-upgrade/plan-bundle.yaml
    • Para clusters K3s:

      curl -o k3s-plan-bundle.yaml https://raw.githubusercontent.com/suse-edge/fleet-examples/refs/tags/release-3.6.1/bundles/day2/system-upgrade-controller-plans/k3s-upgrade/plan-bundle.yaml
  2. Edite a configuração de Bundle:

    • Altere os clusters de destino para o Bundle para apontar para o seu cluster local (gerenciamento):

      spec:
        targets:
        - clusterName: local
      Nota
      Nota

      Existem alguns casos de uso em que seu cluster local pode ter um nome diferente.

      Para recuperar o nome do seu cluster local, execute o comando abaixo:

      kubectl get clusters.fleet.cattle.io -n fleet-local
    • Altere o namespace do Bundle para apontar para o namespace fleet-local.

      # Example
      kind: Bundle
      apiVersion: fleet.cattle.io/v1alpha1
      metadata:
        name: rke2-upgrade
        namespace: fleet-local
      ...
  3. Aplique os recursos do Bundle ao seu management cluster:

    # For RKE2
    kubectl apply -f rke2-plan-bundle.yaml
    
    # For K3s
    kubectl apply -f k3s-plan-bundle.yaml
  4. Visualize o recurso Bundle criado no namespace fleet-local:

    # For RKE2
    kubectl get bundles rke2-upgrade -n fleet-local
    
    # For K3s
    kubectl get bundles k3s-upgrade -n fleet-local
    
    # Example output
    NAME           BUNDLEDEPLOYMENTS-READY   STATUS
    k3s-upgrade    0/0
    rke2-upgrade   0/0
58.2.5.4.3 Implantação do plano SUC - fluxo de trabalho GitOps de terceiros

Pode haver casos de uso em que os usuários gostariam de incorporar o Kubernetes upgrade SUC plans ao seu próprio fluxo de trabalho GitOps de terceiros (por exemplo, Flux).

Para obter os recursos de atualização do K8s de que você precisa, primeiro determine a tag de release do Edge do repositório suse-edge/fleet-examples que você deseja usar.

Depois disso, os recursos podem ser encontrados em:

  • Para uma atualização de cluster RKE2:

    • Para nós control-plane - fleets/day2/system-upgrade-controller-plans/rke2-upgrade/plan-control-plane.yaml

    • Para nós worker - fleets/day2/system-upgrade-controller-plans/rke2-upgrade/plan-worker.yaml

  • Para uma atualização de cluster K3s:

    • Para nós control-plane - fleets/day2/system-upgrade-controller-plans/k3s-upgrade/plan-control-plane.yaml

    • Para nós worker - fleets/day2/system-upgrade-controller-plans/k3s-upgrade/plan-worker.yaml

Importante
Importante

Esses recursos Plan são interpretados pelo System Upgrade Controller e devem ser implantados em cada cluster downstream que você deseja atualizar. Para informações sobre a implantação do SUC, consulte Seção 20.2, “Instalando o Upgrade Controller do Sistema”.

Para entender melhor como seu fluxo de trabalho GitOps pode ser usado para implantar os SUC Plans para fazer upgrade da versão do Kubernetes, pode ser benéfico dar uma olhada na visão geral (Seção 58.2.5.2, “Visão geral”) do procedimento de atualização usando Fleet.

58.2.6 Fazer upgrade do Helm chart

Esta seção abrange as seguintes partes:

  1. Seção 58.2.6.1, “Preparação para ambientes air-gapped” - contém informações sobre como enviar charts e imagens OCI relacionados ao Edge para o seu registro privado.

  2. Seção 58.2.6.2, “Procedimento de upgrade” - contém informações sobre diferentes casos de uso de upgrade do Helm chart e seu procedimento de upgrade.

58.2.6.1 Preparação para ambientes air-gapped

58.2.6.1.1 Certifique-se de ter acesso ao Fleet do seu Helm chart

Dependendo do que seu ambiente suporta, você pode escolher uma das seguintes opções:

  1. Hospede os recursos do Fleet do seu chart em um servidor Git local que seja acessível pelo seu management cluster.

  2. Use a CLI do Fleet para converter um Helm chart em um Bundle que você pode usar diretamente e que não precisará ser hospedado em algum lugar. A CLI do Fleet pode ser obtida na página de release, para usuários de Mac existe uma fleet-cli Homebrew Formulae.

58.2.6.1.2 Encontre os ativos necessários para a sua versão de release do Edge
  1. Vá para a página de release do "Day 2", encontre a release do Edge para a qual você deseja atualizar seu chart e clique em Assets.

  2. Na seção "Assets", baixe os seguintes arquivos:

    Release File

    Descrição

    edge-save-images.sh

    Extrai as imagens especificadas no arquivo edge-release-images.txt e as empacota dentro de um arquivo '.tar.gz'.

    edge-save-oci-artefacts.sh

    Extrai as imagens de chart OCI relacionadas à release específica do Edge e as empacota dentro de um arquivo '.tar.gz'.

    edge-load-images.sh

    Carrega imagens de um arquivo '.tar.gz', renomeia as tags e as envia para um registro privado.

    edge-load-oci-artefacts.sh

    Recebe um diretório contendo pacotes de chart OCI '.tgz' do Edge e os carrega em um registro privado.

    edge-release-helm-oci-artefacts.txt

    Contém uma lista de imagens de chart OCI relacionadas a uma release específica do Edge.

    edge-release-images.txt

    Contém uma lista de imagens relacionadas a uma release específica do Edge.

58.2.6.1.3 Crie o arquivo de imagens de release do Edge

Em uma máquina com acesso à internet:

  1. Torne o edge-save-images.sh executável:

    chmod +x edge-save-images.sh
  2. Gere o arquivo de imagem:

    ./edge-save-images.sh --source-registry registry.suse.com
  3. Isso criará um arquivo pronto para carregamento chamado edge-images.tar.gz.

    Nota
    Nota

    Se a opção -i|--images for especificada, o nome do arquivo pode ser diferente.

  4. Copie este arquivo para sua máquina air-gapped:

    scp edge-images.tar.gz <user>@<machine_ip>:/path
58.2.6.1.4 Crie o arquivo de imagens de chart OCI do Edge

Em uma máquina com acesso à internet:

  1. Torne o edge-save-oci-artefacts.sh executável:

    chmod +x edge-save-oci-artefacts.sh
  2. Gere o arquivo de imagem de chart OCI:

    ./edge-save-oci-artefacts.sh --source-registry registry.suse.com
  3. Isso criará um arquivo chamado oci-artefacts.tar.gz.

    Nota
    Nota

    Se a opção -a|--archive for especificada, o nome do arquivo pode ser diferente.

  4. Copie este arquivo para sua máquina air-gapped:

    scp oci-artefacts.tar.gz <user>@<machine_ip>:/path
58.2.6.1.5 Carregue as imagens de release do Edge em sua máquina air-gapped

Em sua máquina air-gapped:

  1. Faça login no seu registro privado (se necessário):

    podman login <REGISTRY.YOURDOMAIN.COM:PORT>
  2. Torne o edge-load-images.sh executável:

    chmod +x edge-load-images.sh
  3. Execute o script, passando o arquivo copiado edge-images.tar.gz anteriormente:

    ./edge-load-images.sh --source-registry registry.suse.com --registry <REGISTRY.YOURDOMAIN.COM:PORT> --images edge-images.tar.gz
    Nota
    Nota

    Isso carregará todas as imagens do edge-images.tar.gz, renomeará as tags e as enviará para o registro especificado na opção --registry.

58.2.6.1.6 Carregue as imagens de chart OCI do Edge para sua máquina air-gapped.

Em sua máquina air-gapped:

  1. Faça login no seu registro privado (se necessário):

    podman login <REGISTRY.YOURDOMAIN.COM:PORT>
  2. Torne o edge-load-oci-artefacts.sh executável:

    chmod +x edge-load-oci-artefacts.sh
  3. Descompacte o arquivo copiado oci-artefacts.tar.gz:

    tar -xvf oci-artefacts.tar.gz
  4. Isso produzirá um diretório com o modelo de nomenclatura edge-release-oci-tgz-<date>

  5. Passe este diretório para o script edge-load-oci-artefacts.sh para carregar as imagens do chart Edge OCI para seu registro privado:

    Nota
    Nota

    Este script pressupõe que a CLI helm tenha sido pré-instalada em seu ambiente. Para instruções de instalação do Helm, consulte Instalando o Helm.

    ./edge-load-oci-artefacts.sh --archive-directory edge-release-oci-tgz-<date> --registry <REGISTRY.YOURDOMAIN.COM:PORT> --source-registry registry.suse.com
58.2.6.1.7 Configure seu registro privado em sua distribuição Kubernetes

Para RKE2, consulte Configuração de Registro Privado

Para K3s, consulte Configuração de Registro Privado

58.2.6.2 Procedimento de upgrade

Esta seção foca nos seguintes casos de uso do procedimento de upgrade do Helm:

Importante
Importante

Charts do Helm implantados manualmente não podem ser atualizados de forma confiável. Sugerimos reimplantar o chart do Helm usando o método Seção 58.2.6.2.1, “Tenho um novo cluster e gostaria de implantar e gerenciar um chart Helm do Edge.”.

58.2.6.2.1 Tenho um novo cluster e gostaria de implantar e gerenciar um chart Helm do Edge.

Esta seção aborda como:

58.2.6.2.1.1 Prepare os recursos do Fleet para o seu chart.
  1. Adquira os recursos do Fleet do chart a partir da tag de release do Edge que você deseja usar.

  2. Navegue até o Fleet do chart do Helm (fleets/day2/chart-templates/<chart>).

  3. Se você pretende usar um fluxo de trabalho GitOps, copie o diretório do Fleet do chart para o repositório Git de onde você fará o GitOps.

  4. Opcionalmente, se o chart do Helm exigir configurações em seus values, edite a configuração .helm.values dentro do arquivo fleet.yaml do diretório copiado.

  5. Opcionalmente, podem existir casos de uso em que você precise adicionar recursos adicionais ao Fleet do seu chart para que ele possa se ajustar melhor ao seu ambiente. Para obter informações sobre como aprimorar seu diretório Fleet, consulte Conteúdo do Repositório Git.

Nota
Nota

Em alguns casos, o tempo limite padrão que o Fleet usa para operações do Helm pode ser insuficiente, resultando no seguinte erro:

failed pre-install: context deadline exceeded

Nesses casos, adicione a propriedade timeoutSeconds sob a configuração helm do seu arquivo fleet.yaml.

Um exemplo para o Helm chart longhorn seria assim:

  • Estrutura do repositório Git do usuário:

    <user_repository_root>
    ├── longhorn
    │   └── fleet.yaml
    └── longhorn-crd
        └── fleet.yaml
  • Conteúdo fleet.yaml preenchido com dados Longhorn do usuário:

    defaultNamespace: longhorn-system
    
    helm:
      # timeoutSeconds: 10
      releaseName: "longhorn"
      chart: "longhorn"
      repo: "https://charts.rancher.io/"
      version: "1.11.2"
      takeOwnership: true
      # custom chart value overrides
      values:
        # Example for user provided custom values content
        defaultSettings:
          deletingConfirmationFlag: true
    
    # https://fleet.rancher.io/bundle-diffs
    diff:
      comparePatches:
      - apiVersion: apiextensions.k8s.io/v1
        kind: CustomResourceDefinition
        name: engineimages.longhorn.io
        operations:
        - {"op":"remove", "path":"/status/conditions"}
        - {"op":"remove", "path":"/status/storedVersions"}
        - {"op":"remove", "path":"/status/acceptedNames"}
      - apiVersion: apiextensions.k8s.io/v1
        kind: CustomResourceDefinition
        name: nodes.longhorn.io
        operations:
        - {"op":"remove", "path":"/status/conditions"}
        - {"op":"remove", "path":"/status/storedVersions"}
        - {"op":"remove", "path":"/status/acceptedNames"}
      - apiVersion: apiextensions.k8s.io/v1
        kind: CustomResourceDefinition
        name: volumes.longhorn.io
        operations:
        - {"op":"remove", "path":"/status/conditions"}
        - {"op":"remove", "path":"/status/storedVersions"}
        - {"op":"remove", "path":"/status/acceptedNames"}
    Nota
    Nota

    Estes são apenas valores de exemplo que são usados para ilustrar configurações personalizadas no chart longhorn. Eles NÃO devem ser tratados como diretrizes de implantação para o chart longhorn.

58.2.6.2.1.2 Implante o Fleet para o seu chart

Você pode implantar o Fleet para o seu chart usando um GitRepo (Seção 58.2.6.2.1.2.1, “GitRepo”) ou um Bundle (Seção 58.2.6.2.1.2.2, “Pacote”).

Nota
Nota

Ao implantar o Fleet, se você receber uma mensagem Modified, certifique-se de adicionar uma entrada comparePatches correspondente à seção diff do Fleet. Para mais informações, consulte Gerando Diffs para Ignorar GitRepos Modificados.

58.2.6.2.1.2.1 GitRepo

O recurso GitRepo do Fleet contém informações sobre como acessar os recursos do Fleet do seu chart e a quais clusters ele precisa aplicar esses recursos.

O recurso GitRepo pode ser implantado através da Rancher UI, ou manualmente, implantando o recurso no management cluster.

Exemplo de recurso Longhorn GitRepo para implantação manual *:

apiVersion: fleet.cattle.io/v1alpha1
kind: GitRepo
metadata:
  name: longhorn-git-repo
  namespace: fleet-local
spec:
  # If using a tag
  # revision: user_repository_tag
  #
  # If using a branch
  # branch: user_repository_branch
  paths:
  # As seen in the 'Prepare your Fleet resources' example
  - longhorn
  - longhorn-crd
  repo: user_repository_url
58.2.6.2.1.2.2 Pacote

Os recursos Bundle contêm os recursos brutos do Kubernetes que precisam ser implantados pelo Fleet. Normalmente, recomenda-se usar a abordagem GitRepo, mas para casos de uso em que o ambiente é air-gapped e não pode suportar um servidor Git local, o Bundles pode ajudá-lo a propagar o Fleet do seu chart Helm para seus clusters de destino.

Um Bundle pode ser implantado através da Rancher UI (Continuous Delivery → Advanced → Bundles → Create from YAML) ou implantando manualmente o recurso Bundle no namespace correto do Fleet. Para obter informações sobre os namespaces do Fleet, consulte a documentação upstream.

Bundles para charts Helm do Edge podem ser criados utilizando a abordagem Converter um chart Helm em um Bundle do Fleet.

Abaixo você pode encontrar um exemplo de como criar um recurso Bundle a partir dos modelos de Fleet de charts Helm longhorn e longhorn-crd e implantar manualmente este bundle no seu management cluster.

Nota
Nota

Para ilustrar o fluxo de trabalho, o exemplo abaixo usa a estrutura de diretório suse-edge/fleet-examples.

  1. Navegue até o modelo de Fleet do chart longhorn:

    cd fleets/day2/chart-templates/longhorn/longhorn
  2. Crie um arquivo targets.yaml que instruirá o Fleet para quais clusters ele deve implantar o chart Helm:

    cat > targets.yaml <<EOF
    targets:
    # Match your local (management) cluster
    - clusterName: local
    EOF
    Nota
    Nota

    Existem alguns casos de uso onde seu local cluster pode ter um nome diferente.

    Para recuperar o nome do seu local cluster, execute o comando abaixo:

    kubectl get clusters.fleet.cattle.io -n fleet-local
  3. Converta o Fleet do chart Helm Longhorn em um recurso Bundle usando o fleet-cli.

    Nota
    Nota

    A CLI do Fleet pode ser obtida na página de release Assets (fleet-linux-amd64).

    Para usuários de Mac, existe uma fórmula Homebrew chamada fleet-cli.

    fleet apply --compress --targets-file=targets.yaml -n fleet-local -o - longhorn-bundle > longhorn-bundle.yaml
  4. Navegue até o template do chart Fleet longhorn-crd:

    cd fleets/day2/chart-templates/longhorn/longhorn-crd
  5. Crie um arquivo targets.yaml que instruirá o Fleet sobre a quais clusters ele deve implantar o gráfico Helm:

    cat > targets.yaml <<EOF
    targets:
    # Match your local (management) cluster
    - clusterName: local
    EOF
  6. Converta o gráfico Helm Longhorn CRD do Fleet em um recurso Bundle usando o fleet-cli.

    fleet apply --compress --targets-file=targets.yaml -n fleet-local -o - longhorn-crd-bundle > longhorn-crd-bundle.yaml
  7. Implante os arquivos longhorn-bundle.yaml e longhorn-crd-bundle.yaml no seu management cluster:

    kubectl apply -f longhorn-crd-bundle.yaml
    kubectl apply -f longhorn-bundle.yaml

Seguir estes passos garantirá que o SUSE Storage seja implantado em todos os clusters management especificados.

58.2.6.2.1.3 Gerenciar o gráfico Helm implantado

Uma vez implantado com o Fleet, para fazer upgrade de gráficos Helm, consulte Seção 58.2.6.2.2, “Eu gostaria de fazer upgrade de um gráfico Helm gerenciado pelo Fleet”.

58.2.6.2.2 Eu gostaria de fazer upgrade de um gráfico Helm gerenciado pelo Fleet
  1. Determine a versão para a qual você precisa fazer upgrade do seu gráfico para que ele seja compatível com a versão do Edge desejada. A versão do gráfico Helm por versão do Edge pode ser visualizada nas notas de lançamento (Capítulo 75, Notas de versão).

  2. No seu repositório Git monitorado pelo Fleet, edite o arquivo fleet.yaml do gráfico Helm com a versão e o repositório corretos das notas de lançamento (Capítulo 75, Notas de versão).

  3. Após confirmar e enviar as alterações para o seu repositório, isso acionará o fazer upgrade do Helm chart desejado.

58.2.6.2.3 Eu gostaria de fazer upgrade de um Helm chart implantado via EIB.

Capítulo 12, Edge Image Builder implanta Helm charts criando um recurso HelmChart e utilizando o helm-controller introduzido pelo recurso de integração Helm RKE2/K3s.

Para garantir que um Helm chart implantado via EIB seja feito upgrade com sucesso, os usuários precisam fazer upgrade dos respectivos recursos HelmChart.

Abaixo você pode encontrar informações sobre:

58.2.6.2.3.1 Visão geral

Os Helm charts implantados via EIB são feitos upgrade por meio de um fleet chamado eib-charts-upgrader.

Este fleet processa dados fornecidos pelo usuário para atualizar um conjunto específico de recursos HelmChart.

A atualização desses recursos aciona o helm-controller, que faz upgrade dos Helm charts associados aos recursos HelmChart modificados.

Espera-se que o usuário apenas:

  1. Baixe localmente os arquivos para cada Helm chart que precisa ser feito upgrade.

  2. Passe esses arquivos para o generate-chart-upgrade-data.sh generate-chart-upgrade-data.sh script, que incluirá os dados desses arquivos na frota eib-charts-upgrader.

  3. Implante a frota eib-charts-upgrader em seu management cluster. Isso é feito por meio de um recurso GitRepo ou Bundle.

Uma vez implantado, o eib-charts-upgrader, com a ajuda do Fleet, enviará seus recursos para o cluster management desejado.

Esses recursos incluem:

  1. Um conjunto de Secrets contendo os dados do Helm chart fornecidos pelo usuário.

  2. Um Kubernetes Job que implantará um Pod que montará o Secrets mencionado anteriormente e, com base neles, patch os recursos HelmChart correspondentes.

Como mencionado anteriormente, isso acionará o helm-controller que realizará a atualização real do chart Helm.

Abaixo você pode encontrar um diagrama da descrição acima:

fleet day2 management helm eib upgrade
58.2.6.2.3.2 Etapas de upgrade
  1. Clone o repositório suse-edge/fleet-examples da tag de lançamento correta tag.

  2. Crie um diretório no qual você armazenará o(s) arquivo(s) do chart Helm baixado(s).

    mkdir archives
  3. Dentro do diretório recém-criado para os arquivos, pull os arquivos dos charts Helm que você deseja fazer upgrade:

    cd archives
    helm pull [chart URL | repo/chartname]
    
    # Alternatively if you want to pull a specific version:
    # helm pull [chart URL | repo/chartname] --version 0.0.0
  4. De Assets da release tag desejada, baixe o script generate-chart-upgrade-data.sh.

  5. Execute o script generate-chart-upgrade-data.sh:

    chmod +x ./generate-chart-upgrade-data.sh
    
    ./generate-chart-upgrade-data.sh --archive-dir /foo/bar/archives/ --fleet-path /foo/bar/fleet-examples/fleets/day2/eib-charts-upgrader

    Para cada arquivo de chart no diretório --archive-dir, o script gera um arquivo Kubernetes Secret YAML contendo os dados de upgrade do chart e o armazena no diretório base/secrets da frota especificada por --fleet-path.

    O script generate-chart-upgrade-data.sh também aplica modificações adicionais à frota para garantir que os arquivos Kubernetes Secret YAML gerados sejam utilizados corretamente pela carga de trabalho implantada pela frota.

    Importante
    Importante

    Os usuários não devem fazer alterações além do que o script generate-chart-upgrade-data.sh gera.

As etapas abaixo dependem do ambiente em que você está executando:

  1. Para um ambiente que suporta GitOps (por exemplo, não é air-gapped, ou é air-gapped, mas permite o suporte a um servidor Git local):

    1. Copie a fleets/day2/eib-charts-upgrader Fleet para o repositório que você usará para GitOps.

      Nota
      Nota

      Certifique-se de que a Fleet inclua as alterações que foram feitas pelo script generate-chart-upgrade-data.sh.

    2. Configure um recurso GitRepo que será usado para enviar todos os recursos da eib-charts-upgrader Fleet.

      1. Para configuração e implantação do GitRepo por meio da interface do Rancher, consulte Accessing Fleet in the Rancher UI.

      2. Para configuração e implantação manual do GitRepo, consulte Creating a Deployment.

  2. Para um ambiente que não suporta GitOps (por exemplo, é isolado da rede e não permite o uso de servidor Git local):

    1. Baixe o binário fleet-cli da página de rancher/fleet release (fleet-linux-amd64 para Linux). Para usuários de Mac, existe uma Homebrew Formulae que pode ser usada - fleet-cli.

    2. Navegue até a eib-charts-upgrader Fleet:

      cd /foo/bar/fleet-examples/fleets/day2/eib-charts-upgrader
    3. Crie um arquivo targets.yaml que instruirá o Fleet sobre onde implantar seus recursos:

      cat > targets.yaml <<EOF
      targets:
      # To map the local(management) cluster
      - clusterName: local
      EOF
      Nota
      Nota

      Existem alguns casos de uso em que seu cluster local pode ter um nome diferente.

      Para recuperar o nome do seu cluster local, execute o comando abaixo:

      kubectl get clusters.fleet.cattle.io -n fleet-local
    4. Use o fleet-cli para converter o Fleet em um recurso Bundle:

      fleet apply --compress --targets-file=targets.yaml -n fleet-local -o - eib-charts-upgrade > bundle.yaml

      Isso criará um Bundle (bundle.yaml) que conterá todos os recursos modelados do Fleet eib-charts-upgrader.

      Para mais informações sobre o comando fleet apply, consulte fleet apply.

      Para mais informações sobre a conversão de Fleets em Bundles, consulte Convert a Helm Chart into a Bundle.

    5. Implante o Bundle. Isso pode ser feito de duas maneiras:

      1. Através da interface do Rancher - Navegue até Continuous Delivery → Advanced → Bundles → Create from YAML e cole o conteúdo do bundle.yaml ou clique na opção Read from File e envie o próprio arquivo.

      2. Manualmente - Implante o arquivo bundle.yaml manualmente dentro do seu management cluster.

A execução dessas etapas resultará em um recurso GitRepo/Bundle implantado com sucesso. O recurso será captado pelo Fleet e seu conteúdo será implantado nos clusters de destino que o usuário especificou nas etapas anteriores. Para uma visão geral do processo, consulte Seção 58.2.6.2.3.1, “Visão geral”.

Para obter informações sobre como acompanhar o processo de fazer upgrade, você pode consultar Seção 58.2.6.2.3.3, “Exemplo”.

Importante
Importante

Assim que o upgrade do chart for verificado com sucesso, remova o recurso Bundle/GitRepo.

Isso removerá os recursos de upgrade que não são mais necessários do seu cluster management, garantindo que nenhum conflito de versão futuro ocorra.

58.2.6.2.3.3 Exemplo
Nota
Nota

O exemplo abaixo demonstra como fazer upgrade de um Helm chart implantado via EIB de uma versão para outra em um cluster management. Observe que as versões usadas neste exemplo não são recomendações. Para recomendações de versão específicas para uma versão Edge, consulte as notas de versão (Capítulo 75, Notas de versão).

Caso de uso:

  • Um cluster management está executando uma versão mais antiga do Longhorn.

  • O cluster foi implantado por meio do EIB, usando a seguinte definição de imagem snippet:

    kubernetes:
      helm:
        charts:
        - name: longhorn-crd
          repositoryName: rancher-charts
          targetNamespace: longhorn-system
          createNamespace: true
          version: 104.2.0+up1.7.1
          installationNamespace: kube-system
        - name: longhorn
          repositoryName: rancher-charts
          targetNamespace: longhorn-system
          createNamespace: true
          version: 104.2.0+up1.7.1
          installationNamespace: kube-system
        repositories:
        - name: rancher-charts
          url: https://charts.rancher.io/
    ...
  • O SUSE Storage precisa ser feito upgrade para uma versão compatível com a release 3.6 do Edge. Ou seja, ele precisa ser feito upgrade para 1.11.2.

  • Assume-se que o management cluster está air-gapped, sem suporte para um servidor Git local e possui uma configuração do Rancher funcional.

Siga as etapas para fazer upgrade (Seção 58.2.6.2.3.2, “Etapas de upgrade”):

  1. Clone o repositório suse-edge/fleet-example a partir da tag release-3.6.1.

    git clone -b release-3.6.1 https://github.com/suse-edge/fleet-examples.git
  2. Crie um diretório onde o arquivo de fazer upgrade do Longhorn será armazenado.

    mkdir archives
  3. Faça o pull da versão desejada do arquivo do chart Longhorn:

    # First add the Rancher Helm chart repository
    helm repo add rancher-charts https://charts.rancher.io/
    
    # Pull the Longhorn 1.11.2 chart archive
    helm pull oci://dp.apps.rancher.io/charts/suse-storage --version 1.11.2
  4. Fora do diretório archives, baixe o script generate-chart-upgrade-data.sh do release suse-edge/fleet-examples tag.

  5. A configuração do diretório deve ser semelhante a:

    .
    ├── archives
    │   └── longhorn-1.11.2.tgz
    ├── fleet-examples
    ...
    │   ├── fleets
    │   │   ├── day2
    |   |   |   ├── ...
    │   │   │   ├── eib-charts-upgrader
    │   │   │   │   ├── base
    │   │   │   │   │   ├── job.yaml
    │   │   │   │   │   ├── kustomization.yaml
    │   │   │   │   │   ├── patches
    │   │   │   │   │   │   └── job-patch.yaml
    │   │   │   │   │   ├── rbac
    │   │   │   │   │   │   ├── cluster-role-binding.yaml
    │   │   │   │   │   │   ├── cluster-role.yaml
    │   │   │   │   │   │   ├── kustomization.yaml
    │   │   │   │   │   │   └── sa.yaml
    │   │   │   │   │   └── secrets
    │   │   │   │   │       ├── eib-charts-upgrader-script.yaml
    │   │   │   │   │       └── kustomization.yaml
    │   │   │   │   ├── fleet.yaml
    │   │   │   │   └── kustomization.yaml
    │   │   │   └── ...
    │   └── ...
    └── generate-chart-upgrade-data.sh
  6. Execute o script generate-chart-upgrade-data.sh:

    # First make the script executable
    chmod +x ./generate-chart-upgrade-data.sh
    
    # Then execute the script
    ./generate-chart-upgrade-data.sh --archive-dir ./archives --fleet-path ./fleet-examples/fleets/day2/eib-charts-upgrader

    A estrutura do diretório após a execução do script deve ser semelhante a:

    .
    ├── archives
    │   └── longhorn-1.11.2.tgz
    ├── fleet-examples
    ...
    │   ├── fleets
    │   │   ├── day2
    │   │   │   ├── ...
    │   │   │   ├── eib-charts-upgrader
    │   │   │   │   ├── base
    │   │   │   │   │   ├── job.yaml
    │   │   │   │   │   ├── kustomization.yaml
    │   │   │   │   │   ├── patches
    │   │   │   │   │   │   └── job-patch.yaml
    │   │   │   │   │   ├── rbac
    │   │   │   │   │   │   ├── cluster-role-binding.yaml
    │   │   │   │   │   │   ├── cluster-role.yaml
    │   │   │   │   │   │   ├── kustomization.yaml
    │   │   │   │   │   │   └── sa.yaml
    │   │   │   │   │   └── secrets
    │   │   │   │   │       ├── eib-charts-upgrader-script.yaml
    │   │   │   │   │       ├── kustomization.yaml
    │   │   │   │   │       ├── longhorn-VERSION.yaml - secret created by the generate-chart-upgrade-data.sh script
    │   │   │   │   │       └── longhorn-crd-VERSION.yaml - secret created by the generate-chart-upgrade-data.sh script
    │   │   │   │   ├── fleet.yaml
    │   │   │   │   └── kustomization.yaml
    │   │   │   └── ...
    │   └── ...
    └── generate-chart-upgrade-data.sh

    Os arquivos alterados no git devem ser semelhantes a isto:

    Changes not staged for commit:
      (use "git add <file>..." to update what will be committed)
      (use "git restore <file>..." to discard changes in working directory)
        modified:   fleets/day2/eib-charts-upgrader/base/patches/job-patch.yaml
        modified:   fleets/day2/eib-charts-upgrader/base/secrets/kustomization.yaml
    
    Untracked files:
      (use "git add <file>..." to include in what will be committed)
        fleets/day2/eib-charts-upgrader/base/secrets/longhorn-VERSION.yaml
        fleets/day2/eib-charts-upgrader/base/secrets/longhorn-crd-VERSION.yaml
  7. Crie um Bundle para o Fleet eib-charts-upgrader:

    1. Primeiro, navegue até o próprio Fleet:

      cd ./fleet-examples/fleets/day2/eib-charts-upgrader
    2. Em seguida, crie um arquivo targets.yaml:

      cat > targets.yaml <<EOF
      targets:
      - clusterName: local
      EOF
    3. Em seguida, use o binário fleet-cli para converter o Fleet em um Bundle:

      fleet apply --compress --targets-file=targets.yaml -n fleet-local -o - eib-charts-upgrade > bundle.yaml
  8. Implante o Bundle através da interface do Rancher:

    day2 helm chart upgrade example 1
    Figura 58.1: Implantar Bundle através da interface do Rancher

    A partir daqui, selecione Ler de Arquivo e encontre o arquivo bundle.yaml no seu sistema.

    Isso preencherá automaticamente o Bundle dentro da interface do Rancher.

    Selecione Criar.

  9. Após uma implantação bem-sucedida, seu Bundle deverá ser semelhante a:

    day2 helm chart upgrade example 2
    Figura 58.2: Bundle implantado com sucesso

Após a implantação bem-sucedida do Bundle, para monitorar o processo de fazer upgrade:

  1. Verifique os logs do Upgrade Pod:

    day2 helm chart upgrade example 3 management
  2. Agora, verifique os logs do Pod criado para fazer upgrade pelo helm-controller:

    1. O nome do Pod seguirá o seguinte modelo - helm-install-longhorn-<random-suffix>

    2. O Pod estará no namespace onde o recurso HelmChart foi implantado. No nosso caso, este é kube-system.

      day2 helm chart upgrade example 4 management
      Figura 58.3: Logs para o gráfico Longhorn que foi submetido a fazer upgrade com sucesso
  3. Verifique se a versão do HelmChart foi atualizada navegando até a seção HelmCharts do Rancher (More Resources → HelmCharts). Selecione o namespace onde o chart foi implantado; para este exemplo, seria kube-system.

  4. Por fim, verifique se os Pods do Longhorn estão em execução.

Após realizar as validações acima, é seguro presumir que o Helm chart do Longhorn foi submetido a fazer upgrade para a versão 1.11.2.

58.2.6.2.3.4 Fazer upgrade do Helm chart usando uma ferramenta GitOps de terceiros

Pode haver casos de uso em que os usuários desejem usar este procedimento de fazer upgrade com um fluxo de trabalho GitOps diferente do Fleet (por exemplo, Flux).

Para produzir os recursos necessários para o procedimento de fazer upgrade, você pode usar o script generate-chart-upgrade-data.sh para preencher o Fleet eib-charts-upgrader com os dados fornecidos pelo usuário. Para obter mais informações sobre como fazer isso, consulte Seção 58.2.6.2.3.2, “Etapas de upgrade”.

Depois de ter a configuração completa, você pode usar kustomize para gerar uma solução funcional completa que você pode implantar em seu cluster:

cd /foo/bar/fleets/day2/eib-charts-upgrader

kustomize build .

Se você quiser incluir a solução em seu fluxo de trabalho GitOps, você pode remover o arquivo fleet.yaml e usar o que restou como uma configuração Kustomize válida. Apenas não se esqueça de executar primeiro o script generate-chart-upgrade-data.sh, para que ele possa preencher a configuração Kustomize com os dados dos Helm charts que você deseja fazer upgrade.

Para entender como este fluxo de trabalho deve ser usado, pode ser útil consultar Seção 58.2.6.2.3.1, “Visão geral” e Seção 58.2.6.2.3.2, “Etapas de upgrade”.

59 Ações de ciclo de vida

Esta seção aborda as ações de gerenciamento de ciclo de vida para clusters implantados via SUSE Telco Cloud.

59.1 Exclusão de balanceador de carga

Existem muitas ações de ciclo de vida que exigem que os nós sejam drenados. Durante o processo de drenagem, todos os pods serão movidos para outros nós no cluster. Após a conclusão do processo de drenagem, o nó não hospeda nenhum serviço e, portanto, não deve ter nenhum tráfego roteado para ele. Balanceadores de carga, como o MetalLB, podem ser informados disso aplicando um rótulo ao nó:

node.kubernetes.io/exclude-from-external-load-balancers: "true"

Para mais detalhes, consulte: Documentação do Kubernetes.

Para ver os rótulos em todos os seus nós em um cluster, você pode executar:

kubectl get nodes -o json | jq -r '.items[].metadata | .name, .labels'

No caso de fazer upgrade de clusters downstream, isso pode ser automatizado anotando o RKE2ControlPlane no cluster de gerenciamento:

rke2.controlplane.cluster.x-k8s.io/load-balancer-exclusion="true"

Isso cria imediatamente uma anotação em todos os objetos de máquina no cluster de gerenciamento para aquele RKE2ControlPlane.

pre-drain.delete.hook.machine.cluster.x-k8s.io/rke2-lb-exclusion: ""

Com essa anotação nos objetos de máquina, qualquer nó no cluster downstream que esteja agendado para drenagem receberá o rótulo de nó acima anexado antes do início do processo de drenagem. O rótulo será removido do nó assim que ele estiver disponível e pronto novamente.

59.2 Upgrades do cluster de gerenciamento

O upgrade do cluster de gerenciamento é descrito na documentação do Day 2 cluster de gerenciamento (Capítulo 58, Cluster de gerenciamento).

59.3 Upgrades de clusters downstream

O fazer upgrade de clusters downstream envolve a atualização de vários componentes. As seções a seguir cobrem o processo de fazer upgrade para cada um dos componentes.

Atualizando o sistema operacional

Para este processo, verifique a seguinte referência (Capítulo 49, Preparar a imagem do cluster downstream para cenários conectados) para criar a nova imagem com uma nova versão do sistema operacional. Com esta nova imagem gerada por EIB, a próxima fase de provisionamento utiliza a nova versão do sistema operacional fornecida. Na etapa a seguir, a nova imagem é usada para atualizar os nós.

Atualizando o cluster RKE2

As alterações necessárias para atualizar o cluster RKE2 usando o fluxo de trabalho automatizado são as seguintes:

  • Altere o bloco RKE2ControlPlane no capi-provisioning-example.yaml mostrado na seguinte seção (Capítulo 51, Provisionamento de cluster downstream com provisionamento de rede direcionado (nó único)):

    • Especifique o rolloutStrategy desejado.

    • Altere a versão do cluster RKE2 para a nova versão substituindo ${RKE2_NEW_VERSION}.

    • Decida se um controlador de ingresso deve ser implantado no cluster downstream:

      • [Opção 0]: Não implantar nenhum controlador de ingresso

      • [Opção 1]: Implantar apenas Traefik

      • [Opção 2]: Implantar ambos Ingress-NGINX e Traefik (para serem usados em cenários complexos de migração de ingresso)

Nota
Nota

O provedor de ingresso Traefik integrado ao RKE2/K3s é o único controlador de ingresso suportado na versão SUSE Telco Cloud 3.6, sendo ainda possível executar temporariamente Ingress-NGINX junto com Traefik para suportar cenários complexos de migração de ingresso, mas apenas após os clusters de Gerenciamento e/ou Downstream SUSE Telco Cloud terem sido atualizados para a versão 3.6 e pelo tempo necessário para realizar essa migração. Como Traefik ainda não é o controlador de ingresso padrão no RKE2 (será a partir do RKE2 v1.36 em diante), ele deve ser explicitamente "solicitado" no arquivo de configuração do servidor RKE2.

O guia RKE2 Migração de Ingress NGINX para Traefik fornece detalhes sobre os caminhos de migração de ingresso disponíveis assim que o controlador de ingresso Traefik substituir o descontinuado Ingress-NGINX.

apiVersion: controlplane.cluster.x-k8s.io/v1beta2
kind: RKE2ControlPlane
metadata:
  name: single-node-cluster
  namespace: default
spec:
  infrastructureRef:
    apiGroup: infrastructure.cluster.x-k8s.io
    kind: Metal3MachineTemplate
    name: single-node-cluster-controlplane
  version: ${RKE2_NEW_VERSION}
  replicas: 1
  rolloutStrategy:
    type: "RollingUpdate"
    rollingUpdate:
      maxSurge: 0
  serverConfig:
    cni: cilium
  #===========================================================================
  # Uncomment the following lines if selecting [Option 0]: Do not deploy
  # any ingress controller
  #===========================================================================
    #disableComponents:
    #  pluginComponents:
    #  - "rke2-ingress-nginx"
  #---------------------------------------------------------------------------
  rolloutStrategy:
    rollingUpdate:
      maxSurge: 0
  registrationMethod: "control-plane-endpoint"
  agentConfig:
    format: ignition
    additionalUserData:
      config: |
        variant: fcos
        version: 1.4.0
        systemd:
          units:
          - name: rke2-preinstall.service
            enabled: true
            contents: |
              [Unit]
              Description=rke2-preinstall
              Wants=network-online.target
              Before=rke2-install.service
              ConditionPathExists=!/run/cluster-api/bootstrap-success.complete
              [Service]
              Type=oneshot
              User=root
              ExecStartPre=/bin/sh -c "mount -L config-2 /mnt"
              ExecStart=/bin/sh -c "sed -i \"s/BAREMETALHOST_UUID/$(jq -r .uuid /mnt/openstack/latest/meta_data.json)/\" /etc/rancher/rke2/config.yaml"
              ExecStart=/bin/sh -c "echo \"node-name: $(jq -r .name /mnt/openstack/latest/meta_data.json)\" >> /etc/rancher/rke2/config.yaml"
              ExecStart=/bin/sh -c "echo \"node-label:\" >> /etc/rancher/rke2/config.yaml"
              ExecStart=/bin/sh -c "echo \"  - metal3.io/uuid=$(jq -r .uuid /mnt/openstack/latest/meta_data.json)\" >> /etc/rancher/rke2/config.yaml"
              ExecStartPost=/bin/sh -c "umount /mnt"
              [Install]
              WantedBy=multi-user.target
          # rke2-ingress-deployment.service unit
          - name: rke2-ingress-deployment.service
            enabled: true
            contents: |
              [Unit]
              Description=rke2-ingress-deployment
              Wants=rke2-preinstall.service
              Before=rke2-install.service
              ConditionPathExists=!/run/cluster-api/bootstrap-success.complete
              [Service]
              Type=oneshot
              User=root
              #===============================================================================================================================
              # Leave one (and only one) of the two following ExecStart lines uncommented, depending on the desired ingress-controller(s):
              #   [Option 1]: Deploy only "Traefik"
              #   [Option 2]: Deploy both "Ingress-NGINX" and "Traefik"
              #
              # Keep both commented ONLY in case of seleting [Option 0]: "Do not deploy any ingress controller"
              #===============================================================================================================================
              #ExecStart=/bin/sh -c "echo \"ingress-controller: traefik\" >> /etc/rancher/rke2/config.yaml"                       # [Option 1]
              ExecStart=/bin/sh -c "echo -e \"ingress-controller:\n- ingress-nginx\n- traefik\" >> /etc/rancher/rke2/config.yaml" # [Option 2]
              #-------------------------------------------------------------------------------------------------------------------------------
              [Install]
              WantedBy=multi-user.target
        storage:
          directories:
          - path: /var/lib/rancher/rke2/server/manifests
            overwrite: true
          files:
          #############################################################################
          # if [Option 2]: "Deploy both `Ingress-NGINX` and `Traefik`" is selected
          #############################################################################
          - path: /var/lib/rancher/rke2/server/manifests/rke2-ingress-nginx-config.yaml
            overwrite: true
            contents:
              inline: |
                apiVersion: helm.cattle.io/v1
                kind: HelmChartConfig
                metadata:
                  name: rke2-ingress-nginx
                  namespace: kube-system
                spec:
                  valuesContent: |-
                    controller:
                      hostPort:
                        enabled: false  # not needed when exposing through a type:LoadBalancer service
                      config:
                        use-forwarded-headers: "true"
                        enable-real-ip: "true"
                      publishService:
                        enabled: true
                      service:
                        enabled: true
                        type: LoadBalancer
                        externalTrafficPolicy: Local
            mode: 0644
            user:
              name: root
            group:
              name: root
          #############################################################################
          # if [Option 1]: "Deploy only `Traefik`" OR  [Option 2]: "Deploy both
          #`Ingress-NGINX` and `Traefik`" is selected
          #############################################################################
          - 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: false  # Assumes [Option 2]; set to true if [Option 1]: "only deploying `Traefik`"
                    ports:
                      web:
                        hostPort: null    # disallow hostPort
                        exposedPort: 80
                      websecure:
                        hostPort: null    # disallow hostPort
                        exposedPort: 443
                    service:
                      enabled: true
                      type: LoadBalancer
                      spec:
                        externalTrafficPolicy: Local
                        allocateLoadBalancerNodePorts: false  # k8s GA from 1.24; supported by MetalLB
                    providers:
                      kubernetesIngressNginx:  # this provider allows Traefik to "understand" most of the Ingress-NGINX annotations
                        enabled: true
                        ingressClass: "rke2-ingress-nginx-migration"
                        controllerClass: "rke2.​cattle.​io/ingress-nginx-migration"
            mode: 0644
            user:
              name: root
            group:
              name: root
    kubelet:
      extraArgs:
      - provider-id=metal3://BAREMETALHOST_UUID
    nodeName: "localhost.localdomain"
apiVersion: infrastructure.cluster.x-k8s.io/v1beta1
kind: Metal3MachineTemplate
metadata:
  name: single-node-cluster-controlplane
  namespace: default
spec:
  nodeReuse: True
  template:
    spec:
      automatedCleaningMode: metadata
      dataTemplate:
        name: single-node-cluster-controlplane-template
      hostSelector:
        matchLabels:
          cluster-role: control-plane
      image:
        checksum: http://imagecache.local:8080/${NEW_IMAGE_GENERATED}.sha256
        checksumType: sha256
        format: raw
        url: http://imagecache.local:8080/${NEW_IMAGE_GENERATED}.raw

Antes de aplicar o arquivo capi-provisioning-example.yaml, é sempre uma boa prática informar os balanceadores de carga externos (por exemplo, MetalLB) sobre os nós que estão sendo drenados para que eles não encaminhem tráfego para nós nesse estado. Como mencionado na seção Seção 59.1, “Exclusão de balanceador de carga”, você pode automatizar isso anotando o RKE2ControlPlane no cluster de gerenciamento. Neste exemplo, um objeto RKE2ControlPlane chamado multinode-cluster é anotado:

kubectl annotate  RKE2ControlPlane/multinode-cluster  rke2.controlplane.cluster.x-k8s.io/load-balancer-exclusion="true"

Verifique se os objetos de máquina foram anotados:

pre-drain.delete.hook.machine.cluster.x-k8s.io/rke2-lb-exclusion: ""

Obtenha as anotações para todos os seus objetos de máquina:

kubectl get machines -o json | jq -r '.items[].metadata | .name, .annotations'
Nota
Nota

Sem essas anotações, os usuários podem experimentar tempos de resposta mais longos para os serviços, já que os balanceadores de carga não estão cientes dos nós drenados.

Após fazer essas alterações, o arquivo capi-provisioning-example.yaml pode ser aplicado ao cluster usando o seguinte comando:

kubectl apply -f capi-provisioning-example.yaml

Parte IX Guias de procedimentos

Guias de procedimentos e melhores práticas

  • 60 MetalLB no K3s (usando o modo camada 2)
  • O MetalLB é uma implementação de balanceador de carga para clusters Kubernetes bare metal, usando protocolos de roteamento padrão.

  • 61 MetalLB no K3s (usando modo de camada 3)
  • O MetalLB é uma implementação de balanceador de carga para clusters Kubernetes bare metal, usando protocolos de roteamento padrão.

  • 62 MetalLB na frente do servidor de API do Kubernetes
  • Este guia demonstra o uso de um serviço MetalLB para expor a API do RKE2/K3s externamente em um cluster de alta disponibilidade (HA) com três nós de plano de controle. Para conseguir isso, um Service do Kubernetes do tipo LoadBalancer será criado manualmente. Em seguida, um objeto EndpointSlices ser…

  • 63 Implantações air-gapped com o Edge Image Builder
  • Este guia mostrará como implantar vários dos componentes SUSE Telco Cloud de forma totalmente air-gapped no SUSE Linux Micro 6.2 utilizando o Edge Image Builder(EIB) (Capítulo 12, Edge Image Builder). Com isso, você poderá inicializar em uma imagem personalizada e pronta para inicializar (CRB) criad…

  • 64 Criando imagens atualizadas do SUSE Linux Micro com o Kiwi
  • Esta seção explica como gerar imagens atualizadas do SUSE Linux Micro para serem usadas com o Edge Image Builder, com Cluster API (CAPI) + Metal3, ou para gravar a imagem de disco diretamente em um dispositivo de bloco. Este processo é útil em situações onde é necessário incluir os patches mais rece…

  • 65 Usando clusterclass para implantar clusters downstream
  • O provisionamento de clusters Kubernetes é uma tarefa complexa que exige profundo conhecimento na configuração de componentes de cluster. À medida que as configurações se tornam mais complexas, ou à medida que as demandas de diferentes provedores introduzem inúmeras definições de recursos específica…

60 MetalLB no K3s (usando o modo camada 2)

O MetalLB é uma implementação de balanceador de carga para clusters Kubernetes bare metal, usando protocolos de roteamento padrão.

Neste guia, demonstramos como implantar o MetalLB no modo camada 2 (L2).

60.1 Por que usar o MetalLB

O MetalLB é uma escolha atraente para balanceamento de carga em clusters Kubernetes bare metal por vários motivos:

  1. Integração Nativa com o Kubernetes: O MetalLB integra-se perfeitamente ao Kubernetes, tornando fácil implantar e gerenciar usando ferramentas e práticas familiares do Kubernetes.

  2. Compatibilidade bare metal: Ao contrário dos balanceadores de carga baseados em nuvem, o MetalLB foi projetado especificamente para implantações no local onde balanceadores de carga tradicionais podem não estar disponíveis ou ser viáveis.

  3. Suporta Vários Protocolos: O MetalLB suporta os modos camada 2 e BGP (Border Gateway Protocol), proporcionando flexibilidade para diferentes arquiteturas e requisitos de rede.

  4. Alta disponibilidade: Ao distribuir as responsabilidades de balanceamento de carga entre vários nós, o MetalLB garante alta disponibilidade e confiabilidade para seus serviços.

  5. Escalabilidade: O MetalLB pode lidar com implantações em larga escala, escalando junto com seu cluster Kubernetes para atender à demanda crescente.

No modo camada 2, um nó assume a responsabilidade de anunciar um serviço para a rede local. Da perspectiva da rede, parece simplesmente que aquela máquina tem vários endereços IP atribuídos à sua interface de rede.

A principal vantagem do modo camada 2 é sua universalidade: ele funciona em qualquer rede Ethernet, sem necessidade de hardware especial, nem mesmo roteadores sofisticados.

60.2 MetalLB no K3s (usando o modo camada 2)

Neste início rápido, o modo camada 2 (L2) será usado. Isso significa que não precisamos de nenhum equipamento de rede especial, apenas três IPs livres dentro do intervalo da rede.

60.3 Pré-requisitos

  • Um cluster K3s onde o MetalLB será implantado.

Atenção
Atenção

O K3s vem com seu próprio balanceador de carga de serviço chamado Klipper. Você precisa desativá-lo para executar o MetalLB. Para desativar o Klipper, o K3s precisa ser instalado usando a flag --disable=servicelb.

  • Helm

  • Três endereços IP livres dentro do intervalo da rede. Neste exemplo 192.168.122.10-192.168.122.12

Importante
Importante

Você deve garantir que esses endereços IP não estejam atribuídos. Em um ambiente DHCP, esses endereços não devem fazer parte do pool DHCP para evitar atribuições duplas.

60.4 Implantação

Usaremos o Helm chart do MetalLB publicado como parte da solução SUSE Telco Cloud:

helm install \
  metallb oci://registry.suse.com/edge/charts/metallb \
  --namespace metallb-system \
  --create-namespace

while ! kubectl wait --for condition=ready -n metallb-system $(kubectl get\
 pods -n metallb-system -l app.kubernetes.io/component=controller -o name)\
 --timeout=10s; do
 sleep 2
done

60.5 Configuração

Neste ponto, a instalação está concluída. Agora é hora de configurar usando nossos valores de exemplo:

cat <<-EOF | kubectl apply -f -
apiVersion: metallb.io/v1beta1
kind: IPAddressPool
metadata:
  name: ip-pool
  namespace: metallb-system
spec:
  addresses:
  - 192.168.122.10/32
  - 192.168.122.11/32
  - 192.168.122.12/32
EOF
cat <<-EOF | kubectl apply -f -
apiVersion: metallb.io/v1beta1
kind: L2Advertisement
metadata:
  name: ip-pool-l2-adv
  namespace: metallb-system
spec:
  ipAddressPools:
  - ip-pool
EOF

Agora, está pronto para ser usado. Você pode personalizar muitas coisas para o modo camada 2 (L2), como:

E muito mais para BGP.

60.5.1 Traefik e MetalLB

O Traefik é implantado por padrão com o K3s (pode ser desativado com --disable=traefik) e é exposto por padrão como LoadBalancer (para ser usado com o Klipper). No entanto, como o Klipper precisa ser desativado, o serviço do Traefik para ingress ainda é do tipo LoadBalancer. Portanto, no momento da implantação do MetalLB, o primeiro IP será atribuído automaticamente ao Traefik Ingress.

# Before deploying MetalLB
kubectl get svc -n kube-system traefik
NAME      TYPE           CLUSTER-IP     EXTERNAL-IP   PORT(S)                      AGE
traefik   LoadBalancer   10.43.44.113   <pending>     80:31093/TCP,443:32095/TCP   28s
# After deploying MetalLB
kubectl get svc -n kube-system traefik
NAME      TYPE           CLUSTER-IP     EXTERNAL-IP      PORT(S)                      AGE
traefik   LoadBalancer   10.43.44.113   192.168.122.10   80:31093/TCP,443:32095/TCP   3m10s

Isso será aplicado mais tarde (Seção 60.6.1, “Ingress com MetalLB”) no processo.

60.6 Uso

Vamos criar uma implantação de exemplo:

cat <<- EOF | kubectl apply -f -
---
apiVersion: v1
kind: Namespace
metadata:
  name: hello-kubernetes
---
apiVersion: v1
kind: ServiceAccount
metadata:
  name: hello-kubernetes
  namespace: hello-kubernetes
  labels:
    app.kubernetes.io/name: hello-kubernetes
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: hello-kubernetes
  namespace: hello-kubernetes
  labels:
    app.kubernetes.io/name: hello-kubernetes
spec:
  replicas: 2
  selector:
    matchLabels:
      app.kubernetes.io/name: hello-kubernetes
  template:
    metadata:
      labels:
        app.kubernetes.io/name: hello-kubernetes
    spec:
      serviceAccountName: hello-kubernetes
      containers:
        - name: hello-kubernetes
          image: "paulbouwer/hello-kubernetes:1.10"
          imagePullPolicy: IfNotPresent
          ports:
            - name: http
              containerPort: 8080
              protocol: TCP
          livenessProbe:
            httpGet:
              path: /
              port: http
          readinessProbe:
            httpGet:
              path: /
              port: http
          env:
          - name: HANDLER_PATH_PREFIX
            value: ""
          - name: RENDER_PATH_PREFIX
            value: ""
          - name: KUBERNETES_NAMESPACE
            valueFrom:
              fieldRef:
                fieldPath: metadata.namespace
          - name: KUBERNETES_POD_NAME
            valueFrom:
              fieldRef:
                fieldPath: metadata.name
          - name: KUBERNETES_NODE_NAME
            valueFrom:
              fieldRef:
                fieldPath: spec.nodeName
          - name: CONTAINER_IMAGE
            value: "paulbouwer/hello-kubernetes:1.10"
EOF

E, finalmente, o serviço:

cat <<- EOF | kubectl apply -f -
apiVersion: v1
kind: Service
metadata:
  name: hello-kubernetes
  namespace: hello-kubernetes
  labels:
    app.kubernetes.io/name: hello-kubernetes
spec:
  type: LoadBalancer
  ports:
    - port: 80
      targetPort: http
      protocol: TCP
      name: http
  selector:
    app.kubernetes.io/name: hello-kubernetes
EOF

Vamos vê-lo em ação:

kubectl get svc -n hello-kubernetes
NAME               TYPE           CLUSTER-IP     EXTERNAL-IP      PORT(S)        AGE
hello-kubernetes   LoadBalancer   10.43.127.75   192.168.122.11   80:31461/TCP   8s

curl http://192.168.122.11
<!DOCTYPE html>
<html>
<head>
    <title>Hello Kubernetes!</title>
    <link rel="stylesheet" type="text/css" href="/css/main.css">
    <link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Ubuntu:300" >
</head>
<body>

  <div class="main">
    <img src="/images/kubernetes.png"/>
    <div class="content">
      <div id="message">
  Hello world!
</div>
<div id="info">
  <table>
    <tr>
      <th>namespace:</th>
      <td>hello-kubernetes</td>
    </tr>
    <tr>
      <th>pod:</th>
      <td>hello-kubernetes-7c8575c848-2c6ps</td>
    </tr>
    <tr>
      <th>node:</th>
      <td>allinone (Linux 5.14.21-150400.24.46-default)</td>
    </tr>
  </table>
</div>
<div id="footer">
  paulbouwer/hello-kubernetes:1.10 (linux/amd64)
</div>
    </div>
  </div>

</body>
</html>

60.6.1 Ingress com MetalLB

Como o Traefik já está servindo como um controlador de ingress, podemos expor qualquer tráfego HTTP/HTTPS por meio de um objeto Ingress como:

IP=$(kubectl get svc -n kube-system traefik -o jsonpath="{.status.loadBalancer.ingress[0].ip}")
cat <<- EOF | kubectl apply -f -
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: hello-kubernetes-ingress
  namespace: hello-kubernetes
spec:
  rules:
  - host: hellok3s.${IP}.sslip.io
    http:
      paths:
        - path: "/"
          pathType: Prefix
          backend:
            service:
              name: hello-kubernetes
              port:
                name: http
EOF

E então:

curl http://hellok3s.${IP}.sslip.io
<!DOCTYPE html>
<html>
<head>
    <title>Hello Kubernetes!</title>
    <link rel="stylesheet" type="text/css" href="/css/main.css">
    <link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Ubuntu:300" >
</head>
<body>

  <div class="main">
    <img src="/images/kubernetes.png"/>
    <div class="content">
      <div id="message">
  Hello world!
</div>
<div id="info">
  <table>
    <tr>
      <th>namespace:</th>
      <td>hello-kubernetes</td>
    </tr>
    <tr>
      <th>pod:</th>
      <td>hello-kubernetes-7c8575c848-fvqm2</td>
    </tr>
    <tr>
      <th>node:</th>
      <td>allinone (Linux 5.14.21-150400.24.46-default)</td>
    </tr>
  </table>
</div>
<div id="footer">
  paulbouwer/hello-kubernetes:1.10 (linux/amd64)
</div>
    </div>
  </div>

</body>
</html>

Verifique se o MetalLB funciona corretamente:

% arping hellok3s.${IP}.sslip.io

ARPING 192.168.64.210
60 bytes from 92:12:36:00:d3:58 (192.168.64.210): index=0 time=1.169 msec
60 bytes from 92:12:36:00:d3:58 (192.168.64.210): index=1 time=2.992 msec
60 bytes from 92:12:36:00:d3:58 (192.168.64.210): index=2 time=2.884 msec

No exemplo acima, o tráfego flui da seguinte forma:

  1. hellok3s.${IP}.sslip.io é resolvido para o IP real.

  2. Em seguida, o tráfego é tratado pelo pod metallb-speaker.

  3. metallb-speaker redireciona o tráfego para o controlador traefik.

  4. Finalmente, o Traefik encaminha a solicitação para o serviço hello-kubernetes.

61 MetalLB no K3s (usando modo de camada 3)

O MetalLB é uma implementação de balanceador de carga para clusters Kubernetes bare metal, usando protocolos de roteamento padrão.

Neste guia, demonstramos como implantar o MetalLB no modo BGP de camada 3 (L3).

61.1 Por que usar o MetalLB

O MetalLB é uma escolha atraente para balanceamento de carga em clusters Kubernetes bare metal por vários motivos:

  1. Integração Nativa com o Kubernetes: O MetalLB integra-se perfeitamente ao Kubernetes, facilitando a implantação e o gerenciamento usando ferramentas e práticas familiares do Kubernetes.

  2. Compatibilidade com bare metal: Ao contrário dos balanceadores de carga baseados em nuvem, o MetalLB foi projetado especificamente para implantações no local onde balanceadores de carga tradicionais podem não estar disponíveis ou ser viáveis.

  3. Suporta Vários Protocolos: O MetalLB suporta os modos de camada 2 e camada 3 BGP (Border Gateway Protocol), proporcionando flexibilidade para diferentes arquiteturas e requisitos de rede.

  4. Alta disponibilidade: Ao distribuir as responsabilidades de balanceamento de carga entre vários nós, o MetalLB garante alta disponibilidade e confiabilidade para seus serviços.

  5. Escalabilidade: O MetalLB pode lidar com implantações em larga escala, escalando junto com seu cluster Kubernetes para atender à demanda crescente.

No modo de camada 2, um nó assume a responsabilidade de anunciar um serviço para a rede local. Da perspectiva da rede, parece simplesmente que aquela máquina tem vários endereços IP atribuídos à sua interface de rede.

A principal vantagem do modo camada 2 é sua universalidade: ele funciona em qualquer rede Ethernet, sem necessidade de hardware especial, nem mesmo roteadores sofisticados.

61.2 MetalLB no K3s (usando camada 3)

Neste início rápido, o modo camada 3 é usado. Isso significa que precisamos ter roteador(es) vizinho(s) com recursos BGP dentro do intervalo da rede.

61.3 Pré-requisitos

  • Um cluster K3s onde o MetalLB será implantado.

  • Roteador(es) na rede que suportam o protocolo BGP.

  • Um endereço IP livre dentro do intervalo da rede para o serviço. Nesse exemplo 192.168.10.100

Importante
Importante

Você deve garantir que este endereço IP não esteja atribuído. Em um ambiente DHCP, este endereço não deve fazer parte do pool DHCP para evitar atribuições duplas.

61.4 Configuração para Anunciar Endereços IP de Serviço

Por padrão, o BGP anuncia um endereço IP de Serviço para todos os pares que estão configurados. Esses pares, que geralmente são roteadores, receberão uma rota para cada endereço IP de Serviço com uma máscara de rede de 32 bits. Nesse exemplo, usaremos um roteador baseado em FRR que está na mesma rede que nosso cluster. Usaremos então a capacidade BGP do MetalLB para anunciar um serviço para esse roteador baseado em FRR.

61.5 Implantação

Usaremos o Helm chart do MetalLB publicado como parte da solução SUSE Telco Cloud:

helm install \
  metallb oci://registry.suse.com/edge/charts/metallb \
  --namespace metallb-system \
  --create-namespace

while ! kubectl wait --for condition=ready -n metallb-system $(kubectl get\
 pods -n metallb-system -l app.kubernetes.io/component=controller -o name)\
 --timeout=10s; do
 sleep 2
done

61.6 Configuração

  1. Neste ponto, a instalação está concluída. Crie um IPAddressPool:

cat <<-EOF | kubectl apply -f -
apiVersion: metallb.io/v1beta1
kind: IPAddressPool
metadata:
  name: bgp-pool
  namespace: metallb-system
  labels:
    app: httpd
spec:
  addresses:
  - 192.168.10.100/32
  autoAssign: true
  avoidBuggyIPs: false
  serviceAllocation:
    namespaces:
    - metallb-system
    priority: 100
    serviceSelectors:
    - matchExpressions:
      - key: serviceType
        operator: In
        values:
        - httpd
EOF
  1. Configure um BGPPeer.

Nota
Nota

O roteador FRR tem ASN 1000, enquanto nosso BGPPeer terá 1001. Também podemos ver que o Roteador FRR tem um endereço IP que é 192.168.3.140.

cat <<-EOF | kubectl apply -f -
apiVersion: metallb.io/v1beta2
kind: BGPPeer
metadata:
  namespace: metallb-system
  name: mypeertest
spec:
  peerAddress: 192.168.3.140
  peerASN: 1000
  myASN: 1001
  routerID: 4.4.4.4
EOF
  1. Crie o BGPAdvertisement (L3):

cat <<-EOF | kubectl apply -f -
apiVersion: metallb.io/v1beta1
kind: BGPAdvertisement
metadata:
  name: bgpadvertisement-test
  namespace: metallb-system
spec:
  ipAddressPools:
  - bgp-pool
EOF

61.7 Uso

  1. Crie um aplicativo de exemplo com um serviço. Neste caso, o endereço IP do IPAddressPool é 192.168.10.100 para esse serviço.

cat <<- EOF | kubectl apply -f -
apiVersion: apps/v1
kind: Deployment
metadata:
  name: httpd-deployment
  namespace: metallb-system
  labels:
    app: httpd
spec:
  replicas: 3
  selector:
    matchLabels:
      pod-label: httpd
  template:
    metadata:
      labels:
        pod-label: httpd
    spec:
      containers:
      - name: httpdcontainer
        image: image: docker.io/library/httpd:2.4
        ports:
          - containerPort: 80
            protocol: TCP
      restartPolicy: Always

---
apiVersion: v1
kind: Service
metadata:
  name: http-service
  namespace: metallb-system
  labels:
    serviceType: httpd
spec:
  selector:
    pod-label: httpd
  type: LoadBalancer
  ports:
  - protocol: TCP
    port: 8080
    name: 8080-tcp
    targetPort: 80
EOF
  1. Para verificar, faça login no Roteador FRR para poder ver as rotas criadas a partir do anúncio BGP.

42178089cba5# show ip bgp all

For address family: IPv4 Unicast
BGP table version is 3, local router ID is 2.2.2.2, vrf id 0
Default local pref 100, local AS 1000
Status codes:  s suppressed, d damped, h history, * valid, > best, = multipath,
               i internal, r RIB-failure, S Stale, R Removed
Nexthop codes: @NNN nexthop's vrf id, < announce-nh-self
Origin codes:  i - IGP, e - EGP, ? - incomplete
RPKI validation codes: V valid, I invalid, N Not found

   Network          Next Hop            Metric LocPrf Weight Path
* i172.16.0.0/24    1.1.1.1                  0    100      0 i
*>                  0.0.0.0                  0         32768 i
* i172.17.0.0/24    3.3.3.3                  0    100      0 i
*>                  0.0.0.0                  0         32768 i
*= 192.168.10.100/32
                    192.168.3.162                          0 1001 i
*=                  192.168.3.163                          0 1001 i
*>                  192.168.3.161                          0 1001 i

Displayed  3 routes and 7 total paths
kubectl get svc -n hello-kubernetes
NAME               TYPE           CLUSTER-IP     EXTERNAL-IP      PORT(S)        AGE
hello-kubernetes   LoadBalancer   10.43.127.75   192.168.122.11   80:31461/TCP   8s
  1. Se este roteador for o gateway padrão da sua rede, você pode executar o comando curl a partir de uma máquina nessa rede para verificar se eles conseguem alcançar o aplicativo de exemplo httpd.

# curl http://192.168.10.100:8080
<html><body><h1>It works!</h1></body></html>
#

62 MetalLB na frente do servidor de API do Kubernetes

Este guia demonstra o uso de um serviço MetalLB para expor a API do RKE2/K3s externamente em um cluster de alta disponibilidade (HA) com três nós de plano de controle. Para conseguir isso, um Service do Kubernetes do tipo LoadBalancer será criado manualmente. Em seguida, um objeto EndpointSlices será criado automaticamente, o que mantém os IPs de todos os nós do plano de controle disponíveis no cluster. Para que os EndpointSlices sejam sincronizados continuamente com os eventos que ocorrem no cluster (adição/remoção de um nó ou um nó ficar offline), o Endpoint Copier Operator (Capítulo 18, Operador Endpoint Copier) será implantado. O operador monitora os eventos que ocorrem nos EndpointSlices kubernetes padrão e atualiza o gerenciado automaticamente para mantê-los sincronizados. Como o Service gerenciado é do tipo LoadBalancer, o MetalLB atribui a ele um ExternalIP estático. Este ExternalIP será usado para se comunicar com o servidor de API.

62.1 Pré-requisitos

  • Três hosts nos quais implantar o RKE2/K3s.

    • Certifique-se de que os hosts tenham nomes de host diferentes.

    • Para testes, podem ser máquinas virtuais

  • Pelo menos 2 IPs disponíveis na rede (um para o serviço exposto do controlador de entrada Traefik e um para o serviço gerenciado).

  • Helm

62.2 Instalando o RKE2/K3s

Nota
Nota

Se você não quiser usar um cluster novo, mas quiser usar um existente, pule esta etapa e prossiga para a próxima.

Primeiro, um IP livre na rede deve ser reservado, o qual será usado posteriormente para ExternalIP do Service gerenciado.

Conecte-se via SSH ao primeiro host e instale a distribuição desejada no modo de cluster.

Para RKE2:

# As a root user, create the /etc/rancher/rke2/config.yaml config file with the following content:

mkdir -p /etc/rancher/rke2/
cat <<EOF > /etc/rancher/rke2/config.yaml
# An example of the config.yaml file for a server node:
write-kubeconfig-mode: "0644"
ingress-controller: traefik
tls-san:
  - "${VIP_SERVICE_IP}"
  - "https://${VIP_SERVICE_IP}.sslip.io"
EOF

# Install RKE2
curl -sfL https://get.rke2.io | INSTALL_RKE2_EXEC="server" sh -

# Enable and start the RKE2 service with the configuration specified in the config.yaml file
systemctl enable rke2-server.service
systemctl start rke2-server.service

# Fetch the cluster token to be used later:
RKE2_TOKEN=$(tr -d '\n' < /var/lib/rancher/rke2/server/node-token)

Para K3s:

# Export the free IP mentioned above
export VIP_SERVICE_IP=<ip>
export INSTALL_K3S_SKIP_START=false

curl -sfL https://get.k3s.io | INSTALL_K3S_EXEC="server --cluster-init \
 --disable=servicelb --write-kubeconfig-mode=644 --tls-san=${VIP_SERVICE_IP} \
 --tls-san=https://${VIP_SERVICE_IP}.sslip.io" K3S_TOKEN=foobar sh -
Nota
Nota

Certifique-se de que a flag --disable=servicelb seja fornecida no comando k3s server.

Importante
Importante

A partir de agora, os comandos devem ser executados na máquina local.

Para acessar o servidor da API de fora, o IP da VM do RKE2/K3s será usado.

# Replace <node-ip> with the actual IP of the machine
export NODE_IP=<node-ip>
export KUBE_DISTRIBUTION=<k3s/rke2>

scp ${NODE_IP}:/etc/rancher/${KUBE_DISTRIBUTION}/${KUBE_DISTRIBUTION}.yaml ~/.kube/config && sed \
 -i '' "s/127.0.0.1/${NODE_IP}/g" ~/.kube/config && chmod 600 ~/.kube/config

62.3 Configurando um cluster existente

Nota
Nota

Esta etapa é válida apenas se você pretende usar um cluster RKE2/K3s existente.

Para usar um cluster existente, as flags tls-san devem ser modificadas. Adicionalmente, o LB servicelb deve ser desativado para o K3s.

Para alterar as flags dos servidores RKE2 ou K3s, você precisa modificar o arquivo /etc/systemd/system/rke2.service ou /etc/systemd/system/k3s.service em todas as VMs no cluster, dependendo da distribuição.

As flags devem ser inseridas no ExecStart. Por exemplo:

Para RKE2:

# Replace the <vip-service-ip> with the actual ip
ExecStart=/usr/local/bin/rke2 \
    server \
        '--write-kubeconfig-mode=644' \
        '--tls-san=<vip-service-ip>' \
        '--tls-san=https://<vip-service-ip>.sslip.io' \

Para K3s:

# Replace the <vip-service-ip> with the actual ip
ExecStart=/usr/local/bin/k3s \
    server \
        '--cluster-init' \
        '--write-kubeconfig-mode=644' \
        '--disable=servicelb' \
        '--tls-san=<vip-service-ip>' \
        '--tls-san=https://<vip-service-ip>.sslip.io' \

Em seguida, os seguintes comandos devem ser executados para carregar as novas configurações:

systemctl daemon-reload
systemctl restart ${KUBE_DISTRIBUTION}

62.4 Instalando o MetalLB

Para implantar o MetalLB, o guia MetalLB no K3s (Capítulo 60, MetalLB no K3s (usando o modo camada 2)) pode ser usado.

NOTA: Certifique-se de que o endereço IP VIP_SERVICE_IP não se sobreponha ao IPAddressPools existente no cluster.

Crie um IpAddressPool e um L2Advertisement separados que serão usados apenas para o Service gerenciado.

NOTA: O IPAddressPool abaixo será atribuído a um serviço do tipo LoadBalancer no namespace default. Se existirem múltiplos serviços LoadBalancer lá, ServiceSelectors adicionais podem ser configurados para corresponder a este serviço VIP explicitamente.

# Export the VIP_SERVICE_IP on the local machine
# Replace with the actual IP
export VIP_SERVICE_IP=<ip>

cat <<-EOF | kubectl apply -f -
apiVersion: metallb.io/v1beta1
kind: IPAddressPool
metadata:
  name: kubernetes-vip-ip-pool
  namespace: metallb-system
spec:
  addresses:
  - ${VIP_SERVICE_IP}/32
  serviceAllocation:
    priority: 100
    namespaces:
      - default
EOF
cat <<-EOF | kubectl apply -f -
apiVersion: metallb.io/v1beta1
kind: L2Advertisement
metadata:
  name: kubernetes-vip-l2-adv
  namespace: metallb-system
spec:
  ipAddressPools:
  - kubernetes-vip-ip-pool
EOF

62.5 Instalando o Operador Endpoint Copier

helm install \
endpoint-copier-operator oci://registry.suse.com/edge/charts/endpoint-copier-operator \
--namespace endpoint-copier-operator \
--create-namespace

O comando acima implantará o Deployment do operador endpoint-copier-operator com duas réplicas. Uma será a líder e a outra assumirá a função de líder, se necessário.

Agora, o Service kubernetes-vip deve ser implantado, o qual será reconciliado pelo operador e um EndpointSlices com as portas e o IP configurados será criado.

Para RKE2:

cat <<-EOF | kubectl apply -f -
apiVersion: v1
kind: Service
metadata:
  name: kubernetes-vip
  namespace: default
spec:
  ports:
  - name: rke2-api
    port: 9345
    protocol: TCP
    targetPort: 9345
  - name: k8s-api
    port: 6443
    protocol: TCP
    targetPort: 6443
  type: LoadBalancer
EOF

Para K3s:

cat <<-EOF | kubectl apply -f -
apiVersion: v1
kind: Service
metadata:
  name: kubernetes-vip
  namespace: default
spec:
  internalTrafficPolicy: Cluster
  ipFamilies:
  - IPv4
  ipFamilyPolicy: SingleStack
  ports:
  - name: https
    port: 6443
    protocol: TCP
    targetPort: 6443
  sessionAffinity: None
  type: LoadBalancer
EOF

Verifique se o Service kubernetes-vip possui o endereço IP correto:

kubectl get service kubernetes-vip -n default \
 -o=jsonpath='{.status.loadBalancer.ingress[0].ip}'

Certifique-se de que os recursos EndpointSlices kubernetes-vip-* e kubernetes no namespace default apontem para os mesmos IPs.

kubectl get endpointslices | grep kubernetes

Se tudo estiver correto, a última coisa que resta é usar o VIP_SERVICE_IP em nosso Kubeconfig.

sed -i '' "s/${NODE_IP}/${VIP_SERVICE_IP}/g" ~/.kube/config

A partir de agora, todos os kubectl passarão pelo Service kubernetes-vip.

62.6 Adicionando nós do plano de controle

Para monitorar todo o processo, mais duas abas de terminal podem ser abertas.

Primeiro terminal:

watch kubectl get nodes

Segundo terminal:

watch kubectl get endpointslices

Agora execute os comandos abaixo no segundo e terceiro nós.

Para RKE2:

# As a root user, create the /etc/rancher/rke2/config.yaml config file with the following content:

mkdir -p /etc/rancher/rke2/
cat <<EOF > /etc/rancher/rke2/config.yaml
# An example of the config.yaml file for an additional server node:
server: https://${VIP_SERVICE_IP}:9345
write-kubeconfig-mode: "0644"
ingress-controller: traefik
tls-san:
  - "${VIP_SERVICE_IP}"
  - "https://${VIP_SERVICE_IP}.sslip.io"
# The one from above
token: ${RKE2_TOKEN}
EOF

# Install RKE2
curl -sfL https://get.rke2.io | INSTALL_RKE2_TYPE="server" sh -

# Enable the RKE2 service with the configuration specified in the config.yaml file

systemctl enable --now rke2-server.service

# Fetch the cluster token to be used later:
RKE2_TOKEN=$(tr -d '\n' < /var/lib/rancher/rke2/server/node-token)

Para K3s:

# Export the VIP_SERVICE_IP in the VM
# Replace with the actual IP
export VIP_SERVICE_IP=<ip>
export INSTALL_K3S_SKIP_START=false

curl -sfL https://get.k3s.io | INSTALL_K3S_EXEC="server \
 --server https://${VIP_SERVICE_IP}:6443 --disable=servicelb \
 --write-kubeconfig-mode=644" K3S_TOKEN=foobar sh -

63 Implantações air-gapped com o Edge Image Builder

63.1 Intro

Este guia mostrará como implantar vários dos componentes SUSE Telco Cloud de forma totalmente air-gapped no SUSE Linux Micro 6.2 utilizando o Edge Image Builder(EIB) (Capítulo 12, Edge Image Builder). Com isso, você poderá inicializar em uma imagem personalizada e pronta para inicializar (CRB) criada pelo EIB e ter os componentes especificados implantados em um cluster RKE2 ou K3s sem uma conexão com a Internet ou quaisquer etapas manuais. Esta configuração é altamente desejável para clientes que desejam pré-incorporar todos os artefatos necessários para a implantação em sua imagem do SO, de modo que fiquem imediatamente disponíveis na inicialização.

Abordaremos uma instalação air-gapped de:

Atenção
Atenção

O EIB analisará e fará o pré-download de todas as imagens referenciadas nos Helm charts e manifestos do Kubernetes fornecidos. No entanto, algumas delas podem estar tentando baixar imagens de contêiner e criar recursos do Kubernetes com base nelas em tempo de execução. Nestes casos, temos que especificar manualmente as imagens necessárias no arquivo de definição se quisermos configurar um ambiente completamente air-gapped.

63.2 Pré-requisitos

Se você está seguindo este guia, presume-se que você já esteja familiarizado com o EIB (Capítulo 12, Edge Image Builder). Caso contrário, siga o guia de início rápido (Capítulo 5, Clusters autônomos com o Edge Image Builder) para entender melhor os conceitos mostrados na prática abaixo.

63.3 Configuração de rede Libvirt

Nota
Nota

Para demonstrar a implantação air-gapped, este guia será feito usando uma rede libvirt air-gapped simulada e a seguinte configuração será adaptada para isso. Para suas próprias implantações, você pode ter que modificar a configuração host1.local.yaml que será apresentada na próxima etapa.

Se você quiser usar a mesma configuração de rede libvirt, siga as instruções. Se não quiser, vá para Seção 63.4, “Configuração do diretório de base”.

Vamos criar uma configuração de rede isolada com um intervalo de endereços IP 192.168.100.2/24 para DHCP:

cat << EOF > isolatednetwork.xml
<network>
  <name>isolatednetwork</name>
  <bridge name='virbr1' stp='on' delay='0'/>
  <ip address='192.168.100.1' netmask='255.255.255.0'>
    <dhcp>
      <range start='192.168.100.2' end='192.168.100.254'/>
    </dhcp>
  </ip>
</network>
EOF

Agora, a única coisa que resta é criar a rede e iniciá-la:

virsh net-define isolatednetwork.xml
virsh net-start isolatednetwork

63.4 Configuração do diretório de base

A configuração do diretório de base é a mesma em todos os diferentes componentes, então vamos configurá-la aqui.

Primeiro, criaremos os subdiretórios necessários:

export CONFIG_DIR=$HOME/config
mkdir -p $CONFIG_DIR/base-images
mkdir -p $CONFIG_DIR/network
mkdir -p $CONFIG_DIR/kubernetes/helm/values

Certifique-se de adicionar qualquer imagem base que você planeja usar no diretório base-images. Este guia focará na ISO de auto-instalação encontrada aqui.

Vamos copiar a imagem baixada:

cp SL-Micro.x86_64-6.2-Base-SelfInstall-GM.install.iso $CONFIG_DIR/base-images/slemicro.iso
Nota
Nota

O EIB nunca modificará a entrada da imagem base.

Vamos criar um arquivo contendo a configuração de rede desejada:

cat << EOF > $CONFIG_DIR/network/host1.local.yaml
routes:
  config:
  - destination: 0.0.0.0/0
    metric: 100
    next-hop-address: 192.168.100.1
    next-hop-interface: eth0
    table-id: 254
  - destination: 192.168.100.0/24
    metric: 100
    next-hop-address: 192.168.122.1
    next-hop-interface: eth0
    table-id: 254
dns-resolver:
  config:
    server:
    - 192.168.100.1
    - 8.8.8.8
interfaces:
- name: eth0
  type: ethernet
  state: up
  mac-address: 34:8A:B1:4B:16:E7
  ipv4:
    address:
    - ip: 192.168.100.50
      prefix-length: 24
    dhcp: false
    enabled: true
  ipv6:
    enabled: false
EOF

Esta configuração garante que os seguintes estejam presentes nos sistemas provisionados (usando o endereço MAC especificado):

  • uma interface Ethernet com um endereço IP estático

  • roteamento

  • DNS

  • hostname (host1.local)

A estrutura de arquivos resultante deve ficar assim:

├── kubernetes/
│   └── helm/
│       └── values/
├── base-images/
│   └── slemicro.iso
└── network/
    └── host1.local.yaml

63.5 Arquivo de definição de base

O Edge Image Builder está usando arquivos de definição para modificar as imagens do SUSE Linux Micro. Esses arquivos contêm a maioria das opções configuráveis. Muitas dessas opções serão repetidas nas diferentes seções de componentes, portanto, listaremos e explicaremos essas aqui.

Dica
Dica

A lista completa de opções de personalização no arquivo de definição pode ser encontrada na documentação upstream

Daremos uma olhada nos seguintes campos que estarão presentes em todos os arquivos de definição:

apiVersion: 1.3
image:
  imageType: iso
  arch: x86_64
  baseImage: slemicro.iso
  outputImageName: eib-image.iso
operatingSystem:
  users:
    - username: root
      encryptedPassword: $6$jHugJNNd3HElGsUZ$eodjVe4te5ps44SVcWshdfWizrP.xAyd71CVEXazBJ/.v799/WRCBXxfYmunlBO2yp1hm/zb4r8EmnrrNCF.P/
kubernetes:
  version: v1.35.4+rke2r1
embeddedArtifactRegistry:
  images:
    - ...

A seção image é obrigatória e especifica a imagem de entrada, sua arquitetura e tipo, bem como a imagem de saída será chamada.

A seção operatingSystem é opcional e contém a configuração para habilitar o login nos sistemas provisionados com o nome de usuário/senha root/eib.

A seção kubernetes é opcional e define o tipo e a versão do Kubernetes. Vamos usar a distribuição RKE2. Use kubernetes.version: v1.35.4+k3s1 se o K3s for desejado. A menos que configurado explicitamente através do campo kubernetes.nodes, todos os clusters que inicializarmos neste guia serão de nó único.

A seção embeddedArtifactRegistry incluirá todas as imagens que são apenas referenciadas e baixadas em tempo de execução para o componente específico.

63.6 Instalação do Rancher

Nota
Nota

A implantação do Rancher (Capítulo 6, Rancher) que será demonstrada será bastante reduzida para fins de demonstração. Para suas implantações reais, artefatos adicionais podem ser necessários, dependendo da sua configuração.

Os ativos de lançamento do Rancher 2.14.2 contêm um arquivo rancher-images.txt que lista todas as imagens necessárias para uma instalação air-gapped.

Há mais de 600 imagens de contêiner no total, o que significa que a imagem CRB resultante teria aproximadamente 30 GB. Para nossa instalação do Rancher, reduziremos essa lista para a menor configuração funcional. A partir daí, você pode adicionar novamente quaisquer imagens que possa precisar para suas implantações.

Criaremos o arquivo de definição e incluiremos a lista de imagens reduzida:

apiVersion: 1.3
image:
  imageType: iso
  arch: x86_64
  baseImage: slemicro.iso
  outputImageName: eib-image.iso
operatingSystem:
  users:
    - username: root
      encryptedPassword: $6$jHugJNNd3HElGsUZ$eodjVe4te5ps44SVcWshdfWizrP.xAyd71CVEXazBJ/.v799/WRCBXxfYmunlBO2yp1hm/zb4r8EmnrrNCF.P/
kubernetes:
  version: v1.35.4+rke2r1
  manifests:
    urls:
    - https://github.com/cert-manager/cert-manager/releases/download/v1.15.3/cert-manager.crds.yaml
  helm:
    charts:
      - name: rancher
        version: 2.14.2
        repositoryName: rancher-prime
        valuesFile: rancher-values.yaml
        targetNamespace: cattle-system
        createNamespace: true
        installationNamespace: kube-system
      - name: cert-manager
        installationNamespace: kube-system
        createNamespace: true
        repositoryName: jetstack
        targetNamespace: cert-manager
        version: 1.20.1
    repositories:
      - name: jetstack
        url: https://charts.jetstack.io
      - name: rancher-prime
        url: https://charts.rancher.com/server-charts/prime
embeddedArtifactRegistry:
  images:
    - name: registry.rancher.com/rancher/backup-restore-operator:v10.0.2
    - name: registry.rancher.com/rancher/compliance-operator:v1.4.1
    - name: registry.rancher.com/rancher/fleet-agent:v0.15.2
    - name: registry.rancher.com/rancher/fleet:v0.15.2
    - name: registry.rancher.com/rancher/hardened-addon-resizer:1.8.23-build20260413
    - name: registry.rancher.com/rancher/hardened-calico:v3.31.5-build20260415
    - name: registry.rancher.com/rancher/hardened-cluster-autoscaler:v1.10.3-build20260414
    - name: registry.rancher.com/rancher/hardened-cni-plugins:v1.9.1-build20260415
    - name: registry.rancher.com/rancher/hardened-coredns:v1.14.2-build20260416
    - name: registry.rancher.com/rancher/hardened-dns-node-cache:1.26.8-build20260416
    - name: registry.rancher.com/rancher/hardened-etcd:v3.6.7-k3s1-build20260415
    - name: registry.rancher.com/rancher/hardened-flannel:v0.28.4-build20260415
    - name: registry.rancher.com/rancher/hardened-k8s-metrics-server:v0.8.1-build20260413
    - name: registry.rancher.com/rancher/hardened-kubernetes:v1.35.4-rke2r1-build20260416
    - name: registry.rancher.com/rancher/hardened-multus-cni:v4.2.4-build20260310
    - name: registry.rancher.com/rancher/hardened-multus-dynamic-networks-controller:v0.3.7-build20260310
    - name: registry.rancher.com/rancher/hardened-multus-thick:v4.2.4-build20260310
    - name: registry.rancher.com/rancher/hardened-traefik:v3.6.13-build20260416
    - name: registry.rancher.com/rancher/hardened-whereabouts:v0.9.3-build20260408
    - name: registry.rancher.com/rancher/k3s-upgrade:v1.35.4-k3s1
    - name: registry.rancher.com/rancher/klipper-helm:v0.9.17-build20260422
    - name: registry.rancher.com/rancher/klipper-lb:v0.4.16
    - name: registry.rancher.com/rancher/kubectl:v1.35.2
    - name: registry.rancher.com/rancher/kuberlr-kubectl:v7.0.3
    - name: registry.rancher.com/rancher/local-path-provisioner:v0.0.35
    - name: registry.rancher.com/rancher/machine:v0.15.0-rancher142
    - name: registry.rancher.com/rancher/nginx-ingress-controller:v1.14.5-hardened2
    - name: registry.rancher.com/rancher/prom-prometheus:v3.8.1
    - name: registry.rancher.com/rancher/prometheus-federator:v6.0.0
    - name: registry.rancher.com/rancher/pushprox:v0.1.10
    - name: registry.rancher.com/rancher/rancher-agent:v2.14.2
    - name: registry.rancher.com/rancher/rancher-csp-adapter:v9.0.0
    - name: registry.rancher.com/rancher/rancher-webhook:v0.10.6
    - name: registry.rancher.com/rancher/rancher:v2.14.2
    - name: registry.rancher.com/rancher/remotedialer-proxy:v0.7.2
    - name: registry.rancher.com/rancher/rke2-cloud-provider:v1.35.4-0.20260415195656-e51c0636351d-build20260415
    - name: registry.rancher.com/rancher/rke2-runtime:v1.35.4-rke2r1
    - name: registry.rancher.com/rancher/rke2-upgrade:v1.35.4-rke2r1
    - name: registry.rancher.com/rancher/scc-operator:v0.4.1
    - name: registry.rancher.com/rancher/security-scan:v0.9.1
    - name: registry.rancher.com/rancher/shell:v0.1.24
    - name: registry.rancher.com/rancher/supportability-review-app-frontend:v0.19.0
    - name: registry.rancher.com/rancher/supportability-review-internal:latest
    - name: registry.rancher.com/rancher/supportability-review-operator:v0.19.0
    - name: registry.rancher.com/rancher/supportability-review:latest
    - name: registry.rancher.com/rancher/system-agent-installer-k3s:v1.35.4-k3s1
    - name: registry.rancher.com/rancher/system-agent-installer-rke2:v1.35.4-rke2r1
    - name: registry.rancher.com/rancher/system-agent:v0.3.16-suc
    - name: registry.rancher.com/rancher/system-upgrade-controller:v0.19.1
    - name: registry.rancher.com/rancher/turtles:v0.26.2
    - name: registry.rancher.com/rancher/ui-plugin-catalog:4.15.0
    - name: registry.rancher.com/rancher/kubectl:v1.20.2
    - name: registry.rancher.com/rancher/mirrored-ingress-nginx-kube-webhook-certgen:v1.6.7

Em comparação com a lista completa de mais de 600 imagens de contêiner, esta versão reduzida contém apenas ~60, o que torna a nova imagem CRB com apenas cerca de 7 GB.

Também precisamos criar um arquivo de valores Helm para o Rancher:

cat << EOF > $CONFIG_DIR/kubernetes/helm/values/rancher-values.yaml
hostname: 192.168.100.50.sslip.io
replicas: 1
bootstrapPassword: "adminadminadmin"
systemDefaultRegistry: registry.rancher.com
useBundledSystemChart: true
EOF
Atenção
Atenção

Definir systemDefaultRegistry como registry.rancher.com permite que o Rancher procure automaticamente por imagens no registro de artefatos incorporado iniciado dentro da imagem CRB na inicialização. A omissão deste campo pode resultar em falha ao encontrar as imagens de contêiner no nó.

Vamos criar a imagem:

podman run --rm -it --privileged -v $CONFIG_DIR:/eib \
registry.suse.com/edge/3.6/edge-image-builder:1.3.3.1 \
build --definition-file eib-iso-definition.yaml

A saída deve ser similar ao seguinte:

Downloading file: dl-manifest-1.yaml 100% |██████████████████████████████████████████████████████████████████████████████| (583/583 kB, 12 MB/s)
Pulling selected Helm charts... 100% |███████████████████████████████████████████████████████████████████████████████████████████| (2/2, 3 it/s)
Generating image customization components...
Identifier ................... [SUCCESS]
Custom Files ................. [SKIPPED]
Time ......................... [SKIPPED]
Network ...................... [SUCCESS]
Groups ....................... [SKIPPED]
Users ........................ [SUCCESS]
Proxy ........................ [SKIPPED]
Rpm .......................... [SKIPPED]
Os Files ..................... [SKIPPED]
Systemd ...................... [SKIPPED]
Fips ......................... [SKIPPED]
Elemental .................... [SKIPPED]
Suma ......................... [SKIPPED]
Populating Embedded Artifact Registry... 100% |███████████████████████████████████████████████████████████████████████████| (56/56, 8 it/min)
Embedded Artifact Registry ... [SUCCESS]
Keymap ....................... [SUCCESS]
Configuring Kubernetes component...
The Kubernetes CNI is not explicitly set, defaulting to 'cilium'.
Downloading file: rke2_installer.sh
Downloading file: rke2-images-core.linux-amd64.tar.zst 100% |███████████████████████████████████████████████████████████| (644/644 MB, 29 MB/s)
Downloading file: rke2-images-cilium.linux-amd64.tar.zst 100% |█████████████████████████████████████████████████████████| (400/400 MB, 29 MB/s)
Downloading file: rke2.linux-amd64.tar.gz 100% |███████████████████████████████████████████████████████████████████████████| (36/36 MB, 30 MB/s)
Downloading file: sha256sum-amd64.txt 100% |█████████████████████████████████████████████████████████████████████████████| (4.3/4.3 kB, 29 MB/s)
Kubernetes ................... [SUCCESS]
Certificates ................. [SKIPPED]
Cleanup ...................... [SKIPPED]
Building ISO image...
Kernel Params ................ [SKIPPED]
Build complete, the image can be found at: eib-image.iso

Uma vez que um nó usando a imagem criada seja provisionado, podemos verificar a instalação do Rancher:

/var/lib/rancher/rke2/bin/kubectl get all -n cattle-system --kubeconfig /etc/rancher/rke2/rke2.yaml

A saída deve ser semelhante à seguinte, mostrando que tudo foi implantado com sucesso:

NAME                                            READY   STATUS      RESTARTS   AGE
pod/helm-operation-6l6ld                        0/2     Completed   0          107s
pod/helm-operation-8tk2v                        0/2     Completed   0          2m2s
pod/helm-operation-blnrr                        0/2     Completed   0          2m49s
pod/helm-operation-hdcmt                        0/2     Completed   0          3m19s
pod/helm-operation-m74c7                        0/2     Completed   0          97s
pod/helm-operation-qzzr4                        0/2     Completed   0          2m30s
pod/helm-operation-s9jh5                        0/2     Completed   0          3m
pod/helm-operation-tq7ts                        0/2     Completed   0          2m41s
pod/rancher-99d599967-ftjkk                     1/1     Running     0          4m15s
pod/rancher-webhook-79798674c5-6w28t            1/1     Running     0          2m27s
pod/system-upgrade-controller-56696956b-trq5c   1/1     Running     0          104s

NAME                      TYPE        CLUSTER-IP     EXTERNAL-IP   PORT(S)          AGE
service/rancher           ClusterIP   10.43.255.80   <none>        80/TCP,443/TCP   4m15s
service/rancher-webhook   ClusterIP   10.43.7.238    <none>        443/TCP          2m27s

NAME                                        READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/rancher                     1/1     1            1           4m15s
deployment.apps/rancher-webhook             1/1     1            1           2m27s
deployment.apps/system-upgrade-controller   1/1     1            1           104s

NAME                                                  DESIRED   CURRENT   READY   AGE
replicaset.apps/rancher-99d599967                     1         1         1       4m15s
replicaset.apps/rancher-webhook-79798674c5            1         1         1       2m27s
replicaset.apps/system-upgrade-controller-56696956b   1         1         1       104s

E quando vamos para https://192.168.100.50.sslip.io e fazemos login com a senha adminadminadmin que definimos anteriormente, somos recebidos com o painel do Rancher:

air gapped rancher

63.7 Instalação do SUSE Security

Ao contrário da instalação do Rancher, a instalação do SUSE Security não requer nenhum tratamento especial no EIB. O EIB fará automaticamente o air-gap de cada imagem necessária pelo seu componente subjacente NeuVector.

Criaremos o arquivo de definição:

apiVersion: 1.3
image:
  imageType: iso
  arch: x86_64
  baseImage: slemicro.iso
  outputImageName: eib-image.iso
operatingSystem:
  users:
    - username: root
      encryptedPassword: $6$jHugJNNd3HElGsUZ$eodjVe4te5ps44SVcWshdfWizrP.xAyd71CVEXazBJ/.v799/WRCBXxfYmunlBO2yp1hm/zb4r8EmnrrNCF.P/
kubernetes:
  version: v1.35.4+rke2r1
  helm:
    charts:
      - name: neuvector-crd
        version: 109.0.2+up2.10.2
        repositoryName: rancher-charts
        targetNamespace: neuvector
        createNamespace: true
        installationNamespace: kube-system
        valuesFile: neuvector-values.yaml
      - name: neuvector
        version: 109.0.2+up2.10.2
        repositoryName: rancher-charts
        targetNamespace: neuvector
        createNamespace: true
        installationNamespace: kube-system
        valuesFile: neuvector-values.yaml
    repositories:
      - name: rancher-charts
        url: https://charts.rancher.io/

Também criaremos um arquivo de valores Helm para o NeuVector:

cat << EOF > $CONFIG_DIR/kubernetes/helm/values/neuvector-values.yaml
controller:
  replicas: 1
manager:
  enabled: false
cve:
  scanner:
    enabled: false
    replicas: 1
k3s:
  enabled: true
crdwebhook:
  enabled: false
EOF

Vamos criar a imagem:

podman run --rm -it --privileged -v $CONFIG_DIR:/eib \
registry.suse.com/edge/3.6/edge-image-builder:1.3.3.1 \
build --definition-file eib-iso-definition.yaml

A saída deve ser similar ao seguinte:

Pulling selected Helm charts... 100% |███████████████████████████████████████████████████████████████████████████████████████████| (2/2, 4 it/s)
Generating image customization components...
Identifier ................... [SUCCESS]
Custom Files ................. [SKIPPED]
Time ......................... [SKIPPED]
Network ...................... [SUCCESS]
Groups ....................... [SKIPPED]
Users ........................ [SUCCESS]
Proxy ........................ [SKIPPED]
Rpm .......................... [SKIPPED]
Os Files ..................... [SKIPPED]
Systemd ...................... [SKIPPED]
Fips ......................... [SKIPPED]
Elemental .................... [SKIPPED]
Suma ......................... [SKIPPED]
Populating Embedded Artifact Registry... 100% |██████████████████████████████████████████████████████████████████████████████| (5/5, 13 it/min)
Embedded Artifact Registry ... [SUCCESS]
Keymap ....................... [SUCCESS]
Configuring Kubernetes component...
The Kubernetes CNI is not explicitly set, defaulting to 'cilium'.
Downloading file: rke2_installer.sh
Kubernetes ................... [SUCCESS]
Certificates ................. [SKIPPED]
Cleanup ...................... [SKIPPED]
Building ISO image...
Kernel Params ................ [SKIPPED]
Build complete, the image can be found at: eib-image.iso

Uma vez que um nó usando a imagem criada seja provisionado, podemos verificar a instalação do SUSE Security:

/var/lib/rancher/rke2/bin/kubectl get all -n neuvector --kubeconfig /etc/rancher/rke2/rke2.yaml

A saída deve ser semelhante à seguinte, mostrando que tudo foi implantado com sucesso:

NAME                                            READY   STATUS      RESTARTS   AGE
pod/neuvector-cert-upgrader-job-bxbnz           0/1     Completed   0          3m39s
pod/neuvector-controller-pod-7d854bfdc7-nhxjf   1/1     Running     0          3m44s
pod/neuvector-enforcer-pod-ct8jm                1/1     Running     0          3m44s

NAME                                      TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)                         AGE
service/neuvector-svc-admission-webhook   ClusterIP   10.43.234.241   <none>        443/TCP                         3m44s
service/neuvector-svc-controller          ClusterIP   None            <none>        18300/TCP,18301/TCP,18301/UDP   3m44s
service/neuvector-svc-crd-webhook         ClusterIP   10.43.50.190    <none>        443/TCP                         3m44s

NAME                                    DESIRED   CURRENT   READY   UP-TO-DATE   AVAILABLE   NODE SELECTOR   AGE
daemonset.apps/neuvector-enforcer-pod   1         1         1       1            1           <none>          3m44s

NAME                                       READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/neuvector-controller-pod   1/1     1            1           3m44s

NAME                                                  DESIRED   CURRENT   READY   AGE
replicaset.apps/neuvector-controller-pod-7d854bfdc7   1         1         1       3m44s

NAME                                        SCHEDULE    TIMEZONE   SUSPEND   ACTIVE   LAST SCHEDULE   AGE
cronjob.batch/neuvector-cert-upgrader-pod   0 0 1 1 *   <none>     True      0        <none>          3m44s
cronjob.batch/neuvector-updater-pod         0 0 * * *   <none>     False     0        <none>          3m44s

NAME                                    STATUS     COMPLETIONS   DURATION   AGE
job.batch/neuvector-cert-upgrader-job   Complete   1/1           7s         3m39s

63.8 Instalação do SUSE Storage

A documentação oficial do Longhorn contém um arquivo longhorn-images.txt que lista todas as imagens necessárias para uma instalação air-gapped. Incluiremos suas contrapartes espelhadas do registro de contêineres do Rancher em nosso arquivo de definição. Vamos criá-lo:

apiVersion: 1.3
image:
  imageType: iso
  arch: x86_64
  baseImage: slemicro.iso
  outputImageName: eib-image.iso
operatingSystem:
  users:
    - username: root
      encryptedPassword: $6$jHugJNNd3HElGsUZ$eodjVe4te5ps44SVcWshdfWizrP.xAyd71CVEXazBJ/.v799/WRCBXxfYmunlBO2yp1hm/zb4r8EmnrrNCF.P/
  packages:
    sccRegistrationCode: [reg-code]
    packageList:
      - open-iscsi
kubernetes:
  version: v1.35.4+rke2r1
  helm:
    charts:
      - name: suse-storage
        releaseName: longhorn
        repositoryName: rancher-application-collection
        targetNamespace: longhorn-system
        createNamespace: true
        version: 1.11.2
    repositories:
      - name: rancher-application-collection
        url: oci://dp.apps.rancher.io/charts
        authentication:
          username: $APPS.RANCHER.IO_USERNAME
          password: $APPS.RANCHER.IO_ACCESS_TOKEN
embeddedArtifactRegistry:
    registries:
      - uri: dp.apps.rancher.io
        authentication:
          username: $APPS.RANCHER.IO_USERNAME
          password: $APPS.RANCHER.IO_ACCESS_TOKEN
    - name: dp.apps.rancher.io/containers/kubernetes-csi-external-attacher:4.11.0-13.2
    - name: dp.apps.rancher.io/containers/kubernetes-csi-external-provisioner:5.3.0-14.1
    - name: dp.apps.rancher.io/containers/kubernetes-csi-external-resizer:2.1.0-6.2
    - name: dp.apps.rancher.io/containers/kubernetes-csi-external-snapshotter:8.5.0-13.2
    - name: dp.apps.rancher.io/containers/kubernetes-csi-livenessprobe:2.18.0-13.2
    - name: dp.apps.rancher.io/containers/kubernetes-csi-node-driver-registrar:2.16.0-13.2
    - name: dp.apps.rancher.io/containers/longhorn-backing-image-manager:1.11.2-4.1
    - name: dp.apps.rancher.io/containers/longhorn-engine:1.11.2-4.2
    - name: dp.apps.rancher.io/containers/longhorn-instance-manager:1.11.2-4.3
    - name: dp.apps.rancher.io/containers/longhorn-manager:1.11.2-4.2
    - name: dp.apps.rancher.io/containers/longhorn-share-manager:1.11.2-4.1
    - name: dp.apps.rancher.io/containers/longhorn-ui:1.11.2-4.1
    - name: dp.apps.rancher.io/containers/rancher-support-bundle-kit:0.0.84-9.4
Nota
Nota

Você notará que o arquivo de definição lista o pacote open-iscsi. Isso é necessário, já que o Longhorn depende de um daemon iscsiadm sendo executado nos diferentes nós para fornecer volumes persistentes ao Kubernetes.

Vamos criar a imagem:

podman run --rm -it --privileged -v $CONFIG_DIR:/eib \
registry.suse.com/edge/3.6/edge-image-builder:1.3.3.1 \
build --definition-file eib-iso-definition.yaml

A saída deve ser similar ao seguinte:

Setting up Podman API listener...
Pulling selected Helm charts... 100% |██████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████| (2/2, 3 it/s)
Generating image customization components...
Identifier ................... [SUCCESS]
Custom Files ................. [SKIPPED]
Time ......................... [SKIPPED]
Network ...................... [SUCCESS]
Groups ....................... [SKIPPED]
Users ........................ [SUCCESS]
Proxy ........................ [SKIPPED]
Resolving package dependencies...
Rpm .......................... [SUCCESS]
Os Files ..................... [SKIPPED]
Systemd ...................... [SKIPPED]
Fips ......................... [SKIPPED]
Elemental .................... [SKIPPED]
Suma ......................... [SKIPPED]
Populating Embedded Artifact Registry... 100% |███████████████████████████████████████████████████████████████████████████████████████████████████████████| (15/15, 20956 it/s)
Embedded Artifact Registry ... [SUCCESS]
Keymap ....................... [SUCCESS]
Configuring Kubernetes component...
The Kubernetes CNI is not explicitly set, defaulting to 'cilium'.
Downloading file: rke2_installer.sh
Downloading file: rke2-images-core.linux-amd64.tar.zst 100% (782/782 MB, 108 MB/s)
Downloading file: rke2-images-cilium.linux-amd64.tar.zst 100% (367/367 MB, 104 MB/s)
Downloading file: rke2.linux-amd64.tar.gz 100% (34/34 MB, 108 MB/s)
Downloading file: sha256sum-amd64.txt 100% (3.9/3.9 kB, 7.5 MB/s)
Kubernetes ................... [SUCCESS]
Certificates ................. [SKIPPED]
Cleanup ...................... [SKIPPED]
Building ISO image...
Kernel Params ................ [SKIPPED]
Build complete, the image can be found at: eib-image.iso

Uma vez que um nó usando a imagem criada seja provisionado, podemos verificar a instalação do Longhorn:

/var/lib/rancher/rke2/bin/kubectl get all -n longhorn-system --kubeconfig /etc/rancher/rke2/rke2.yaml

A saída deve ser semelhante à seguinte, mostrando que tudo foi implantado com sucesso:

NAME                                                    READY   STATUS    RESTARTS   AGE
pod/csi-attacher-787fd9c6c8-sf42d                       1/1     Running   0          2m28s
pod/csi-attacher-787fd9c6c8-tb82p                       1/1     Running   0          2m28s
pod/csi-attacher-787fd9c6c8-zhc6s                       1/1     Running   0          2m28s
pod/csi-provisioner-74486b95c6-b2v9s                    1/1     Running   0          2m28s
pod/csi-provisioner-74486b95c6-hwllt                    1/1     Running   0          2m28s
pod/csi-provisioner-74486b95c6-mlrpk                    1/1     Running   0          2m28s
pod/csi-resizer-859d4557fd-t54zk                        1/1     Running   0          2m28s
pod/csi-resizer-859d4557fd-vdt5d                        1/1     Running   0          2m28s
pod/csi-resizer-859d4557fd-x9kh4                        1/1     Running   0          2m28s
pod/csi-snapshotter-6f69c6c8cc-r62gr                    1/1     Running   0          2m28s
pod/csi-snapshotter-6f69c6c8cc-vrwjn                    1/1     Running   0          2m28s
pod/csi-snapshotter-6f69c6c8cc-z65nb                    1/1     Running   0          2m28s
pod/engine-image-ei-4623b511-9vhkb                      1/1     Running   0          3m13s
pod/instance-manager-6f95fd57d4a4cd0459e469d75a300552   1/1     Running   0          2m43s
pod/longhorn-csi-plugin-gx98x                           3/3     Running   0          2m28s
pod/longhorn-driver-deployer-55f9c88499-fbm6q           1/1     Running   0          3m28s
pod/longhorn-manager-dpdp7                              2/2     Running   0          3m28s
pod/longhorn-ui-59c85fcf94-gg5hq                        1/1     Running   0          3m28s
pod/longhorn-ui-59c85fcf94-s49jc                        1/1     Running   0          3m28s

NAME                                  TYPE        CLUSTER-IP     EXTERNAL-IP   PORT(S)    AGE
service/longhorn-admission-webhook    ClusterIP   10.43.77.89    <none>        9502/TCP   3m28s
service/longhorn-backend              ClusterIP   10.43.56.17    <none>        9500/TCP   3m28s
service/longhorn-conversion-webhook   ClusterIP   10.43.54.73    <none>        9501/TCP   3m28s
service/longhorn-frontend             ClusterIP   10.43.22.82    <none>        80/TCP     3m28s
service/longhorn-recovery-backend     ClusterIP   10.43.45.143   <none>        9503/TCP   3m28s

NAME                                      DESIRED   CURRENT   READY   UP-TO-DATE   AVAILABLE   NODE SELECTOR   AGE
daemonset.apps/engine-image-ei-4623b511   1         1         1       1            1           <none>          3m13s
daemonset.apps/longhorn-csi-plugin        1         1         1       1            1           <none>          2m28s
daemonset.apps/longhorn-manager           1         1         1       1            1           <none>          3m28s

NAME                                       READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/csi-attacher               3/3     3            3           2m28s
deployment.apps/csi-provisioner            3/3     3            3           2m28s
deployment.apps/csi-resizer                3/3     3            3           2m28s
deployment.apps/csi-snapshotter            3/3     3            3           2m28s
deployment.apps/longhorn-driver-deployer   1/1     1            1           3m28s
deployment.apps/longhorn-ui                2/2     2            2           3m28s

NAME                                                  DESIRED   CURRENT   READY   AGE
replicaset.apps/csi-attacher-787fd9c6c8               3         3         3       2m28s
replicaset.apps/csi-provisioner-74486b95c6            3         3         3       2m28s
replicaset.apps/csi-resizer-859d4557fd                3         3         3       2m28s
replicaset.apps/csi-snapshotter-6f69c6c8cc            3         3         3       2m28s
replicaset.apps/longhorn-driver-deployer-55f9c88499   1         1         1       3m28s
replicaset.apps/longhorn-ui-59c85fcf94                2         2         2       3m28s

63.9 Instalação do KubeVirt e CDI

Os gráficos Helm para KubeVirt e CDI instalam apenas seus respectivos operadores. Cabe aos operadores implantar o restante dos sistemas, o que significa que teremos que incluir todas as imagens de contêiner necessárias em nosso arquivo de definição. Vamos criá-lo:

apiVersion: 1.3
image:
  imageType: iso
  arch: x86_64
  baseImage: slemicro.iso
  outputImageName: eib-image.iso
operatingSystem:
  users:
    - username: root
      encryptedPassword: $6$jHugJNNd3HElGsUZ$eodjVe4te5ps44SVcWshdfWizrP.xAyd71CVEXazBJ/.v799/WRCBXxfYmunlBO2yp1hm/zb4r8EmnrrNCF.P/
kubernetes:
  version: v1.35.4+rke2r1
  helm:
    charts:
      - name: kubevirt
        repositoryName: suse-edge
        version: 306.0.2+up0.7.0
        targetNamespace: kubevirt-system
        createNamespace: true
        installationNamespace: kube-system
      - name: cdi
        repositoryName: suse-edge
        version: 306.0.2+up0.7.0
        targetNamespace: cdi-system
        createNamespace: true
        installationNamespace: kube-system
    repositories:
      - name: suse-edge
        url: oci://registry.suse.com/edge/charts
embeddedArtifactRegistry:
  images:
    - name: registry.suse.com/suse/sles/15.7/cdi-apiserver:1.64.0-150700.9.6.1
    - name: registry.suse.com/suse/sles/15.7/cdi-controller:1.64.0-150700.9.6.1
    - name: registry.suse.com/suse/sles/15.7/cdi-operator:1.64.0-150700.9.6.1
    - name: registry.suse.com/suse/sles/15.7/cdi-uploadproxy:1.64.0-150700.9.6.1
    - name: registry.suse.com/suse/sles/15.7/virt-api:1.7.0-150700.3.16.2
    - name: registry.suse.com/suse/sles/15.7/virt-controller:1.7.0-150700.3.16.2
    - name: registry.suse.com/suse/sles/15.7/virt-handler:1.7.0-150700.3.16.2
    - name: registry.suse.com/suse/sles/15.7/virt-launcher:1.7.0-150700.3.16.2
    - name: registry.suse.com/suse/sles/15.7/virt-operator:1.7.0-150700.3.16.2

Vamos criar a imagem:

podman run --rm -it --privileged -v $CONFIG_DIR:/eib \
registry.suse.com/edge/3.6/edge-image-builder:1.3.3.1 \
build --definition-file eib-iso-definition.yaml

A saída deve ser similar ao seguinte:

Pulling selected Helm charts... 100% |███████████████████████████████████████████████████████████████████████████████████████████████████████████████████████| (2/2, 48 it/min)
Generating image customization components...
Identifier ................... [SUCCESS]
Custom Files ................. [SKIPPED]
Time ......................... [SKIPPED]
Network ...................... [SUCCESS]
Groups ....................... [SKIPPED]
Users ........................ [SUCCESS]
Proxy ........................ [SKIPPED]
Rpm .......................... [SKIPPED]
Os Files ..................... [SKIPPED]
Systemd ...................... [SKIPPED]
Fips ......................... [SKIPPED]
Elemental .................... [SKIPPED]
Suma ......................... [SKIPPED]
Populating Embedded Artifact Registry... 100% |██████████████████████████████████████████████████████████████████████████████████████████████████████████| (15/15, 4 it/min)
Embedded Artifact Registry ... [SUCCESS]
Keymap ....................... [SUCCESS]
Configuring Kubernetes component...
The Kubernetes CNI is not explicitly set, defaulting to 'cilium'.
Downloading file: rke2_installer.sh
Kubernetes ................... [SUCCESS]
Certificates ................. [SKIPPED]
Cleanup ...................... [SKIPPED]
Building ISO image...
Kernel Params ................ [SKIPPED]
Build complete, the image can be found at: eib-image.iso

Uma vez que um nó usando a imagem criada seja provisionado, podemos verificar a instalação do KubeVirt e do CDI.

Verify KubeVirt:

/var/lib/rancher/rke2/bin/kubectl get all -n kubevirt-system --kubeconfig /etc/rancher/rke2/rke2.yaml

A saída deve ser semelhante à seguinte, mostrando que tudo foi implantado com sucesso:

NAME                                  READY   STATUS    RESTARTS   AGE
pod/virt-api-59cb997648-mmt67         1/1     Running   0          2m34s
pod/virt-controller-69786b785-7cc96   1/1     Running   0          2m8s
pod/virt-controller-69786b785-wq2dz   1/1     Running   0          2m8s
pod/virt-handler-2l4dm                1/1     Running   0          2m8s
pod/virt-operator-7c444cff46-nps4l    1/1     Running   0          3m1s
pod/virt-operator-7c444cff46-r25xq    1/1     Running   0          3m1s

NAME                                  TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)   AGE
service/kubevirt-operator-webhook     ClusterIP   10.43.167.109   <none>        443/TCP   2m36s
service/kubevirt-prometheus-metrics   ClusterIP   None            <none>        443/TCP   2m36s
service/virt-api                      ClusterIP   10.43.18.202    <none>        443/TCP   2m36s
service/virt-exportproxy              ClusterIP   10.43.142.188   <none>        443/TCP   2m36s

NAME                          DESIRED   CURRENT   READY   UP-TO-DATE   AVAILABLE   NODE SELECTOR            AGE
daemonset.apps/virt-handler   1         1         1       1            1           kubernetes.io/os=linux   2m8s

NAME                              READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/virt-api          1/1     1            1           2m34s
deployment.apps/virt-controller   2/2     2            2           2m8s
deployment.apps/virt-operator     2/2     2            2           3m1s

NAME                                        DESIRED   CURRENT   READY   AGE
replicaset.apps/virt-api-59cb997648         1         1         1       2m34s
replicaset.apps/virt-controller-69786b785   2         2         2       2m8s
replicaset.apps/virt-operator-7c444cff46    2         2         2       3m1s

NAME                            AGE    PHASE
kubevirt.kubevirt.io/kubevirt   3m1s   Deployed

Verificar CDI:

/var/lib/rancher/rke2/bin/kubectl get all -n cdi-system --kubeconfig /etc/rancher/rke2/rke2.yaml

A saída deve ser semelhante à seguinte, mostrando que tudo foi implantado com sucesso:

NAME                                   READY   STATUS    RESTARTS   AGE
pod/cdi-apiserver-5598c9bf47-pqfxw     1/1     Running   0          3m44s
pod/cdi-deployment-7cbc5db7f8-g46z7    1/1     Running   0          3m44s
pod/cdi-operator-777c865745-2qcnj      1/1     Running   0          3m48s
pod/cdi-uploadproxy-646f4cd7f7-fzkv7   1/1     Running   0          3m44s

NAME                             TYPE        CLUSTER-IP     EXTERNAL-IP   PORT(S)    AGE
service/cdi-api                  ClusterIP   10.43.2.224    <none>        443/TCP    3m44s
service/cdi-prometheus-metrics   ClusterIP   10.43.237.13   <none>        8080/TCP   3m44s
service/cdi-uploadproxy          ClusterIP   10.43.114.91   <none>        443/TCP    3m44s

NAME                              READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/cdi-apiserver     1/1     1            1           3m44s
deployment.apps/cdi-deployment    1/1     1            1           3m44s
deployment.apps/cdi-operator      1/1     1            1           3m48s
deployment.apps/cdi-uploadproxy   1/1     1            1           3m44s

NAME                                         DESIRED   CURRENT   READY   AGE
replicaset.apps/cdi-apiserver-5598c9bf47     1         1         1       3m44s
replicaset.apps/cdi-deployment-7cbc5db7f8    1         1         1       3m44s
replicaset.apps/cdi-operator-777c865745      1         1         1       3m48s
replicaset.apps/cdi-uploadproxy-646f4cd7f7   1         1         1       3m44s

63.10 Instalação do SUSE Private Registry

Para incluir o SUSE Private Registry em uma implantação air-gapped, devemos atualizar o arquivo de definição para incluir o gráfico helm necessário, bem como os artefatos incorporados para as novas imagens.

Vamos atualizar o arquivo de definição:

apiVersion: 1.3
image:
  imageType: iso
  arch: x86_64
  baseImage: slemicro.iso
  outputImageName: eib-image.iso
operatingSystem:
  users:
    - username: root
      encryptedPassword: $6$jHugJNNd3HElGsUZ$eodjVe4te5ps44SVcWshdfWizrP.xAyd71CVEXazBJ/.v799/WRCBXxfYmunlBO2yp1hm/zb4r8EmnrrNCF.P/
kubernetes:
  version: v1.35.4+rke2r1
  helm:
    charts:
      - name: metallb
        version: 306.0.2+up0.15.3
        targetNamespace: metallb-system
        createNamespace: true
        repositoryName: suse-edge-charts
        installationNamespace: kube-system
      - name: suse-storage
        releaseName: longhorn
        repositoryName: rancher-application-collection
        targetNamespace: longhorn-system
        createNamespace: true
        version: 1.11.2
      - name: private-registry-helm
        createNamespace: true
        installationNamespace: kube-system
        repositoryName: privateregistry
        targetNamespace: suse-private-registry
        valuesFile: privateregistry.yaml
        version: 1.1.1
    repositories:
      - name: privateregistry
        authentication:
          username: ${PRIVATE_REGISTRY_USERNAME}
          password: ${PRIVATE_REGISTRY_PASSWORD}
        plainHTTP: false
        skipTLSVerify: false
        url: oci://registry.suse.com/private-registry
      - name: rancher-application-collection
        url: oci://dp.apps.rancher.io/charts
        authentication:
          username: $APPS.RANCHER.IO_USERNAME
          password: $APPS.RANCHER.IO_ACCESS_TOKEN
embeddedArtifactRegistry:
  registries:
    - uri: registry.suse.com
      authentication:
        username: ${PRIVATE_REGISTRY_USERNAME}
        password: ${PRIVATE_REGISTRY_PASSWORD}
    - uri: dp.apps.rancher.io
        authentication:
          username: $APPS.RANCHER.IO_USERNAME
          password: $APPS.RANCHER.IO_ACCESS_TOKEN
  images:
    - name: registry.suse.com/private-registry/harbor-core:1.1.1-1.19
    - name: registry.suse.com/private-registry/harbor-jobservice:1.1.1-1.19
    - name: registry.suse.com/private-registry/harbor-portal:1.1.1-1.20
    - name: registry.suse.com/private-registry/harbor-registry:1.1.1-1.19
    - name: registry.suse.com/private-registry/harbor-registryctl:1.1.1-1.19
    - name: registry.suse.com/private-registry/harbor-trivy-adapter:1.1.1-1.24
Nota
Nota

Você precisará de certas credenciais, que podem ser obtidas seguindo a documentação oficial do SUSE Private Registry. Você também deve modificar as variáveis ${PRIVATE_REGISTRY_USERNAME} e ${PRIVATE_REGISTRY_PASSWORD}. Certifique-se de listar as imagens que contêm as versões dos componentes de que você precisa.

Agora precisamos adicionar os manifestos do Kubernetes necessários para configurar corretamente o SUSE Private Registry.

Você precisa modificar o ${MGMT_CLUSTER_REGISTRY_IP} com um IP estático reservado para o SUSE Private Registry nos seguintes arquivos:

  1. kubernetes/manifests/metallb-registry.yaml

    apiVersion: metallb.io/v1beta1
    kind: L2Advertisement
    metadata:
      name: private-registry
      namespace: metallb-system
    spec:
      ipAddressPools:
      - private-registry-pool
    ---
    apiVersion: metallb.io/v1beta1
    kind: IPAddressPool
    metadata:
      name: private-registry-pool
      namespace: metallb-system
    spec:
      addresses:
      - ${MGMT_CLUSTER_REGISTRY_IP}/32
      serviceAllocation:
        namespaces:
        - suse-private-registry
  2. kubernetes/helm/values/privateregistry.yaml

    core:
      secretName: suse-registry-tls
    expose:
      tls:
        certSource: secret
        enabled: true
        secret:
          secretName: suse-registry-tls
      type: loadBalancer
    externalURL: https://${MGMT_CLUSTER_REGISTRY_IP}
    persistence:
      persistentVolumeClaim:
        registry:
          size: 20Gi

Finalmente, o kubernetes/manifests/suse-private-registry-creds.yaml deve ser criado com o seguinte conteúdo:

apiVersion: v1
kind: Secret
metadata:
  name: suse-registry
  namespace: suse-private-registry
type: kubernetes.io/dockerconfigjson
data:
  .dockerconfigjson: ${DOCKER_CONFIG_JSON_BASE64}
---
apiVersion: v1
kind: Secret
metadata:
    name: suse-registry-tls
    namespace: suse-private-registry
type: kubernetes.io/tls
data:
    tls.crt: ${TLS_CRT_BASE64}
    tls.key: ${TLS_KEY_BASE64}

Para configurar corretamente o json de configuração do docker (base64) para o ${DOCKER_CONFIG_JSON_BASE64}, execute:

# ${DOCKER_CONFIG_JSON_BASE64} CONTENT
echo -n '{"auths": {"<MGMT_CLUSTER_REGISTRY_IP>": {"username": "<USERNAME>", "password": "<PASSWORD>", "auth": "<AUTH>"}}}' | base64

Onde o IP é o mesmo que o ${MGMT_CLUSTER_REGISTRY_IP} configurado anteriormente, e o username, password e auth podem ser obtidos na documentação oficial do SUSE Private Registry.

Para gerar o certificado TLS e a chave codificados em base64 (tls.crt e tls.key) para ${TLS_CRT_BASE64} e ${TLS_KEY_BASE64}, você pode criar os seus próprios executando:

# Generate a self-signed certificate and key
openssl req -x509 -newkey rsa:4096 -keyout key.pem -out cert.pem -sha256 -days 365 -nodes

# Convert them to base64 for the suse-private-registry-creds.yaml file
cat cert.pem | base64 -w 0
cat key.pem | base64 -w 0

Verificar SUSE Private Registry:

/var/lib/rancher/rke2/bin/kubectl get pods -n suse-private-registry --kubeconfig /etc/rancher/rke2/rke2.yaml

A saída deve ser semelhante à seguinte, mostrando que tudo foi implantado com sucesso:

NAME                                                      READY   STATUS    RESTARTS   AGE
pod/private-registry-harbor-core-588fd4876f-8tqnv         1/1     Running   0          4m30s
pod/private-registry-harbor-database-0                    1/1     Running   0          4m30s
pod/private-registry-harbor-jobservice-7658f97fbc-4vq6n   1/1     Running   0          4m30s
pod/private-registry-harbor-portal-5455ccc4bc-jpmt5       1/1     Running   0          4m30s
pod/private-registry-harbor-redis-0                       1/1     Running   0          4m30s
pod/private-registry-harbor-registry-5648b9d89-wdswz      2/2     Running   0          4m30s
pod/private-registry-harbor-trivy-0                       1/1     Running   0          4m30s

63.11 Instalação do Metal3

Ao implantar o Metal3 em um ambiente air-gapped usando EIB e Hauler, uma configuração especial é necessária para a imagem do Ironic Python Agent (IPA). A imagem IPA é usada pelo Metal3 para inspeção e provisionamento de hosts bare-metal.

Nota
Nota

Para obter mais informações sobre a instalação e configuração do Metal3, incluindo a configuração do MetalLB, consulte Capítulo 4, Implantações automatizadas de BMC com Metal3.

Para incluir o Metal3 em uma implantação air-gapped, você precisa:

  1. Adicione o gráfico Helm do Metal3 ao seu arquivo de definição

  2. Adicione a imagem IPA ao registro de artefatos incorporado

  3. Crie um arquivo de valores Helm com useHauler: true

Adicione o seguinte à seção kubernetes.helm.charts do seu arquivo de definição:

  helm:
    charts:
      - name: metal3
        version: 306.0.29+up0.15.0
        targetNamespace: metal3-system
        createNamespace: true
        repositoryName: suse-edge-charts
        installationNamespace: kube-system
        valuesFile: metal3-values.yaml

Adicione a imagem IPA à seção embeddedArtifactRegistry.images:

embeddedArtifactRegistry:
  images:
    - name: registry.suse.com/edge/3.6/ironic-python-agent:3.0.9

Crie um arquivo de valores Helm para o Metal3:

cat << EOF > $CONFIG_DIR/kubernetes/helm/values/metal3-values.yaml
global:
  ironicIP: <STATIC_IRONIC_IP>
metal3-ironic:
  ipa:
    useHauler: true
EOF
Importante
Importante

O valor metal3-ironic.ipa.useHauler deve ser definido como true (valor booleano) ao implantar em ambientes air-gapped usando EIB/Hauler. Isso instrui o Metal3 a recuperar a imagem IPA do registro de artefatos incorporado em vez de tentar baixá-la da internet.

63.12 Solução de problemas

Se você encontrar problemas ao criar as imagens ou quiser testar e depurar ainda mais o processo, consulte a documentação do upstream.

64 Criando imagens atualizadas do SUSE Linux Micro com o Kiwi

Esta seção explica como gerar imagens atualizadas do SUSE Linux Micro para serem usadas com o Edge Image Builder, com Cluster API (CAPI) + Metal3, ou para gravar a imagem de disco diretamente em um dispositivo de bloco. Este processo é útil em situações onde é necessário incluir os patches mais recentes nas imagens iniciais de inicialização do sistema (para minimizar a transferência de patches pós-instalação), ou para cenários onde o CAPI é usado, onde é preferível reinstalar o sistema operacional com uma nova imagem em vez de atualizar os hosts no local.

Este processo faz uso do Kiwi para executar a compilação da imagem. O SUSE Telco Cloud fornece uma versão conteinerizada que simplifica o processo geral com um utilitário auxiliar integrado, permitindo especificar o arquivo de controle de destino necessário. O arquivo de controle define o tipo de imagem de saída necessária, com os comuns listados abaixo:

  • "Base" - Uma imagem de disco do SUSE Linux Micro com um conjunto reduzido de pacotes (inclui podman).

  • "Base-SelfInstall" - Uma imagem SelfInstall baseada na "Base" acima.

  • "Base-RT" - O mesmo que a "Base" acima, mas usando um kernel de tempo real (rt).

  • "Base-RT-SelfInstall" - Uma imagem SelfInstall baseada na "Base-RT" acima

  • "Default" - Uma imagem de disco do SUSE Linux Micro baseada na "Base" acima, mas com algumas ferramentas adicionais, incluindo a pilha de virtualização, Cockpit e salt-minion.

  • "Default-SelfInstall" - Uma imagem SelfInstall baseada no "Default" acima

Consulte a documentação do SUSE Linux Micro 6.2 para obter mais detalhes.

Nota
Nota

Este processo funciona para ambas as arquiteturas AMD64/Intel 64 e AArch64, mas é necessário usar um host de compilação com a mesma arquitetura das imagens que estão sendo criadas. Em outras palavras, para criar uma imagem AArch64, é necessário usar um host de compilação AArch64, e vice-versa para AMD64/Intel 64 - compilações cruzadas não são suportadas no momento.

64.1 Pré-requisitos

O construtor de imagens Kiwi requer o seguinte:

  • Um host 6.2 SUSE Linux Micro (\"sistema de compilação\") com a mesma arquitetura da imagem sendo compilada.

  • O sistema de compilação precisa já estar registrado via SUSEConnect (o registro é usado para obter os pacotes mais recentes dos repositórios SUSE)

  • Uma conexão com a internet que possa ser usada para obter os pacotes necessários. Se conectado via proxy, o host de compilação precisa estar pré-configurado.

  • O SELinux precisa estar desativado no host de compilação (já que a rotulagem do SELinux ocorre no contêiner e pode entrar em conflito com a política do host)

  • Pelo menos 10 GB de espaço livre em disco para acomodar a imagem do contêiner, a raiz de compilação e a(s) imagem(ns) de saída resultante(s)

64.2 Conceitos Básicos

Devido a certas limitações, é necessário atualmente desativar o SELinux. Conecte-se ao host de compilação da imagem 6.2 SUSE Linux Micro e certifique-se de que o SELinux esteja desativado:

# setenforce 0

Crie um diretório de saída para ser compartilhado com o contêiner de compilação Kiwi para salvar as imagens resultantes:

# mkdir ~/output

Baixe a imagem mais recente do construtor Kiwi do Registro SUSE:

# podman pull registry.suse.com/edge/3.6/kiwi-builder:10.2.29.1
(...)

64.3 Construindo a imagem Default

Este é o comportamento padrão do contêiner de imagem Kiwi se nenhum argumento for fornecido durante a execução da imagem do contêiner. O comando a seguir executa o podman com dois diretórios mapeados para o contêiner:

  • O /etc/zypp/repos.d diretório do repositório de pacotes SUSE Linux Micro do host subjacente.

  • O diretório ~/output de saída criado acima.

O contêiner de imagem Kiwi requer a execução do build-image script auxiliar como:

# podman run --privileged -v /etc/zypp/repos.d:/micro-sdk/repos/ -v ~/output:/tmp/output \
    -it registry.suse.com/edge/3.6/kiwi-builder:10.2.29.1 build-image
(...)
Nota
Nota

Espera-se que, se você estiver executando este script pela primeira vez, ele falhe logo após iniciar com \"ERRO: O teste inicial do dispositivo de loop falhou, tente executar o contêiner novamente.\", este é um sintoma de dispositivos de loop sendo criados no sistema host subjacente que não estão imediatamente visíveis dentro da imagem do contêiner. Simplesmente execute o comando novamente e ele deverá prosseguir sem problemas.

Após alguns minutos, as imagens podem ser encontradas no diretório de saída local:

(...)
INFO: Image build successful, generated images are available in the 'output' directory.

# ls -1 output/
SLE-Micro.x86_64-6.2.changes
SLE-Micro.x86_64-6.2.packages
SLE-Micro.x86_64-6.2.raw
SLE-Micro.x86_64-6.2.verified
build
kiwi.result
kiwi.result.json

64.4 Construindo imagens com outros arquivos de controle

Para construir diferentes arquivos de controle de imagem, a opção de comando "-p" no script auxiliar de imagem de contêiner Kiwi é usada. Por exemplo, para construir a imagem ISO \"Default-SelfInstall\":

# podman run --privileged -v /etc/zypp/repos.d:/micro-sdk/repos/ -v ~/output:/tmp/output \
    -it registry.suse.com/edge/3.6/kiwi-builder:10.2.29.1 build-image -p Default-SelfInstall
(...)
Nota
Nota

Para evitar perda de dados, o Kiwi se recusará a executar se houver imagens no output diretório. É necessário remover o conteúdo do diretório de saída antes de prosseguir com rm -f output/*.

Alternativamente, para construir uma imagem ISO SelfInstall com o kernel de tempo real ("kernel-rt"):

# podman run --privileged -v /etc/zypp/repos.d:/micro-sdk/repos/ -v ~/output:/tmp/output \
    -it registry.suse.com/edge/3.6/kiwi-builder:10.2.29.1 build-image -p Base-RT-SelfInstall
(...)

64.5 Construindo imagens com tamanhos de setor grandes

Alguns hardwares exigem uma imagem com um tamanho de setor grande, ou seja, 4096 bytes em vez dos 512 bytes padrão. O construtor Kiwi conteinerizado suporta a capacidade de gerar imagens com tamanho de bloco grande especificando o parâmetro \"-b\". Por exemplo, para construir uma imagem "Default-SelfInstall" com um tamanho de setor grande:

# podman run --privileged -v /etc/zypp/repos.d:/micro-sdk/repos/ -v ~/output:/tmp/output \
    -it registry.suse.com/edge/3.6/kiwi-builder:10.2.29.1 build-image -p Default-SelfInstall -b
(...)

64.6 Usando um arquivo de definição de imagem Kiwi personalizado

Para casos de uso avançados, um arquivo de definição de imagem Kiwi personalizado (SL-Micro.kiwi) pode ser usado juntamente com quaisquer scripts de pós-construção necessários. Isso requer substituir as definições padrão pré-empacotadas pela equipe do SUSE Telco Cloud.

Crie um novo diretório e mapeie-o para dentro da imagem do contêiner onde o script auxiliar está procurando (/micro-sdk/defs):

# mkdir ~/mydefs/
# cp /path/to/SL-Micro.kiwi ~/mydefs/
# cp /path/to/config.sh ~/mydefs/
# podman run --privileged -v /etc/zypp/repos.d:/micro-sdk/repos/ -v ~/output:/tmp/output -v ~/mydefs/:/micro-sdk/defs/ \
    -it registry.suse.com/edge/3.6/kiwi-builder:10.2.29.1 build-image
(...)
Atenção
Atenção

Isso é necessário apenas para casos de uso avançados e pode causar problemas de suporte. Entre em contato com seu representante SUSE para obter mais conselhos e orientações.

Para obter os arquivos de definição de imagem Kiwi padrão incluídos no contêiner, os seguintes comandos podem ser usados:

$ podman create --name kiwi-builder registry.suse.com/edge/3.6/kiwi-builder:10.2.29.1
$ podman cp kiwi-builder:/micro-sdk/defs/SL-Micro.kiwi .
$ podman cp kiwi-builder:/micro-sdk/defs/SL-Micro.kiwi.4096 .
$ podman rm kiwi-builder
$ ls ./SL-Micro.*
(...)

65 Usando clusterclass para implantar clusters downstream

65.1 Introdução

O provisionamento de clusters Kubernetes é uma tarefa complexa que exige profundo conhecimento na configuração de componentes de cluster. À medida que as configurações se tornam mais complexas, ou à medida que as demandas de diferentes provedores introduzem inúmeras definições de recursos específicas do provedor, a criação de clusters pode parecer assustadora. Felizmente, a Kubernetes Cluster API (CAPI) oferece uma abordagem declarativa mais elegante, que é ainda mais aprimorada pelo ClusterClass. Esse recurso introduz um modelo orientado a templates, permitindo que você defina uma classe de cluster reutilizável que encapsula a complexidade e promove a consistência.

65.2 O que é ClusterClass?

O projeto CAPI introduziu o recurso ClusterClass como uma mudança de paradigma no gerenciamento do ciclo de vida de clusters Kubernetes por meio da adoção de uma metodologia baseada em templates para a instanciação de clusters. Em vez de definir recursos independentemente para cada cluster, os usuários definem uma ClusterClass, que serve como um projeto abrangente e reutilizável. Essa representação abstrata encapsula o estado desejado e a configuração de um cluster Kubernetes, permitindo a criação rápida e consistente de múltiplos clusters que aderem às especificações definidas. Essa abstração reduz a carga de configuração, resultando em manifestos de implantação mais gerenciáveis. Isso significa que os componentes principais de um cluster de carga de trabalho são definidos no nível da classe, permitindo que os usuários usem esses modelos como tipos de cluster Kubernetes que podem ser reutilizados uma ou várias vezes para o provisionamento de clusters. A implementação do ClusterClass gera várias vantagens importantes que abordam os desafios inerentes ao gerenciamento tradicional do CAPI em escala:

  • Redução substancial na complexidade e na verbosidade do YAML

  • Processos de manutenção e atualização otimizados

  • Consistência e padronização aprimoradas em todas as implantações

  • Escalabilidade e recursos de automação aprimorados

  • Gerenciamento declarativo e controle de versão robusto

clusterclass v1beta2

65.3 Exemplo de arquivo de provisionamento CAPI atual

A implantação de um cluster Kubernetes, aproveitando a Cluster API (CAPI) com os provedores CAPRKE2 (plano de controle e inicialização) e CAPM3 (infraestrutura), exige que você defina vários recursos personalizados. Esses recursos definem o estado desejado do cluster e sua infraestrutura subjacente, permitindo que o CAPI orquestre o ciclo de vida de provisionamento e gerenciamento. O trecho de código abaixo ilustra os tipos de recursos que devem ser configurados para instanciar um cluster Kubernetes apenas com nós do plano de controle:

  • Cluster: Este recurso encapsula configurações de alto nível, incluindo a topologia de rede que regerá a comunicação entre nós e a descoberta de serviços. Além disso, ele estabelece vínculos essenciais com a especificação do plano de controle e o recurso de provedor de infraestrutura designado, informando assim ao CAPI sobre a arquitetura de cluster desejada e a infraestrutura subjacente na qual ele será provisionado.

  • Metal3Cluster: Este recurso define atributos de nível de infraestrutura exclusivos do Metal3, por exemplo, o endpoint externo através do qual o servidor de API do Kubernetes será acessível.

  • RKE2ControlPlane: O recurso RKE2ControlPlane define as características e o comportamento dos nós do plano de controle do cluster. Dentro desta especificação, parâmetros como o número desejado de réplicas do plano de controle (crucial para garantir alta disponibilidade e tolerância a falhas), a versão específica da distribuição Kubernetes (alinhada com a versão do RKE2 escolhida) e a estratégia para implementar atualizações nos componentes do plano de controle são configurados. Além disso, este recurso determina a Interface de Rede de Contêiner (CNI) a ser empregada no cluster e facilita a injeção de configurações específicas do agente, frequentemente utilizando o Ignition para o provisionamento fluido e automatizado dos agentes RKE2 nos nós do plano de controle.

  • Metal3MachineTemplate: Este recurso serve como um modelo para a criação das instâncias de computação individuais que formam os nós do plano de controle do cluster.

  • Metal3DataTemplate: Complementando o Metal3MachineTemplate, o recurso Metal3DataTemplate permite que metadados adicionais sejam especificados para as instâncias de máquina recém-provisionadas.

    apiVersion: cluster.x-k8s.io/v1beta2
    kind: Cluster
    metadata:
      name: emea-spa-cluster-3
      namespace: emea-spa
      labels:
        cluster-api.cattle.io/rancher-auto-import: "true"
    spec:
      clusterNetwork:
        pods:
          cidrBlocks:
            - 192.168.0.0/18
        services:
          cidrBlocks:
            - 10.96.0.0/12
      controlPlaneRef:
        apiGroup: controlplane.cluster.x-k8s.io
        kind: RKE2ControlPlane
        name: emea-spa-cluster-3
      infrastructureRef:
        apiGroup: infrastructure.cluster.x-k8s.io
        kind: Metal3Cluster
        name: emea-spa-cluster-3
    ---
    apiVersion: infrastructure.cluster.x-k8s.io/v1beta1
    kind: Metal3Cluster
    metadata:
      name: emea-spa-cluster-3
      namespace: emea-spa
    spec:
      controlPlaneEndpoint:
        host: 192.168.122.203
        port: 6443
      cloudProviderEnabled: false
    ---
    apiVersion: controlplane.cluster.x-k8s.io/v1beta2
    kind: RKE2ControlPlane
    metadata:
      name: emea-spa-cluster-3
      namespace: emea-spa
    spec:
      machineTemplate:
        spec:
          infrastructureRef:
            apiGroup: infrastructure.cluster.x-k8s.io
            kind: Metal3MachineTemplate
            name: emea-spa-cluster-3
      replicas: 1
      version: v1.35.4+rke2r1
      rolloutStrategy:
        type: "RollingUpdate"
        rollingUpdate:
          maxSurge: 1
      registrationMethod: "control-plane-endpoint"
      registrationAddress: 192.168.122.203
      serverConfig:
        cni: cilium
        cniMultusEnable: true
        tlsSan:
          - 192.168.122.203
          - https://192.168.122.203.sslip.io
      agentConfig:
        format: ignition
        additionalUserData:
          config: |
            variant: fcos
            version: 1.4.0
            storage:
              files:
                - path: /var/lib/rancher/rke2/server/manifests/endpoint-copier-operator.yaml
                  overwrite: true
                  contents:
                    inline: |
                      apiVersion: helm.cattle.io/v1
                      kind: HelmChart
                      metadata:
                        name: endpoint-copier-operator
                        namespace: kube-system
                      spec:
                        chart: oci://registry.suse.com/edge/charts/endpoint-copier-operator
                        targetNamespace: endpoint-copier-operator
                        version: 306.0.1+up0.3.0
                        createNamespace: true
                - path: /var/lib/rancher/rke2/server/manifests/metallb.yaml
                  overwrite: true
                  contents:
                    inline: |
                      apiVersion: helm.cattle.io/v1
                      kind: HelmChart
                      metadata:
                        name: metallb
                        namespace: kube-system
                      spec:
                        chart: oci://registry.suse.com/edge/charts/metallb
                        targetNamespace: metallb-system
                        version: 306.0.2+up0.15.3
                        createNamespace: true
                - path: /var/lib/rancher/rke2/server/manifests/metallb-cr.yaml
                  overwrite: true
                  contents:
                    inline: |
                      apiVersion: metallb.io/v1beta1
                      kind: IPAddressPool
                      metadata:
                        name: kubernetes-vip-ip-pool
                        namespace: metallb-system
                      spec:
                        addresses:
                          - 192.168.122.203/32
                        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:
                        ports:
                        - name: rke2-api
                          port: 9345
                          protocol: TCP
                          targetPort: 9345
                        - name: k8s-api
                          port: 6443
                          protocol: TCP
                          targetPort: 6443
                        type: LoadBalancer
            systemd:
              units:
                - name: rke2-preinstall.service
                  enabled: true
                  contents: |
                    [Unit]
                    Description=rke2-preinstall
                    Wants=network-online.target
                    Before=rke2-install.service
                    ConditionPathExists=!/run/cluster-api/bootstrap-success.complete
                    [Service]
                    Type=oneshot
                    User=root
                    ExecStartPre=/bin/sh -c "mount -L config-2 /mnt"
                    ExecStart=/bin/sh -c "sed -i \"s/BAREMETALHOST_UUID/$(jq -r .uuid /mnt/openstack/latest/meta_data.json)/\" /etc/rancher/rke2/config.yaml"
                    ExecStart=/bin/sh -c "echo \"node-name: $(jq -r .name /mnt/openstack/latest/meta_data.json)\" >> /etc/rancher/rke2/config.yaml"
                    ExecStart=/bin/sh -c "echo \"node-label:\" >> /etc/rancher/rke2/config.yaml"
                    ExecStart=/bin/sh -c "echo \"  - metal3.io/uuid=$(jq -r .uuid /mnt/openstack/latest/meta_data.json)\" >> /etc/rancher/rke2/config.yaml"
                    ExecStartPost=/bin/sh -c "umount /mnt"
                    [Install]
                    WantedBy=multi-user.target
        kubelet:
          extraArgs:
          - provider-id=metal3://BAREMETALHOST_UUID
        nodeName: "localhost.localdomain"
    ---
    apiVersion: infrastructure.cluster.x-k8s.io/v1beta1
    kind: Metal3MachineTemplate
    metadata:
      name: emea-spa-cluster-3
      namespace: emea-spa
    spec:
      nodeReuse: True
      template:
        spec:
          automatedCleaningMode: metadata
          dataTemplate:
            name: emea-spa-cluster-3
          hostSelector:
            matchLabels:
              cluster-role: control-plane
              deploy-region: emea-spa
              cluster-type: group-3
          image:
            checksum: http://fileserver.local:8080/eibimage-downstream-cluster.raw.sha256
            checksumType: sha256
            format: raw
            url: http://fileserver.local:8080/eibimage-downstream-cluster.raw
    ---
    apiVersion: infrastructure.cluster.x-k8s.io/v1beta1
    kind: Metal3DataTemplate
    metadata:
      name: emea-spa-cluster-3
      namespace: emea-spa
    spec:
      clusterName: emea-spa-cluster-3
      metaData:
        objectNames:
        - key: name
          object: machine
        - key: local-hostname
          object: machine
        - key: local_hostname
          object: machine
Nota
Nota

Adicionar o rótulo cluster-api.cattle.io/rancher-auto-import: "true" a um objeto de API Cluster no grupo de API cluster.x-k8s.io importará o cluster para o Rancher (criando um objeto de API Cluster do Rancher correspondente no grupo de API management.cattle.io). Consulte a documentação da Cluster API para obter mais informações.

65.4 Transformando o arquivo de provisionamento CAPI para ClusterClass

65.4.1 Definição de ClusterClass

O código a seguir define um recurso ClusterClass, um modelo declarativo para implantar consistentemente tipos específicos de clusters Kubernetes. Esta especificação inclui configurações comuns de infraestrutura e plano de controle, permitindo o provisionamento eficiente e o gerenciamento de ciclo de vida uniforme em uma frota de clusters. Existem algumas variáveis definidas no exemplo de ClusterClass a seguir, que serão substituídas durante o processo de instanciação do cluster usando os valores reais solicitados para cada instância de cluster. As variáveis a seguir são usadas no exemplo:

  • metallbHelmChartVersion: Esta variável opcional permite especificar a versão do gráfico Helm MetalLB a ser implantado no cluster; quando não fornecida, o gráfico Helm MetalLB não será implantado.

  • endpointCopierOperatorHelmChartVersion: Esta variável opcional permite especificar a versão do gráfico Helm Endpoint Copier Operator a ser implantado no cluster (quando uma versão para o gráfico Helm MetalLB também tiver sido fornecida); quando não fornecida, o gráfico Helm Endpoint Copier Operator não será implantado.

  • controlPlaneMachineTemplateImageURL: Esta variável obrigatória permite especificar a URL da imagem a ser usada para provisionar as máquinas do plano de controle.

  • controlPlaneMachineTemplateHostSelectorDeployRegion: Esta variável obrigatória permite especificar o valor do seletor de host deploy-region para as máquinas do plano de controle.

  • controlPlaneMachineTemplateHostSelectorClusterType: Esta variável obrigatória permite especificar o valor do seletor de host cluster-type para as máquinas do plano de controle.

  • controlPlaneMachineTemplateDataTemplateName: Esta variável obrigatória permite especificar o nome do objeto de API Metal3DataTemplate a ser usado para as máquinas do plano de controle.

  • controlPlaneEndpointHost: Esta variável obrigatória permite especificar o nome de host ou o endereço IP do endpoint do plano de controle.

  • tlsSan: Esta variável obrigatória permite especificar a lista de Nomes Alternativos de Assunto (SANs) TLS para o endpoint do plano de controle.

O arquivo de definição de ClusterClass consiste nos quatro recursos a seguir:

  • ClusterClass: Este recurso encapsula toda a definição do ClusterClass, incluindo os modelos de plano de controle e de infraestrutura. Além disso, ele inclui a lista de variáveis que serão substituídas durante o processo de instanciação (e define os patches que as utilizam).

  • RKE2ControlPlaneTemplate: Este recurso define o modelo do plano de controle, especificando a configuração desejada para os nós do plano de controle. Além disso, alguns parâmetros serão substituídos pelos valores corretos durante o processo de instanciação.

  • Metal3ClusterTemplate: Este recurso define o modelo de infraestrutura, especificando a configuração desejada para a infraestrutura subjacente. Ele inclui parâmetros como o endpoint do plano de controle e a flag cloudProviderEnabled (true|false). Além disso, alguns parâmetros serão substituídos pelos valores corretos durante o processo de instanciação.

  • Metal3MachineTemplate: Este recurso define o blueprint para as máquinas dos nós do plano de controle, fornecendo os espaços reservados para que os parâmetros sejam substituídos pelos valores corretos durante o processo de instanciação.

    apiVersion: controlplane.cluster.x-k8s.io/v1beta2
    kind: RKE2ControlPlaneTemplate
    metadata:
      name: example-controlplane
      namespace: emea-spa
    spec:
      template:
        spec:
          rolloutStrategy:
            type: "RollingUpdate"
            rollingUpdate:
              maxSurge: 1
          registrationMethod: "control-plane-endpoint"
          registrationAddress: TO-BE-PATCHED-AUTOMATICALLY  # This will be replaced by the involved patch when applying the cluster instance
          serverConfig:
            cni: cilium
            cniMultusEnable: true
            tlsSan:
            - TO-BE-PATCHED-AUTOMATICALLY    # This will be replaced by the involved patch when applying the cluster instance
          agentConfig:
            format: ignition
            additionalUserData:
              config: |          # This will be replaced by the involved patch when applying the cluster instance
                TO-BE-PATCHED-AUTOMATICALLY
            kubelet:
              extraArgs:
              - provider-id=metal3://BAREMETALHOST_UUID
            nodeName: "localhost.localdomain"
    ---
    apiVersion: infrastructure.cluster.x-k8s.io/v1beta1
    kind: Metal3ClusterTemplate
    metadata:
      name: example-cluster-template
      namespace: emea-spa
    spec:
      template:
        spec:
          controlPlaneEndpoint:
            host: TO-BE-PATCHED-AUTOMATICALLY  # This will be replaced by the involved patch when applying the cluster instance
            port: 6443
          cloudProviderEnabled: false
    ---
    apiVersion: infrastructure.cluster.x-k8s.io/v1beta1
    kind: Metal3MachineTemplate
    metadata:
      name: example-controlplane-machineinfrastructure
      namespace: emea-spa
    spec:
      nodeReuse: true
      template:
        spec:
          automatedCleaningMode: metadata
          dataTemplate:
            name: to-be-patched-automatically  # This will be replaced by the involved patch when applying the cluster instance
          hostSelector:
            matchLabels:  # The labels used to identify the BMHs to select.
              cluster-role: control-plane
              deploy-region: TO-BE-PATCHED-AUTOMATICALLY # This will be replaced by the involved patch when applying the cluster instance
              cluster-type: TO-BE-PATCHED-AUTOMATICALLY  # This will be replaced by the involved patch when applying the cluster instance
          image:
            checksum: http://TO-BE-PATCHED-AUTOMATICALLY # This will be replaced by the involved patch when applying the cluster instance
            checksumType: sha256
            format: raw
            url: http://TO-BE-PATCHED-AUTOMATICALLY      # This will be replaced by the involved patch when applying the cluster instance
    ---
    apiVersion: cluster.x-k8s.io/v1beta2
    kind: ClusterClass
    metadata:
      name: example-clusterclass
      namespace: emea-spa
    spec:
      infrastructure:
        templateRef:
          kind: Metal3ClusterTemplate
          apiVersion: infrastructure.cluster.x-k8s.io/v1beta1
          name: example-cluster-template
      controlPlane:
        templateRef:
          kind: RKE2ControlPlaneTemplate
          apiVersion: controlplane.cluster.x-k8s.io/v1beta2
          name: example-controlplane
        machineInfrastructure:
          templateRef:
            kind: Metal3MachineTemplate
            apiVersion: infrastructure.cluster.x-k8s.io/v1beta1
            name: example-controlplane-machineinfrastructure
      variables:
      - name: metallbHelmChartVersion
        required: false
        schema:
          openAPIV3Schema:
            type: string
      - name: endpointCopierOperatorHelmChartVersion
        required: false
        schema:
          openAPIV3Schema:
            type: string
      - name: controlPlaneMachineTemplateImageURL
        required: true
        schema:
          openAPIV3Schema:
            type: string
      - name: controlPlaneMachineTemplateHostSelectorDeployRegion
        required: true
        schema:
          openAPIV3Schema:
            type: string
      - name: controlPlaneMachineTemplateHostSelectorClusterType
        required: true
        schema:
          openAPIV3Schema:
            type: string
      - name: controlPlaneMachineTemplateDataTemplateName
        required: true
        schema:
          openAPIV3Schema:
            type: string
      - name: controlPlaneEndpointHost
        required: true
        schema:
          openAPIV3Schema:
            type: string
      - name: tlsSan
        required: true
        schema:
          openAPIV3Schema:
            type: array
            items:
              type: string
      patches:
      - name: setControlPlaneMachineTemplateImageURL
        definitions:
        - selector:
            apiVersion: infrastructure.cluster.x-k8s.io/v1beta1
            kind: Metal3MachineTemplate
            matchResources:
              controlPlane: true        # Added to select ControlPlane
          jsonPatches:
          - op: replace
            path: "/spec/template/spec/image/url"
            valueFrom:
              variable: controlPlaneMachineTemplateImageURL
          - op: replace
            path: "/spec/template/spec/image/checksum"
            valueFrom:
              template: "{{ .controlPlaneMachineTemplateImageURL }}.sha256"
      - name: setControlPlaneMachineTemplateHostSelectorDeployRegion
        definitions:
        - selector:
            apiVersion: infrastructure.cluster.x-k8s.io/v1beta1
            kind: Metal3MachineTemplate
            matchResources:
              controlPlane: true
          jsonPatches:
          - op: replace
            path: "/spec/template/spec/hostSelector/matchLabels/deploy-region"
            valueFrom:
              variable: controlPlaneMachineTemplateHostSelectorDeployRegion
      - name: setControlPlaneMachineTemplateHostSelectorClusterType
        definitions:
        - selector:
            apiVersion: infrastructure.cluster.x-k8s.io/v1beta1
            kind: Metal3MachineTemplate
            matchResources:
              controlPlane: true        # Added to select ControlPlane
          jsonPatches:
          - op: replace
            path: "/spec/template/spec/hostSelector/matchLabels/cluster-type"
            valueFrom:
              variable: controlPlaneMachineTemplateHostSelectorClusterType
      - name: setControlPlaneMachineTemplateDataTemplateName
        definitions:
        - selector:
            apiVersion: infrastructure.cluster.x-k8s.io/v1beta1
            kind: Metal3MachineTemplate
            matchResources:
              controlPlane: true        # Added to select ControlPlane
          jsonPatches:
          - op: replace
            path: "/spec/template/spec/dataTemplate/name"
            valueFrom:
              variable: controlPlaneMachineTemplateDataTemplateName
      - name: setControlPlaneEndpoint
        definitions:
        - selector:
            apiVersion: infrastructure.cluster.x-k8s.io/v1beta1
            kind: Metal3ClusterTemplate
            matchResources:
              infrastructureCluster: true  # Added to select InfraCluster
          jsonPatches:
          - op: replace
            path: "/spec/template/spec/controlPlaneEndpoint/host"
            valueFrom:
              variable: controlPlaneEndpointHost
      - name: setRegistrationAddress
        definitions:
        - selector:
            apiVersion: controlplane.cluster.x-k8s.io/v1beta2
            kind: RKE2ControlPlaneTemplate
            matchResources:
              controlPlane: true        # Added to select ControlPlane
          jsonPatches:
          - op: replace
            path: "/spec/template/spec/registrationAddress"
            valueFrom:
              variable: controlPlaneEndpointHost
      - name: setTlsSan
        definitions:
        - selector:
            apiVersion: controlplane.cluster.x-k8s.io/v1beta2
            kind: RKE2ControlPlaneTemplate
            matchResources:
              controlPlane: true        # Added to select ControlPlane
          jsonPatches:
          - op: replace
            path: "/spec/template/spec/serverConfig/tlsSan"
            valueFrom:
              variable: tlsSan
      - name: updateAdditionalUserData
        definitions:
        - selector:
            apiVersion: controlplane.cluster.x-k8s.io/v1beta2
            kind: RKE2ControlPlaneTemplate
            matchResources:
              controlPlane: true
          jsonPatches:
          - op: replace
            path: "/spec/template/spec/agentConfig/additionalUserData"
            valueFrom:
              template: |
                config: |
                  variant: fcos
                  version: 1.4.0
                  {{ if .metallbHelmChartVersion }}
                  storage:
                    files:
                    - 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: {{ .metallbHelmChartVersion }}
                            createNamespace: true
                    {{ if .endpointCopierOperatorHelmChartVersion }}
                    - 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: {{ .endpointCopierOperatorHelmChartVersion }}
                            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:
                              - {{ .controlPlaneEndpointHost }}/32
                            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:
                            ports:
                            - name: rke2-api
                              port: 9345
                              protocol: TCP
                              targetPort: 9345
                            - name: k8s-api
                              port: 6443
                              protocol: TCP
                              targetPort: 6443
                            type: LoadBalancer
                    {{ end }}
                  {{ end }}
                  systemd:
                    units:
                    - name: rke2-preinstall.service
                      enabled: true
                      contents: |
                        [Unit]
                        Description=rke2-preinstall
                        Wants=network-online.target
                        Before=rke2-install.service
                        ConditionPathExists=!/run/cluster-api/bootstrap-success.complete
                        [Service]
                        Type=oneshot
                        User=root
                        ExecStartPre=/bin/sh -c "mount -L config-2 /mnt"
                        ExecStart=/bin/sh -c "sed -i \"s/BAREMETALHOST_UUID/$(jq -r .uuid /mnt/openstack/latest/meta_data.json)/\" /etc/rancher/rke2/config.yaml"
                        ExecStart=/bin/sh -c "echo \"node-name: $(jq -r .name /mnt/openstack/latest/meta_data.json)\" >> /etc/rancher/rke2/config.yaml"
                        ExecStart=/bin/sh -c "echo \"node-label:\" >> /etc/rancher/rke2/config.yaml"
                        ExecStart=/bin/sh -c "echo \"  - metal3.io/uuid=$(jq -r .uuid /mnt/openstack/latest/meta_data.json)\" >> /etc/rancher/rke2/config.yaml"
                        ExecStartPost=/bin/sh -c "umount /mnt"
                        [Install]
                        WantedBy=multi-user.target

65.4.2 Definição da instância de cluster

Dentro do contexto de ClusterClass, uma instância de cluster refere-se a uma instanciação específica e em execução de um cluster que foi criado com base em uma ClusterClass definida. Ela representa uma implantação concreta com suas configurações, recursos e estado operacional exclusivos, derivados diretamente do blueprint especificado na ClusterClass. Isso inclui o conjunto específico de máquinas, configurações de rede e componentes do Kubernetes associados que estão em execução ativa. Entender a instância de cluster é crucial para gerenciar o ciclo de vida, realizar atualizações, executar operações de escalonamento e conduzir o monitoramento de um cluster implantado específico que foi provisionado usando a estrutura ClusterClass.

Para definir uma instância de cluster, precisamos definir os dois recursos a seguir:

  • Cluster: Este recurso representa a instância de cluster real, incluindo uma referência ao seu topology (ou seja, objeto ClusterClass), a versão necessária do Kubernetes, o número de nós do plano de controle a serem instanciados e os valores fornecidos para cada uma das variáveis definidas no ClusterClass referenciado, que serão usados durante o processo de instanciação.

  • Metal3DataTemplate: Este recurso fornece metadados adicionais para as máquinas no cluster (apenas máquinas do plano de controle neste exemplo), complementando o objeto Metal3MachineTemplate criado automaticamente para cada cluster instanciado. Observe que não é possível definir um único recurso Metal3DataTemplate válido para todos os clusters instanciados a partir de um ClusterClass comum, uma vez que o campo clusterName na especificação Metal3DataTemplate deve referenciar a instância de cluster específica à qual ele "pertence".

    apiVersion: cluster.x-k8s.io/v1beta2
    kind: Cluster
    metadata:
      name: emea-spa-cluster-3
      namespace: emea-spa
      labels:
        cluster-api.cattle.io/rancher-auto-import: "true"
    spec:
      topology:
        classRef:
          name: example-clusterclass
          namespace: emea-spa
        version: v1.35.3+rke2r3
        controlPlane:
          replicas: 1
        variables:                       # Values to be replaced in the clusterclass template variables to create this specific cluster
        - name: endpointCopierOperatorHelmChartVersion
          value: 306.0.1+up0.3.0
        - name: metallbHelmChartVersion
          value: 306.0.2+up0.15.3
        - name: controlPlaneMachineTemplateImageURL
          value: http://fileserver.local:8080/eibimage-downstream-cluster.raw.sha256
        - name: controlPlaneMachineTemplateHostSelectorDeployRegion
          value: emea-spa
        - name: controlPlaneMachineTemplateHostSelectorClusterType
          value: group-3
        - name: controlPlaneMachineTemplateDataTemplateName
          value: emea-spa-cluster-3
        - name: controlPlaneEndpointHost
          value: 192.168.122.203
        - name: tlsSan
          value:
          - 192.168.122.203
          - https://192.168.122.203.sslip.io
    ---
    apiVersion: infrastructure.cluster.x-k8s.io/v1beta1
    kind: Metal3DataTemplate
    metadata:
      name: emea-spa-cluster-3
      namespace: emea-spa
    spec:
      clusterName: emea-spa-cluster-3
      metaData:
        objectNames:
        - key: name
          object: machine
        - key: local-hostname
          object: machine
        - key: local_hostname
          object: machine
Nota
Nota

Adicionar o rótulo cluster-api.cattle.io/rancher-auto-import: "true" a um objeto de API Cluster no grupo de API cluster.x-k8s.io importará o cluster para o Rancher (criando um objeto de API Cluster do Rancher correspondente no grupo de API management.cattle.io). Consulte a documentação da Cluster API para obter mais informações.

Essa abordagem simplifica o processo, permitindo que você implante um cluster usando apenas dois recursos assim que os blueprints do ClusterClass forem definidos.

Parte X Dicas e truques

Dicas e truques para componentes Edge

  • 66 Edge Image Builder
  • Se você estiver em um ambiente que não seja Linux e estiver seguindo estas instruções para criar uma imagem, provavelmente está executando o Podman por meio de uma máquina virtual. Por padrão, esta máquina virtual será configurada para ter uma pequena quantidade de recursos do sistema alocados a ela…

  • 67 Metal3
  • Uma vez que um objeto de cluster Metalˆ3ˆ e seus objetos associados correspondentes são criados, um processo para escolher qual BareMetalHost fará parte do cluster é realizado. Este processo conecta um BareMetalHost a um Metal3MachineTemplate específico usando rótulos do Kubernetes e seletores padrã…

66 Edge Image Builder

66.1 Comum

  • Se você estiver em um ambiente que não seja Linux e estiver seguindo estas instruções para criar uma imagem, provavelmente está executando o Podman por meio de uma máquina virtual. Por padrão, esta máquina virtual será configurada para ter uma pequena quantidade de recursos do sistema alocados a ela, o que pode causar instabilidade para o Edge Image Builder durante operações que exigem muitos recursos, como o processo de resolução de RPM. Você precisará ajustar os recursos da máquina podman, usando o Podman Desktop (ícone de engrenagem de configurações → ícone de edição da máquina podman) ou diretamente via podman-machine-set comando

  • Neste momento, o Edge Image Builder não é capaz de criar imagens em uma configuração de arquitetura cruzada, ou seja, você precisa executá-lo em:

    • AArch64sistemas (como Apple Silicon) para criar imagens do SL Micro aarch64

    • AMD64/Intel 64sistemas para criar imagens do SL Micro x86_64.

66.2 SUSE Linux Micro

  • O carregamento de módulos do kernel na inicialização pode ser feito usando o `/etc/modprobe.d/module.conf`arquivo correspondente. Crie a `os-files`pasta correspondente usando o Edge Image Builder:

.
├── definition.yaml
└── os-files
    └── etc
        └── modprobe.d
            └── module.conf

Para mais informações, consulte a seção "Managing kernel modules" da documentação do SUSE Linux Enterprise Server

66.3 Kubernetes

  • A criação de clusters Kubernetes com vários nós requer o ajuste da `kubernetes`seção no arquivo de definição para:

    • listar todos os nós de servidor e agente em kubernetes.nodes

    • definir um endereço IP virtual que será utilizado para que todos os nós que não são inicializadores se juntem ao cluster em kubernetes.network.apiVIP

    • Opcionalmente, defina um host de API para especificar um endereço de domínio para acessar o cluster em kubernetes.network.apiHost Para saber mais sobre essa configuração, consulte a documentação da seção Kubernetes.

  • O Edge Image Builder depende dos nomes de host dos diferentes nós para determinar seu tipo de Kubernetes (server ou agent). Embora essa configuração seja gerenciada no arquivo de definição, para a configuração de rede das máquinas, podemos utilizar o DHCP conforme descrito em Capítulo 13, Rede de borda.

67 Metal3

67.1 BareMetalHost seleção e associação de cluster

Uma vez que um objeto de cluster Metalˆ3ˆ e seus objetos associados correspondentes são criados, um processo para escolher qual BareMetalHost fará parte do cluster é realizado. Este processo conecta um BareMetalHost a um Metal3MachineTemplate específico usando rótulos do Kubernetes e seletores padrão.

Como exemplo, cada BareMetalHost é rotulado para identificar suas propriedades e o cluster pretendido (por exemplo, sua função de cluster, o nome do cluster, localização, etc.):

apiVersion: metal3.io/v1alpha1
kind: BareMetalHost
metadata:
  name: mynode1
  labels:
    cluster-role: control-plane
    cluster: foobar
    location: madrid
    datacenter: xyz
<snip>
---
apiVersion: metal3.io/v1alpha1
kind: BareMetalHost
metadata:
  name: mynode2
  labels:
    cluster-role: worker
    cluster: foobar
    location: madrid
    datacenter: xyz
<snip>
---
apiVersion: metal3.io/v1alpha1
kind: BareMetalHost
metadata:
  name: mynode3
  labels:
    cluster-role: worker
    cluster: foobar2
    location: madrid
    datacenter: xyz
<snip>
...

Então, o objeto Metal3MachineTemplate usa o campo spec.hostSelector para corresponder ao BareMetalHost desejado.

Tanto matchLabels (para correspondência exata de chave-valor) quanto matchExpressions (para regras mais complexas) podem ser usados:

apiVersion: infrastructure.cluster.x-k8s.io/v1beta2
kind: Metal3MachineTemplate
metadata:
  name: foobar-cluster-controlplane
  namespace: mynamespace
spec:
  template:
    spec:
      hostSelector:
        matchLabels:
          cluster-role: control-plane
          cluster: foobar
<snip>
---
apiVersion: infrastructure.cluster.x-k8s.io/v1beta2
kind: Metal3MachineTemplate
metadata:
  name: foobar-cluster-worker
  namespace: mynamespace
spec:
  template:
    spec:
      hostSelector:
        matchExpressions:
          - { key: cluster-role, operator: In, values: [worker] }
          - { key: cluster, operator: In, values: [foobar] }
<snip>
Nota
Nota

Namespaces do Kubernetes também podem ser usados para organizar melhor os diferentes objetos.

67.2 Limpar entradas de inicialização EFI antigas

Às vezes, o gerenciador de inicialização UEFI contém múltiplas entradas para sistemas operacionais mais antigos que provavelmente não são mais necessários (especialmente para hosts sendo reprovisionados várias vezes). Você pode limpar essas entradas antigas seguindo qualquer um dos procedimentos a seguir:

  • Exclua-as diretamente na interface de configuração do BIOS/EFI (o procedimento exato dependerá do hardware).

  • Execute o shell UEFI bcfg como:

    # List the entries
    bcfg boot dump -b
    # Delete entry number X
    bcfg boot rm X
    # X is the number associated the entry to remove. For example, if the entry is "Boot0002 foobar", then X is 2.
  • Use o efibootmgr em um sistema Linux como:

    # List the entries
    efibootmgr -v
    # Delete entry number X
    efibootmgr -b X -B

O processo pode deixar arquivos órfãos na Partição de Sistema EFI (ESP), geralmente encontrados em subdiretórios nomeados pelo fornecedor (por exemplo, EFI/opensuse ou EFI/Microsoft). Embora esses arquivos sejam geralmente inofensivos, eles devem ser excluídos se consumirem espaço excessivo, pois isso pode impedir a instalação de um novo SO ou uma atualização do gerenciador de inicialização. A remoção pode exigir a montagem explícita da ESP, normalmente montada como /boot/efi/EFI em sistemas Linux.

67.3 Configuração de rede personalizada usando a abordagem de dois segredos

Quando o Metal3 provisiona um nó bare metal, ele passa por duas fases distintas que podem exigir, cada uma, uma configuração de rede diferente:

  • A fase IPA, onde o ramdisk do Ironic Python Agent (IPA) é executado durante a inspeção e o provisionamento do hardware

  • A fase do SO de destino, onde o sistema SLE Micro implantado é executado após a primeira inicialização

A abordagem de dois segredos resolve isso permitindo um segredo de configuração de rede separado para cada fase, usando o campo preprovisioningNetworkDataName para a fase IPA e o campo networkData para a fase do SO de destino. Isso é particularmente útil quando os nomes das interfaces diferem entre as fases, o que pode acontecer porque o kernel IPA e o kernel SLE Micro podem descobrir o mesmo hardware com nomes diferentes.

67.3.1 Exemplo de renomeação de interface para VLANs

Um cenário comum é quando o hardware recebe um nome de interface longo baseado em PCI, como enp1s0np123. Adicionar uma VLAN sobre ele pode exceder o limite rígido do kernel Linux de 15 caracteres para nomes de interface:

enp1s0np123.100   = 15 chars  (barely fits, risky)
enp1s0np123.3669  = 17 chars  (exceeds limit, fails)
eth0.3669         =  9 chars  (works)

A fase IPA deve referenciar enp1s0np123 (o nome descoberto pelo kernel), enquanto o SO de destino deve usar um nome curto como eth0 para que eth0.3669 permaneça abaixo do limite.
nmc (nm-configurator) faz a ponte entre as duas fases correspondendo as interfaces via endereço MAC em vez de nome — você declara name: eth0 junto com o endereço MAC do hardware, e o nmc cria o perfil do NetworkManager com o nome desejado, independentemente do que o kernel atribuiu.

67.3.2 Pré-requisitos:

67.3.2.1 Configuração da imagem EIB

Conforme o guia de configuração de rede estática, a imagem EIB deve incluir um script de primeira inicialização que lê a configuração de rede da partição config-2 que o Metal3 grava durante o provisionamento. Crie o seguinte script em /opt/EIB/network/configure-network.sh:

#!/bin/bash
set -eux

# Source: https://documentation.suse.com/suse-edge/3.6/html/edge/quickstart-metal3.html#metal3-add-network-eib

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

Em seguida, torne-o executável e crie a imagem EIB normalmente:

mkdir -p /opt/EIB/network
chmod +x /opt/EIB/network/configure-network.sh
Nota
Nota

=== O EIB seleciona automaticamente scripts do diretório network/. O Combustion os executa na primeira inicialização no initramfs, antes que o SO completo seja iniciado. ===

Nota
Nota

=== O script também define o nome do host do nó a partir do campo de metadados do Metal3metal3-name. ===

67.3.3 Configurando os dois segredos

Os exemplos a seguir usam valores fictícios: MAC da NIC de dados aa:bb:cc:11:22:33, MAC da NIC de inicialização aa:bb:cc:44:55:66, IP do nó 10.0.0.10/24, gateway 10.0.0.1, DNS 10.0.0.53, ID da VLAN 100 e endereço BMC 10.1.0.10.

Segredo 1 — fase IPA (static-networkdata-ipa.yaml): referencia o nome da interface atribuído pelo kernel. O DHCP é usado aqui para manter a simplicidade durante a descoberta de hardware:

apiVersion: v1
kind: Secret
metadata:
  name: static-networkdata-ipa
  namespace: default
type: Opaque
stringData:
  networkData: |
    interfaces:
    - name: enp1s0np123
      type: ethernet
      state: up
      mac-address: "aa:bb:cc:11:22:33"
      ipv4:
        enabled: true
        dhcp: true
    dns-resolver:
      config:
        server:
        - 10.0.0.53

Segredo 2 — fase do SO de destino (static-networkdata-os.yaml): referencia o nome curto desejado e declara a VLAN. O mesmo endereço MAC é usado para que o nmc possa corresponder à interface:

apiVersion: v1
kind: Secret
metadata:
  name: static-networkdata-os
  namespace: default
type: Opaque
stringData:
  networkData: |
    interfaces:
    - name: eth0
      type: ethernet
      state: up
      mac-address: "aa:bb:cc:11:22:33"
      mtu: 1500
      ipv4:
        enabled: false
        dhcp: false
    - name: eth0.100
      type: vlan
      state: up
      mtu: 1500
      vlan:
        base-iface: eth0
        id: 100
      ipv4:
        address:
        - ip: 10.0.0.10
          prefix-length: 24
        enabled: true
        dhcp: false
    dns-resolver:
      config:
        server:
        - 10.0.0.53
    routes:
      config:
      - destination: 0.0.0.0/0
        next-hop-address: 10.0.0.1
        next-hop-interface: eth0.100

O objeto BareMetalHost referencia ambos os segredos:

apiVersion: metal3.io/v1alpha1
kind: BareMetalHost
metadata:
  name: my-node
  namespace: default
spec:
  online: true
  bootMACAddress: "aa:bb:cc:44:55:66"
  rootDeviceHints:
    deviceName: /dev/nvme0n1
  bmc:
    address: redfish-virtualmedia://10.1.0.10/redfish/v1/Systems/1/
    disableCertificateVerification: true
    credentialsName: my-node-credentials
  preprovisioningNetworkDataName: static-networkdata-ipa
  networkData:
    name: static-networkdata-os
Atenção
Atenção

preprovisioningNetworkDataName é um campo de string simples, enquanto networkData é um objeto SecretReference que requer uma subchave name:. A sintaxe difere entre os dois e é uma fonte comum de erros.

Aplique todos os objetos:

kubectl apply -f bmc-credentials.yaml
kubectl apply -f static-networkdata-ipa.yaml
kubectl apply -f static-networkdata-os.yaml
kubectl apply -f baremetalhost.yaml

Após o provisionamento, conecte-se via SSH ao nó e verifique:

# Interface names
ip link show
# Expected: eth0 and eth0.100@eth0

# IP on VLAN interface
ip addr show eth0.100

# NetworkManager profiles
nmcli connection show

# VLAN details
nmcli connection show eth0.100 | grep -E '(vlan.parent|vlan.id)'

Parte XI Solução de problemas

Esta seção fornece orientação para diagnosticar e resolver problemas comuns com SUSE Telco Cloud implantações e operações. Ela abrange vários tópicos, oferecendo etapas de solução de problemas específicas de componentes, ferramentas principais e locais de log relevantes.

68 Princípios Gerais de Solução de Problemas

Antes de mergulhar em problemas específicos de componentes, considere estes princípios gerais:

  • Verificar logs: Os logs são a principal fonte de informação. Na maioria das vezes, os erros são autoexplicativos e contêm dicas sobre o que falhou.

  • Verificar relógios: Ter diferenças de relógio entre sistemas pode levar a todos os tipos de erros diferentes. Certifique-se de que os relógios estejam sincronizados. O EIB pode ser instruído a forçar a sincronização do relógio no momento da inicialização, veja Configurando a Hora do SO (Capítulo 5, Clusters autônomos com o Edge Image Builder).

  • Problemas de Inicialização: Se o sistema travar durante a inicialização, anote as últimas mensagens exibidas. Acesse o console (físico ou via BMC) para observar as mensagens de inicialização.

  • Problemas de Rede: Verifique a configuração da interface de rede (ip a), a tabela de roteamento (ip route), teste a conectividade de/para outros nós e serviços externos (ping, nc). Certifique-se de que as regras do gateway de segurança não estejam bloqueando portas necessárias.

  • Verificar status do componente: Use kubectl get e kubectl describe para recursos do Kubernetes. Use kubectl get events --sort-by='.lastTimestamp' -n <namespace> para ver os eventos em um namespace específico do Kubernetes.

  • Verificar status dos serviços: Use systemctl status <service> para serviços do systemd.

  • Verifique a sintaxe: O software espera uma determinada estrutura e sintaxe nos arquivos de configuração. Para arquivos yaml, por exemplo, use yamllint ou ferramentas similares para verificar a sintaxe correta.

  • Isole o problema: Tente restringir o problema a um componente ou camada específica (por exemplo, rede, armazenamento, SO, Kubernetes, Metal3, Ironic,…​).

  • Documentação: Consulte sempre a SUSE Telco Cloud documentação oficial e também a documentação upstream para obter informações detalhadas.

  • Versões: SUSE Telco Cloud é uma versão opinativa e minuciosamente testada de diferentes componentes SUSE. As versões de cada componente por versão do SUSE Telco Cloud podem ser observadas na SUSE Telco Cloud matriz de suporte.

  • Problemas conhecidos: Para cada versão do SUSE Telco Cloud, há uma seção “Problemas conhecidos” nas notas de versão que contém informações sobre problemas que serão corrigidos em versões futuras, mas que podem afetar a atual.

69 Solucionando problemas do Kiwi

O Kiwi é usado para gerar imagens atualizadas do SUSE Linux Micro para serem usadas com o Edge Image Builder.

Problemas comuns
  • Incompatibilidade de versão do SL Micro: A versão do sistema operacional do host de build deve corresponder à versão do sistema operacional que está sendo compilada (host SL Micro 6.0 → imagem SL Micro 6.0).

  • SELinux em modo enforcing: Devido a certas limitações, atualmente é necessário desativar o SELinux temporariamente para conseguir gerar imagens com o Kiwi. Verifique o status do SELinux com getenforce e desative-o antes de executar o processo de build com setenforce 0.

  • Host de build não registrado: O processo de build usa as assinaturas do host de build para conseguir extrair pacotes do SUSE SCC. Se o host não estiver registrado, ele falhará.

  • Falha no teste do dispositivo de loop: Na primeira vez que o processo de build do Kiwi for executado, ele falhará logo após o início com \"ERROR: Falha no teste inicial do dispositivo de loop, por favor, tente novamente executar o contêiner.", este é um sintoma de dispositivos de loop sendo criados no sistema host subjacente que não são imediatamente visíveis dentro da imagem do contêiner. Execute o processo de build do Kiwi novamente e ele deverá prosseguir sem problemas.

  • Permissões ausentes: O processo de build espera ser executado como usuário root (ou via sudo).

  • Privilégios incorretos: O processo de build espera a flag --privileged ao executar o contêiner. Verifique novamente se ela está presente.

Registros
  • Logs do contêiner de build: Verifique os logs do contêiner de build. Os logs são gerados no diretório que foi usado para armazenar os artefatos. Verifique também os logs do docker ou os logs do podman para obter as informações necessárias.

  • Diretórios de build temporários: O Kiwi cria diretórios temporários durante o processo de build. Verifique-os em busca de logs ou artefatos intermediários se a saída principal for insuficiente.

Etapas de solução de problemas
  1. Revisar saída do build-image: A mensagem de erro na saída do console geralmente é muito indicativa.

  2. Verificar ambiente de build: Certifique-se de que todos os pré-requisitos para o próprio Kiwi (por exemplo, docker/podman, SELinux, espaço em disco suficiente) sejam atendidos na máquina que executa o Kiwi.

  3. Inspecionar logs do contêiner de build: Revise os logs do contêiner que falhou para obter erros mais detalhados (veja acima).

  4. Verificar arquivo de definição: Se você estiver usando um arquivo de definição de imagem Kiwi personalizado, verifique novamente o arquivo em busca de erros de digitação ou sintaxe.

70 Solução de problemas do Edge Image Builder (EIB)

O EIB é usado para criar SUSE Telco Cloud imagens personalizadas.

Problemas comuns
  • Código SCC incorreto: Certifique-se de que o código SCC usado no arquivo de definição do EIB corresponda à versão e arquitetura do SL Micro.

  • Dependências ausentes: Certifique-se de que não haja pacotes ou ferramentas ausentes no ambiente de compilação.

  • Tamanho de imagem incorreto: Para imagens raw, o parâmetro diskSize é obrigatório e depende muito das imagens, RPMs e outros artefatos incluídos na imagem.

  • Permissões: Se armazenar um script no diretório custom/files, certifique-se de que ele tenha permissões de execução, pois esses arquivos ficam disponíveis apenas no momento da combustão, mas nenhuma alteração é realizada pelo EIB.

  • Dependências de grupo do sistema operacional: Ao criar uma imagem com usuários e grupos personalizados, os grupos definidos como “primaryGroup” devem ser criados explicitamente.

  • As chaves SSH do usuário do sistema operacional exigem uma pasta home: Ao criar uma imagem com usuários com chaves SSH, a pasta home também precisa ser criada com createHomeDir=true.

  • Problemas de combustão: O EIB depende da combustão para a personalização do SO e a implantação de todos os outros componentes SUSE Telco Cloud. Isso também inclui scripts personalizados sendo colocados na pasta custom/scripts. Observe que o processo de combustão está sendo executado no momento initrd, portanto, o sistema não está completamente inicializado quando os scripts são executados.

  • Tamanho da máquina Podman: Conforme explicado na seção de Dicas e Truques do EIB (Parte X, “Dicas e truques”), verifique se a máquina podman tem CPU/memória suficiente para executar o contêiner EIB em sistemas operacionais que não sejam Linux.

  • Imagem incorreta: Certifique-se de que a imagem base sendo usada esteja corretamente baixada verificando o checksum. Se você estiver criando a imagem com kiwi-builder (Capítulo 64, Criando imagens atualizadas do SUSE Linux Micro com o Kiwi), verifique também o arquivo de soma gerado pelo processo.

Registros
  • Saída do EIB: A saída do console do comando eib build é crucial.

  • Logs do contêiner de compilação: Verifique os logs do contêiner de compilação. Os logs são gerados no diretório que foi usado para armazenar os artefatos. Verifique docker logs ou podman logs para obter as informações necessárias também.

    Nota
    Nota

    Para obter mais informações, consulte Depuração.

  • Diretórios temporários de compilação: O EIB cria diretórios temporários durante o processo de compilação. Verifique-os em busca de logs intermediários ou artefatos se a saída principal for insuficiente.

  • Logs de combustão: Se a imagem sendo criada com o EIB não inicializar por qualquer motivo, um shell root estará disponível. Conecte-se ao console do host (seja fisicamente, via BMC, etc.) e verifique os logs de combustão com journalctl -u combustion e, em geral, todos os logs do sistema operacional com journalctl para encontrar a causa raiz da falha.

Etapas de solução de problemas
  1. Analise a saída de eib-build: A mensagem de erro na saída do console geralmente é muito indicativa.

  2. Verificar ambiente de compilação: Certifique-se de que todos os pré-requisitos para o próprio EIB (por exemplo, docker/podman, espaço em disco suficiente) sejam atendidos na máquina que executa o EIB.

  3. Inspecionar logs do contêiner de compilação: Analise os logs do contêiner com falha para obter erros mais detalhados (veja acima).

  4. Verificar configuração de eib: Verifique novamente o arquivo de configuração eib em busca de erros de digitação ou caminhos incorretos para arquivos de origem ou scripts de compilação.

    • Testar componentes individualmente: Se a compilação do EIB envolver scripts ou estágios personalizados, execute-os de forma independente para isolar falhas.

71 Solução de problemas de rede de borda (NMC)

O NMC é injetado em imagens SL Micro EIB para configurar a rede dos hosts de borda no momento da inicialização via combustion. Ele também está sendo executado no fluxo de trabalho Metal3 como parte do processo de inspeção. Problemas podem ocorrer quando o host está sendo inicializado pela primeira vez ou no processo de inspeção do Metal3.

Problemas comuns
  • Host não consegue inicializar corretamente na primeira vez: Arquivos de definição de rede malformados podem levar a falha na fase de combustion e, então, o host abre um shell root.

  • Os arquivos não são gerados corretamente: Certifique-se de que os arquivos de rede correspondam ao formato NMState.

  • As interfaces de rede não estão configuradas corretamente: Certifique-se de que os endereços MAC correspondam às interfaces sendo usadas no host.

  • Incompatibilidade entre os nomes das interfaces: O SL Micro habilita o Esquema de Nomenclatura Previsível para Interfaces de Rede por padrão, portanto, não existe mais eth0, mas outros esquemas de nomenclatura, como enp2s0.

Registros
  • Logs do combustion: Como o NMC é usado no momento do combustion, verifique os logs do combustion com journalctl -u combustion no host que está sendo provisionado.

  • Logs do NetworkManager: No fluxo de trabalho de implantação do Metal3, o NMC faz parte da execução do IPA e é executado como uma dependência do serviço NetworkManager usando a funcionalidade ExecStartPre do systemd. Verifique os logs do NetworkManager no host IPA como journalctl -u NetworkManager (consulte a seção Solução de problemas de provisionamento de rede direcionado (Capítulo 72, Solução de problemas de provisionamento de rede direcionado) para entender como acessar o host quando inicializado com o IPA).

Etapas de solução de problemas
  1. Verifique a sintaxe yaml: os arquivos de configuração do NMC são arquivos yaml, verifique a sintaxe correta com yamllint ou ferramentas similares.

  2. Execute o NMC manualmente: Como o NMC faz parte do contêiner EIB, para depurar quaisquer problemas, um comando podman local pode ser usado.

    1. Crie uma pasta temporária para armazenar os arquivos do NMC.

      mkdir -p ${HOME}/tmp/foo
    2. Salve os arquivos do NMC nesse local.

      ❯ tree --noreport ${HOME}/tmp/foo
      /Users/johndoe/tmp/foo
      ├── host1.example.com.yaml
      └── host2.example.com.yaml
    3. Execute o contêiner EIB com o NMC como o ponto de entrada e o comando generate para realizar as mesmas tarefas que o NMC faria no momento do combustion:

      podman run -it --rm -v ${HOME}/tmp/foo:/tmp/foo:Z --entrypoint=/usr/bin/nmc registry.suse.com/edge/3.6/edge-image-builder:1.3.3.1 generate --config-dir /tmp/foo --output-dir /tmp/foo/
      
      [2025-06-04T11:58:37Z INFO  nmc::generate_conf] Generating config from "/tmp/foo/host2.example.com.yaml"...
      [2025-06-04T11:58:37Z INFO  nmc::generate_conf] Generating config from "/tmp/foo/host1.example.com.yaml"...
      [2025-06-04T11:58:37Z INFO  nmc] Successfully generated and stored network config
    4. Observe os logs e os arquivos sendo gerados na pasta temporária.

72 Solução de problemas de provisionamento de rede direcionado

Cenários de provisionamento de rede direcionada envolvem o uso de elementos Metal3 e CAPI para provisionar o cluster downstream. Também inclui o EIB para criar uma imagem de sistema operacional. Problemas podem ocorrer quando o host está sendo inicializado pela primeira vez ou durante os processos de inspeção ou provisionamento.

Problemas comuns
  • Firmware antigo: Verifique se todos os diferentes firmwares nos hosts físicos que estão sendo usados estão atualizados. Isso inclui o firmware do BMC, pois, às vezes, o Metal3 requer versões específicas/atualizadas.

  • Falha no provisionamento com erros de SSL: Se o servidor web que fornece as imagens usa https, o Metal3 precisa ser configurado para injetar e confiar no certificado na imagem IPA. Consulte pasta Kubernetes (Seção 29.4, “Kubernetes folder”) sobre como incluir um arquivo ca-additional.crt no chart do Metal3.

  • Problemas de certificados ao inicializar os hosts com IPA: Alguns fornecedores de servidores 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. Pode acontecer de o host estar sendo inicializado, mas cair em um shell UEFI. Consulte Desabilitando TLS para anexo de ISO de mídia virtual (Seção 4.7.2, “Desabilitando TLS para anexo de ISO de virtualmedia”) sobre como corrigir isso.

  • Referência de nome ou rótulo incorreta: Se o cluster referencia um nó pelo nome ou rótulo incorreto, o cluster é considerado implantado, mas o BMH permanece como “Available”. Verifique novamente as referências nos objetos envolvidos para os BMHs.

  • Problemas de comunicação com o BMC: Certifique-se de que os pods do Metal3 em execução no cluster de gerenciamento consigam alcançar o BMC dos hosts que estão sendo provisionados (geralmente a rede BMC é muito restrita).

  • Estado incorreto do host bare metal: O objeto BMH passa por diferentes estados (inspecionando, preparando, provisionado, etc.) durante seu ciclo de vida Ciclo de vida da máquina de estados. Se um estado incorreto for detectado, verifique o campo status do objeto BMH, pois ele contém mais informações como kubectl get bmh <name> -o jsonpath=’{.status}’| jq.

  • Host não sendo desprovisionado: No caso de um host que deveria ser desprovisionado falhar, a remoção pode ser tentada após adicionar a anotação “detached” ao objeto BMH como: kubectl annotate bmh/<BMH> baremetalhost.metal3.io/detached=””.

  • Erros de imagem: Verifique se a imagem sendo criada com o EIB para o cluster downstream está disponível, possui um checksum adequado e não é muito grande para descompactar ou muito grande para o disco.

  • Incompatibilidade de tamanho de disco: Por padrão, o disco não expandirá para preencher todo o disco. Conforme explicado na seção Growfs script (Seção 4.4.4.1.2, “Script Growfs”), um script growfs precisa ser incluído na imagem sendo criada com o EIB para os hosts do cluster downstream.

  • Processo de limpeza travado: O processo de limpeza é tentado novamente várias vezes. Se, devido a um problema com o host, a limpeza não for mais possível, desative a limpeza primeiro definindo o campo automatedCleanMode como disabled no objeto BMH.

    Atenção
    Atenção

    Não é recomendado remover manualmente o finalizador quando o processo de limpeza estiver demorando mais do que o desejado ou falhando. Fazer isso remove o registro do host do Kubernetes, mas o deixa no Ironic. A ação em execução continua em segundo plano, e uma tentativa de adicionar o host novamente pode falhar devido ao conflito.

  • Problemas com pods do Metal3/Rancher Turtles/CAPI: O fluxo de implantação para todos os componentes necessários é:

    • O controlador Rancher Turtles implanta o controlador do operador CAPI.

    • O controlador do operador CAPI então implanta os controladores do provedor (CAPI core, CAPM3 e RKE2 controlplane/bootstrap).

Verifique se todos os pods estão sendo executados corretamente e, caso contrário, verifique os logs.

Registros
  • Logs do Metal3:Verifique os logs dos diferentes pods.

    kubectl logs -n metal3-system -l app.kubernetes.io/component=baremetal-operator
    kubectl logs -n metal3-system -l app.kubernetes.io/component=ironic
    Nota
    Nota

    O pod metal3-ironic contém pelo menos 4 contêineres diferentes (ironic-httpd, ` ironic-log-watch`, ironic e ironic-ipa-downloader (init)) no mesmo pod. Use a flag -c ao usar kubectl logs para verificar os logs de cada um dos contêineres.

    Nota
    Nota

    O contêiner ironic-log-watch expõe logs de console dos hosts após a inspeção/provisionamento, desde que a conectividade de rede permita o envio desses logs de volta para o cluster de gerenciamento. Isso pode ser útil em casos onde há erros de provisionamento, mas você não tem acesso direto aos logs do console do BMC.

  • Logs do Rancher Turtles: Verifique os logs dos diferentes pods.

    kubectl logs -n cattle-turtles-system -l control-plane=controller-manager
    kubectl logs -n cattle-turtles-system -l app.kubernetes.io/name=cluster-api-operator
    kubectl logs -n rke2-bootstrap-system -l cluster.x-k8s.io/provider=bootstrap-rke2
    kubectl logs -n rke2-control-plane-system -l cluster.x-k8s.io/provider=control-plane-rke2
    kubectl logs -n cattle-capi-system -l cluster.x-k8s.io/provider=cluster-api
    kubectl logs -n capm3-system -l cluster.x-k8s.io/provider=infrastructure-metal3
  • Logs do BMC: Geralmente, os BMCs possuem uma interface de usuário onde a maior parte da interação pode ser feita. Geralmente, há uma seção de “logs” que pode ser observada para possíveis problemas (não conseguir acessar a imagem, falhas de hardware, etc.).

  • Logs do console: Conecte-se ao console do BMC (via interface web do BMC, serial, etc.) e verifique se há erros nos logs que estão sendo gravados.

Etapas de solução de problemas
  1. Verificar o status do BareMetalHost:

    • kubectl get bmh -A mostra o estado atual. Procure por provisioning, ready, error, registering.

    • kubectl describe bmh -n <namespace> <bmh_name> fornece eventos e condições detalhados que explicam por que um BMH pode estar travado.

  2. Testar conectividade RedFish:

    • Use curl do plano de controle do Metal3 para testar a conectividade com os BMCs via redfish.

    • Certifique-se de que as credenciais corretas do BMC sejam fornecidas na definição BareMetalHost-Secret.

  3. Verificar status dos pods turtles/CAPI/metal3: Certifique-se de que os contêineres no cluster de gerenciamento estejam ativos e em execução: kubectl get pods -n metal3-system e kubectl get pods -n cattle-turtles-system (veja também cattle-capi-system, capm3-system, rke2-bootstrap-system e rke2-control-plane-system).

  4. Verificar se o endpoint do ironic está acessível a partir do host que está sendo provisionado: O host que está sendo provisionado precisa ser capaz de alcançar o endpoint do Ironic para reportar ao Metal3. Verifique o IP com kubectl get svc -n metal3-system metal3-metal3-ironic e tente alcançá-lo via curl/nc.

  5. Verificar se a imagem do IPA está acessível a partir do BMC: O IPA é servido pelo endpoint do Ironic e precisa estar acessível a partir do BMC, pois está sendo usado como um CD virtual.

  6. Verificar se a imagem do SO está acessível a partir do host que está sendo provisionado: A imagem usada para provisionar o host precisa estar acessível a partir do próprio host (ao executar o IPA), pois será baixada temporariamente e gravada no disco.

  7. Examinar logs dos componentes do Metal3: Veja acima.

  8. Acionar novamente a inspeção do BMH: Se uma inspeção falhou ou o hardware de um host disponível mudou, um novo processo de inspeção pode ser acionado anotando o objeto BMH com inspect.metal3.io: "". Consulte o guia Controle de inspeção do Metal3 para obter mais informações.

  9. Console IPA bare metal: Para solucionar problemas do IPA, existem algumas alternativas:

    • Habilite o “autologin”. Isso permite que o usuário root seja conectado automaticamente ao se conectar ao console do IPA.

      Atenção
      Atenção

      Isso é apenas para fins de depuração, pois dá acesso total ao host.

      Para habilitar o login automático, o valor global.ironicKernelParams do helm Metal3 deve ser parecido com: console=ttyS0 suse.autologin=ttyS0 (dependendo do console, ttyS0 pode ser alterado). Em seguida, uma reimplantação do gráfico Metal3 deve ser realizada. (Observe que ttyS0 é um exemplo, isso deve corresponder ao terminal real, por exemplo, pode ser tty1 em muitos casos em bare metal, isso pode ser verificado observando a saída do console do ramdisk IPA na inicialização, onde /etc/issue imprime o nome do console).

      Outra maneira de fazer isso é alterando o parâmetro IRONIC_KERNEL_PARAMS no configmap ironic no namespace metal3-system. Isso pode ser mais fácil, pois pode ser feito via edição kubectl, mas será sobrescrito ao atualizar o gráfico. Em seguida, o pod Metal3 precisa ser reiniciado com kubectl delete pod -n metal3-system -l app.kubernetes.io/component=ironic.

    • Injete uma chave ssh para o usuário root no IPA.

      Atenção
      Atenção

      Isso é apenas para fins de depuração, pois dá acesso total ao host.

      Para injetar a chave ssh para o usuário root, deve ser usado o valor do helm Metal3 debug.ironicRamdiskSshKey. Em seguida, deve ser realizada a reimplantação do chart Metal3.

      Outra maneira de fazer isso é alterando o parâmetro IRONIC_RAMDISK_SSH_KEY no ironic configmap do namespace metal3-system. Isso pode ser mais fácil, pois pode ser feito via kubectl editar, mas será sobrescrito ao atualizar o chart. Em seguida, o pod Metal3 precisa ser reiniciado com kubectl delete pod -n metal3-system -l app.kubernetes.io/component=ironic

73 Solucionando problemas de outros componentes

Guias de solução de problemas de outros SUSE Telco Cloud componentes podem ser consultados em sua documentação oficial:

Você também pode consultar a Base de Conhecimento SUSE.

74 Coleta de diagnósticos para suporte

Ao entrar em contato com o Suporte da SUSE, fornecer informações de diagnóstico abrangentes é crucial.

Informações essenciais a serem coletadas
  • Descrição detalhada do problema: O que aconteceu, quando aconteceu, o que você estava fazendo, qual é o comportamento esperado e qual é o comportamento real?

  • Passos para reproduzir: Você consegue reproduzir o problema de forma confiável? Se sim, liste os passos exatos.

  • Versões dos componentes: SUSE Telco Cloud versão, versões dos componentes (RKE2/K3, EIB, Metal3, Elemental,..).

  • Logs relevantes:

    • journalctl saída (filtrada por serviço, se possível, ou logs de inicialização completos).

    • Logs de pod do Kubernetes (kubectl logs).

    • Logs de componentes Metal³/Elemental.

    • Logs de compilação do EIB e outros logs

  • Informações sobre o sistema:

    • uname -a

    • df -h

    • ip a

    • /etc/os-release

  • Arquivos de configuração: Arquivos de configuração relevantes para Elemental, Metal3, EIB, como valores de helm chart, configmaps, etc.

  • Informações do Kubernetes: Nós, Serviços, Implantações, etc.

  • Objetos do Kubernetes afetados: BMH, MachineRegistration, etc.

Como coletar
  • Para logs: Redirecione a saída do comando para arquivos (por exemplo, journalctl -u k3s > k3s_logs.txt).

  • Para recursos do Kubernetes: Use kubectl get <resource> -o yaml > <resource_name>.yaml para obter definições YAML detalhadas.

  • Para informações do sistema: Colete a saída dos comandos listados acima.

  • Para SL Micro: Consulte a documentação SUSE Linux Micro Troubleshooting Guide sobre como coletar informações do sistema para suporte com supportconfig.

  • Para RKE2/Rancher: Consulte o artigo The Rancher v2.x Linux log collector script para executar o script de coleta de logs do Rancher v2.x Linux.

  • Para Edge (Nessie): O Nessie 1.1.0 é uma ferramenta de diagnóstico poderosa projetada para coletar logs e dados de configuração de ambientes SUSE Telco Cloud. Ele reúne informações abrangentes tanto do sistema host quanto dos clusters Kubernetes, tornando-o inestimável para solução de problemas e suporte.

    • O Nessie possui dois "modos": um modo kubernetes e um modo de sistema.

      • Para coletar logs de um cluster SUSE Telco Cloud, execute (desde que você tenha acesso ao arquivo kubeconfig localmente):

        podman run --rm --privileged \
          -v /etc/rancher/k3s/k3s.yaml:/etc/rancher/k3s/k3s.yaml:ro \
          -v /var/log/journal:/var/log/journal:ro \
          -v /run/systemd:/run/systemd:ro \
          -v /etc/machine-id:/etc/machine-id:ro \
          -v /tmp:/tmp \
          -e NESSIE_LOG_DIR="/tmp" \
          -e NESSIE_ZIP_DIR="/tmp" \
          registry.suse.com/edge/3.6/nessie:1.1.0
        Nota
        Nota

        Ajuste os caminhos do arquivo k3s.yaml/rke2.yaml, se necessário. Consulte Nessie para obter mais informações. Você deve conseguir executar este contêiner em modo não privilegiado se tiver as permissões adequadas (normalmente os arquivos k3s.yaml / rke2-server.yaml pertencem ao [root]).

      • Para coletar logs no modo de sistema a partir do sistema operacional real, execute:

        podman run --rm --privileged \
          -v /var/log/journal:/var/log/journal:ro \
          -v /run/systemd:/run/systemd:ro \
          -v /etc/machine-id:/etc/machine-id:ro \
          -v /tmp:/tmp \
          -e NESSIE_LOG_DIR="/tmp" \
          -e NESSIE_ZIP_DIR="/tmp" \
          -e NESSIE_VERBOSE="1" \
          -e NESSIE_SKIP_POD_LOGS="true" \
          -e NESSIE_SKIP_K8S_CONFIGS="true" \
          -e NESSIE_SKIP_METRICS="true" \
          registry.suse.com/edge/3.6/nessie:1.1.0
        Nota
        Nota

        Certifique-se de verificar Nessie para obter mais detalhes e informações sobre como executar o Nessie em seu ambiente. Da mesma forma, você deve conseguir executar este contêiner em modo não privilegiado, desde que tenha as permissões adequadas.

Contatar Suporte. Verifique o artigo disponível em Procedimentos para trabalhar efetivamente com o Suporte Técnico da SUSE e o manual de suporte localizado em SUSE Technical Support Handbook para obter mais detalhes sobre como entrar em contato com o suporte da SUSE.

Parte XII Apęndice

  • 75 Notas de versão
  • SUSE Telco Cloud 3.6 é uma solução de ponta a ponta fortemente integrada e abrangentemente validada para abordar os desafios únicos da implantação de infraestrutura e aplicativos nativos de nuvem na borda. Seu foco principal é fornecer uma plataforma opinativa, porém altamente flexível, altamente es…

75 Notas de versão

75.1 Abstrato

SUSE Telco Cloud 3.6 é uma solução de ponta a ponta fortemente integrada e abrangentemente validada para abordar os desafios únicos da implantação de infraestrutura e aplicativos nativos de nuvem na borda. Seu foco principal é fornecer uma plataforma opinativa, porém altamente flexível, altamente escalável e segura que abrange a construção de imagem de implantação inicial, provisionamento e integração de nós, implantação de aplicativos, observabilidade e gerenciamento de ciclo de vida.

A solução foi projetada com a noção de que não existe uma plataforma de borda de "tamanho único" devido aos requisitos e expectativas amplamente variados de nossos clientes. As implantações de borda nos levam a resolver, e evoluir continuamente, alguns dos problemas mais desafiadores, incluindo escalabilidade massiva, disponibilidade de rede restrita, restrições de espaço físico, novas ameaças de segurança e vetores de ataque, variações na arquitetura de hardware e recursos do sistema, o requisito de implantar e interagir com infraestrutura e aplicativos legados, e soluções de clientes que possuem vida útil estendida.

O SUSE Telco Cloud é construído sobre o melhor software de código aberto desde o início, consistente com nossa história de 30 anos na entrega de plataformas SUSE Linux seguras, estáveis e certificadas e nossa experiência no fornecimento de gerenciamento de Kubernetes altamente escalável e rico em recursos com nosso portfólio Rancher. O SUSE Telco Cloud baseia-se nessas capacidades para fornecer funcionalidade que pode atender a um grande número de segmentos de mercado, incluindo varejo, médico, transporte, logística, telecomunicações, manufatura inteligente e IoT Industrial.

Para obter mais informações sobre atualizações do ciclo de vida de suporte do produto para SUSE Telco Cloud, consulte Product Support Lifecycle.

Nota
Nota

O SUSE Telco Cloud é um derivado do SUSE Edge, com otimizações e componentes adicionais que permitem que a plataforma atenda aos requisitos encontrados em casos de uso de telecomunicações.

75.2 Sobre

Estas Notas de Lançamento são, a menos que explicitamente especificado e explicado, idênticas em todas as arquiteturas, e a versão mais recente, juntamente com as notas de lançamento de todos os outros produtos SUSE, estão sempre disponíveis online em https://www.suse.com/releasenotes.

As entradas são listadas apenas uma vez, mas podem ser referenciadas em vários lugares se forem importantes e pertencerem a mais de uma seção. As notas de lançamento geralmente listam apenas as alterações que ocorreram entre dois lançamentos subsequentes. Algumas entradas importantes das notas de lançamento de versões anteriores do produto podem ser repetidas. Para tornar essas entradas mais fáceis de identificar, elas contêm uma nota para esse efeito.

No entanto, as entradas repetidas são fornecidas apenas como uma cortesia. Portanto, se você estiver pulando um ou mais lançamentos, verifique também as notas de lançamento dos lançamentos ignorados. Se você estiver lendo apenas as notas de lançamento da versão atual, poderá perder alterações importantes que podem afetar o comportamento do sistema. As versões SUSE Telco Cloud são definidas como x.y.z, onde 'x' denota a versão principal, 'y' denota a versão secundária e 'z' denota a versão de patch, também conhecida como "z-stream". Os ciclos de vida do produto SUSE Telco Cloud são definidos com base em um determinado lançamento secundário, por exemplo. "3.6", mas são fornecidos com atualizações de patch subsequentes ao longo de seu ciclo de vida, por exemplo. "3.6.1".

Nota
Nota

Os lançamentos z-stream do SUSE Telco Cloud são fortemente integrados e completamente testados como uma pilha versionada. Fazer upgrade de quaisquer componentes individuais para versões diferentes daquelas listadas acima provavelmente resultará em tempo de inatividade do sistema. Embora seja possível executar clusters Edge em configurações não testadas, isso não é recomendado e pode levar mais tempo para fornecer uma resolução por meio dos canais de suporte.

75.3 Release 3.6.1

Data de disponibilidade: 26 de junho de 2026

Data de término do suporte completo: 27 de novembro de 2026

Data de término do suporte de manutenção: 27 de maio de 2028

EOL: 28 de maio de 2028

Resumo: SUSE Telco Cloud 3.6.1 é a primeira versão z-stream no fluxo de versão SUSE Telco Cloud 3.6.

75.3.1 Novos recursos

75.3.2 Correções de bug e atualizações de segurança

75.3.3 Problemas conhecidos

Atenção
Atenção

Se estiver implantando novos clusters, siga Capítulo 64, Criando imagens atualizadas do SUSE Linux Micro com o Kiwi para criar imagens novas primeiro. Isso é sugerido para clusters de gerenciamento e downstream para garantir que as imagens contenham as correções de segurança e bugs mais recentes.

  • Ao implantar via Edge Image Builder, os manifestos HelmChartConfigs podem falhar se forem colocados no diretório de configuração kubernetes/manifests. Em vez disso, recomenda-se colocar qualquer HelmChartConfigs em /var/lib/rancher/{rke2/k3s}/server/manifests/ usando a interface os-files do EIB. Consulte Seção 29.1, “Estrutura de diretórios” para obter um exemplo. A falha em fazer isso pode fazer com que os nós permaneçam no estado NotReady na inicialização inicial, conforme discutido em #8357 problema do RKE2.

  • Nas versões RKE2/K3s 1.34 e 1.35, o diretório /etc/cni usado para armazenar configurações de CNI pode não disparar uma notificação dos arquivos sendo gravados lá para containerd devido a certas condições relacionadas ao overlayfs (consulte o #8356 problema do RKE2). Isso, por sua vez, faz com que a implantação do RKE2/K3s fique travada aguardando a inicialização do CNI, e os nós do RKE2/K3s permaneçam no estado NotReady. Isso pode ser visto no nível do nó com kubectl describe node <affected_node>:

Conditions:
  Type   Status  LastHeartbeatTime                LastTransitionTime               Reason           Message
  ----   ------  -----------------                ------------------               ------           -------
  Ready  False   Thu, 05 Jun 2025 17:41:28 +0000  Thu, 05 Jun 2025 14:38:16 +0000  KubeletNotReady  container runtime network not ready: NetworkReady=false reason:NetworkPluginNotReady message:Network plugin returns error: cni plugin not initialized

Como solução alternativa, um volume tmpfs pode ser montado no diretório /etc/cni antes que o RKE2 seja iniciado. Isso evita o uso de overlayfs, o que faz com que o containerd perca notificações, e as configurações devem ser reescritas toda vez que o nó for reiniciado e os initcontainers dos pods forem executados novamente. Se estiver usando o EIB, isso pode ser um script 04-tmpfs-cni.sh no diretório custom/scripts (conforme explicado aqui) que se parece com:

#!/bin/bash
mkdir -p /etc/cni
mount -t tmpfs -o mode=0700,size=5M tmpfs /etc/cni
echo "tmpfs /etc/cni tmpfs defaults,size=5M,mode=0700 0 0" >> /etc/fstab
  • Não há documentação ou exemplos oficiais para configurar o SyncE via synce4l e GNSS via gpsd disponíveis neste estágio. Esses tópicos serão abordados em versões futuras.

  • Alguns repositórios de contêineres estão acessíveis atualmente apenas via IPv4; por esse motivo, um repositório local no Cluster de Gerenciamento é necessário para um cluster downstream apenas com IPv6.

75.3.4 Versões dos componentes

A tabela a seguir descreve os componentes individuais que compõem a versão 3.6.1, incluindo a versão, a versão do gráfico Helm (se aplicável) e de onde o artefato lançado pode ser extraído no formato binário. Siga a documentação associada para exemplos de uso e implantação.

Nome

Versão

Versão do gráfico Helm

Local do artefato (URL/Imagem)

SUSE Linux Micro

6.2 (mais recente)

N/A

Página de download do SUSE Linux Micro

SUSE Linux Micro

6.2 (mais recente)

N/A

Checksums e assinaturas estão disponíveis para download na Página de download do SUSE Linux Micro
SL-Micro.x86_64-6.2-Base-SelfInstall-GM.install.iso
SL-Micro.x86_64-6.2-Base-RT-SelfInstall-GM.install.iso
SL-Micro.x86_64-6.2-Base-GM.raw.xz
SL-Micro.x86_64-6.2-Base-RT-GM.raw.xz

SUSE Multi-Linux Manager

5.1

N/A

Página de download do SUSE Multi-Linux Manager

K3s

1.35.4

N/A

Versão upstream do K3s

RKE2

1.35.4

N/A

Versão upstream do RKE2

SUSE Rancher Prime

2.14.2

2.14.2

Repositório Helm do Rancher Prime
https://prime.ribs.rancher.io/rancher/v2.14.2/rancher-images.txt[Rancher 2.14.2 Container Images]

SUSE Storage (Longhorn)

1.11.2

1.11.2

Repositório Helm do SUSE Storage
https://apps.rancher.io/applications/suse-storage/components[Imagens de contêiner do SUSE Storage]

SUSE Security (NeuVector)

5.5.2

109.0.2+up2.10.2

Repositório Helm de Charts do Rancher
registry.rancher.com/rancher/neuvector-controller:5.5.2
registry.rancher.com/rancher/neuvector-enforcer:5.5.2
registry.suse.com/rancher/neuvector-compliance-config:1.0.12

Provedores do Rancher Turtles (CAPI)

0.26.2

306.0.7+up0.26.2

registry.suse.com/edge/3.6/rancher-turtles-providers-chart:306.0.7+up0.26.2
registry.rancher.com/rancher/cluster-api-controller:v1.12.2
registry.rancher.com/rancher/turtles:v0.26.2
registry.suse.com/rancher/cluster-api-provider-rke2-bootstrap:v0.24.3
registry.suse.com/rancher/cluster-api-provider-rke2-controlplane:v0.24.3

Metal3

0.15.0

306.0.29+up0.15.0

registry.suse.com/edge/3.6/metal3-chart:306.0.29+up0.15.0
registry.suse.com/edge/3.6/baremetal-operator:0.12.3.0
registry.suse.com/edge/3.6/ironic:35.0.0.2
registry.suse.com/edge/3.6/ironic-ipa-downloader:3.1.1
registry.suse.com/edge/3.6/ironic-python-agent:3.0.9

MetalLB

0.15.3

306.0.2+up0.15.3

registry.suse.com/edge/3.6/metallb-chart:306.0.2+up0.15.3
registry.suse.com/edge/3.6/metallb-controller:v0.15.3
registry.suse.com/edge/3.6/metallb-speaker:v0.15.3

Elemental

1.9.0

1.9.0

registry.suse.com/rancher/elemental-operator-chart:1.9.0
registry.suse.com/rancher/elemental-operator-crds-chart:1.9.0
registry.suse.com/rancher/elemental-operator:1.9.0

Extensão do Painel Elemental

3.0.1

3.0.1

Helm Chart da Extensão Elemental

Edge Image Builder

1.3.3.1

N/A

registry.suse.com/edge/3.6/edge-image-builder:1.3.3.1

KubeVirt

1.7.0

306.0.2+up0.7.0

registry.suse.com/edge/3.6/kubevirt-chart:306.0.2+up0.7.0
registry.suse.com/suse/sles/15.7/virt-operator:1.7.0-150700.3.16.2
registry.suse.com/suse/sles/15.7/virt-api:1.7.0-150700.3.16.2
registry.suse.com/suse/sles/15.7/virt-controller:1.7.0-150700.3.16.2
registry.suse.com/suse/sles/15.7/virt-handler:1.7.0-150700.3.16.2
registry.suse.com/suse/sles/15.7/virt-launcher:1.7.0-150700.3.16.2

Extensão do Painel KubeVirt

1.3.3

306.0.4+up1.3.3

registry.suse.com/edge/3.6/kubevirt-dashboard-extension-chart:306.0.4+up1.3.3

Containerized Data Importer (CDI)

1.64.0

306.0.2+up0.7.0

registry.suse.com/edge/3.6/cdi-chart:306.0.2+up0.7.0
registry.suse.com/suse/sles/15.7/cdi-operator:1.64.0-150700.9.6.1
registry.suse.com/suse/sles/15.7/cdi-controller:1.64.0-150700.9.6.1
registry.suse.com/suse/sles/15.7/cdi-apiserver:1.64.0-150700.9.6.1
registry.suse.com/suse/sles/15.7/cdi-uploadproxy:1.64.0-150700.9.6.1

Operador Endpoint Copier

0.3.0

306.0.1+up0.3.0

registry.suse.com/edge/3.6/endpoint-copier-operator-chart:306.0.1+up0.3.0
registry.suse.com/edge/3.6/endpoint-copier-operator:0.3.0

Operador de Rede SR-IOV

1.6.0

306.0.4+up1.6.0

registry.suse.com/edge/3.6/sriov-network-operator-chart:306.0.4+up1.6.0
registry.suse.com/edge/3.6/sriov-crd-chart:306.0.4+up1.6.0

Controlador de Atualização do Sistema

0.19.1

109.0.1

Repositório Helm de Charts do Rancher
registry.rancher.com/rancher/system-upgrade-controller:v0.19.1

Upgrade Controller

0.1.3

306.0.4+up0.1.3

registry.suse.com/edge/3.6/upgrade-controller-chart:306.0.4+up0.1.3
registry.suse.com/edge/3.6/upgrade-controller:0.1.3
registry.rancher.com/rancher/kubectl:v1.35.2
registry.suse.com/edge/3.6/release-manifest:3.6.1

SUSE Private Registry

1.1.1

1.1.1

oci://registry.suse.com/private-registry/private-registry-helm[Repositório Helm do SUSE Private Registry]
registry.suse.com/private-registry/harbor-core:1.1.1-1.19
registry.suse.com/private-registry/harbor-jobservice:1.1.1-1.19
registry.suse.com/private-registry/harbor-portal:1.1.1-1.20
registry.suse.com/private-registry/harbor-registry:1.1.1-1.19
registry.suse.com/private-registry/harbor-registryctl:1.1.1-1.19
registry.suse.com/private-registry/harbor-trivy-adapter:1.1.1-1.24

Kiwi Builder

10.2.29.1

N/A

registry.suse.com/edge/3.6/kiwi-builder:10.2.29.1

Cert-Manager

1.20.1

1.20.1

Repositório Helm Jetstack
quay.io/jetstack/cert-manager-controller:v1.20.1
quay.io/jetstack/cert-manager-webhook:v1.20.1
quay.io/jetstack/cert-manager-cainjector:v1.20.1

75.4 Release 3.6.0

Data de disponibilidade: 27 de maio de 2026

Data de término do suporte completo: 27 de novembro de 2026

Data de término do suporte de manutenção: 27 de maio de 2028

EOL: 28 de maio de 2028

Resumo: SUSE Telco Cloud 3.6.0 é a primeira versão no fluxo de lançamentos 3.6.

75.4.1 Novos recursos

  • Atualizado para Kubernetes 1.35.3 e Rancher Prime 2.14.1

  • Atualizado para SUSE Security (NeuVector) 5.5.1 Notas de Lançamento do NeuVector

  • Atualizado para SUSE Storage (Longhorn) 1.11.1 Notas de Lançamento do Longhorn Upstream

  • Atualizado para Rancher Turtles (CAPI) 0.26.1 Documentação do Rancher Turtles

  • Atualizado para MetalLB 0.15.3 Notas de Lançamento Upstream

  • Atualizado para KubeVirt 1.7.0 e CDI (Containerized Data Importer) 1.64.0

  • Atualizado para Elemental 1.9.0 Notas de Lançamento do Elemental

  • Atualizado para Cert-Manager 1.20.1 Notas de Lançamento Upstream

  • Atualizado Metal3/Ironic para 0.15.0 com Ironic 35.0.0

  • O modo BGP para MetalLB era uma Prévia Tecnológica no SUSE Telco Cloud 3.5 e agora é totalmente suportado

  • O Precision Time Protocol (PTP) em implantações downstream era uma Prévia Tecnológica no SUSE Telco Cloud 3.5 e agora é totalmente suportado, juntamente com o suporte a SyncE e GNSS

  • Implantações de cluster downstream IPv6 de pilha única agora são suportadas, no entanto, observe que isso requer um cluster de gerenciamento de pilha dupla (clusters de gerenciamento de pilha única permanecem como uma Prévia Tecnológica)

75.4.2 Correções de bug e segurança

75.4.3 Problemas conhecidos

Atenção
Atenção

Se estiver implantando novos clusters, siga Capítulo 64, Criando imagens atualizadas do SUSE Linux Micro com o Kiwi para criar novas imagens primeiro. Isso é sugerido para clusters de gerenciamento e downstream para garantir que as imagens contenham as correções de segurança e de bug mais recentes.

  • Ao implantar via Edge Image Builder, os manifestos HelmChartConfigs podem falhar se forem colocados no diretório de configuração kubernetes/manifests. Em vez disso, recomenda-se colocar qualquer HelmChartConfigs em /var/lib/rancher/{rke2/k3s}/server/manifests/ usando a interface os-files do EIB. Consulte Seção 29.1, “Estrutura de diretórios” para obter um exemplo. Falhar em fazer isso pode fazer com que os nós permaneçam no estado NotReady na inicialização inicial, conforme discutido em #8357 problema do RKE2.

  • Nas versões RKE2/K3s 1.34 e 1.35, o diretório /etc/cni usado para armazenar configurações de CNI pode não disparar uma notificação dos arquivos gravados para containerd devido a certas condições relacionadas ao overlayfs (consulte o #8356 problema do RKE2). Isso, por sua vez, faz com que a implantação do RKE2/K3s fique travada aguardando a inicialização do CNI, e os nós do RKE2/K3s permaneçam no estado NotReady. Isso pode ser visto no nível do nó com kubectl describe node <affected_node>:

Conditions:
  Type   Status  LastHeartbeatTime                LastTransitionTime               Reason           Message
  ----   ------  -----------------                ------------------               ------           -------
  Ready  False   Thu, 05 Jun 2025 17:41:28 +0000  Thu, 05 Jun 2025 14:38:16 +0000  KubeletNotReady  container runtime network not ready: NetworkReady=false reason:NetworkPluginNotReady message:Network plugin returns error: cni plugin not initialized

Como solução alternativa, um volume tmpfs pode ser montado no diretório /etc/cni antes que o RKE2 seja iniciado. Isso evita o uso de overlayfs, o que faz com que o containerd perca notificações, e as configurações devem ser reescritas toda vez que o nó for reiniciado e os initcontainers dos pods forem executados novamente. Se estiver usando o EIB, isso pode ser um script 04-tmpfs-cni.sh no diretório custom/scripts (conforme explicado aqui) que se parece com:

#!/bin/bash
mkdir -p /etc/cni
mount -t tmpfs -o mode=0700,size=5M tmpfs /etc/cni
echo "tmpfs /etc/cni tmpfs defaults,size=5M,mode=0700 0 0" >> /etc/fstab
  • Não há documentação ou exemplos oficiais para configurar o SyncE via synce4l e GNSS via gpsd disponíveis neste estágio; esses tópicos serão abordados em versões futuras.

  • Alguns repositórios de contêiner estão acessíveis atualmente apenas via IPv4; por esse motivo, um repositório local no Cluster de Gerenciamento é necessário para um cluster downstream somente com IPv6.

75.4.4 Versões dos Componentes

A tabela a seguir descreve os componentes individuais que compõem a versão 3.6.0, incluindo a versão, a versão do gráfico Helm (se aplicável) e de onde o artefato lançado pode ser extraído no formato binário. Siga a documentação associada para exemplos de uso e implantação.

Nome

Versão

Versão do Gráfico Helm

Local do artefato (URL/Imagem)

SUSE Linux Micro

6.2 (mais recente)

N/A

Página de download do SUSE Linux Micro

SUSE Linux Micro

6.2 (mais recente)

N/A

Checksums e assinaturas estão disponíveis para download na Página de download do SUSE Linux Micro
SL-Micro.x86_64-6.2-Base-SelfInstall-GM.install.iso
SL-Micro.x86_64-6.2-Base-RT-SelfInstall-GM.install.iso
SL-Micro.x86_64-6.2-Base-GM.raw.xz
SL-Micro.x86_64-6.2-Base-RT-GM.raw.xz

SUSE Multi-Linux Manager

5.1

N/A

Página de download do SUSE Multi-Linux Manager

K3s

1.35.3

N/A

Versão upstream do K3s

RKE2

1.35.3

N/A

Versão upstream do RKE2

SUSE Rancher Prime

2.14.1

2.14.1

Repositório Helm do Rancher Prime
https://prime.ribs.rancher.io/rancher/v2.14.1/rancher-images.txt[Rancher 2.14.1 Container Images]

SUSE Storage (Longhorn)

1.11.1

1.11.1

Repositório Helm do SUSE Storage
https://apps.rancher.io/applications/suse-storage/components[Imagens de Contêiner do SUSE Storage]

SUSE Security (NeuVector)

5.5.1

109.0.1+up2.8.13

Repositório Helm de Charts do Rancher
registry.rancher.com/rancher/neuvector-controller:5.5.1
registry.rancher.com/rancher/neuvector-enforcer:5.5.1
registry.suse.com/rancher/neuvector-compliance-config:1.0.12

Provedores do Rancher Turtles (CAPI)

0.26.1

306.0.6+up0.26.1

registry.suse.com/edge/3.6/rancher-turtles-providers-chart:306.0.6+up0.26.1
registry.rancher.com/rancher/cluster-api-controller:v1.12.2
registry.rancher.com/rancher/turtles:v0.26.1
registry.suse.com/rancher/cluster-api-provider-rke2-bootstrap:v0.24.3
registry.suse.com/rancher/cluster-api-provider-rke2-controlplane:v0.24.3

Metal3

0.15.0

306.0.26+up0.15.0

registry.suse.com/edge/3.6/metal3-chart:306.0.26+up0.15.0
registry.suse.com/edge/3.6/baremetal-operator:0.12.3.0
registry.suse.com/edge/3.6/ironic:35.0.0.1
registry.suse.com/edge/3.6/ironic-ipa-downloader:3.1.1
registry.suse.com/edge/3.6/ironic-python-agent:3.0.8

MetalLB

0.15.3

306.0.2+up0.15.3

registry.suse.com/edge/3.6/metallb-chart:306.0.2+up0.15.3
registry.suse.com/edge/3.6/metallb-controller:v0.15.3
registry.suse.com/edge/3.6/metallb-speaker:v0.15.3

Elemental

1.9.0

1.9.0

registry.suse.com/rancher/elemental-operator-chart:1.9.0
registry.suse.com/rancher/elemental-operator-crds-chart:1.9.0
registry.suse.com/rancher/elemental-operator:1.9.0

Extensão do Painel Elemental

3.0.1

3.0.1

Helm Chart da Extensão Elemental

Edge Image Builder

1.3.3.1

N/A

registry.suse.com/edge/3.6/edge-image-builder:1.3.3.1

KubeVirt

1.7.0

306.0.2+up0.7.0

registry.suse.com/edge/3.6/kubevirt-chart:306.0.2+up0.7.0
registry.suse.com/suse/sles/15.7/virt-operator:1.7.0-150700.3.16.2
registry.suse.com/suse/sles/15.7/virt-api:1.7.0-150700.3.16.2
registry.suse.com/suse/sles/15.7/virt-controller:1.7.0-150700.3.16.2
registry.suse.com/suse/sles/15.7/virt-handler:1.7.0-150700.3.16.2
registry.suse.com/suse/sles/15.7/virt-launcher:1.7.0-150700.3.16.2

Extensão do Painel KubeVirt

1.3.3

306.0.4+up1.3.3

registry.suse.com/edge/3.6/kubevirt-dashboard-extension-chart:306.0.4+up1.3.3

Containerized Data Importer (CDI)

1.64.0

306.0.2+up0.7.0

registry.suse.com/edge/3.6/cdi-chart:306.0.2+up0.7.0
registry.suse.com/suse/sles/15.7/cdi-operator:1.64.0-150700.9.6.1
registry.suse.com/suse/sles/15.7/cdi-controller:1.64.0-150700.9.6.1
registry.suse.com/suse/sles/15.7/cdi-apiserver:1.64.0-150700.9.6.1
registry.suse.com/suse/sles/15.7/cdi-uploadproxy:1.64.0-150700.9.6.1

Operador Endpoint Copier

0.3.0

306.0.1+up0.3.0

registry.suse.com/edge/3.6/endpoint-copier-operator-chart:306.0.1+up0.3.0
registry.suse.com/edge/3.6/endpoint-copier-operator:0.3.0

Operador de Rede SR-IOV

1.6.0

306.0.4+up1.6.0

registry.suse.com/edge/3.6/sriov-network-operator-chart:306.0.4+up1.6.0
registry.suse.com/edge/3.6/sriov-crd-chart:306.0.4+up1.6.0

Upgrade Controller

0.19.1

109.0.1

Repositório Helm de Charts do Rancher
registry.rancher.com/rancher/system-upgrade-controller:v0.19.1

Upgrade Controller

0.1.3

306.0.3+up0.1.3

registry.suse.com/edge/3.6/upgrade-controller-chart:306.0.3+up0.1.3
registry.suse.com/edge/3.6/upgrade-controller:0.1.3
registry.rancher.com/rancher/kubectl:v1.35.2
registry.suse.com/edge/3.6/release-manifest:3.6.0

SUSE Private Registry

1.1.1

1.1.1

oci://registry.suse.com/private-registry/private-registry-helm[Repositório Helm do SUSE Private Registry]
registry.suse.com/private-registry/harbor-core:1.1.1-1.19
registry.suse.com/private-registry/harbor-jobservice:1.1.1-1.19
registry.suse.com/private-registry/harbor-portal:1.1.1-1.20
registry.suse.com/private-registry/harbor-registry:1.1.1-1.19
registry.suse.com/private-registry/harbor-registryctl:1.1.1-1.19
registry.suse.com/private-registry/harbor-trivy-adapter:1.1.1-1.24

Kiwi Builder

10.2.29.1

N/A

registry.suse.com/edge/3.6/kiwi-builder:10.2.29.1

Cert-Manager

1.20.1

1.20.1

Repositório Helm Jetstack
quay.io/jetstack/cert-manager-controller:v1.20.1
quay.io/jetstack/cert-manager-webhook:v1.20.1
quay.io/jetstack/cert-manager-cainjector:v1.20.1

75.5 Recursos removidos

Salvo indicação em contrário, estes se aplicam à versão 3.6.0 e a todas as versões z-stream subsequentes.

  • O Akri era uma oferta de Technology Preview em versões anteriores do Edge e foi descontinuado a partir da 3.4.0. Ele foi completamente removido da oferta.

75.6 Prévias de tecnologia

Salvo indicação em contrário, estes se aplicam à versão 3.6.0 e a todas as versões z-stream subsequentes.

  • Implantações de cluster de gerenciamento IPv6 de pilha única são uma oferta de Technology Preview e não estão sujeitas ao escopo padrão de suporte.

75.7 Verificação de componentes

Os componentes mencionados acima podem ser verificados usando os dados da Lista de Materiais de Software (SBOM) - por exemplo, usando cosign conforme descrito abaixo:

Baixe a chave pública do contêiner SUSE Telco Cloud da fonte de chaves de assinatura da SUSE:

> cat key.pem
-----BEGIN PUBLIC KEY-----
MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA7N0S2d8LFKW4WU43bq7Z
IZT537xlKe17OQEpYjNrdtqnSwA0/jLtK83m7bTzfYRK4wty/so0g3BGo+x6yDFt
SVXTPBqnYvabU/j7UKaybJtX3jc4SjaezeBqdi96h6yEslvg4VTZDpy6TFP5ZHxZ
A0fX6m5kU2/RYhGXItoeUmL5hZ+APYgYG4/455NBaZT2yOywJ6+1zRgpR0cRAekI
OZXl51k0ebsGV6ui/NGECO6MB5e3arAhszf8eHDE02FeNJw5cimXkgDh/1Lg3KpO
dvUNm0EPWvnkNYeMCKR+687QG0bXqSVyCbY6+HG/HLkeBWkv6Hn41oeTSLrjYVGa
T3zxPVQM726sami6pgZ5vULyOleQuKBZrlFhFLbFyXqv1/DokUqEppm2Y3xZQv77
fMNogapp0qYz+nE3wSK4UHPd9z+2bq5WEkQSalYxadyuqOzxqZgSoCNoX5iIuWte
Zf1RmHjiEndg/2UgxKUysVnyCpiWoGbalM4dnWE24102050Gj6M4B5fe73hbaRlf
NBqP+97uznnRlSl8FizhXzdzJiVPcRav1tDdRUyDE2XkNRXmGfD3aCmILhB27SOA
Lppkouw849PWBt9kDMvzelUYLpINYpHRi2+/eyhHNlufeyJ7e7d6N9VcvjR/6qWG
64iSkcF2DTW61CN5TrCe0k0CAwEAAQ==
-----END PUBLIC KEY-----

Verifique o hash da imagem do contêiner, por exemplo, usando crane:

> crane digest registry.suse.com/edge/3.6/baremetal-operator:0.12.3.0 --platform linux/amd64
sha256:example-digest-placeholder
Nota
Nota

Para imagens multi-arquitetura, também é necessário especificar uma plataforma ao obter o digest, por exemplo, --platform linux/amd64 ou --platform linux/arm64. A falha em fazer isso resultará em um erro na etapa a seguir (Error: no matching attestations).

Verifique com cosign:

> cosign verify-attestation --type spdxjson --key key.pem registry.suse.com/edge/3.6/baremetal-operator@sha256:example-digest-placeholder > /dev/null
#
Verification for registry.suse.com/edge/3.6/baremetal-operator@sha256:example-digest-placeholder --
The following checks were performed on each of these signatures:
  - The cosign claims were validated
  - Existence of the claims in the transparency log was verified offline
  - The signatures were verified against the specified public key

Extraia os dados da SBOM conforme descrito na documentação da SBOM da SUSE:

> cosign verify-attestation --type spdxjson --key key.pem registry.suse.com/edge/3.6/baremetal-operator@sha256:example-digest-placeholder | jq '.payload | @base64d | fromjson | .predicate'

75.8 Etapas de Atualização

Consulte o Parte VIII, “Operações do Dia Dois” para obter detalhes sobre como fazer upgrade para uma nova versão.

75.9 Ciclo de vida de suporte de produtos

O SUSE Telco Cloud conta com o suporte premiado da SUSE, uma líder tecnológica estabelecida com um histórico comprovado de entrega de serviços de suporte com qualidade empresarial. Para mais informações, consulte https://www.suse.com/lifecycle e a página da Política de Suporte em https://www.suse.com/support/policy.html. Se você tiver alguma dúvida sobre como abrir um caso de suporte, como a SUSE classifica os níveis de severidade ou o escopo do suporte, consulte o Manual de Suporte Técnico em https://www.suse.com/support/handbook/.

O SUSE Telco Cloud \"3.6\" é suportado por 24 meses de suporte de produção, com 6 meses iniciais de \"suporte completo\", seguidos por 18 meses de \"suporte de manutenção\". Após essas fases de suporte, o produto atinge o "fim do serviço" (EOL) e não é mais suportado. Mais informações sobre as fases do ciclo de vida podem ser encontradas na tabela abaixo:

Suporte Completo (6 meses)

Correções de bugs urgentes e de alta prioridade selecionadas serão lançadas durante a janela de suporte completo, e todos os outros patches (não urgentes, melhorias, novos recursos) serão lançados por meio do cronograma de lançamento regular.

Suporte de Manutenção (18 meses)

Durante este período, apenas correções críticas serão lançadas por meio de patches. Outras correções de bugs podem ser lançadas a critério da SUSE, mas não devem ser esperadas.

Fim do Serviço (EOL)

Assim que uma versão de produto atinge sua data de Fim do Serviço (EOL), o cliente pode continuar a usar o produto dentro dos termos do contrato de licenciamento do produto. Os Planos de Suporte da SUSE não se aplicam a versões de produtos após sua data de EOL.

A menos que explicitamente declarado, todos os componentes listados são considerados Geralmente Disponíveis (GA) e são cobertos pelo escopo padrão de suporte da SUSE. Alguns componentes podem ser listados como "Technology Preview", onde a SUSE fornece aos clientes acesso a recursos e funcionalidades pré-GA iniciais para avaliação, mas não estão sujeitos às políticas de suporte padrão e não são recomendados para casos de uso em produção. A SUSE aceita muito bem comentários e sugestões sobre as melhorias que podem ser feitas nos componentes de Technology Preview, mas a SUSE reserva-se o direito de descontinuar um recurso de Technology Preview antes que ele se torne Geralmente Disponível se ele não atender às necessidades de nossos clientes ou não atingir um estado de maturidade que exigimos.

Observe que a SUSE deve ocasionalmente descontinuar recursos ou alterar especificações de API. Os motivos para a descontinuação de recursos ou alteração de API podem incluir um recurso sendo atualizado ou substituído por uma nova implementação, um novo conjunto de recursos, a tecnologia upstream não estar mais disponível ou a comunidade upstream ter introduzido alterações incompatíveis. Não se pretende que isso aconteça dentro de uma determinada versão secundária (x.z), portanto, todas as versões z-stream manterão a compatibilidade de API e a funcionalidade de recursos. A SUSE se esforçará para fornecer avisos de descontinuação com bastante antecedência nas notas de versão, juntamente com soluções alternativas, sugestões e mitigações para minimizar a interrupção do serviço.

A equipe SUSE Telco Cloud também aceita comentários da comunidade, onde problemas podem ser levantados no respectivo repositório de código dentro de https://www.github.com/suse-edge.

75.10 Obtenção de código-fonte

Este produto SUSE inclui materiais licenciados para a SUSE sob a GNU General Public License (GPL) e várias outras licenças de código aberto. A GPL exige que a SUSE forneça o código-fonte que corresponde ao material licenciado pela GPL e que a SUSE esteja em conformidade com todos os outros requisitos de licença de código aberto. Como tal, a SUSE disponibiliza todo o código-fonte, que geralmente pode ser encontrado no repositório GitHub SUSE Telco Cloud (https://www.github.com/suse-edge), no repositório GitHub do SUSE Rancher (https://www.github.com/rancher) para componentes dependentes e, especificamente, para o SUSE Linux Micro, o código-fonte está disponível para download em https://www.suse.com/download/sle-micro na "Medium 2".

75.11 Informações legais

A SUSE não faz representações ou garantias quanto ao conteúdo ou à utilização desta documentação e, especificamente, isenta-se de quaisquer garantias explícitas ou implícitas de comerciabilidade ou adequação a qualquer propósito específico. Além disso, a SUSE reserva-se o direito de revisar esta publicação e de fazer mudanças em seu conteúdo a qualquer momento, sem a obrigação de notificar qualquer pessoa ou entidade sobre essas revisões ou mudanças.

Além disso, a SUSE não faz representações ou garantias quanto a qualquer software e, especificamente, isenta-se de quaisquer garantias explícitas ou implícitas de comerciabilidade ou adequação a qualquer propósito específico. Além disso, a SUSE reserva-se o direito de fazer mudanças em qualquer parte do software SUSE, a qualquer momento, sem a obrigação de notificar qualquer pessoa ou entidade sobre essas mudanças.

Todos os produtos ou as informaçőes técnicas fornecidas neste Contrato podem estar sujeitas aos controles de exportação dos Estados Unidos e ŕs leis de comércio de outros países. Você concorda em obedecer a todos os regulamentos de controle de exportação e em obter quaisquer licenças ou classificações necessárias para exportar, reexportar ou importar produtos. Você concorda em não exportar ou reexportar para entidades nas listas de exclusão de exportação atuais dos Estados Unidos ou para países sob embargo ou considerados terroristas, conforme especificado nas leis de exportação dos Estados Unidos. Você concorda em não usar entregáveis para fins proibidos relacionados a armas nucleares, mísseis ou armamentos químicos/biológicos. Consulte https://www.suse.com/company/legal/ para obter mais informações sobre a exportação do software SUSE. A SUSE não assume qualquer responsabilidade caso você não obtenha as aprovações necessárias para exportação.

Copyright © 2024 SUSE LLC.

Este documento de notas de versão está licenciado sob uma Licença Creative Commons Atribuição-SemDerivações 4.0 Internacional (CC-BY-ND-4.0). Você deve ter recebido uma cópia da licença juntamente com este documento. Caso não tenha recebido, consulte https://creativecommons.org/licenses/by-nd/4.0/.

A SUSE possui direitos de propriedade intelectual relacionados à tecnologia incorporada ao produto descrito neste documento. Em particular, e sem limitações, esses direitos de propriedade intelectual podem incluir uma ou mais patentes dos EUA listadas em https://www.suse.com/company/legal/ e uma ou mais patentes adicionais ou pedidos de patentes pendentes nos EUA e em outros países.

Para marcas registradas da SUSE, consulte a lista de Marcas Registradas e Marcas de Serviço da SUSE (https://www.suse.com/company/legal/). Todas as marcas registradas de terceiros pertencem aos seus respectivos proprietários. Para obter informações sobre a marca SUSE e requisitos de uso, consulte as diretrizes publicadas em https://brand.suse.com/.