sábado, 3 de outubro de 2026

Kubernetes do Zero - Parte 2: Preparando nosso laboratório e subindo nosso cluster


Fala pessoal, tudo bem?

Hoje vamos para a parte 2, da nossa sequência de postagens Kubernetes do Zero.

Vamos preparar nosso ambiente que servirá de laboratório para começarmos a colocar um pouco a mão na massa.

O ambiente

Para o laboratório eu vou utilizar a seguinte infraestrutura:

  • Meu notebook rodando Windows
  • Hypervisor – VirtualBox
  • 3 VMs com Ubuntu server instalado (versão 26.04)

o   1 VM será o control plane

§  2 vCPUs

§  3 GB memória (pela documentação do kubernetes.io , pode ser apenas 2GB)

§  20 GB de disco

o   2 VMs serão os workers

§  2 vCPUs

§  3 GB memória (pela documentação do kubernetes.io , pode ser apenas 2GB)

  • Placas em modo Bridge, assim as VMs receberão um IP da minha rede DHC.

Importante: Não precisamos instalar o Ubuntu nas 3 VMs. Podemos fazer a instalação de uma VM e depois usar o recurso de clone do VirtualBox. Assim poupamos um pouco de tempo de instalação. Apenas a parte da instalação e criação do cluster kubernetes que iremos fazer em cada uma devido a particularidade.

Preparação

Com as VMs criadas e com sistema operacional instalado, vamos agora fazer a preparação necessária antes de instalar o kubernetes e começar a subir nosso cluster.

Desativar o swap

O kubernetes exige que a memória swap seja desativada. Nas 3 máquinas vamos executar o seguinte comando:

sudo swapoff -a

É necessário com o vim, deletar a linha do swap no /etc/fstab e assim não fazer com que suba novamente caso o servidor reinicie.


Obs.: Isso deve ser feito nos workers também.

Carregar módulos do kernel

Para o kubernetes funcionar corretamente, precisamos carregar os módulos overlay e br_netfilter.

  • Overley – sistema de arquivos de sobreposição que permitirá unir múltiplos diretórios ou partições em uma única estrutura de arquivos virtual e transparente.
  • Br_netfilter – vai permitir que o tráfego de rede que passar por nossa interface de rede seja processado pelas regras do firewall Iptables.

No terminal, vamos executar o seguinte bloco de comandos:

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

       Ativar o encaminhamento do IP (Sysctl)

Isso é necessário para que nosso Linux, seja capaz de funcionar como um roteador, repassando pacotes de dados de uma rede para outra.

No terminal, execute o seguinte bloco de comandos:

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


Instalar o containerd

Como falamos na primeira parte, o kubernetes não executa nativamente, por assim dizer os containers, então para isso vamos instalar o containerd. Ele será o nosso container runtime.

Novamente no terminal, execute o seguinte bloco de comandos:

sudo apt update
sudo apt install containerd -y
sudo mkdir -p /etc/containerd
containerd config default | sudo tee /etc/containerd/config.toml

·        O kubernetes trabalha com cgroups.

Cgroups – ou control groups (grupos de controle), é um recurso do kernel do Linux que permite limitar, contabilizar e isolar o uso de recursos de hadware, como CPU, memória, I/O de disco e rede para um determinado grupo de processos.

Para isso funcionar, vamos permitir que o containerd use cgroups. No arquivo de configuração /etc/containerd/config.toml, o parâmetro SystemdCgroup será alterado de false para true.

Novamente no terminal, execute o seguinte bloco de comandos:

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


Pronto!!!

O que era pré-requisito já foi feito.

Só lembrando ... reforçando ... Esses procedimentos precisam ser feitos em todos os nós do cluster. No nosso caso, no nó 1 que é o control plane e no nó 2 e 3 que são os workers.

Agora, vamos adicionar o repositório do kubernetes nos 3 nós e instalar os pacotes necessários.

Instalando os pacotes base e os pacotes do kubernetes

Para adicionar o repositório e o certificado, vamos executar o bloco de comandos abaixo:

sudo apt install apt-transport-https ca-certificates curl gnupg
conntrack
curl -fsSL https://pkgs.k8s.io/core:/stable:/v1.37/deb/Release.key |
sudo gpg --dearmor -o /etc/apt/keyrings/kubernetes-apt-keyring.gpg
sudo chmod 644 /etc/apt/keyrings/kubernetes-apt-keyring.gpg
echo 'deb [signed-by=/etc/apt/keyrings/kubernetes-apt-keyring.gpg] https://pkgs.k8s.io/core:/stable:/v1.37/deb/
/' | sudo tee /etc/apt/sources.list.d/kubernetes.list
sudo chmod 644 /etc/apt/sources.list.d/kubernetes.list


Para instalar o kubeadm, kubelet e kubectl, o bloco de comandos abaixo:

sudo apt update
sudo apt install -y kubelet kubeadm kubectl
sudo apt-mark hold kubelet kubeadm kubectl

 

O apt-mark hold serve para que toda vez que alguém executar o update/upgrade no servidor, não corra o risco de atualizar automaticamente o kubernetes também. Isso evita muita dor de cabeça para nada quebrar durante uma atualização não planejada.

Finalmente, vamos subir nosso cluster =]

Subindo nosso primeiro cluster kubernetes

Agora, esse comando será executado apenas no control plane. Que no nosso laboratório será a VM kub-node1

sudo kubeadm init --pod-network-cidr=10.244.0.0/16
--apiserver-advertise-address=<O IP QUE VAI FALAR COM OS NODES>

Veja que podemos informar o endereçamento de rede que queremos usar na comunicação interna (rede escolhida 10.244.0.0/16), entre os pods e também informar o IP do nosso apiserve que nada mais é do que nosso control plane (192.168.0.62)

Então no nosso caso, o comando ficaria assim:

sudo kubeadm init --pod-network-cidr=10.244.0.0/16
--apiserver-advertise-address=192.168.0.62

Essa parte pode demorar um pouco, mediante a performance do ambiente e também da conectividade de rede/internet. Uma vez que começa toda a preparação de validar pré-requisitos e baixar tudo que é necessário para criar a estrutura do cluster.

Dando tudo certo, ao final teremos uma saída assim:


Veja que temos duas informações importantes aqui.

1° - Para podermos usar o cluster, com um usuário regular, temos alguns comandos a serem executados no control plane.

  • Criar o diretório para o arquivo de configuração do kubernetes no nosso diretório home
  • Copiar o arquivo de configuração do kubernetes para essa diretório criado no home do nosso usuário

·         Trocar o grupo e o dono para nosso usuário neste arquivo de configuração

2° - Não menos importante, veja que ele trás o comando que vamos precisar executar nos nodes workers para eles serem membros do nosso cluster efetivamente. Lembrando que para dar certo, precisamos executar com o sudo. Então ficaria assim, de acordo com nosso exemplo:

Sudo kubeadm join 192.168.0.62:6443 --token 48trth.zgu9q9l8t0tve24v
--discovery-token-ca-cert-hash sha256:0674a4a83bd943e86fc5a1784cd5d410c7571336bdb417dbb5b264bbb2876aa5

Dando tudo certo (que é o esperado), devemos receber um log semelhante a esse:


E por fim, para validar, no shell do servidor do control plane:

$ kubectl get nodes

 


Prontinho!!!

Nosso cluster está pronto, certo?

Só que não rs...

Veja que na coluna STATUS ainda temos tudo como NotReady. Mas por que será?

Ainda falta instalarmos nosso CNI para kubernetes e assim ele conseguir proporcionar a comunicação entre os pods. E aí sim, tudo estará funcional em nosso cluster para ele ficar pronto ... ou no caso, Ready.

Mas o que é CNI?

CNI (Container Network Interface) é uma especificação e conjunto de bibliotecas para as configurações de rede em containers. É através dele que temos a comunicação entre os pods e serviços facilitada.

Existem várias opções de CNI, como Calico, Flannel, Cilium e etc...

Eu gosto do Cilium, então ele será o CNI escolhido para o nosso ambiente.

Segue o site do projeto https://docs.cilium.io/en/stable/gettingstarted/k8s-install-default/ contendo todas informações e documentações.

De acordo com a página de documentação do Cilium, para instalarmos no nosso ambiente Linux que já contém um cluster, devemos rodar o seguinte bloco de comandos:

CILIUM_CLI_VERSION=$(curl -s
https://raw.githubusercontent.com/cilium/cilium-cli/main/stable.txt)
CLI_ARCH=amd64
if [ "$(uname -m)" = "aarch64" ]; then CLI_ARCH=arm64;
fi
curl -L --fail --remote-name-all
https://github.com/cilium/cilium-cli/releases/download/${CILIUM_CLI_VERSION}/cilium-linux-${CLI_ARCH}.tar.gz{,.sha256sum}
sha256sum --check cilium-linux-${CLI_ARCH}.tar.gz.sha256sum
sudo tar xzvfC cilium-linux-${CLI_ARCH}.tar.gz /usr/local/bin
rm cilium-linux-${CLI_ARCH}.tar.gz{,.sha256sum}

 

Isso fará o download do binário do Cilium e o moverá para o diretório /usr/local/bin permitindo que você consiga executa-lo com seu usuário.

Após o download, vamos rodar a instalação com o comando:

$ cilium install

E vamos acompanhar o processo com o comando:

$ cilium status

Ou

$ cilium status -w

(isso fará com que o shell fique informando a cada atualização, sem que seja necessário executar o comando de status várias vezes)


É normal olharmos o status e aparecerem alguns erros durante o processo de subida. Isso ocorre devido ao cilium estar preparando o ambiente.

Se você tiver mais curiosidade e for impaciente como eu, o cilium faz o deploy dos seus serviços no namespace do kube-system. Para acompanhar podemos ver tudo com o comando:

$ kubectl get pods -n kube-system


Na coluna STATUS, iremos ver status de Init, ContainerCreating e dando tudo certo ... Running.

Assim que tudo estiver running, podemos validar novamente o status dos nodes:

$ kubectl get nodes


Agora sim. Nosso cluster está funcional no que diz respeito a todos os nodes estarem como Ready, com comunicação e visíveis para o control plane.

Fazendo um teste subindo nosso primeiro deployment

Para fazermos um teste bem rápido se está tudo OK, podemos rodar o seguinte comando:

$ kubectl create deployment nginx --image=nginx --replicas 4

Isso vai instruir a criação de um deploy do serviço do nginx, com 4 réplicas. Ou seja, 4 pods espalhados pelos workers.


O processo de subida dos pods pode demorar um pouco também, algo entre de 1 – 4 minutos. Mas vale levar em consideração que o kubernetes vai precisar baixar a imagem, fazer as criações e inicializações dos pods, então isso pode levar esse tempinho ou um pouco a mais.


Tudo como Running!

Que demais!!!

Mas será que o scheduler trabalhou direitinho e balanceou as réplicas pra gente? Já que ele é o responsável por este trabalho?

Vamos validar e para isso vamos executar o comando:

$ kubectl get pods -o wide


Veja que na coluna NODE, temos a informação de onde cada pod está rodando.

Como pedimos 4 réplicas, o scheduler colocou 2 réplicas no kub-node3 e 2 no kub-node2.

- Mas por que ele não usou o control plane, se ele é um node também?

Por via de regra, não teremos nossos pods em execução no control plane. É possível habilitar isso? Sim. Mas não é recomendado.

É até recomendado termos mais de um nó só para o control plane por questões de redundância e resiliência do nosso cluster.

- Eu consigo pegar mais informações dos nossos nodes?

Consegue sim. Basta executar o comando describe, da seguinte forma:

$ kubectl describe node kub-node2

Este é um exemplo do describe do node2


Aqui é apenas um trecho, pois a saída de informações é muito maior.

- Consigo fazer o describe também nos pods?

Sim!!!

$ kubectl describe pods nginx-69b9cdbbdd-bb8lj


Então, para reforçar:

  •          Usamos o get quando queremos pegar alguma informação
  •          Usamos o describe quando queremos pegar mais informações com detalhes

Finalizando a parte 2

Hoje aprendemos como preparar nosso ambiente para receber a instalação do kubernetes e como subir nosso primeiro cluster, contemplando a instalação do nosso CNI para permitir a comunicação entre os pods no ambiente e também como podemos validar se os nodes estão funcionando corretamente através de um deploy da aplicação do nginx.

Vamos ver o que nos espera na parte 3 ..., mas posso garantir pra vocês que essa jornada está apenas começando e ainda tem muita coisa legal para aprendermos.

Abs e até a próxima.

quinta-feira, 1 de outubro de 2026

Kubernetes do Zero - Parte 1: Conceitos, Arquitetura e Componentes Essenciais


E aí pessoal, tudo bem?

Uma das coisas que sempre gostei de fazer durante minha jornada profissional e de aprendizado, foi compartilhar conhecimento/criar procedimentos.

Isso é muito bom, por que me ajuda a fixar o que aprendi e também ajudar as pessoas que estão na mesma jornada.

Recentemente embarquei e me aprofundei nos estudos sobre Kubernetes.

Mas afinal, o que é Kubernetes?

"Kubernetes é uma plataforma open source que gerencia containers em escala, cuidando de deploy, escalonamento e alta disponibilidade."

- Projeto desenvolvido pela Google em 2014. Criado para atuar como orquestrador de containers para a própria Google.

Curiosidade: O nome Kubernetes (K8S) vem do Grego que significa “timoneiro”. Isso explicar o timão no logo do projeto.

Antes do Kubernetes a Google já havia criado pelo menos outros dois orquestradores de containers. Mas apenas o Kubernetes é de código aberto (Open Source).

Código Aberto (Open Source) – Isso quer dizer que o código-fonte é público, pode ser explorado livremente, modificado e distribuído por qualquer pessoa.

Arquitetura do Kubernetes

Falando um pouco sobre a arquitetura do Kubernetes, ele segue a estrutura control plane e workers, fazendo assim a concepção de um cluster.

Recomendação mínima para funcionamento do cluster: 3 nós

  • 1 control plane
  • 2 workers



Explicando cada um


Control plane: responsável por todo gerenciamento do cluster
Workers: onde efetivamente rodam as aplicações que subirmos no cluster

Se formos falar de laboratório para estudo, OK, é possível usar dois nós ou até mesmo um nó, rodando tudo. Mas nunca para ambientes fora deste contexto.

Vale lembrar que também é possível emular tudo isso usando seu próprio desktop, usando ferramentas como: Kind, Minikube, MicroK8S (da Canonical/Ubuntu) ... dentre outros.

Componentes do control plane

kube-apiserver: sendo um dos principais componentes do Kubernetes, expõe uma API formato JSON sobre HTTP, processando todos os comandos e requisições do usuário utilizando principalmente o utilitário kubeclt. A comunicação estabelecida entre os componentes é através de requisições REST.

etcd: nada mais é do que um banco de dados chave-valor. Ele armazena todos os dados de configuração do cluster bem como seu estado e metadados de todo cluster. Todos os dados armazenados aqui são manipulados via API. Pensando em questões de segurança ele só pode ser executado em nós que sejam do tipo control plane, mas o etcd pode ser executado em nós dedicados para essa função, sendo hosts externos ao cluster por exemplo.

kube-scheduler: componente responsável por escolher em qual nó um determinado Pod (falarei sobre o Pod mais pra frente) irá executar/residir. O scheduler faz a seleção do nó com base na quantidade de recursos disponíveis e com o estado de cada nó, mas não somente isso, ele também pode levar em consideração políticas definidas pelo administrador do cluster, como afinidade, localização, etc.

kube-control-manager: responsável por garantir que o cluster esteja no estado definido no etcd. Um exemplo disso é se temos um deploy configurado para ter 3 réplicas de um Pod. Cabe ao control manager verificar no cluster se o estado atual cumpri essa determinação e caso não, em como irá conciliar para satisfazer essa condição.

Componentes do worker

Pod: é denominado a menor unidade em um cluster Kubernetes. Pode agrupar/conter um ou mais containers que irão compartilhar os mesmos recursos de rede e armazenamento do Pod.

Talvez não seja muito comum vermos Pods com mais de um container, isso vai depender muito do comportamento e perfil da aplicação que irá rodar.

Kubelet: é propriamente o agente do kubernetes que roda em cada worker responsável por gerenciar os pods que o control manager direcionou. Ele tem controle e permissão para iniciar, parar e manter os pods e seus respectivos containers em funcionamento de acordo com o que foi instruído pelo control manager.

Kube-proxy: tem função de proxy propriamente dita, mas também como um load balancer, sendo responsável pelo roteamento das requisições para os pods corretos e assim cuidar também da parte de rede do nó.

Container runtime: é o software responsável pela execução dos containers nos nós. Quando estamos usando um Docker ou mesmo um Podman, para que seja possível executar container na nossa máquina, estamos usando um container runtime. Na verdade, temos uma Container Engine usando um Container Runtine para isso.

Existem 4 tipos de container runtime: Low-level, High-level, Sandbox e Virtualized

Low-level: executados diretamente pelo kernel, como o runc por exemplo. Mas vale lembrar que temos outros também.

High-level: executados pelo container engine, como é o caso do containerd.

Sandbox: executados pelo container engine mas são executados de forma segura em unikernels ou usando algum mecanismo de proxy para comunicação com o kernel.

Virtualized: container engine responsável por executar containers de forma segura em máquinas virtuais. Agora vale informar que existe uma certa “penalidade” quanto a performance. Ela é um pouco menor se comparado ao formato de executar nativamente.

Portas

Existem algumas portas que devemos conhecer e saber que existem para o correto funcionamento de todo cluster do kubernetes.

  • Control Plane ports:

 

Protocol

Direction

Port Range

Purpose

Used By

TCP

Inbound

6443*

Kubernetes API server

All

TCP

Inbound

2379-2380

etcd server client API

kube-apiserver, etcd

TCP

Inbound

10250

Kubelet API

Self, Control plane

TCP

Inbound

10251

kube-scheduler

Self

TCP

Inbound

10252

kube-controller-manager

Self

 

* Obs.: no caso da porta 6443 ela pode ser customizada, ou seja, podemos trocar por uma porta da nossa escolha. Mas precisamos lembrar que ela precisa estar “aberta”. 

  • Workers ports:

 

Protocol

Direction

Port Range

Purpose

Used By

TCP

Inbound

10250

Kubelet API

Self, Control plane

TCP

Inbound

30000-32767

NodePort

Services All


Fechando nosso entendimento sobre o ponto chave do kubernetes

Um ponto bem importante é que o kubernetes não gerencia diretamente os containers, assim como o docker swarm por exemplo. Ele faz a gestão através dos pods.

Pods - é a menor unidade dentro de um cluster kubernetes. Sendo essa a camada administrada pelo kubernetes e dentro dela podendo residir um ou mais containers compartilhando os mesmos recursos do pod, como IP, volumes, ciclos de CPU e memória.

Deployment - responsável por gerenciar o ciclo de vida das aplicações, associar características a aplicação (imagem, porta, volumes, réplicas, dentro outros). São especificados em arquivos do tipo “yaml” ou “JSON” passados como parâmetro para o kubectl executar o deploy. Esse tipo de ação contempla tanto criação como atualização e remoção do que está especificado no deployment.

ReplicaSets - objeto responsável por garantir a quantidade de pods que queremos em execução.

Services - usado quando queremos expor a comunicação por um ClusterIP, NodePort ou LoadBalancer para que seja feita a distribuição de carga entre os pods que compõem um deployment/aplicação.

Com isso, conseguimos entender a relação entre os principais objetos do Kubernetes.

O Deployment define como a aplicação deverá ser executada, informando, por exemplo, qual imagem será utilizada e quantas réplicas desejamos manter. O ReplicaSet fica responsável por garantir que essa quantidade de Pods esteja sempre disponível. Os Pods executam os containers da aplicação e o Service permite que esses Pods sejam acessados e que as requisições sejam distribuídas entre eles.

Essa estrutura permite que o Kubernetes mantenha o estado desejado da aplicação mesmo quando algum Pod apresenta falha. Nesse caso, o próprio Kubernetes pode criar um novo Pod para substituir aquele que deixou de funcionar.

É importante destacar que este é apenas um primeiro contato com a arquitetura e os principais componentes do Kubernetes. Ainda existem diversos outros recursos importantes, como Namespaces, ConfigMaps, Secrets, Ingress, volumes persistentes, probes de saúde e ferramentas de monitoramento.

Para quem está iniciando os estudos, uma boa forma de fixar esse conhecimento é criar um laboratório utilizando ferramentas como Kind, Minikube ou MicroK8s. A partir disso, é possível praticar a criação de Pods, Deployments e Services utilizando arquivos no formato YAML.

Este foi um resumo dos conceitos iniciais que venho estudando sobre Kubernetes. Espero que o conteúdo possa ajudar outras pessoas que também estão iniciando nessa jornada.

Em breve, pretendo compartilhar novos aprendizados e exemplos práticos sobre o assunto.

E você, já utiliza Kubernetes no dia a dia ou também está começando os estudos?