3 Clusters independentes 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 todas as três áreas de implantação do SUSE Edge, já que é flexível o suficiente para oferecer desde as menores personalizações, como adicionar um usuário ou definir o fuso horário, até uma imagem amplamente configurada que comporta, por exemplo, configurações de redes complexas, implantações de clusters Kubernetes de vários nós, implantações de cargas de trabalho de clientes e registros na plataforma de gerenciamento centralizado pelo Rancher/Elemental e SUSE Multi-Linux Manager. O EIB é executado como uma imagem de contêiner, o que o torna incrivelmente portátil entre as plataformas e garante que todas as dependências necessárias sejam autossuficientes, exercendo um impacto muito mínimo sobre os pacotes instalados do sistema usado para operar a ferramenta.
Nos cenários de vários nós, o EIB implanta automaticamente o MetalLB e o Endpoint Copier Operator para que os hosts provisionados que usam a mesma imagem criada ingressem em um cluster Kubernetes de maneira automática.
Para obter mais informações, leia a introdução do Edge Image Builder (Capítulo 11, Edge Image Builder).
O Edge Image Builder 1.2.1 suporta a personalização de imagens no SUSE Linux Micro 6.1. As versões mais antigas, como o SUSE Linux Enterprise Micro 5.5 ou 6.0, não são compatíveis.
3.1 Pré-requisitos #
Uma máquina host de build AMD64/Intel 64 (física ou virtual) com o SLES 15 SP6.
O mecanismo de contêiner Podman
Uma imagem ISO SelfInstall do SUSE Linux Micro 6.1 criada pelo procedimento do construtor Kiwi (Capítulo 28, Criando imagens atualizadas do SUSE Linux Micro com o Kiwi)
Para fins que não sejam de produção, é possível usar o openSUSE Leap 15.6 ou o openSUSE Tumbleweed como máquina host de build. Outros sistemas operacionais podem funcionar, desde que um tempo de execução do contêiner compatível esteja disponível.
3.1.1 Obtendo a imagem do EIB #
A imagem de contêiner do EIB é publicamente disponível e pode ser baixada do registro do SUSE Edge executando o seguinte comando no host de build da imagem:
podman pull registry.suse.com/edge/3.3/edge-image-builder:1.2.1
3.2 Criando o diretório de configuração de imagem #
Como o EIB é executado dentro de um contêiner, precisamos montar um diretório de configuração do host, o que permite especificar a configuração desejada e, durante o processo de criação, o EIB tem o acesso aos arquivos de entrada necessários e artefatos auxiliares. Esse diretório deve seguir uma estrutura específica. Vamos criá-lo imaginando que ele existe em seu diretório pessoal com o nome "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.1. Vamos garantir que a imagem seja copiada para o diretório de configuração:
cp /path/to/SL-Micro.x86_64-6.1-Base-SelfInstall-GM.install.iso $CONFIG_DIR/base-images/slemicro.iso
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.
Neste momento, o diretório de configuração deve ter a seguinte aparência:
└── base-images/
└── slemicro.iso
3.3 Criando o arquivo de definição de imagem #
O arquivo de definição descreve grande parte das opções configuráveis disponíveis no Edge Image Builder. Um exemplo completo das opções é apresentado aqui, e recomendamos que você leia o guia de imagens de criação upstream para ver exemplos mais detalhados do que vamos executar a seguir. Vamos começar com um arquivo de definição bem básico para a nossa imagem de sistema operacional:
cat << EOF > $CONFIG_DIR/iso-definition.yaml
apiVersion: 1.2
image:
imageType: iso
arch: x86_64
baseImage: slemicro.iso
outputImageName: eib-image.iso
EOF
Essa 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ção posterior é uma imagem iso
chamada
slemicro.iso
, que esperamos que esteja no local
$CONFIG_DIR/base-images/slemicro.iso
. Ela também descreve
que, depois que o EIB terminar de modificar a imagem, a imagem de saída se
chamará eib-image.iso
e, por padrão, residirá em
$CONFIG_DIR
.
Agora a estrutura do nosso diretório deve ter esta aparência:
├── iso-definition.yaml
└── base-images/
└── slemicro.iso
Nas seções a seguir, vamos analisar alguns exemplos de operações comuns:
3.3.1 Configurando usuários do sistema operacional #
O EIB permite pré-configurar 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 corrigir a senha de root, e o primeiro passo é usar o
OpenSSL
para criar uma senha criptografada unidirecional:
openssl passwd -6 SecurePassword
A saída será semelhante a esta:
$6$G392FCbxVgnLaFw1$Ujt00mdpJ3tDHxEg1snBU3GjujQf6f8kvopu7jiCBIhRbRvMmKUqwcmXAKggaSSKeUUOEtCP3ZUoZQY7zTXnC1
Em seguida, podemos adicionar uma seção chamada
operatingSystem
ao arquivo de definição com uma matriz
users
dentro dela. O arquivo resultante terá esta
aparência:
apiVersion: 1.2
image:
imageType: iso
arch: x86_64
baseImage: slemicro.iso
outputImageName: eib-image.iso
operatingSystem:
users:
- username: root
encryptedPassword: $6$G392FCbxVgnLaFw1$Ujt00mdpJ3tDHxEg1snBU3GjujQf6f8kvopu7jiCBIhRbRvMmKUqwcmXAKggaSSKeUUOEtCP3ZUoZQY7zTXnC1
É possível também adicionar outros usuários, criar diretórios pessoais, 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 ver mais exemplos.
3.3.2 Configurando o horário do sistema operacional #
A seção time
é opcional, mas sua configuração é altamente
recomendada para evitar possíveis problemas com certificados e divergência
do relógio. O EIB configura o chronyd e o /etc/localtime
dependendo desses parâmetros.
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, "Europa/Londres"). É possível ver a lista completa executando o comandotimedatectl list-timezones
no sistema Linux.ntp: define atributos relacionados à configuração do NTP (usando o chronyd).
forceWait: solicita que o chronyd tente sincronizar as fontes de horário antes de iniciar outros serviços, com um tempo limite de 180 segundos.
pools: especifica uma lista de pools que o chronyd usará como fontes de dados (usando o
iburst
para melhorar o tempo gasto na sincronização inicial).servers: especifica uma lista de servidores que o chronyd usará como fontes de dados (usando o
iburst
para melhorar o tempo gasto na sincronização inicial).
Os valores apresentados neste exemplo são apenas para fins ilustrativos. Ajuste-os de acordo com seus requisitos específicos.
3.3.3 Adicionando certificados #
Arquivos de certificado com a extensão ".pem" ou ".crt" armazenados no
diretório certificates
serão instalados no armazenamento
de certificados global do sistema do nó:
.
├── definition.yaml
└── certificates
├── my-ca.pem
└── my-ca.crt
Consulte o guia "Securing Communication with TLS Certificate" (Protegendo a comunicação com o certificado TLS) para obter mais informações.
3.3.4 Configurando pacotes RPM #
Um dos principais recursos do EIB é o mecanismo para adicionar outros pacotes de software à imagem, dessa forma, o sistema pode aproveitar os pacotes instalados assim que a instalação é concluída. O EIB permite que os usuários especifiquem o seguinte:
Pacotes por nome em uma lista na definição da imagem
Repositórios de rede nos quais pesquisar os pacotes
Credenciais do SUSE Customer Center (SCC) para pesquisar os pacotes listados em repositórios oficiais da SUSE
Por um diretório
$CONFIG_DIR/rpms
, fazer sideload dos RPMs personalizados que não existem nos repositórios de redePelo mesmo diretório (
$CONFIG_DIR/rpms/gpg-keys
), chaves GPG para habilitar a validação de pacotes de terceiros
Em seguida, o EIB é executado por um processo de resolução de pacote no momento da criação da imagem, usando a imagem base como entrada, e tenta obter e instalar todos os pacotes fornecidos, especificados pela lista ou fornecidos localmente. O EIB faz download de todos os pacotes, incluindo as dependências, em um repositório existente na imagem de saída, e instrui o sistema a instalá-los durante o processo da primeira inicialização. A execução desse processo durante a criação da imagem garante que os pacotes sejam devidamente instalados na plataforma desejada, por exemplo, o nó de borda, durante a primeira inicialização. Isso também é vantajoso em ambientes nos quais você deseja fazer bake dos pacotes adicionais na imagem, em vez de extraí-los pela rede durante a operação, por exemplo, em ambientes air-gapped ou de rede restrita.
Como um exemplo simples para demonstrar esse procedimento, vamos instalar o
pacote RPM nvidia-container-toolkit
encontrado no
repositório NVIDIA mantido por fornecedor terceirizado:
packages:
packageList:
- nvidia-container-toolkit
additionalRepos:
- url: https://nvidia.github.io/libnvidia-container/stable/rpm/x86_64
O arquivo de definição resultante terá esta aparência:
apiVersion: 1.2
image:
imageType: iso
arch: x86_64
baseImage: slemicro.iso
outputImageName: eib-image.iso
operatingSystem:
users:
- username: root
encryptedPassword: $6$G392FCbxVgnLaFw1$Ujt00mdpJ3tDHxEg1snBU3GjujQf6f8kvopu7jiCBIhRbRvMmKUqwcmXAKggaSSKeUUOEtCP3ZUoZQY7zTXnC1
packages:
packageList:
- nvidia-container-toolkit
additionalRepos:
- url: https://nvidia.github.io/libnvidia-container/stable/rpm/x86_64
O exemplo acima é simples, mas para uma totalidade, faça download da chave de assinatura do pacote NVIDIA antes de gerar a imagem:
$ mkdir -p $CONFIG_DIR/rpms/gpg-keys
$ curl -fsSL https://nvidia.github.io/libnvidia-container/gpgkey > $CONFIG_DIR/rpms/gpg-keys/nvidia.gpg
A adição de outros RPMs por esse método tem como objetivo incluir componentes de terceiros compatíveis ou pacotes fornecidos (e mantidos) pelo usuário. Esse mecanismo não deve ser usado para adicionar pacotes que não costumam ser suportados no SUSE Linux Micro. Se ele for usado para adicionar componentes de repositórios openSUSE (que não são suportados), inclusive de versões ou pacotes de serviço mais recentes, você poderá acabar com um configuração sem suporte, principalmente quando a resolução de dependência resulta na substituição de partes importantes do sistema operacional, mesmo que o sistema resultante pareça funcionar conforme o esperado. Se você tiver qualquer dúvida, entre em contato com seu representante SUSE para obter ajuda para determinar se a configuração desejada é suportada.
Um guia mais completo com exemplos adicionais está disponível no guia de instalação de pacotes upstream.
3.3.5 Configurando o cluster Kubernetes e as cargas de trabalho dos usuários #
Outro recurso do EIB é a capacidade de usá-lo para automatizar a implantação de clusters Kubernetes altamente disponíveis, tanto de nó único quanto de vários nós, que são "inicializados no local" (ou seja, não exigem a coordenação de nenhuma forma de infraestrutura de gerenciamento centralizado). O principal motivador dessa abordagem são as implantações air-gapped, ou ambientes de rede restrita, mas ela também é útil para inicializar rapidamente clusters independentes, mesmo com acesso à rede total e irrestrito disponível.
Com esse método, é possível implantar o sistema operacional personalizado e especificar a configuração do Kubernetes, componentes adicionais em camadas por gráficos Helm e cargas de trabalho de usuários por manifestos fornecidos pelo Kubernetes. No entanto, o princípio do projeto por trás do uso desse método é que já consideramos que o usuário deseja se desconectar e, portanto, os itens especificados na definição da imagem serão inseridos na imagem, o que inclui as cargas de trabalho fornecidas pelo usuário. O EIB garantirá que todas as imagens descobertas necessárias, conforme as definições especificadas, sejam copiadas localmente e enviadas pelo registro de imagens incorporado ao sistema implantado resultante.
Neste exemplo, vamos usar nossa definição de imagem existente e especificar uma configuração do Kubernetes (não há uma lista dos sistemas e suas funções, portanto, vamos considerar um nó único), que vai instruir o EIB a provisionar um cluster Kubernetes RKE2 de nó único. Para mostrar a automação da implantação das cargas de trabalho fornecidas pelo usuário (por manifesto) e dos componentes em camadas (por Helm), vamos instalar o KubeVirt por meio do gráfico Helm do SUSE Edge e o NGINX por meio de um manifesto do Kubernetes. A configuração adicional que precisamos para anexar a definição da imagem existente é:
kubernetes:
version: v1.32.4+rke2r1
manifests:
urls:
- https://k8s.io/examples/application/nginx-app.yaml
helm:
charts:
- name: kubevirt
version: 303.0.0+up0.5.0
repositoryName: suse-edge
repositories:
- name: suse-edge
url: oci://registry.suse.com/edge/charts
O arquivo de definição completo resultante agora tem esta aparência:
apiVersion: 1.2
image:
imageType: iso
arch: x86_64
baseImage: slemicro.iso
outputImageName: eib-image.iso
operatingSystem:
users:
- username: root
encryptedPassword: $6$G392FCbxVgnLaFw1$Ujt00mdpJ3tDHxEg1snBU3GjujQf6f8kvopu7jiCBIhRbRvMmKUqwcmXAKggaSSKeUUOEtCP3ZUoZQY7zTXnC1
packages:
packageList:
- nvidia-container-toolkit
additionalRepos:
- url: https://nvidia.github.io/libnvidia-container/stable/rpm/x86_64
kubernetes:
version: v1.32.4+k3s1
manifests:
urls:
- https://k8s.io/examples/application/nginx-app.yaml
helm:
charts:
- name: kubevirt
version: 303.0.0+up0.5.0
repositoryName: suse-edge
repositories:
- name: suse-edge
url: oci://registry.suse.com/edge/charts
Há outros exemplos de opções, como implantações de vários nós, rede personalizada e opções/valores do gráfico Helm, disponíveis na documentação upstream.
3.3.6 Configurando a rede #
No último exemplo deste início rápido, vamos configurar a rede que será criada quando um sistema for provisionado com a imagem gerada pelo EIB. É importante entender que, exceto se uma configuração de rede for especificada, o DHCP usará o modelo padrão em todas as interfaces descobertas no momento da inicialização. No entanto, ela nem sempre é a configuração desejada, principalmente se o DHCP não estiver disponível e você precisar fazer configurações estáticas, configurar estruturas de rede mais complexas, como vínculos, LACP e VLANs, ou substituir determinados parâmetros, por exemplo, nomes de host, servidores DNS e rotas.
O EIB permite fazer configurações por nó (em que o sistema em questão é
identificado exclusivamente por seu endereço MAC) ou uma substituição para
especificar uma configuração idêntica para cada máquina, o que é mais útil
quando não se sabe os endereços MAC do sistema. O EIB usa uma ferramenta
adicional chamada Network Manager Configurator, ou nmc
na
forma abreviada, que foi desenvolvida pela equipe do SUSE Edge para que a
configuração de rede personalizada seja aplicada com base no esquema de rede
declarativo nmstate.io e, no
momento da inicialização, identificará o nó em que está sendo inicializado e
aplicará a configuração de rede desejada antes da ativação de quaisquer
serviços.
Agora vamos aplicar uma configuração de rede estática a um sistema com uma
interface única descrevendo o estado desejado da rede em um arquivo
específico do nó (com base no nome de host desejado) no diretório
network
exigido:
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:
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
O exemplo acima foi configurado para a sub-rede padrão
192.168.122.0/24
considerando que o teste é executado em
uma máquina virtual. Adapte-o de acordo com o seu ambiente, lembrando do
endereço MAC. Como é possível usar a mesma imagem para provisionar vários
nós, a rede configurada pelo EIB (via nmc
) depende da
capacidade de identificar exclusivamente o nó por seu endereço MAC. Como
resultado, durante a inicialização, o nmc
aplicará a
configuração de rede correta a cada máquina. Isso significa que você precisa
saber os endereços MAC dos sistemas nos quais deseja instalar. Como
alternativa, o comportamento padrão é confiar no DHCP, mas você pode usar o
gancho configure-network.sh
para aplicar uma configuração
comum a todos os nós. Consulte o guia de rede (Capítulo 12, Rede de borda) para obter mais detalhes.
A estrutura do arquivo resultante deverá ter esta aparência:
├── 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 necessários do NetworkManager serão automaticamente gerados e inseridos na nova imagem de instalação que o EIB criará. Esses arquivos serão aplicados durante o provisionamento do host, resultando na configuração de rede completa.
Consulte o componente de rede de borda (Capítulo 12, Rede de borda) para ver uma explicação mais abrangente da configuração acima e exemplos desse recurso.
3.4 Criando a imagem #
Agora que temos uma imagem base e uma definição da imagem para o EIB usar,
vamos criar a imagem. Para isso, simplesmente usaremos 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.3/edge-image-builder:1.2.1 \
build --definition-file iso-definition.yaml
A saída do comando deve ter esta aparência:
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 build cria uma pasta com marcação de data e hora em
$CONFIG_DIR/_build/
, que inclui os registros do build, os
artefatos usados durante o build e os diretórios
combustion
e artefacts
com todos os
scripts e artefatos adicionados à imagem CRB.
O conteúdo do diretório deve ter esta aparência:
├── 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 houver falha no build, eib-build.log
será o primeiro
registro com as informações. A partir disso, ele vai direcionar você para o
componente com falha para depuração.
Neste ponto, você deve ter uma imagem pronta para uso que:
Implantará o SUSE Linux Micro 6.1.
Configurará a senha de root.
Instalará o pacote
nvidia-container-toolkit
.Configurará um registro de contêiner incorporado para enviar o conteúdo localmente.
Instalará o RKE2 de nó único.
Configurará a rede estática.
Instalará o KubeVirt.
Implantará um manifesto fornecido pelo usuário.
3.5 Depurando o processo de criação da imagem #
Se o processo de criação da imagem falhar, consulte o guia de depuração upstream.
3.6 Testando a imagem recém-criada #
Para obter instruções de como testar a imagem CRB recém-criada, consulte o guia de teste de imagem upstream.