Preparação do Ambiente e Virtualização KVM
O ambiente de implantação consiste em máquinas virtuais Debian 12 (Bookworm), utilizando containerd como Container Runtime Interface (CRI), Calico como Container Network Interface (CNI) e Kubernetes na versão 1.27.10.
Inicialmente, valide se o processador do host físico suporta virtualização de hardware:
grep -wE '(vmx|svm)' /proc/cpuinfo
Instale os pacotes fundamentais para criação e gerenciamento de máquinas virtuais:
apt update
apt install -y qemu-kvm libvirt-daemon-system libvirt-clients virtinst guestfs-tools
Após a instalação, inicie o serviço libvirtd. Baixe a imagem qcow2 do Debian 12 e configure o disco virtual conforme a necessidade de expansão. Para instanciar as VMs, utilize o virt-install. Como a versão 4.1.0 do virt-install pode não reconhecer nativamente o Debian 12, utilize parâmetros genéricos:
virt-install --name k8s-cp1 --os-type linux --os-variant generic --disk ...
Para redimensionar recursos dinamicamente em VMs em execução, utilize comandos como virsh setvcpus e virsh setmem. Caso a VM não suporte redimensionamento a quente, desligue-a, edite o XML com virsh edit e ligue-a novamente.
Confgiuração de Rede e Acesso Externo
Por padrão, as VMs recém-criadas não possuem acesso à internet. Configure regras de NAT no host físico para permitir a saída de tráfego da sub-rede das VMs:
sysctl -w net.ipv4.ip_forward=1
echo "net.ipv4.ip_forward=1" > /etc/sysctl.d/99-k8s.conf
iptables -t nat -A POSTROUTING -s 192.168.100.0/24 -o eth0 -j MASQUERADE
apt install iptables-persistent -y
netfilter-persistent save
Automação de Provisionamento das VMs
Instale os pacotes necessários no host para automação das configurações nas VMs:
apt -y install sshpass git python3-pip
Gere chaves SSH e distribua para os nós do cluster:
ssh-keygen -t rsa -N '' -f ~/.ssh/k8s_id -b 2048
for i in {1..3}; do
sshpass -p'K8sPass' ssh-copy-id -i ~/.ssh/k8s_id.pub k8s-cp$i
sshpass -p'K8sPass' ssh-copy-id -i ~/.ssh/k8s_id.pub k8s-wk$i
done
Configure os endereços IP estáticos, gateways e DNS nas VMs usando o NetworkManager:
for i in {1..3}; do
ssh k8s-cp$i "nmcli con modify eth0 ipv4.addresses 192.168.100.1$i/24 ipv4.gateway 192.168.100.1 ipv4.method manual ipv4.dns 8.8.8.8 +ipv4.dns 1.1.1.1"
ssh k8s-wk$i "nmcli con modify eth0 ipv4.addresses 192.168.100.2$i/24 ipv4.gateway 192.168.100.1 ipv4.method manual ipv4.dns 8.8.8.8 +ipv4.dns 1.1.1.1"
ssh k8s-cp$i "nmcli con reload && nmcli con up eth0"
ssh k8s-wk$i "nmcli con reload && nmcli con up eth0"
done
Atualize os repositórios APT e instale utilitários básicos nas VMs:
for i in {1..3}; do
ssh k8s-cp$i "apt update && apt -y install vim bash-completion network-manager net-tools"
ssh k8s-wk$i "apt update && apt -y install vim bash-completion network-manager net-tools"
done
Execução do Kubespray
Clone o repositório do Kubespray e prepare o inventário Ansible:
git clone -b release-2.23 https://github.com/kubernetes-sigs/kubespray.git
cd kubespray/
echo "ansible_ssh_pass: K8sPass" >> inventory/sample/group_vars/all/all.yml
Defina a topologia do cluster no arquivo de inventário:
cat > inventory/sample/inventory.ini <<EOF
[all]
k8s-cp1 ansible_host=192.168.100.11
k8s-cp2 ansible_host=192.168.100.12
k8s-cp3 ansible_host=192.168.100.13
k8s-wk1 ansible_host=192.168.100.21
k8s-wk2 ansible_host=192.168.100.22
k8s-wk3 ansible_host=192.168.100.23
[kube_control_plane]
k8s-cp1
k8s-cp2
k8s-cp3
[etcd]
k8s-cp1
k8s-cp2
k8s-cp3
[kube_node]
k8s-cp1
k8s-cp2
k8s-cp3
k8s-wk1
k8s-wk2
k8s-wk3
[k8s_cluster:children]
kube_control_plane
kube_node
EOF
Para evitar conflitos com pacotes Python do sistema operacional, crie um ambiente virtual para executar o playbook do Ansible:
python3 -m venv venv
source venv/bin/activate
pip install -r requirements.txt
ansible-playbook -i inventory/sample/inventory.ini cluster.yml -u root --private-key=~/.ssh/k8s_id -v
Operações Básicas com Pods
Após a conclusão da implantação, verifique o estado do cluster:
kubectl get nodes
kubectl get pods -A
Principais comandos para manipulação de Pods:
kubectl describe pod <nome> -n <namespace>: Detalha eventos e condições do Pod.kubectl run <nome> --image=<imagem>: Cria um Pod de teste.kubectl delete pod <nome>: Remove o Pod.kubectl logs <nome>: Exibe os logs do contêiner.kubectl exec -it <nome> -- /bin/sh: Acessa o terminal do contêiner.
No ecossistema de contêineres, ferramentas como crictl, nerdctl e ctr permitem a interação direta com o containerd. Um Pod pode conter contêineres do tipo Pause (Infra), Init, aplicação principal, Sidecar e Ephemeral.
A política de obtenção de imagens (imagePullPolicy) suporta três estados: Always, IfNotPresent (padrão para tags fixas) e Never. Já a política de reinício (restartPolicy) define o comportamento diante de falhas, sendo Always o padrão, além de OnFailure e Never.
Configuração de Alta Disponibilidade (HA)
O Kubespray configura o endpoint do kube-apiserevr localmente em 127.0.0.1. Para garantir alta disponibilidade real no plano de controle, implemente um balanceador de carga com Keepalived e HAProxy. Crie os seguintes templates Ansible em um dirretório dedicado:
templates/keepalived.conf.j2
global_defs {
router_id K8S_HA_PROXY
}
vrrp_instance VI_1 {
state MASTER
interface {{ vrrp_interface }}
virtual_router_id 42
priority {{ keepalived_priority }}
advert_int 1
authentication {
auth_type PASS
auth_pass HAPass123
}
virtual_ipaddress {
{{ virtual_ip }}/32 dev {{ vrrp_interface }}
}
}
templates/haproxy.cfg.j2
global
log stdout format raw local0
maxconn 4096
defaults
log global
mode tcp
option tcplog
retries 3
timeout connect 5s
timeout client 30m
timeout server 30m
frontend k8s_api_frontend
bind *:{{ haproxy_frontend_port }}
default_backend k8s_api_backend
backend k8s_api_backend
balance roundrobin
{% for host in groups['kube_control_plane'] %}
server {{ host }} {{ hostvars[host].ansible_host }}:{{ haproxy_backend_port }} check
{% endfor %}
deploy-ha.yml
---
- name: Provisionar Keepalived e HAProxy no Plano de Controle
hosts: kube_control_plane
vars:
virtual_ip: "192.168.100.50"
keepalived_priority: 100
vrrp_interface: "eth0"
haproxy_frontend_port: 16443
haproxy_backend_port: 6443
tasks:
- name: Instalar pacotes HA
apt:
update_cache: yes
name: ['keepalived', 'haproxy']
state: present
- name: Configurar Keepalived
template:
src: templates/keepalived.conf.j2
dest: /etc/keepalived/keepalived.conf
notify: Reiniciar Keepalived
- name: Configurar HAProxy
template:
src: templates/haproxy.cfg.j2
dest: /etc/haproxy/haproxy.cfg
notify: Reiniciar HAProxy
- name: Habilitar servicos
systemd:
name: "{{ item }}"
state: started
enabled: yes
loop: ['keepalived', 'haproxy']
handlers:
- name: Reiniciar Keepalived
systemd: name=keepalived state=restarted
- name: Reiniciar HAProxy
systemd: name=haproxy state=restarted
Execute o playbook:
ansible-playbook -i inventory/sample/inventory.ini deploy-ha.yml -v
Atualize o arquivo ~/.kube/config nos nós de controle para apontar para o IP Virtual (VIP) na porta do HAProxy, e reexecute o playbook do Kubespray para sincronizar os certificados:
for i in {1..3}; do
ssh k8s-cp$i "sed -i 's|server:.*|server: https://192.168.100.50:16443|' ~/.kube/config"
done
ansible-playbook -i inventory/sample/inventory.ini cluster.yml -u root --private-key=~/.ssh/k8s_id -v
Para validar a alta disponibilidade, desligue o nó que detém o VIP. O Keepalived migrará o IP para outro nó de controle e o acesso ao kube-apiserver permanecerá ininterrupto, verificável através de kubectl get --raw /healthz. O uso de máscara /32 para o VIP é a prática recomendada, pois cria uma rota de host específica e otimiza o tráfego.