Pular para o conteúdo principal

O K8S

Este texto nasceu após o meu primeiro k8s de produção, sem antes ter feito em bancada, como a curva de aprendizado foi rápida, decidi montar um lab baseado na experiencia que tive, documentando a montagem de um cluster multimaster em Ubuntu 22.04 usando containerd, Calico, MetalLB e ingress-nginx

Os possas seguidos aqui, podem facilmente ser replicados para produção.

Requisitos base

3 mastergarante quórum no etcd e alta disponibilidade do plano de controle: se um nó cair, os outros dois ainda formam maioria e mantêm o cluster operante.

2 workerpara garantir um cluster altamente disponivel, um worker pode parar que o outro continua servindo aplicações.

O mínimo a ser feito

Quando comento com o mínimo, me refiro ao básico que precisa ser feito para que comecemos a instalação e configuração do k8s, seguindo um processo lógico/pratico.

  • Configurar ntpd
  • Configurar SSSD (integração com AD ou LDAP)se tiver
  • Configurar agente de monitoramentose tiver
  • SSH
  • Sudoers
  • Grupos
  • Usuários
  • Permissões

Preparando o Linux

Dividi em três seções:

  • Passos para todos os nós
  • Passos para os masters
  • Passos para os workers

Passos para todos os nós

Verificar MAC address: Não pode ter mac duplicado

ip link show

Verificar UUID da máquina: Assim como o mac o UUID da maquinda deve ser unico

cat /etc/machine-id

Caso tenha duplicidade, basta executar para regerar:

rm -f /etc/machine-id
systemd-machine-id-setup

Desativar o swap:

# Verificando
swapon -s

# Desativando
sudo swapoff -a

# Removendo do fstab
sudo sed -i '/swap/d' /etc/fstab

para utilizar a swap, necessário configurar seguinte parâmetro:
No kubelet (/etc/default/kubelet), adicionar
failSwapOn: false
ou configurar swapBehavior.

Se tiver um arquivo /swap.img no sistema, apague também, pois isso é um arquivo e ocupa bastante espaço dependendo do tamanho.

Ativando overlay e br_netfilter

  • OverlayFS: sistema de arquivos em camadas. Escreve por cima, sem mexer na base. Requisito para os containers (docs)
  • br_netfilter: permite que o tráfego de uma bridge passe pelo netfilter, possibilitando a gerência das interfaces de rede dos containers (docs)

Ativando os módulos no boot:

cat <<EOF | sudo tee /etc/modules-load.d/k8s.conf
overlay
br_netfilter
EOF

Carregando os módulos:

sudo modprobe overlay
sudo modprobe br_netfilter

Verificando os módulos:

lsmod | grep overlay
lsmod | grep br_netfilter

Parâmetros de rede

Por padrão, o Linux ignora o tráfego que passa por bridges. Só que o CNI (plugin de rede) do Kubernetes precisa ver esse tráfego pra funcionar.

Ativando o monitoramento do trafego

cat <<EOF | sudo tee /etc/sysctl.d/k8s.conf
net.bridge.bridge-nf-call-iptables = 1
net.ipvip_forward = 1
net.bridge.bridge-nf-call-ip6tables = 1
EOF

Ativando sem precisar reiniciar o ambiente:

sudo sysctl --system

Configuração dos repositórios necessários

Para o lab, foi necessário instalar as seguintes ferramentas:

  • apt-transport-https: Utiliza repositórios HTTPS, garantindo downloads mais seguros
  • ca-certificates: Gerencia certificados digitais para conexões HTTPS
  • curl: Baixa arquivos e dados via terminal
  • gpg e gnupg2: Gerenciam chaves criptográficas
  • software-properties-common: Ferramenta para adicionar repositórios externos (add-apt-repository)
sudo apt update
sudo apt install -y apt-transport-https ca-certificates curl gpg gnupg2 software-properties-common

Criando a pasta para armazenar as chaves GPG:

sudo mkdir -p /etc/apt/keyrings

Adicionando o repositório Docker no Ubuntu:

curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg

echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu $(. /etc/os-release && echo "$VERSION_CODENAME") stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null

Adicionando o repositório do Kubernetes (v31):

sudo curl -fsSL https://pkgs.k8s.io/core:/stable:/v31/deb/Release.key | sudo gpg --dearmor -o /etc/apt/keyrings/kubernetes-apt-keyring.gpg

echo "deb [signed-by=/etc/apt/keyrings/kubernetes-apt-keyring.gpg] https://pkgs.k8s.io/core:/stable:/v31/deb/ /" | sudo tee /etc/apt/sources.list.d/kubernetes.list > /dev/null

Atualizando a base de pacotes:

sudo apt update

Instalar containerd

sudo apt install -y containerd.io

containerd.io: Runtime utilizado pelo Kubernetes para gerenciar e executar containers.

Configurar o containerd

O containerd é o runtime de containers utilizado pelo Kubernetes para gerenciar a execução de containers em cada nó. Para garantir compatibilidade com o kubelet, é necessário configurar o uso de cgroups com systemd.

Passos:

sudo mkdir -p /etc/containerd

containerd config default | sudo tee /etc/containerd/config.toml > /dev/null

sudo sed -i 's/SystemdCgroup = false/SystemdCgroup = true/' /etc/containerd/config.toml

[!NOTE]
Essa alteração é necessária para que o kubelet funcione corretamente com o containerd em sistemas que utilizam o systemd como gerenciador de serviços (como Ubuntu e Debian). Sem isso, o Kubernetes pode falhar ao iniciar os pods.

Na sequência, o serviço do containerd pode ser iniciado e habilitado com:

sudo systemctl restart containerd
sudo systemctl enable containerd

Resumo dos comandos

Todos os comandos desta etapa
# Verificar MAC address
ip link show

# Verificar UUID da máquina
cat /etc/machine-id

# Caso alguma máquina esteja com o mesmo ID
rm -f /etc/machine-id
systemd-machine-id-setup

# Verificar swap
swapon -s

# Desativar swap
sudo swapoff -a

# Remover swap do fstab
sudo sed -i '/swap/d' /etc/fstab

# (Opcional) Apagar o arquivo de swap se existir
sudo rm -f /swap.img

# Configuração para carregar módulos no boot
cat <<EOF | sudo tee /etc/modules-load.d/k8s.conf
overlay
br_netfilter
EOF

# Carregando os modulos
sudo modprobe overlay
sudo modprobe br_netfilter

# Verificação dos módulos
lsmod | grep overlay
lsmod | grep br_netfilter

# Parâmetros para redirecionamento e inspeção de tráfego bridge
cat <<EOF | sudo tee /etc/sysctl.d/k8s.conf
net.bridge.bridge-nf-call-iptables = 1
net.ipvip_forward = 1
net.bridge.bridge-nf-call-ip6tables = 1
EOF

# Aplicar as configurações sem precisa reiniciar
sudo sysctl --system

Passos para os masters

Este lab foi montado com a versão 1.38.

Isso é importante, pois na hora de instalar os pacotes, precisamos garantir que isso seja cumprido corretamente para não ter nenhuma situação inesperada que se torne um impeditivo no futuro.

ComponenteVersãoDetalhes
kube-apiserverv3xTodos os nós de controle (masters) devem rodar exatamente essa versão
kube-controller-managerv3xDeve estar sincronizado com o kube-apiserver
kube-schedulerv3xTambém deve estar na mesma versão
kubeletv30.x ou v3xPode estar até uma versão menor atrás, mas nunca à frente
kube-proxyv30.x, v3x, v3xPode estar até uma versão acima ou abaixo
kubectlv30.x, v3x, v3xFlexível para facilitar administração de diferentes clusters
kubeadmv3xUse a mesma versão do cluster desejado (neste caso, v3x)

Referência: Version skew policy | Kubernetes

Instalar e configurar os componentes principais do Kubernetes

sudo apt install -y  kubectl
apt-mark hold kubelet
systemctl enable kubelet
  • kubelet: Agente que roda em todos os nós, responsável por garantir que os containers estejam em execução conforme definido

Inicializando o cluster

Aqui é onde vem uma "pegada" minha para organização, o k8s no geral pede para baixar os arquivos e ir fazendo o kubectl apply -f qualquercoisa.yml mas com isso o ambiente fica muito desorganizado, aqui vai uma proposta para melhorar isso.

mkdir -p k8s/base/calico \
k8s/base/metallb \
k8s/base/ippool \
k8s/base/networkpolicy \
k8s/base/rbac \
k8s/namespaces/devops/networkpolicy \
k8s/namespaces/devops/rbac \
k8s/namespaces/sistema-x-prod/networkpolicy \
k8s/namespaces/sistema-x-prod/rbac \
k8s/namespaces/modelo/networkpolicy \
k8s/namespaces/modelo/rbac \
k8s/scripts

Assim cada yml utilizado fica no seu lugar, de forma organizada.

Com isto, vamos começar a realizar o download dos ymls e preparar as coisas, aqui apenas fiz o download dos arquivos para depois aplicar as configurações no cluster

**CNI*Calico

curl -sSL https://raw.githubusercontent.com/projectcalico/calico/v27.0/manifests/calico.yaml -o "/etc/k8s/calico/calico.yaml"

CNIPool Calico

cat <<EOF > "/etc/k8s/ippool/default-ippool.yaml"
allation/api#operator.tigera.io/vInstallation
apiVersion: operator.tigera.io/v1
kind: Installation
metadata:
name: default
spec:
# Configures Calico networking.
calicoNetwork:
ipPools:
name: default-ipv4-ippool
blockSize: 26
cidr: 10.240.0/16
encapsulation: VXLANCrossSubnet
natOutgoing: Enabled
nodeSelector: all()

MetalLB

curl -sSL https://raw.githubusercontent.com/metallb/metallb/v0.19/config/manifests/metallb-native.yaml  -o "/etc/k8s/metallb/metallb-native.yaml

**Ingress*Nginx

curl -sSL https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v12/deploy/static/provider/cloud/deploy.yaml  -o "/etc/k8s/ingress/nginx_deploy.yaml

Baixando as imagens para o containerd

kubeadm config images pull --cri-socket unix:///var/run/containerd/containerd.sock

Inicializando o cluster Atenção ao podnetwork, quando iniciar o calico, precisará utilizar a mesma subnet, caso contrario os pods não inicializarão.

kubeadm init --pod-network-cidr=10.240.0/16 --cri-socket unix:///var/run/containerd/containerd.sock --v=5

Configurando kubectl para conectar no cluster

mkdir -p $HOME/.kube
cp /etc/kubernetes/admin.conf $HOME/.kube/config
chown $(id -u):$(id -g) $HOME/.kube/config

verificando cluster

kubectl get nodes

Configurando o cluster

kubectl get nodes

Passos para os workers

Os workers são os que menos dão trabalho, pois basicamente precisamos instalar o containerd, kubelet e kubeadm e depois incluir no cluster.