cd ..
KUBERNETES

Criando e administrando Pods com kubectl e manifestos YAML

Este artigo é uma continuação do post Conhecendo os Pods e o kubectl. Se você ainda não leu a primeira parte, recomendo começar por ela para entender os conceitos fundamentais antes de avançar para os manifestos YAML.

Conhecendo manifestos YAML e administrando Pods com kubectl

No artigo anterior conhecemos os Pods e aprendemos como criar nosso primeiro recurso utilizando o comando kubectl run.

Embora esse comando seja extremamente útil para estudos e testes rápidos, ele não representa a forma mais comum de trabalhar com Kubernetes em ambientes de produção.

Na prática, a maioria das aplicações é criada através de manifestos YAML que ficam versionados em um repositório Git.

Neste artigo vamos aprender como gerar esses manifestos automaticamente utilizando o kubectl, entender sua estrutura, criar um Pod com múltiplos containers e conhecer alguns dos comandos mais utilizados para administrar Pods.

Gerando um manifesto YAML

Imagine que desejamos criar um Pod utilizando a imagem do Nginx.

Poderíamos executar diretamente:

kubectl run corinthians --image=nginx

Entretanto, existe uma forma muito melhor de fazer isso.

kubectl run corinthians \
  --image=nginx \
  --port=80 \
  --dry-run=client \
  -o yaml > pod.yaml

Esse comando não cria nenhum recurso.

Ele apenas gera o manifesto YAML e salva seu conteúdo dentro do arquivo pod.yaml.

Vamos entender cada opção.

O parâmetro --image

--image=nginx

Define qual imagem será utilizada pelo container.

Quando o Pod for criado, o Kubernetes tentará localizar essa imagem em um registro de containers.

Caso ela não exista localmente, será baixada automaticamente.

O parâmetro --port

--port=80

Informa que o container utiliza a porta 80.

Isso faz com que o manifesto contenha:

ports:
  - containerPort: 80

É importante lembrar que essa opção não publica a aplicação.

Para isso ainda será necessário criar um Service.

O parâmetro --dry-run=client

Essa é uma das opções mais úteis durante os estudos.

--dry-run=client

O termo dry-run significa executar uma simulação.

Em vez de enviar uma requisição para o Kubernetes, o kubectl monta o recurso localmente.

Na prática acontece o seguinte:

kubectl


Monta o objeto


Gera o YAML


Não cria nenhum recurso

Como toda a simulação acontece dentro do próprio kubectl, utilizamos a opção client.

O parâmetro -o yaml

A opção -o significa output.

-o yaml

Ela informa ao kubectl que desejamos visualizar o recurso no formato YAML.

O resultado será semelhante ao seguinte:

apiVersion: v1
kind: Pod

metadata:
  labels:
    run: corinthians
  name: corinthians

spec:
  containers:
  - image: nginx
    name: corinthians
    ports:
    - containerPort: 80

  dnsPolicy: ClusterFirst
  restartPolicy: Always

O operador >

A parte final do comando costuma gerar dúvidas.

> pod.yaml

Isso não pertence ao Kubernetes.

Esse operador faz parte do shell Linux.

Ele redireciona a saída do comando para um arquivo.

Sem ele, o YAML seria exibido diretamente no terminal.

Com ele, todo o conteúdo será salvo em pod.yaml.

Conhecendo a estrutura do manifesto

Agora que o arquivo foi criado, podemos entender sua estrutura.

apiVersion

Define qual versão da API será utilizada.

apiVersion: v1

kind

Informa qual recurso será criado.

kind: Pod

metadata

Armazena informações de identificação do recurso.

metadata:
  name: corinthians
  labels:
    run: corinthians

spec

É a parte mais importante do manifesto.

Ela descreve o estado desejado do recurso.

Dentro dela encontramos:

containers

Lista todos os containers pertencentes ao Pod.

containers:
- image: nginx
  name: corinthians

Caso existam Sidecars, eles também aparecerão nessa lista.

restartPolicy

restartPolicy: Always

Define o comportamento do Kubernetes caso o container seja encerrado.

Por padrão, Pods criados dessa forma utilizam Always.

dnsPolicy

dnsPolicy: ClusterFirst

Essa política informa que o Pod utilizará o serviço de DNS do próprio cluster.

Criando o Pod

Depois de revisar o manifesto basta aplicá-lo.

kubectl apply -f pod.yaml

Resultado esperado:

pod/corinthians created

Agora o Kubernetes enviará esse manifesto para o API Server e iniciará o processo de criação do Pod.

Criando um Pod com múltiplos containers

Até agora trabalhamos com um Pod contendo apenas um container.

Entretanto, um Pod também pode executar dois ou mais containers ao mesmo tempo.

No exemplo abaixo, criaremos um Pod chamado corinthians com dois containers:

apiVersion: v1
kind: Pod
metadata:
  labels:
    run: corinthians
  name: corinthians
spec:
  containers:
  - image: nginx
    name: corinthians
    resources: {}

  - image: busybox
    name: busybox
    args:
    - sleep
    - "700"

  dnsPolicy: ClusterFirst
  restartPolicy: Always

O primeiro container executa o Nginx.

O segundo utiliza a imagem do BusyBox e executa o comando:

sleep 700

Esse comando mantém o container ativo durante 700 segundos. Sem um processo em execução, o container BusyBox seria encerrado logo após iniciar.

Depois de aplicar o manifesto:

kubectl apply -f pod.yaml

Podemos consultar o Pod com informações adicionais:

kubectl get pods -o wide

Resultado:

NAME          READY   STATUS    RESTARTS        AGE    IP           NODE
corinthians   2/2     Running   9 (2m18s ago)   4h5m   10.244.2.5   giropops-worker

A coluna READY apresenta:

2/2

Isso significa que o Pod possui dois containers e ambos estão prontos.

A coluna NODE mostra que o Pod está sendo executado no Node:

giropops-worker

Podemos representar essa estrutura da seguinte forma:

Cluster Kubernetes
└── Node: giropops-worker
    └── Pod: corinthians
        ├── Container: corinthians
        │   └── Imagem: nginx
        └── Container: busybox
            └── Comando: sleep 700

É importante entender que os containers não são executados diretamente pelo Node como recursos separados.

Os dois containers estão dentro do mesmo Pod, e o Pod é que está sendo executado no Node.

Eles também compartilham:

Nesse exemplo, o endereço IP 10.244.2.5 pertence ao Pod.

Entendendo os reinícios do BusyBox

Na saída do comando, a coluna RESTARTS mostra que os containers já foram reiniciados:

9 (2m18s ago)

Isso acontece porque o BusyBox executa:

sleep 700

Depois de 700 segundos, esse processo termina.

Como o manifesto utiliza:

restartPolicy: Always

o Kubernetes inicia o container novamente.

Por isso o número de reinicializações aumenta ao longo do tempo.

Administrando containers específicos

Quando um Pod possui múltiplos containers, precisamos informar qual container queremos acessar.

Para visualizar os logs do Nginx:

kubectl logs corinthians -c corinthians

Para consultar o BusyBox:

kubectl logs corinthians -c busybox

Também podemos executar comandos dentro de um container específico.

No container do Nginx:

kubectl exec -it corinthians -c corinthians -- sh

No container BusyBox:

kubectl exec -it corinthians -c busybox -- sh

A opção -c informa o nome do container que será utilizado.

Consultando os Pods

O primeiro comando que normalmente executamos é:

kubectl get pods

Também podemos obter informações adicionais.

kubectl get pods -o wide

Essa opção mostra informações como:

Obtendo detalhes

Caso seja necessário investigar um recurso específico:

kubectl describe pod corinthians

Esse comando exibe:

É um dos comandos mais utilizados durante processos de troubleshooting.

Visualizando logs

Para visualizar os logs de um container utilizamos:

kubectl logs corinthians

Caso desejemos acompanhar os logs em tempo real:

kubectl logs -f corinthians

Se o Pod possuir múltiplos containers, será necessário informar qual deles desejamos consultar.

kubectl logs corinthians -c busybox

Executando comandos dentro do container

Em muitos momentos será necessário acessar um container para realizar testes ou investigações.

Para isso utilizamos o kubectl exec.

kubectl exec -it corinthians -- sh

Esse comando cria um novo processo dentro do container.

Depois disso podemos executar comandos normalmente.

ls

env

hostname

cat /etc/os-release

Na prática, kubectl exec é muito mais utilizado do que kubectl attach.

Conhecendo o kubectl attach

O comando attach possui um comportamento diferente.

Enquanto o exec cria um novo processo, o attach conecta nosso terminal ao processo principal do container.

kubectl attach -it corinthians

Na maioria das situações utilizamos o exec.

O attach costuma ser utilizado apenas em aplicações interativas que já estão aguardando entrada pelo terminal.

Removendo o Pod

Para remover o recurso:

kubectl delete pod corinthians

Após alguns segundos ele deixará de existir no cluster.

Resumindo

Durante este artigo aprendemos um fluxo muito utilizado no dia a dia.

kubectl run


--dry-run=client


-o yaml


pod.yaml


kubectl apply


kubectl get


kubectl describe


kubectl logs


kubectl exec


kubectl delete

Esse fluxo representa a base do trabalho com Kubernetes e será utilizado em praticamente todos os próximos recursos que estudaremos, como Deployments, Services, ConfigMaps e Ingress.

Nos próximos artigos vamos evoluir para recursos declarativos mais complexos e entender como aplicações reais são executadas dentro de um cluster Kubernetes.

Referências

O que achou?