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.341.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 EOF1.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/configPasso 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 crioVerifique se o serviço está ativo.
sudo systemctl status crio2.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}.tgzAtive 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.conflistReinicie o serviço para aplicar as mudanças.
sudo systemctl restart crioPasso 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.confConteúdo:
[crio.runtime] enable_devices = falseReinicie o CRI-O:
sudo systemctl restart crioPasso 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.gzExtraia 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 --versionVerifique se Runtime e Network aparecem como Ready no crictl info (vamos inspecionar o final da saída):
sudo crictl info | tail -204.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.jsonConteú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 podsCrie o arquivo nginx-container.json:
vi nginx-container.jsonConteú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_IDConfirme o estado:
sudo crictl psVeja logs do Nginx:
sudo crictl logs $CONTAINER_IDInspecione 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 | headTeste 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