CRI-O no RHEL 10: como instalar, corrigir o erro do sandbox e testar com Nginx

CRI-O no RHEL 10: como instalar, corrigir o erro do sandbox e testar com Nginx

O Docker deixou de ser o runtime padrão no Kubernetes, e isso acelerou a adoção de runtimes nativos de CRI. No RHEL 10, o CRI-O se encaixa muito bem nesse cenário por ser leve, OCI-compliant e focado exclusivamente no que o Kubernetes precisa.

A seguir você vai instalar o CRI-O no RHEL 10, adicionar os plugins CNI, aplicar o fix crítico de systemd eBPF, e validar tudo criando manualmente um Pod Sandbox e um container Nginx via crictl.

Arquitetura e conceitos (entenda em 90 segundos)

CRI (Container Runtime Interface) é a interface que o Kubernetes usa para falar com o runtime de containers. O CRI-O implementa essa interface e entrega apenas o necessário para o Kubernetes, por isso costuma ser mais enxuto que soluções genéricas.

OCI (Open Container Initiative) define padrões para imagens e runtime. O CRI-O é OCI-compliant, significa que ele segue esses padrões, facilitando interoperabilidade.

Um Pod Sandbox é a “casca” do Pod, onde entram namespace de rede e outras bases do isolamento. Para rede, o CRI-O usa plugins CNI, normalmente com binários em /opt/cni/bin e definições em /etc/cni/net.d/.

Pré-requisitos

  • Um sistema RHEL 10 em execução.
  • Usuário local com acesso sudo.
  • Assinatura Red Hat ativa (ou assinatura de desenvolvedor válida).
  • Conectividade com a internet.
  • Atenção: as versões do CRI-O devem corresponder à versão minor do Kubernetes.

Passo 1: Preparação do repositório e sistema

1.1 Defina a versão do CRI-O

Vamos usar a variável CRIO_VERSION para apontar o repo correto. Ajuste conforme a versão minor do Kubernetes do seu cluster.

CRIO_VERSION=v1.34

1.2 Crie o arquivo de repositório do CRI-O

Este passo grava o repo em /etc/yum.repos.d/cri-o.repo usando o repositório upstream da OpenSUSE.

cat <<EOF | sudo tee /etc/yum.repos.d/cri-o.repo [cri-o] name=CRI-O baseurl=https://download.opensuse.org/repositories/isv:/cri-o:/stable:/$CRIO_VERSION/rpm/ enabled=1 gpgcheck=1 gpgkey=https://download.opensuse.org/repositories/isv:/cri-o:/stable:/$CRIO_VERSION/rpm/repodata/repomd.xml.key EOF

1.3 SELinux em modo permissive (somente para validação inicial)

SELinux em permissive. Recomendado apenas para validação inicial; em produção, configure as políticas corretas.

sudo setenforce 0 sudo sed -i 's/^SELINUX=enforcing/SELINUX=permissive/' /etc/selinux/config

Passo 2: Instalação do CRI-O e plugins CNI

2.1 Instale o CRI-O

Com o repo configurado, instale o pacote e habilite o serviço no boot.

sudo dnf install cri-o -y sudo systemctl start crio && sudo systemctl enable crio

Verifique se o serviço está ativo.

sudo systemctl status crio

2.2 Instale os plugins CNI

Sem CNI Plugins, o CRI-O não consegue criar e gerenciar redes de Pods. Agora vamos baixar o bundle de plugins e extrair em /opt/cni/bin.

Defina a versão e arquitetura usadas no exemplo.

CNI_VERSION="v1.6.0" ARCH="amd64" curl -LO "https://github.com/containernetworking/plugins/releases/download/${CNI_VERSION}/cni-plugins-linux-${ARCH}-${CNI_VERSION}.tgz"

Crie o diretório e extraia os binários.

sudo mkdir -p /opt/cni/bin sudo tar -C /opt/cni/bin -xzf cni-plugins-linux-${ARCH}-${CNI_VERSION}.tgz

Ative o arquivo bridge do CRI-O (mova o arquivo .disabled).

sudo mv /etc/cni/net.d/10-crio-bridge.conflist.disabled /etc/cni/net.d/10-crio-bridge.conflist

Reinicie o serviço para aplicar as mudanças.

sudo systemctl restart crio

Passo 3: O fix crítico do RHEL 10 (eBPF)

Há um problema específico do RHEL 10: a criação do sandbox pode falhar por systemd eBPF device filtering. O ajuste recomendado é desabilitar enable_devices via um arquivo drop-in em /etc/crio/crio.conf.d/.

Crie o arquivo 99-disable-ebpf.conf:

sudo vi /etc/crio/crio.conf.d/99-disable-ebpf.conf

Conteúdo:

[crio.runtime] enable_devices = false

Reinicie o CRI-O:

sudo systemctl restart crio

Passo 4: Ferramentas e validação (crictl)

4.1 Instale o cri-tools (crictl)

Recomendamos que a versão do crictl acompanhe a do CRI-O para evitar incompatibilidades. No exemplo, v1.34.0.

export VERSION="v1.34.0" wget https://github.com/kubernetes-sigs/cri-tools/releases/download/$VERSION/crictl-$VERSION-linux-amd64.tar.gz

Extraia em /usr/local/bin e copie para /usr/bin.

sudo tar zxvf crictl-$VERSION-linux-amd64.tar.gz -C /usr/local/bin sudo cp /usr/local/bin/crictl /usr/bin/

Valide a versão e o endpoint do CRI-O:

sudo crictl --runtime-endpoint unix:///var/run/crio/crio.sock version crictl --version

Verifique se Runtime e Network aparecem como Ready no crictl info (vamos inspecionar o final da saída):

sudo crictl info | tail -20

4.2 Teste prático: criando um Pod Sandbox e um container Nginx via JSON

Este teste valida o fluxo completo: criação do Pod Sandbox, pull de imagem e start de container. Ele também ajuda a isolar problemas de rede (CNI), permissões e runtime.

Crie o arquivo nginx-pod.json:

vi nginx-pod.json

Conteúdo:

{ "metadata": { "name": "nginx-pod", "namespace": "default", "attempt": 1, "uid": "nginx-pod-uid" }, "linux": {} }

Crie o sandbox do Pod e capture o ID:

POD_ID=$(sudo crictl runp nginx-pod.json)

Liste os Pods:

sudo crictl pods

Crie o arquivo nginx-container.json:

vi nginx-container.json

Conteúdo:

{ "metadata": { "name": "nginx" }, "image": { "image": "docker.io/library/nginx:latest" }, "log_path": "nginx.log", "linux": { "security_context": { "privileged": false } }, "port_mappings": [ { "container_port": 80, "protocol": "TCP" } ] }

Crie o container dentro do Pod, com pull de imagem, e capture o ID:

CONTAINER_ID=$(sudo crictl create --with-pull $POD_ID nginx-container.json nginx-pod.json)

Inicie o container:

sudo crictl start $CONTAINER_ID

Confirme o estado:

sudo crictl ps

Veja logs do Nginx:

sudo crictl logs $CONTAINER_ID

Inspecione o Pod para obter o IP (no exemplo, vamos usar --output table e filtra o topo). Substitua o identificador pelo ID real que você tem.

sudo crictl inspectp --output table $POD_ID | head

Teste com curl contra o IP do Pod:

curl -I <IP_DO_POD>

Se o retorno HTTP aparecer, você validou que o sandbox, a rede CNI e o container estão operacionais.

4.3 Limpeza do ambiente de teste

Finalize o container e o Pod Sandbox:

sudo crictl stop $CONTAINER_ID sudo crictl rm $CONTAINER_ID sudo crictl stopp $POD_ID sudo crictl rmp $POD_ID