Pods e workloads
Esta aula aborda os conceitos fundamentais de Pods e workloads no Kubernetes, incluindo Pods, Deployments, ReplicaSets e o ciclo de vida dos Pods. Você aprenderá como criar, gerenciar e escalar aplicações containerizadas, além de entender o comportamento e os estados dos Pods.
Nesta aula, vamos mergulhar nos conceitos essenciais de Pods e workloads no Kubernetes. Compreender esses elementos é fundamental para orquestrar aplicações containerizadas de forma eficiente, garantindo alta disponibilidade, escalabilidade e resiliência. Você aprenderá não apenas a definição teórica, mas também como aplicar esses conceitos na prática, usando comandos e manifestos YAML.
O Kubernetes é uma plataforma de orquestração de contêineres que abstrai a complexidade de gerenciar aplicações distribuídas. No centro dessa abstração estão os Pods, a menor unidade de computação que o Kubernetes pode criar e gerenciar. A partir deles, construímos workloads como Deployments, que garantem a execução contínua e a evolução controlada das aplicações. Vamos explorar cada um desses componentes, suas interações e o ciclo de vida que os governa.
Pods
Um Pod é a menor unidade de implantação no Kubernetes. Ele representa um processo único ou um grupo de processos que compartilham o mesmo contexto de execução, incluindo rede e armazenamento. Cada Pod possui seu próprio endereço IP e um conjunto de portas, e os contêineres dentro de um Pod compartilham esses recursos, podendo se comunicar entre si via localhost. Essa arquitetura é ideal para casos em que múltiplos contêineres precisam operar de forma coesa, como um contêiner de aplicação e um sidecar para coleta de logs.
Os Pods são efêmeros por natureza: eles são criados, executam e podem ser destruídos a qualquer momento. Quando um Pod é substituído (por exemplo, após uma falha ou atualização), ele é recriado com um novo IP, o que torna o endereço IP não confiável para comunicação direta. Para resolver isso, utilizamos Services, que fornecem um endpoint estável. Apesar disso, entender como criar e gerenciar Pods diretamente é essencial para dominar o Kubernetes.
Criando um Pod
Podemos criar um Pod de forma imperativa com o comando kubectl run, mas a prática recomendada é usar manifestos YAML, que são declarativos e versionáveis. Veja um exemplo de manifesto para um Pod simples:
apiVersion: v1
kind: Pod
metadata:
name: meu-pod
spec:
containers:
- name: nginx
image: nginx:latest
ports:
- containerPort: 80
Para aplicar esse manifesto, salve-o em um arquivo (por exemplo, pod.yaml) e execute:
kubectl apply -f pod.yaml
Para verificar se o Pod está em execução, use kubectl get pods. Você verá o nome do Pod, o status (Running, Pending, etc.) e outras informações. Para obter detalhes mais completos, utilize kubectl describe pod meu-pod, que exibe eventos, condições e configurações.
É importante notar que criar Pods diretamente não é a melhor prática para produção. Em vez disso, recomendamos usar workloads como Deployments, que fornecem gerenciamento de ciclo de vida, escalabilidade e atualizações contínuas.
ReplicaSets
Um ReplicaSet é um controlador que garante que um número especificado de réplicas de um Pod esteja sempre em execução. Ele monitora o cluster e, se algum Pod falhar ou for excluído, o ReplicaSet cria um novo para manter o número desejado. Isso garante a disponibilidade da aplicação, mesmo diante de falhas.
O ReplicaSet utiliza seletores de rótulos (labels) para identificar os Pods que deve gerenciar. No manifesto, definimos o seletor e o template do Pod. O template é um modelo de Pod que será usado para criar novas réplicas. Aqui está um exemplo de manifesto de ReplicaSet:
apiVersion: apps/v1
kind: ReplicaSet
metadata:
name: meu-replicaset
spec:
replicas: 3
selector:
matchLabels:
app: meu-app
template:
metadata:
labels:
app: meu-app
spec:
containers:
- name: nginx
image: nginx:latest
ports:
- containerPort: 80
Para criar o ReplicaSet, execute kubectl apply -f replicaset.yaml. Depois, verifique com kubectl get replicasets e kubectl get pods para ver as réplicas em execução. Se você deletar um dos Pods, o ReplicaSet criará um novo automaticamente.
Apesar de os ReplicaSets serem úteis, eles não suportam atualizações contínuas (rolling updates) nem rollbacks. Para isso, usamos Deployments, que gerenciam ReplicaSets internamente e oferecem uma abstração de mais alto nível.
Deployments
Um Deployment é um controlador que gerencia ReplicaSets e fornece recursos de atualização declarativa, escalabilidade e rollback. Ele é o workload mais comum para aplicações stateless. Com um Deployment, você define o estado desejado da aplicação (imagem, réplicas, etc.) e o Kubernetes trabalha para alcançar esse estado, realizando atualizações de forma controlada.
O Deployment cria um ReplicaSet para cada versão da aplicação. Quando você atualiza a imagem ou a configuração, o Deployment cria um novo ReplicaSet e gradualmente escala o novo enquanto reduz o antigo, garantindo que a aplicação permaneça disponível durante o processo. Se algo der errado, você pode reverter para uma versão anterior com um simples comando.
Vamos criar um Deployment de exemplo:
apiVersion: apps/v1
kind: Deployment
metadata:
name: meu-deployment
spec:
replicas: 3
selector:
matchLabels:
app: meu-app
template:
metadata:
labels:
app: meu-app
spec:
containers:
- name: nginx
image: nginx:1.20
ports:
- containerPort: 80
Aplique com kubectl apply -f deployment.yaml. Para ver o status, use kubectl get deployments, kubectl get replicasets e kubectl get pods. O Deployment garante que o número especificado de réplicas esteja sempre em execução.
Uma das grandes vantagens do Deployment é a facilidade de escalar. Você pode alterar o número de réplicas com kubectl scale deployment meu-deployment --replicas=5 ou editando o manifesto e aplicando novamente. Além disso, atualizações são simples: mude a imagem no manifesto e aplique, ou use kubectl set image deployment/meu-deployment nginx=nginx:1.21. O Kubernetes fará uma atualização contínua, garantindo que não haja downtime.
Se necessário, você pode reverter uma atualização com kubectl rollout undo deployment/meu-deployment. Para ver o histórico de versões, use kubectl rollout history deployment/meu-deployment.
Ciclo de vida
O ciclo de vida de um Pod é composto por várias fases: Pending, Running, Succeeded, Failed, e Unknown. Entender essas fases é crucial para diagnosticar problemas e gerenciar aplicações.
Pending: o Pod foi aceito pelo cluster, mas ainda não está em execução. Isso pode ocorrer porque o nó ainda está inicializando ou porque não há recursos suficientes. O scheduler está tentando alocar o Pod a um nó.
Running: o Pod foi alocado a um nó e todos os contêineres foram criados. Pelo menos um contêiner está em execução ou está em processo de inicialização.
Succeeded: todos os contêineres terminaram com sucesso e não serão reiniciados. Isso é comum em jobs ou pods de tarefa única.
Failed: pelo menos um contêiner terminou com falha (código de saída diferente de zero). O Pod pode ser reiniciado dependendo da política de reinicialização.
Unknown: o estado do Pod não pode ser obtido, geralmente devido a uma falha de comunicação com o nó.
Além das fases, os Pods têm condições que fornecem mais detalhes: PodScheduled, Initialized, ContainersReady e Ready. Essas condições são booleanas e ajudam a entender o progresso e a prontidão do Pod.
O Kubernetes também define estados para os contêineres: Waiting, Running e Terminated. O estado Waiting indica que o contêiner está aguardando para ser iniciado (por exemplo, baixando a imagem). Running significa que o contêiner está em execução. Terminated indica que o contêiner terminou, seja com sucesso ou falha.
Para inspecionar o ciclo de vida de um Pod, use kubectl describe pod, que mostra eventos como criação, agendamento, pull de imagem e início dos contêineres. Esses eventos são inestimáveis para depuração.
Além disso, você pode definir probes (liveness, readiness e startup) para controlar quando um contêiner é considerado saudável e pronto para receber tráfego. Essas sondas são configuradas no manifesto do Pod e são essenciais para garantir que apenas Pods saudáveis recebam tráfego.
Boas práticas e observações finais
Ao trabalhar com Pods e workloads, é importante seguir algumas boas práticas:
- Prefira usar Deployments em vez de Pods ou ReplicaSets diretamente, a menos que você tenha um caso específico que exija controle fino.
- Use labels e seletores de forma consistente para organizar e selecionar recursos.
- Defina recursos (CPU e memória) para cada contêiner, evitando que um Pod consuma todos os recursos do nó.
- Utilize health checks (liveness e readiness probes) para que o Kubernetes possa gerenciar a disponibilidade da aplicação.
- Mantenha os manifestos versionados e use ambientes separados para desenvolvimento, staging e produção.
Com esse conhecimento, você está pronto para criar e gerenciar aplicações no Kubernetes de forma eficiente e robusta.
Referências
- Kubernetes Documentation: Pods
- Kubernetes Documentation: Deployments
- Kubernetes Documentation: ReplicaSet
- Kubernetes Documentation: Pod Lifecycle
- Kubernetes Documentation: Configure Liveness, Readiness and Startup Probes
Exercícios
Crie um Pod chamado
nginx-podcom a imagemnginx:lateste exponha a porta 80. Use um manifesto YAML e aplique-o. Verifique se o Pod está em execução.✓ Resposta: Crie um arquivopod.yamlcom o conteúdo:
Aplique comapiVersion: v1 kind: Pod metadata: name: nginx-pod spec: containers: - name: nginx image: nginx:latest ports: - containerPort: 80kubectl apply -f pod.yamle verifique comkubectl get pods.Dado o ReplicaSet abaixo, quantas réplicas ele manterá? E se você deletar um Pod, o que acontece?
apiVersion: apps/v1 kind: ReplicaSet metadata: name: rs-exemplo spec: replicas: 3 selector: matchLabels: app: meu-app template: metadata: labels: app: meu-app spec: containers: - name: nginx image: nginx:latest✓ Resposta: O ReplicaSet manterá 3 réplicas. Se você deletar um Pod, o ReplicaSet criará um novo Pod automaticamente para manter o número desejado de 3.Explique a diferença entre ReplicaSet e Deployment. Quando você usaria um em vez do outro?
✓ Resposta: Um ReplicaSet garante que um número específico de réplicas de um Pod esteja em execução, mas não oferece suporte a atualizações contínuas ou rollbacks. Um Deployment gerencia ReplicaSets e fornece atualizações declarativas, escalabilidade e rollback. Você deve usar Deployment para a maioria das aplicações, pois é mais alto nível e fornece mais funcionalidades. ReplicaSet é usado internamente pelo Deployment, mas pode ser usado diretamente em cenários específicos onde você precisa de controle fino sobre o número de réplicas sem atualizações.Descreva as fases do ciclo de vida de um Pod e o que cada uma significa.
✓ Resposta: As fases são: Pending (Pod aceito, mas ainda não em execução), Running (Pod alocado a um nó e contêineres em execução), Succeeded (todos os contêineres terminaram com sucesso), Failed (pelo menos um contêiner terminou com falha) e Unknown (estado não pode ser obtido).Como você faria uma atualização contínua em um Deployment? Mostre o comando ou a edição de manifesto.
✓ Resposta: Para fazer uma atualização contínua, você pode editar o manifesto do Deployment alterando a imagem da aplicação e aplicar novamente comkubectl apply -f deployment.yaml. Alternativamente, use o comandokubectl set image deployment/meu-deployment nginx=nginx:1.21 --record. O Kubernetes fará um rolling update, criando um novo ReplicaSet e gradualmente substituindo os Pods antigos.