Post

Kubernetes: Instalação no Debian 13 com CRI-O e Calico - Parte 1

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

HostnamevCPUMemóriaIPv4IPv6Papel
kube-ctrl-0148 GB10.16.47.2fd00:0:0:4::2Control Plane
kube-wk-0148 GB10.16.47.10fd00:0:0:4::10Worker
kube-wk-0248 GB10.16.47.11fd00:0:0:4::11Worker

1.2 Redes do Kubernetes

TipoIPv4IPv6
Pod Network10.80.0.0/16fd00:0:0:100::/56
Service Network10.96.0.0/16fd00:0:0:f800::/108
MetalLB10.16.47.208/28fd00::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.yaml para 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.yaml para 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 ObservadoProblemaCausa ProvávelSolução
Nós com status NotReadyNetworking não configuradoCalico não foi implantado.Execute kubectl apply -f custom-resources.yaml e aguarde a implantação.
Pods não conseguem se comunicarFirewall bloqueandoPortas de rede não abertas entre nós.Verifique regras de firewall e abra portas 6443, 10250, 4789 (VXLAN).
CRI-O não iniciaMódulos de kernel não carregadosMódulos overlay e br_netfilter não presentes.Execute sudo modprobe overlay e sudo modprobe br_netfilter.
Kubeadm init falhaDisco cheioPartição raiz sem espaço.Verifique espaço com df -h e libere espaço se necessário.
Workers não conseguem fazer joinToken expiradoToken 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


Referências

This post is licensed under CC BY 4.0 by the author.