Kubernetes: Instalação no Debian 13 com CRI-O e Calico - Parte 1
Introdução
Este tutorial é a Parte 1 de uma série completa sobre implementação de Kubernetes em ambientes on-premises. Aqui, vamos construir a base de um cluster Kubernetes robusto, com suporte completo a dual-stack (IPv4 e IPv6), usando CRI-O como container runtime e Calico para networking avançado.
O que será visto nesta parte
- Planejamento de Infraestrutura: Especificação de nós, redes e armazenamento.
- Preparação dos Nós: Configuração de hostname, discos adicionais e LVM.
- Instalação do CRI-O: Container runtime compatível com Kubernetes.
- Instalação do Kubernetes: Componentes kubelet, kubeadm e kubectl.
- Inicialização do Cluster: Configuração do nó de controle (control plane).
- Adição de Workers: Integração dos nós de trabalho.
- Networking com Calico: Configuração de rede dual-stack com políticas de rede.
Pré-requisitos
- Três máquinas virtuais ou físicas com Debian 13 instalado.
- Acesso root ou sudo em todas as máquinas.
- Conectividade de rede entre todos os nós.
- Pelo menos 4 vCPUs e 8 GB de RAM por nó.
- Hypervisor KVM (para criação de discos adicionais).
1. Planejamento de Infraestrutura
1.1 Especificação dos Nós
| Hostname | vCPU | Memória | IPv4 | IPv6 | Papel |
|---|---|---|---|---|---|
| kube-ctrl-01 | 4 | 8 GB | 10.16.47.2 | fd00:0:0:4::2 | Control Plane |
| kube-wk-01 | 4 | 8 GB | 10.16.47.10 | fd00:0:0:4::10 | Worker |
| kube-wk-02 | 4 | 8 GB | 10.16.47.11 | fd00:0:0:4::11 | Worker |
1.2 Redes do Kubernetes
| Tipo | IPv4 | IPv6 |
|---|---|---|
| Pod Network | 10.80.0.0/16 | fd00:0:0:100::/56 |
| Service Network | 10.96.0.0/16 | fd00:0:0:f800::/108 |
| MetalLB | 10.16.47.208/28 | fd00::4:1000:0:0:70/124 |
1.3 Armazenamento Adicional
Cada nó requer uma partição adicional para o container runtime (CRI-O):
- Ponto de Montagem:
/var/lib/containers - Tamanho: 32 GB por nó
- Tipo: Partição LVM com filesystem ext4
1.4 Infraestrutura de Virtualização
Nota: Para esta implementação foi usado o KVM para montar a infraestrutura.
2. Preparação dos Nós
2.1 Definição de Hostname
Configure o hostname em cada nó:
1
2
3
4
5
6
7
8
# Em kube-ctrl-01
sudo hostnamectl set-hostname kube-ctrl-01.lab4it.com.br
# Em kube-wk-01
sudo hostnamectl set-hostname kube-wk-01.lab4it.com.br
# Em kube-wk-02
sudo hostnamectl set-hostname kube-wk-02.lab4it.com.br
2.2 Criação de Disco Adicional (Hypervisor KVM)
No hypervisor, crie volumes de disco para cada nó:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
# Criar volumes de disco
sudo virsh vol-create-as --pool images --name kube-ctrl-01-vdb.img --capacity 32G --format raw
sudo virsh vol-create-as --pool images --name kube-wk-01-vdb.img --capacity 32G --format raw
sudo virsh vol-create-as --pool images --name kube-wk-02-vdb.img --capacity 32G --format raw
# Anexar discos às máquinas virtuais
sudo virsh attach-disk kube-ctrl-01 /datastore/images/kube-ctrl-01-vdb.img vdb --targetbus virtio --persistent
sudo virsh attach-disk kube-wk-01 /datastore/images/kube-wk-01-vdb.img vdb --targetbus virtio --persistent
sudo virsh attach-disk kube-wk-02 /datastore/images/kube-wk-02-vdb.img vdb --targetbus virtio --persistent
# Verificar discos anexados
sudo virsh domblklist kube-ctrl-01
sudo virsh domblklist kube-wk-01
sudo virsh domblklist kube-wk-02
2.3 Configuração de Armazenamento em Cada Nó
Execute os seguintes comandos em todos os nós para configurar o disco adicional com LVM:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
# Definir variáveis
MOUNT_POINT=/var/lib/containers
DISK_DEVICE=/dev/vdb
# Criar volume físico e grupo de volume
sudo pvcreate ${DISK_DEVICE}
sudo vgcreate vg_containers ${DISK_DEVICE}
# Criar volume lógico e filesystem
sudo lvcreate -l 100%FREE -n lv_containers vg_containers
sudo mkfs.ext4 /dev/mapper/vg_containers-lv_containers
# Criar ponto de montagem
sudo mkdir ${MOUNT_POINT}
# Backup e configuração do fstab
sudo cp -p /etc/fstab{,.dist}
echo "/dev/mapper/vg_containers-lv_containers /var/lib/containers ext4 defaults,noatime 1 2" | sudo tee -a /etc/fstab
# Recarregar daemon e montar
sudo systemctl daemon-reload
sudo mount ${MOUNT_POINT}
# Verificar montagem
df -hT | grep containers
Saída esperada:
1
/dev/mapper/vg_containers-lv_containers ext4 32G 2.1M 30G 1% /var/lib/containers
3. Instalação do CRI-O
3.1 Carregamento de Módulos de Kernel
CRI-O requer alguns módulos de kernel para funcionar corretamente. Configure-os em todos os nós:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# Criar arquivo de configuração de módulos
cat <<EOF | sudo tee /etc/modules-load.d/crio.conf
overlay
br_netfilter
EOF
# Carregar módulos imediatamente
sudo modprobe overlay
sudo modprobe br_netfilter
# Persistir módulos
echo "overlay" | sudo tee -a /etc/modules
echo "br_netfilter" | sudo tee -a /etc/modules
# Verificar se os módulos foram carregados
lsmod | grep br_netfilter
lsmod | grep overlay
3.2 Configuração de Parâmetros do Kernel
Configure os parâmetros de rede necessários para o Kubernetes:
1
2
3
4
5
6
7
8
9
10
# Criar arquivo de configuração sysctl
cat <<EOF | sudo tee /etc/sysctl.d/99-kubernetes-cri.conf
net.ipv4.conf.all.forwarding = 1
net.ipv6.conf.all.forwarding = 1
net.bridge.bridge-nf-call-iptables = 1
net.bridge.bridge-nf-call-ip6tables = 1
EOF
# Aplicar configurações
sudo sysctl --system
3.3 Instalação do CRI-O
Defina as versões desejadas e instale o CRI-O em todos os nós:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
# Definir versões
KUBERNETES_VERSION=v1.35
CRIO_VERSION=v1.35
# Atualizar lista de pacotes
sudo apt-get update
sudo apt-get install -y apt-transport-https ca-certificates curl gnupg
# Adicionar chave de assinatura do repositório CRI-O
curl -fsSL https://download.opensuse.org/repositories/isv:/cri-o:/stable:/$CRIO_VERSION/deb/Release.key |
sudo gpg --dearmor -o /etc/apt/keyrings/cri-o-apt-keyring.gpg
# Adicionar repositório CRI-O
echo "deb [signed-by=/etc/apt/keyrings/cri-o-apt-keyring.gpg] https://download.opensuse.org/repositories/isv:/cri-o:/stable:/$CRIO_VERSION/deb/ /" |
sudo tee /etc/apt/sources.list.d/cri-o.list
# Instalar CRI-O
sudo apt update
sudo apt install -y cri-o
# Verificar versão instalada
apt show cri-o
4. Instalação do Kubernetes
4.1 Desabilitar Swap
O Kubernetes requer que o swap esteja desabilitado em todos os nós:
1
2
3
4
5
6
# Desabilitar swap imediatamente
sudo swapoff -a
# Remover swap do fstab para desabilitar permanentemente
sudo cp -fp /etc/fstab{,.dist}
sudo sed -i '/swap/d' /etc/fstab
4.2 Instalação de Componentes Kubernetes
Execute em todos os nós:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# Adicionar chave de assinatura do repositório Kubernetes
curl -fsSL https://pkgs.k8s.io/core:/stable:/$KUBERNETES_VERSION/deb/Release.key |
sudo gpg --dearmor -o /etc/apt/keyrings/kubernetes-apt-keyring.gpg
# Adicionar repositório Kubernetes
echo "deb [signed-by=/etc/apt/keyrings/kubernetes-apt-keyring.gpg] https://pkgs.k8s.io/core:/stable:/$KUBERNETES_VERSION/deb/ /" |
sudo tee /etc/apt/sources.list.d/kubernetes.list
# Instalar kubelet, kubeadm e kubectl
sudo apt update
sudo apt install -y kubelet kubeadm kubectl
# Fixar versão (evita atualizações automáticas)
sudo apt-mark hold kubelet kubeadm kubectl
# Recarregar daemon do systemd
sudo systemctl daemon-reload
4.3 Inicialização dos Serviços
Execute em todos os nós:
1
2
3
4
5
6
7
8
# Habilitar e iniciar CRI-O
sudo systemctl enable crio --now
# Verificar status do CRI-O
sudo systemctl status crio
# Habilitar kubelet (será iniciado após kubeadm init)
sudo systemctl enable kubelet
5. Configuração do Nó de Controle (kube-ctrl-01)
5.1 Download de Imagens
Antes de inicializar o cluster, faça download das imagens necessárias:
1
sudo kubeadm config images pull
Saída esperada:
1
2
3
4
5
6
7
[config/images] Pulled registry.k8s.io/kube-apiserver:v1.35.0
[config/images] Pulled registry.k8s.io/kube-controller-manager:v1.35.0
[config/images] Pulled registry.k8s.io/kube-scheduler:v1.35.0
[config/images] Pulled registry.k8s.io/kube-proxy:v1.35.0
[config/images] Pulled registry.k8s.io/coredns/coredns:v1.13.1
[config/images] Pulled registry.k8s.io/pause:3.10.1
[config/images] Pulled registry.k8s.io/etcd:3.6.6-0
Verifique as imagens baixadas:
1
sudo crictl image
5.2 Criação do Arquivo de Configuração
Crie um diretório para armazenar os arquivos de configuração:
1
2
mkdir -p ~/artefacts/yaml/config
cd ~/artefacts/yaml/config
Crie o arquivo kubeadm-config.yaml:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
apiVersion: kubeadm.k8s.io/v1beta4
kind: InitConfiguration
localAPIEndpoint:
advertiseAddress: 10.16.47.2
bindPort: 6443
nodeRegistration:
criSocket: unix:///var/run/crio/crio.sock
kubeletExtraArgs:
- name: node-ip
value: 10.16.47.2,fd00:0:0:4::2
name: kube-ctrl-01
---
apiVersion: kubeadm.k8s.io/v1beta4
clusterName: kubernetes
kind: ClusterConfiguration
kubernetesVersion: 1.35.0
networking:
dnsDomain: cluster.local
podSubnet: 10.80.0.0/16,fd00:0:0:100::/56
serviceSubnet: 10.96.0.0/16,fd00:0:0:f800::/108
Dica: Use
kubeadm config print init-defaults > kubeadm-config.yamlpara gerar um arquivo base com todas as opções disponíveis.
5.3 Inicialização do Cluster
1
sudo kubeadm init --config=kubeadm-config.yaml
Após a conclusão bem-sucedida, você verá uma mensagem contendo o comando para adicionar workers:
1
2
3
4
5
6
7
8
9
10
11
12
Your Kubernetes control-plane has initialized successfully!
To start using your cluster, you need to run the following as a regular user:
mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config
Then you can join any number of worker nodes by running the following on each as root:
kubeadm join 10.16.47.2:6443 --token qlu8mn.8sd2iqpmrbl5es42 \
--discovery-token-ca-cert-hash sha256:9f9acd0000d613b9cabe39ebaa387e2331118f08e4195f660ec7df939b83980a
5.4 Configuração do kubectl
Configure o acesso ao cluster para o usuário atual:
1
2
3
mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config
5.5 Configuração de Autocompletar
Instale bash completion para os comandos do Kubernetes:
1
2
3
4
5
6
7
8
9
10
# Instalar bash-completion se não estiver presente
sudo apt install -y bash-completion
# Gerar arquivos de autocompletar
sudo sh -c 'kubeadm completion bash > /etc/bash_completion.d/kubeadm'
sudo sh -c 'kubectl completion bash > /etc/bash_completion.d/kubectl'
sudo sh -c 'crictl completion bash > /etc/bash_completion.d/crictl'
# Carregar autocompletar no shell atual
source /usr/share/bash-completion/bash_completion
6. Adição de Nós de Trabalho
6.1 Configuração do kube-wk-01
Em kube-wk-01, crie o arquivo de configuração kubeadm-config.yaml:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
apiVersion: kubeadm.k8s.io/v1beta4
discovery:
bootstrapToken:
apiServerEndpoint: 10.16.47.2:6443
caCertHashes:
- sha256:9f9acd0000d613b9cabe39ebaa387e2331118f08e4195f660ec7df939b83980a
token: qlu8mn.8sd2iqpmrbl5es42
tlsBootstrapToken: qlu8mn.8sd2iqpmrbl5es42
kind: JoinConfiguration
nodeRegistration:
criSocket: unix:///var/run/crio/crio.sock
kubeletExtraArgs:
- name: node-ip
value: 10.16.47.10,fd00:0:0:4::10
name: kube-wk-01
Dica: Use
kubeadm config print join-defaults > kubeadm-config.yamlpara gerar um arquivo base.
Execute o join:
1
sudo kubeadm join --config=kubeadm-config.yaml
6.2 Configuração do kube-wk-02
Repita o processo para kube-wk-02, alterando apenas o endereço IP:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
apiVersion: kubeadm.k8s.io/v1beta4
discovery:
bootstrapToken:
apiServerEndpoint: 10.16.47.2:6443
caCertHashes:
- sha256:9f9acd0000d613b9cabe39ebaa387e2331118f08e4195f660ec7df939b83980a
token: qlu8mn.8sd2iqpmrbl5es42
tlsBootstrapToken: qlu8mn.8sd2iqpmrbl5es42
kind: JoinConfiguration
nodeRegistration:
criSocket: unix:///var/run/crio/crio.sock
kubeletExtraArgs:
- name: node-ip
value: 10.16.47.11,fd00:0:0:4::11
name: kube-wk-02
Execute o join:
1
sudo kubeadm join --config=kubeadm-config.yaml
7. Configuração de Networking com Calico
7.1 Implantação do Operador Calico
Crie os Custom Resource Definitions (CRDs) do Calico:
1
kubectl create -f https://raw.githubusercontent.com/projectcalico/calico/v3.31.3/manifests/operator-crds.yaml
Implante o operador Calico:
1
kubectl create -f https://raw.githubusercontent.com/projectcalico/calico/v3.31.3/manifests/tigera-operator.yaml
7.2 Definição de Recursos Personalizados do Calico
Crie o arquivo custom-resources.yaml:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
apiVersion: operator.tigera.io/v1
kind: Installation
metadata:
name: default
spec:
calicoNetwork:
ipPools:
- name: default-ipv4-ippool
blockSize: 26
cidr: 10.80.0.0/16
encapsulation: VXLANCrossSubnet
natOutgoing: Enabled
nodeSelector: all()
- name: default-ipv6-ippool
cidr: fd00:0:0:100::/56
encapsulation: VXLANCrossSubnet
natOutgoing: Enabled
nodeSelector: all()
---
apiVersion: operator.tigera.io/v1
kind: APIServer
metadata:
name: default
spec: {}
---
apiVersion: operator.tigera.io/v1
kind: Goldmane
metadata:
name: default
---
apiVersion: operator.tigera.io/v1
kind: Whisker
metadata:
name: default
Aplique os recursos:
1
kubectl apply -f custom-resources.yaml
7.3 Verificação da Implantação
Verifique se todos os pods estão em execução:
1
kubectl get pod --all-namespaces -o wide
Verifique o status dos nós:
1
kubectl get nodes -o wide
Saída esperada:
1
2
3
4
NAME STATUS ROLES AGE VERSION INTERNAL-IP EXTERNAL-IP OS-IMAGE KERNEL-VERSION CONTAINER-RUNTIME
kube-ctrl-01 Ready control-plane 8m13s v1.35.0 10.16.47.2 <none> Debian GNU/Linux 13 (trixie) 6.12.63+deb13-amd64 cri-o://1.35.0
kube-wk-01 Ready <none> 5m51s v1.35.0 10.16.47.10 <none> Debian GNU/Linux 13 (trixie) 6.12.63+deb13-amd64 cri-o://1.35.0
kube-wk-02 Ready <none> 4m59s v1.35.0 10.16.47.11 <none> Debian GNU/Linux 13 (trixie) 6.12.63+deb13-amd64 cri-o://1.35.0
8. Solucionando Problemas Comuns
| Sintoma Observado | Problema | Causa Provável | Solução |
|---|---|---|---|
Nós com status NotReady | Networking não configurado | Calico não foi implantado. | Execute kubectl apply -f custom-resources.yaml e aguarde a implantação. |
| Pods não conseguem se comunicar | Firewall bloqueando | Portas de rede não abertas entre nós. | Verifique regras de firewall e abra portas 6443, 10250, 4789 (VXLAN). |
| CRI-O não inicia | Módulos de kernel não carregados | Módulos overlay e br_netfilter não presentes. | Execute sudo modprobe overlay e sudo modprobe br_netfilter. |
| Kubeadm init falha | Disco cheio | Partição raiz sem espaço. | Verifique espaço com df -h e libere espaço se necessário. |
| Workers não conseguem fazer join | Token expirado | Token de bootstrap expirou (24 horas). | Gere novo token com kubeadm token create --print-join-command. |
Conclusão
Você agora possui um cluster Kubernetes funcional com suporte completo a dual-stack (IPv4 e IPv6), usando CRI-O como container runtime e Calico para networking avançado. O cluster está pronto para executar cargas de trabalho.
Na Parte 2, vamos adicionar MetalLB para load balancing e Gateway API para roteamento avançado de tráfego.
Próximos Passos
Clique aqui para ir para Kubernetes: Configuração do MetalLB e do Gateway API - Parte 2