🇺🇸 English version coming soon.
Na Parte 5 desta série, validamos o cluster de ponta a ponta fazendo o deploy do Nginx. Agora vamos um passo além: construir a imagem Docker de uma aplicação própria, publicá-la, colocá-la para rodar no cluster e explorar operações do dia a dia — atualização de versão, rollback e escalabilidade (manual e automática).
Como exemplo, foi utilizada uma API REST simples (myapp.war), feita em Spring Boot, apenas para fins didáticos — o processo se aplica a qualquer aplicação empacotada como imagem de container.
Criando a imagem Docker da aplicação
O primeiro passo é escrever o Dockerfile da aplicação. Neste exemplo, foi usada uma imagem base leve (alpine), com o Java 11 instalado para rodar a aplicação:
FROM alpine
WORKDIR /opt/app
RUN apk update && apk add vim openjdk11-jre
COPY runapp.sh .
CMD ash runapp.sh
Enter fullscreen mode Exit fullscreen mode
Construindo a imagem
docker image build -t oregontecnologia/myapp-api:1.0.0 .
Enter fullscreen mode Exit fullscreen mode
Publicando a imagem
Antes de usar a imagem no cluster, ela precisa estar disponível em algum registro — seja o Docker Hub, seja um registro privado. Se você optar por hospedar seu próprio registro on-premise (recomendado para ambientes corporativos ou sem acesso à internet), veja o artigo complementar sobre como criar um servidor de registro local.
Para publicar no Docker Hub:
docker login
username:
password:
docker push oregontecnologia/myapp-api:1.0.0
Enter fullscreen mode Exit fullscreen mode
Fazendo o deploy da aplicação
Com a imagem publicada, é possível verificar o estado atual do cluster antes de prosseguir:
kubectl get pods -o wide
kubectl get deploy -o wide
Enter fullscreen mode Exit fullscreen mode
Crie o Deployment diretamente pela linha de comando, apontando para a imagem publicada:
kubectl create deploy myapp-deploy --image=oregontecnologia/myapp-api:1.0.0
Enter fullscreen mode Exit fullscreen mode
Diferente dos exemplos anteriores desta série (onde usamos arquivos YAML com
kubectl apply -f), aqui o Deployment é criado diretamente via linha de comando comkubectl create deploy. Ambas as abordagens são válidas — arquivos YAML são mais indicados quando você precisa versionar e reaplicar configurações de forma consistente.
Expondo a aplicação externamente
Para tornar a aplicação acessível fora do cluster, crie um Service do tipo LoadBalancer, associando um IP externo fixo:
kubectl expose deploy myapp-deploy --type=LoadBalancer --external-ip=10.0.10.100 --port=80
Enter fullscreen mode Exit fullscreen mode
Em ambientes on-premise, o tipo
LoadBalancernormalmente não provisiona um balanceador automaticamente (isso é um recurso nativo de provedores de nuvem). Por isso, aqui é informado manualmente um IP externo (--external-ip) já disponível na rede local.
Removendo a aplicação
Caso precise remover o Deployment:
kubectl delete deploy myapp-deploy
Enter fullscreen mode Exit fullscreen mode
Atualizando e revertendo versões da aplicação
Uma das grandes vantagens do Kubernetes é gerenciar atualizações de forma controlada, sem downtime perceptível (rolling update).
Atualizando para uma nova versão
kubectl set image deployments/myapp-deploy myapp-api=oregontecnologia/myapp-api:1.0.2 --record
Enter fullscreen mode Exit fullscreen mode
Esse comando atualiza a imagem do container myapp-api dentro do Deployment para a versão 1.0.2. A flag --record registra o comando no histórico de revisões do Deployment, o que facilita identificar depois o que mudou em cada rollout.
Revertendo para a versão anterior
Se a nova versão apresentar problemas, é possível reverter rapidamente para a revisão anterior:
kubectl rollout undo deployments/myapp-deploy
Enter fullscreen mode Exit fullscreen mode
Escalando a aplicação
Escalonamento manual
Para ajustar manualmente o número de réplicas em execução — por exemplo, para 3:
kubectl scale deploy myapp-deploy --replicas=3
Enter fullscreen mode Exit fullscreen mode
Escalonamento automático (HPA)
Para deixar o próprio Kubernetes ajustar o número de réplicas automaticamente, com base no uso de CPU, é possível configurar um Horizontal Pod Autoscaler (HPA). No exemplo abaixo, o cluster começa com 2 réplicas e pode escalar até 10, sempre que a utilização média de CPU ultrapassar 75%:
kubectl autoscale deploy myapp-deploy --min=2 --max=10 --cpu-percent=75
Enter fullscreen mode Exit fullscreen mode
Ajuste os valores de
--min,--maxe--cpu-percentconforme a capacidade real do seu cluster e o comportamento esperado da aplicação.
Para verificar o estado atual do autoscaler:
kubectl get hpa
Enter fullscreen mode Exit fullscreen mode
Esse comando mostra, entre outras informações, o uso atual de CPU em relação ao alvo configurado, e o número de réplicas em execução no momento.
Para remover o autoscaler:
kubectl delete hpa myapp-deploy
Enter fullscreen mode Exit fullscreen mode
Agora vamos colocar todo este processo manual em um arquivo YAML para facilitar as coisas.
Ao longo desta série, usamos diversos arquivos .yaml para criar Deployments, Services e outros objetos no cluster. Neste artigo, vamos dar um passo atrás e entender a estrutura básica desses manifestos — o que é obrigatório em todo arquivo, como descobrir a apiVersion correta e como ficam, na prática, os principais tipos de objeto que já usamos: Pod, ReplicaSet, Deployment e Service.
A estrutura mínima de um manifesto
Todo objeto do Kubernetes, independente do tipo, é descrito por um YAML com quatro campos principais:
apiVersion:
kind:
metadata:
spec:
Enter fullscreen mode Exit fullscreen mode
-
apiVersion: a versão da API do Kubernetes usada para criar aquele objeto (por exemplo,
v1ouapps/v1); -
kind: o tipo de objeto que será criado (
Pod,Deployment,Service, etc.); - metadata: os metadados do objeto — nome, labels, namespace, entre outros;
- spec: a especificação propriamente dita do objeto — no caso de um Pod, por exemplo, é aqui que ficam os containers.
Como descobrir a apiVersion correta
Cada tipo de objeto (kind) pertence a uma apiVersion específica, e isso pode variar entre versões do Kubernetes. Para consultar quais recursos estão disponíveis no seu cluster e a qual API cada um pertence, use:
$ kubectl api-resources
Enter fullscreen mode Exit fullscreen mode
Esse comando lista todos os recursos suportados pelo cluster, junto com o grupo de API correspondente (coluna APIVERSION) — é a fonte mais confiável para saber qual apiVersion usar em cada manifesto, já que isso pode mudar conforme a versão do Kubernetes instalada.
Atenção à indentação
YAML é um formato sensível à indentação — diferente de chaves {} ou colchetes [], a hierarquia dos dados é definida puramente pelos espaços. Por isso:
- Nunca use TAB para indentar um arquivo YAML — use sempre espaços.
- O padrão recomendado (e usado nos exemplos abaixo) é 2 espaços por nível de indentação.
-
metadataespecsão mapeamentos (chave-valor), não listas — ou seja, seus campos internos (name,labels, etc.) não devem começar com-.
Esse último ponto é um erro comum: é fácil confundir listas (que usam -) com mapeamentos simples. No exemplo de Pod abaixo, note que name e labels ficam diretamente sob metadata, sem traço.
Pod
O objeto mais básico do Kubernetes é o Pod — a menor unidade que pode ser criada e gerenciada no cluster, contendo um ou mais containers.
apiVersion: v1
kind: Pod
metadata:
name: meupod
labels:
app: meupod-label
spec:
containers:
- name: myapp-api
image: oregontecnologia/myapp-api:1.0.2
Enter fullscreen mode Exit fullscreen mode
Criando o objeto: create vs apply
Existem dois comandos principais para aplicar um manifesto no cluster:
$ kubectl create -f arquivo.yaml
$ kubectl apply -f arquivo.yaml
Enter fullscreen mode Exit fullscreen mode
A diferença entre eles é importante:
-
createcria o objeto apenas se ele ainda não existir — se o objeto já foi criado anteriormente, o comando retorna erro. -
applycria o objeto caso ele não exista, ou atualiza o objeto existente caso haja alguma mudança no manifesto. Por isso,applyé o comando mais usado no dia a dia, já que permite reaplicar o mesmo arquivo continuamente conforme ele evolui.
Verificando a criação
$ kubectl get pods
Enter fullscreen mode Exit fullscreen mode
A flag
-o widemostra informações adicionais sobre o pod em execução, como o nó onde ele está rodando e seu IP interno.
Para ver todos os detalhes de um pod ou deployment (incluindo eventos recentes, o que ajuda bastante na hora de depurar problemas):
$ kubectl describe pod myapp-api
Enter fullscreen mode Exit fullscreen mode
Ou, para um deployment:
$ kubectl describe deploy myapp-deploy
Enter fullscreen mode Exit fullscreen mode
ReplicaSet
Um Pod sozinho não se recupera automaticamente se falhar. É aí que entra o ReplicaSet: um objeto responsável por garantir que um número definido de réplicas do mesmo Pod esteja sempre em execução.
apiVersion: apps/v1
kind: ReplicaSet
metadata:
name: meureplicaset
spec:
replicas: 5
selector:
matchLabels:
app: meupod-label
template:
metadata:
labels:
app: meupod-label
spec:
containers:
- name: myapp-api
image: oregontecnologia/myapp-api:1.0.2
Enter fullscreen mode Exit fullscreen mode
Repare que a estrutura é um pouco mais aninhada que a do Pod: dentro de spec, temos o selector (que define quais Pods pertencem a este ReplicaSet, com base nos labels) e o template (que descreve como cada réplica do Pod deve ser criada).
Verificando a criação:
$ kubectl get replicaset
Enter fullscreen mode Exit fullscreen mode
Na prática, é raro criar ReplicaSets diretamente — normalmente eles são gerenciados automaticamente por um Deployment, que veremos a seguir. Ainda assim, entender essa camada ajuda a compreender como o Kubernetes garante a disponibilidade dos Pods.
Deployment
O Deployment é a forma mais comum de rodar aplicações no Kubernetes. Ele gerencia ReplicaSets automaticamente, adicionando recursos como rolling updates e rollback — que já vimos na prática na Parte 6 desta série.
apiVersion: apps/v1
kind: Deployment
metadata:
name: meudeploy
spec:
replicas: 5
selector:
matchLabels:
app: meupod-label
template:
metadata:
labels:
app: meupod-label
spec:
containers:
- name: myapp-api
image: oregontecnologia/myapp-api:1.0.2
Enter fullscreen mode Exit fullscreen mode
Note que a estrutura é praticamente idêntica à do ReplicaSet — o que faz sentido, já que um Deployment cria e gerencia ReplicaSets por trás dos panos. A diferença está no kind e nas funcionalidades adicionais que o Deployment oferece.
Verificando a criação:
$ kubectl get deploy
Enter fullscreen mode Exit fullscreen mode
Service
Por fim, o Service é o objeto responsável por expor Pods de forma estável, com um endereço fixo, independente de quantas vezes os Pods sejam recriados.
apiVersion: v1
kind: Service
metadata:
name: meudservice
spec:
selector:
app: meupod-label
ports:
- port: 80
type: LoadBalancer # ClusterIP | NodePort | LoadBalancer
Enter fullscreen mode Exit fullscreen mode
O campo type define como o serviço será exposto:
- ClusterIP (padrão): expõe o serviço apenas internamente, dentro do cluster;
- NodePort: expõe o serviço em uma porta fixa em todos os nós do cluster (usamos esse tipo na Parte 5, com o Nginx);
- LoadBalancer: solicita um balanceador de carga externo — em nuvem, provisionado automaticamente pelo provedor; em ambientes on-premise, normalmente requer um IP configurado manualmente ou uma solução como o MetalLB.
Verificando a criação:
$ kubectl get services
Enter fullscreen mode Exit fullscreen mode
Resumo
| Objeto | Função principal |
|---|---|
| Pod | Unidade mínima de execução (um ou mais containers) |
| ReplicaSet | Garante um número fixo de réplicas de um Pod |
| Deployment | Gerencia ReplicaSets, com suporte a rolling update e rollback |
| Service | Expõe Pods de forma estável, com IP e nome fixos |
Entender essa hierarquia — Pod → ReplicaSet → Deployment, mais o Service como camada de exposição — é a base para ler (e escrever) qualquer manifesto do Kubernetes com confiança, independente da complexidade da aplicação.
Fechando o ciclo operacional
Com o deploy de uma aplicação própria, atualizações controladas, rollback e escalabilidade (manual e automática), cobrimos as operações mais comuns do dia a dia de um cluster Kubernetes on-premise. A partir daqui, o cluster está pronto não só para hospedar aplicações, mas também para operá-las de forma resiliente conforme a demanda aumenta.
Isso encerra o conteúdo mais conceitual desta série. Nos próximos artigos, seguimos explorando tópicos práticos do dia a dia de um cluster on-premise.
Nos próximos artigos da série, vamos aprofundar em temas como registro de imagens privado on-premise, armazenamento persistente e observabilidade do cluster.
Artigos relacionados:
- Adicionando e removendo worker ao cluster.
- Criando um servidor de registros para suas imagens docker.
- Renovando certificado do kubernetes.
- Addons uteis para seu kubernetes.
- Metric server
- NGinx Ingress controller
- Cert-Manager
- Portainer
- Prometheus
- Grafana
0 Comments
Log in to join the conversation.No comments yet. Be the first to share your thoughts.