Docker & Kubernetes

Como Usar Kubernetes: Arquitetura do Cluster, Control Plane e Worker Nodes em Produção

14 min de leitura

Como Usar Kubernetes: Arquitetura do Cluster, Control Plane e Worker Nodes em Produção

Introdução ao Kubernetes e Sua Arquitetura Kubernetes, frequentemente abreviado como K8s, é uma plataforma de orquestração de containers desenvolvida pelo Google e mantida pela Cloud Native Computing Foundation. Ela resolve um problema fundamental na computação moderna: como gerenciar, escalar e manter aplicações containerizadas em ambientes de produção distribuídos. A arquitetura do Kubernetes é baseada em um modelo cliente-servidor onde um cluster é dividido em dois componentes principais: o Control Plane (antes chamado de Master) e os Worker Nodes. Essa divisão permite que você execute aplicações de forma resiliente, com alta disponibilidade e escalabilidade automática. Neste artigo, vamos desmontar cada componente e entender como eles trabalham juntos para orquestrar sua infraestrutura containerizada. Arquitetura Geral do Cluster Kubernetes A Estrutura Hierárquica Um cluster Kubernetes funciona como um sistema distribuído onde o Control Plane atua como o "cérebro" do sistema, tomando decisões sobre o estado desejado dos containers, enquanto os Worker Nodes são os "músculos" que executam efetivamente os containers. A comunicação entre

<h2>Introdução ao Kubernetes e Sua Arquitetura</h2>

<p>Kubernetes, frequentemente abreviado como K8s, é uma plataforma de orquestração de containers desenvolvida pelo Google e mantida pela Cloud Native Computing Foundation. Ela resolve um problema fundamental na computação moderna: como gerenciar, escalar e manter aplicações containerizadas em ambientes de produção distribuídos.</p>

<p>A arquitetura do Kubernetes é baseada em um modelo cliente-servidor onde um cluster é dividido em dois componentes principais: o <strong>Control Plane</strong> (antes chamado de Master) e os <strong>Worker Nodes</strong>. Essa divisão permite que você execute aplicações de forma resiliente, com alta disponibilidade e escalabilidade automática. Neste artigo, vamos desmontar cada componente e entender como eles trabalham juntos para orquestrar sua infraestrutura containerizada.</p>

<h2>Arquitetura Geral do Cluster Kubernetes</h2>

<h3>A Estrutura Hierárquica</h3>

<p>Um cluster Kubernetes funciona como um sistema distribuído onde o Control Plane atua como o &quot;cérebro&quot; do sistema, tomando decisões sobre o estado desejado dos containers, enquanto os Worker Nodes são os &quot;músculos&quot; que executam efetivamente os containers. A comunicação entre eles ocorre através de APIs RESTful e segue um padrão declarativo: você descreve o estado desejado, e o Kubernetes trabalha para alcançá-lo.</p>

<p>A arquitetura é completamente descentralizada em termos de execução. Se um Worker Node falha, o Control Plane detecta a falha e reconstrói os containers em outro nó saudável. Isso é possível porque o Kubernetes mantém um registro do estado desejado e constantemente verifica se a realidade corresponde a esse desejo, em um padrão conhecido como <strong>reconciliation loop</strong>.</p>

<pre><code>┌─────────────────────────────────────────────────────────────┐

│ KUBERNETES CLUSTER │

├────────────────────┬────────────────────────────────────────┤

│ CONTROL PLANE │ WORKER NODES │

│ (Master Node) │ │

│ │ ┌──────────┐ ┌──────────┐ │

│ ┌──────────────┐ │ │ Node 1 │ │ Node 2 │ │

│ │ API Server │ │ │ ┌──────┐ │ │ ┌──────┐ │ │

│ └──────────────┘ │ │ │Pod A │ │ │ │Pod C │ │ │

│ │ │ ├──────┤ │ │ ├──────┤ │ │

│ ┌──────────────┐ │ │ │Pod B │ │ │ │Pod D │ │ │

│ │ Scheduler │ │ │ └──────┘ │ │ └──────┘ │ │

│ └──────────────┘ │ └──────────┘ └──────────┘ │

│ │ │

│ ┌──────────────┐ │ │

│ │Controller Mgr│ │ │

│ └──────────────┘ │ │

│ │ │

│ ┌──────────────┐ │ │

│ │ etcd (DB) │ │ │

│ └──────────────┘ │ │

└────────────────────┴────────────────────────────────────────┘</code></pre>

<h2>O Control Plane: O Cérebro do Cluster</h2>

<h3>Componentes Principais do Control Plane</h3>

<p>O Control Plane é composto por vários componentes que trabalham em conjunto. O <strong>API Server</strong> é o ponto central de comunicação; toda solicitação ao cluster passa por ele, seja para criar novos recursos ou consultar o estado atual. Ele valida as requisições, autoriza as ações e persiste as mudanças no banco de dados.</p>

<p>O <strong>Scheduler</strong> é responsável por decidir qual Worker Node executará cada Pod. Ele analisa os requisitos de recursos (CPU, memória), constraints de afinidade e outras políticas para tomar decisões otimizadas. O <strong>Controller Manager</strong> executa diversos controladores que monitoram o estado do cluster e trabalham continuamente para manter o estado desejado. Por fim, o <strong>etcd</strong> é um banco de dados chave-valor distribuído que armazena todo o estado do cluster de forma durável.</p>

<pre><code class="language-yaml"># Exemplo: Consultando componentes do Control Plane em um cluster real

apiVersion: v1

kind: Pod

metadata:

name: diagnostico-control-plane

namespace: kube-system

spec:

containers:

  • name: check-components

image: alpine:3.18

command:

  • sh
  • -c

- |

echo &quot;=== Verificando componentes do Control Plane ===&quot;

Em um cluster real, você veria pods como:

kube-apiserver-master-1

kube-scheduler-master-1

kube-controller-manager-master-1

etcd-master-1

sleep 3600</code></pre>

<h3>Como o API Server Funciona</h3>

<p>O API Server é a base de toda operação em Kubernetes. Quando você executa <code>kubectl apply</code>, o comando é convertido em uma requisição HTTP para o API Server. Ele valida a sintaxe YAML, verifica permissões (RBAC), aplica mutating webhooks, e finalmente armazena o recurso no etcd.</p>

<pre><code class="language-yaml"># Exemplo prático: Criar um Deployment e acompanhar o fluxo

apiVersion: apps/v1

kind: Deployment

metadata:

name: nginx-deployment

labels:

app: nginx

spec:

replicas: 3

selector:

matchLabels:

app: nginx

template:

metadata:

labels:

app: nginx

spec:

containers:

  • name: nginx

image: nginx:1.25

ports:

  • containerPort: 80

resources:

requests:

cpu: 100m

memory: 128Mi

limits:

cpu: 200m

memory: 256Mi</code></pre>

<p>Quando este YAML é aplicado:</p>

<ol>

<li>O API Server recebe a requisição e valida a estrutura</li>

<li>O Scheduler observa que há uma nova Deployment com 3 réplicas</li>

<li>O Scheduler atribui cada Pod a um Worker Node específico</li>

<li>O kubelet em cada nó recebe a instrução e puxa a imagem Docker</li>

<li>O container é iniciado e o etcd registra o estado</li>

</ol>

<h3>O etcd: Persistência do Estado</h3>

<p>O etcd é o coração da durabilidade do cluster. Todo recurso criado no Kubernetes é armazenado aqui. É um banco de dados chave-valor distribuído que oferece forte consistência. Nunca perca seus dados do etcd em produção; implemente snapshots regulares e replicação entre múltiplos nós do Control Plane.</p>

<pre><code class="language-bash"># Exemplo: Fazendo backup do etcd (executar no master)

Nota: Em clusters gerenciados (EKS, GKE, AKS), isso é automatizado

ETCDCTL_API=3 etcdctl snapshot save /backup/etcd-snapshot.db \

--endpoints=https://127.0.0.1:2379 \

--cacert=/etc/kubernetes/pki/etcd/ca.crt \

--cert=/etc/kubernetes/pki/etcd/server.crt \

--key=/etc/kubernetes/pki/etcd/server.key

Verificando o snapshot

ETCDCTL_API=3 etcdctl snapshot status /backup/etcd-snapshot.db</code></pre>

<h2>Worker Nodes: Onde a Ação Acontece</h2>

<h3>Componentes de um Worker Node</h3>

<p>Cada Worker Node é uma máquina (física ou virtual) que executa containers. O componente mais importante é o <strong>kubelet</strong>, um agente que roda em cada nó e é responsável por garantir que os containers especificados estão rodando. Ele comunica-se constantemente com o API Server para obter as instruções e relata o status.</p>

<p>O <strong>kube-proxy</strong> gerencia a rede no nó. Ele implementa o Kubernetes Service, criando regras de firewall e redirecionamento de tráfego para que os Pods possam se comunicar entre si e com o mundo exterior. O <strong>container runtime</strong> é o mecanismo que realmente executa os containers; pode ser Docker, containerd, CRI-O ou outro compatível com a Container Runtime Interface (CRI).</p>

<pre><code class="language-yaml"># Exemplo: Inspecionando um Worker Node

apiVersion: v1

kind: Node

metadata:

name: worker-node-1

labels:

kubernetes.io/os: linux

node.kubernetes.io/instance-type: t3.medium

spec:

Taints são restrições que impedem pods de serem agendados

taints:

  • key: dedicated

value: worker

effect: NoSchedule

Podemos adicionar labels customizados

labels:

disktype: ssd

node-role: compute-heavy

status:

capacity:

cpu: &quot;2&quot;

memory: &quot;4Gi&quot;

pods: &quot;110&quot;

allocatable:

cpu: &quot;1900m&quot;

memory: &quot;3800Mi&quot;

pods: &quot;110&quot;

conditions:

  • type: Ready

status: &quot;True&quot;

lastHeartbeatTime: &quot;2024-01-15T10:30:00Z&quot;</code></pre>

<h3>O Kubelet: O Agente Local</h3>

<p>O kubelet é um daemon que roda em cada nó e sincroniza constantemente com o API Server. Ele recebe especificações de Pods, executa-as através do container runtime, monitora sua saúde e relata status. Se um container falha, o kubelet tenta reiniciá-lo conforme a política de restart.</p>

<pre><code class="language-bash"># Exemplo: Verificar logs do kubelet em um nó

SSH no worker node

ssh ubuntu@worker-node-1

Visualizar status do kubelet

sudo systemctl status kubelet

Ver logs em tempo real

sudo journalctl -u kubelet -f

Verificar configuração do kubelet

cat /var/lib/kubelet/kubeconfig.conf

Reiniciar o kubelet (cuidado em produção!)

sudo systemctl restart kubelet</code></pre>

<h3>Networking e o kube-proxy</h3>

<p>O kube-proxy implementa a abstração de Service do Kubernetes. Quando você cria um Service, o kube-proxy cria regras de iptables (ou IPVS em clusters maiores) que redirecionam o tráfego para os Pods corretos. Isso permite comunicação entre Pods sem conhecer seus IPs específicos.</p>

<pre><code class="language-yaml"># Exemplo: Service e como o kube-proxy roteia tráfego

apiVersion: v1

kind: Service

metadata:

name: web-service

spec:

type: ClusterIP

selector:

app: web

ports:

  • protocol: TCP

port: 80

targetPort: 8080

---

apiVersion: v1

kind: Pod

metadata:

name: web-pod-1

labels:

app: web

spec:

containers:

  • name: web

image: nginx:1.25

ports:

  • containerPort: 8080</code></pre>

<p>Quando o Service é criado, o kube-proxy em cada nó cria regras que fazem com que requisições para <code>web-service:80</code> sejam redirecionadas para um dos Pods rotulados com <code>app: web</code> na porta <code>8080</code>.</p>

<h2>Comunicação Entre Componentes</h2>

<h3>O Fluxo de uma Requisição do Usuário</h3>

<p>Quando você executa <code>kubectl apply -f deployment.yaml</code>, aqui está o que acontece internamente. O kubectl envia a requisição YAML para o API Server no Control Plane. O API Server valida a requisição, aplica políticas de admissão e armazena o recurso no etcd. Simultaneamente, o Deployment Controller observa a mudança e cria ReplicaSets conforme especificado. O ReplicaSet Controller cria Pods conforme a réplica desejada. O Scheduler observa os Pods pendentes e atribui-os aos Worker Nodes. Por fim, o kubelet em cada nó detecta que há um Pod assignado a ele e executa o container.</p>

<pre><code class="language-bash"># Exemplo: Acompanhar este fluxo em tempo real

Terminal 1: Observar eventos do cluster

kubectl get events --all-namespaces --watch

Terminal 2: Criar uma deployment

kubectl apply -f deployment.yaml

Terminal 3: Observar o status dos pods

kubectl get pods --watch

Você verá a progressão: Pending → ContainerCreating → Running</code></pre>

<h3>Heartbeat e Health Checks</h3>

<p>O kubelet periodicamente envia informações sobre o nó e os Pods para o API Server. Se um nó não enviar heartbeat por mais de alguns minutos, o Control Plane marca-o como <code>NotReady</code> e começa a reagendar seus Pods em outros nós. Dentro dos Pods, você pode configurar liveness probes para detectar aplicações travadas e restart probes para recuperar-se de falhas.</p>

<pre><code class="language-yaml"># Exemplo: Configurar health checks em um Pod

apiVersion: v1

kind: Pod

metadata:

name: app-com-health-checks

spec:

containers:

  • name: app

image: my-app:1.0

ports:

  • containerPort: 8000

Liveness probe: reinicia o container se falhar

livenessProbe:

httpGet:

path: /health

port: 8000

initialDelaySeconds: 5

periodSeconds: 10

timeoutSeconds: 2

failureThreshold: 3

Readiness probe: remove do tráfego se falhar

readinessProbe:

httpGet:

path: /ready

port: 8000

initialDelaySeconds: 3

periodSeconds: 5

Startup probe: aguarda aplicação iniciar

startupProbe:

httpGet:

path: /startup

port: 8000

failureThreshold: 30

periodSeconds: 10</code></pre>

<h2>Multi-Master: Alta Disponibilidade do Control Plane</h2>

<h3>Configuração de Redundância</h3>

<p>Em ambientes de produção, nunca execute um Control Plane com apenas um nó. Se aquele nó falhar, todo seu cluster fica indisponível. A melhor prática é ter no mínimo 3 nós de Control Plane para garantir quórum em caso de falhas. Todos os nós do Control Plane executam os mesmos componentes, mas o etcd é replicado entre eles para garantir consistência.</p>

<pre><code class="language-yaml"># Exemplo: Verificar nós do Control Plane em um cluster

Execute: kubectl get nodes -L node-role.kubernetes.io/control-plane

Saída esperada:

NAME STATUS ROLES AGE

master-1 Ready control-plane,master 30d

master-2 Ready control-plane,master 30d

master-3 Ready control-plane,master 30d

worker-1 Ready &lt;none&gt; 25d

worker-2 Ready &lt;none&gt; 25d</code></pre>

<h3>Load Balancing do API Server</h3>

<p>Para que os clientes (como kubectl) se conectem ao Control Plane sem conhecer qual nó master está saudável, você precisa de um load balancer na frente dos API Servers. Em ambientes cloud, use os load balancers nativos (AWS ELB, Azure Load Balancer, etc.). Em on-premise, considere HAProxy ou similares.</p>

<pre><code class="language-bash"># Exemplo: Configuração de HAProxy para load balancer do K8s API

/etc/haproxy/haproxy.cfg

global

log /dev/log local0

maxconn 4096

defaults

mode tcp

timeout connect 10s

timeout client 30s

timeout server 30s

frontend kubernetes-api

bind 10.0.0.10:6443

mode tcp

default_backend kubernetes-api-backend

backend kubernetes-api-backend

mode tcp

balance roundrobin

server master-1 10.0.0.11:6443 check

server master-2 10.0.0.12:6443 check

server master-3 10.0.0.13:6443 check

Então, todos os clientes se conectam a 10.0.0.10:6443

E o HAProxy roteia para o master disponível</code></pre>

<h2>Conclusão</h2>

<p>Dominar a arquitetura do Kubernetes é fundamental para operar clusters em produção. Os três pontos principais que você deve levar para casa são:</p>

<ol>

<li><strong>A dualidade Control Plane e Worker Nodes</strong>: O Control Plane é o &quot;gerenciador&quot; que toma decisões sobre o que deve rodar e como deve rodar, enquanto os Worker Nodes são os executores que realmente mantêm os containers funcionando. A comunicação entre eles segue um padrão declarativo onde você descreve o estado desejado.</li>

</ol>

<ol>

<li><strong>Reconciliation e resiliência contínua</strong>: O Kubernetes não é um sistema &quot;fire and forget&quot;. Ele constantemente verifica se a realidade corresponde ao desejo declarado e corrige desvios. Se um Pod falha, ele é reiniciado. Se um nó morre, seus Pods são reagendados. Esta natureza auto-recuperável é o que torna o Kubernetes poderoso.</li>

</ol>

<ol>

<li><strong>Alta disponibilidade no design</strong>: De múltiplos nós de Control Plane ao etcd replicado e kubelet robusto, Kubernetes foi construído para tolerância a falhas. Compreender essas camadas de redundância permite que você construa sistemas realmente resilientes que continuam funcionando mesmo com falhas parciais.</li>

</ol>

<h2>Referências</h2>

<ul>

<li><a href="https://kubernetes.io/docs/concepts/architecture/" target="_blank" rel="noopener noreferrer">Kubernetes Official Documentation - Cluster Architecture</a></li>

<li><a href="https://kubernetes.io/docs/reference/command-line-tools-reference/kube-apiserver/" target="_blank" rel="noopener noreferrer">Kubernetes API Server Documentation</a></li>

<li><a href="https://etcd.io/" target="_blank" rel="noopener noreferrer">etcd Project - Official Repository</a></li>

<li><a href="https://www.kubernetes.io/blog/2019/07/kubernetes-1-15-release-announcement/" target="_blank" rel="noopener noreferrer">The Kubernetes Book - Nigel Poulton</a></li>

<li><a href="https://www.cncf.io/certification/cka/" target="_blank" rel="noopener noreferrer">CNCF Kubernetes Certified Administrator Exam Guide</a></li>

</ul>

<p>&lt;!-- FIM --&gt;</p>

Comentários

Mais em Docker & Kubernetes

Como Usar DaemonSets e Jobs em Kubernetes: Agentes e Tarefas em Lote em Produção
Como Usar DaemonSets e Jobs em Kubernetes: Agentes e Tarefas em Lote em Produção

DaemonSets e Jobs em Kubernetes: Agentes e Tarefas em Lote Quando você começa...

Como Usar Chaos Engineering em Kubernetes: LitmusChaos e Testes de Resiliência em Produção
Como Usar Chaos Engineering em Kubernetes: LitmusChaos e Testes de Resiliência em Produção

O que é Chaos Engineering e por que é Crítico em Kubernetes Chaos Engineering...

Guia Completo de StatefulSets em Kubernetes: Bancos de Dados e Workloads com Estado
Guia Completo de StatefulSets em Kubernetes: Bancos de Dados e Workloads com Estado

O que é StatefulSet? Um StatefulSet é um objeto do Kubernetes projetado para...