Domine Deployments no Kubernetes: Guia Completo para Iniciantes

Foto do autor

By luis

Kubernetes destaca-se como uma das plataformas de automatização mais utilizadas para a implementação, escalabilidade e gestão de aplicações conteinerizadas num conjunto de servidores ou nós.

Este artigo aprofunda um dos elementos cruciais do Kubernetes: o *Deployment* (Implantação). O objetivo é desvendar o seu funcionamento e como podemos criá-lo, atualizá-lo e eliminá-lo.

O que é um Deployment?

Um *Deployment* é um objeto usado para lançar *pods*. As melhores práticas do Kubernetes recomendam o uso de *Deployments* para aplicações sem estado. Sem um *Deployment*, a criação, atualização e exclusão manual de vários *pods* seria um processo árduo e inviável para um grande número de *pods*.

Um *Deployment* define um único objeto em YAML que não só cria *pods*, como também garante que eles se mantêm atualizados e operacionais. É possível também redimensionar automaticamente as aplicações de forma simples, usando um *Deployment* no Kubernetes. Desta forma, um *Deployment* é utilizado para escalar, implementar e reverter versões das aplicações dentro dos *pods*.

Um *Deployment* informa ao Kubernetes quantas réplicas de um *pod* desejamos executar, e o Kubernetes trata do resto. O controlador associado cria um *ReplicaSet* a partir da sua configuração ao criar um *Deployment*. O controlador do *ReplicaSet* gera então uma série de *pods* com base na configuração do *ReplicaSet*.

As vantagens de usar um *Deployment* em vez de criar diretamente um *ReplicaSet* são:

  • Histórico do objeto: cada modificação ao objeto (através de um “aplicar” ou “editar”) resulta num backup da versão anterior.
  • Gestão de *rollout* e *rollback*: É possível reverter para uma configuração anterior, em conjunto com o ponto acima.

Como Criar um Deployment

Existem duas abordagens para criar um *Deployment* no Kubernetes:

Abordagem Imperativa

As APIs do Kubernetes proporcionam uma abordagem mais direta e imperativa, sem necessidade de arquivos de configuração ou manifestos em formato YAML. Nesta abordagem, o utilizador especifica o resultado desejado, e o Kubernetes encarrega-se de definir os passos necessários para atingir esse objetivo.

Para utilizar o método imperativo, basta executar o comando seguinte:

kubectl create deployment nginx-deployment --image nginx --port=80

Abordagem Declarativa

Nesta abordagem, o utilizador declara todos os detalhes necessários, e quando este código é aplicado, o Kubernetes interpreta as definições e cria os recursos exatamente como especificado.

Para utilizar a abordagem declarativa, é necessário criar um arquivo YAML.

Exemplo de arquivo YAML para um *Deployment* com o nome new_deployment.yaml:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
spec:
  #Especifica o número de cópias do Pod
  replicas: 3
  #Seleciona o Pod a ser gerenciado pelo deployment
  selector:
    #Corresponde aos rótulos definidos
    matchLabels:
      deploy: example
  template:
    metadata:
      #Especifica os rótulos no Pod.
      labels:
        deploy: example
    spec:
      containers:
        - name: nginx
          image: nginx:1.20.2 

Neste arquivo YAML, depois de definir a versão da API do Kubernetes, o tipo de objeto a criar e o nome do *Deployment*, encontra-se a seção *spec*. Nesta seção, começa-se por definir a chave *replicas*, que indica o número de instâncias de *pod* que o *Deployment* deve manter ativas.

Utiliza-se um seletor de rótulo para identificar os *pods* no *Deployment*. Para tal, usa-se o rótulo de *deployment*, que informa que todos os *pods* que correspondem a estes rótulos são agrupados no *Deployment*.

Após isto, encontra-se o objeto *template*, que contém um modelo de *pod* dentro da sua especificação de *deployment*. Quando o *Deployment* cria *pods*, fá-lo usando este modelo. A especificação de um *pod* regular pode ser encontrada na chave do *template*.

Com este *Deployment*, as imagens Nginx com rótulos serão implementadas em *pods*. É importante notar que o *Pod* é a unidade de escalabilidade no Kubernetes, pelo que é crucial pensar no padrão a utilizar se se pretender colocar vários contêineres no mesmo *Pod*.

De seguida, para aplicar o arquivo Yaml new_deployment.yaml, utiliza-se o seguinte comando:

kubectl apply -f new_deployment.yaml

Após alguns instantes, é possível verificar o estado do *Deployment* usando o seguinte comando:

kubectl get all

Obter e Atualizar o Deployment

Como pode observar, existem *Pods* criados, o *Deployment* e também um *ReplicaSet*. Um *Deployment* cria e gere sempre um *ReplicaSet*. Para obter mais detalhes sobre o *Deployment*, pode usar o seguinte comando:

kubectl describe deployment nginx-deployment 

Agora, tem uma descrição detalhada do *Deployment*. Destaca a estratégia utilizada para criar/reconstruir os *pods* quando uma atualização é definida como *RollingUpdate*.

A estratégia *RollingUpdate* permite uma migração controlada de uma versão de uma aplicação para uma versão mais recente. Esta é a estratégia padrão no Kubernetes.

Adicionalmente, existem também as seguintes estratégias:

  • Recriar: termina as instâncias de *Pod* que estão em execução e ‘recria-as’ com a nova versão;
  • Azul/Verde: Esta estratégia cria dois ambientes separados mas idênticos. No ambiente azul, a aplicação está a correr como está, enquanto no ambiente verde, a aplicação corre como estará no futuro;
  • Canary: Uma estratégia de implementação em que um subconjunto de utilizadores está envolvido no lançamento incremental de uma aplicação ou serviço.

Ao escolher *rolling-update*, é possível configurar o seu comportamento relativamente ao número de réplicas desejado.

  • *maxSurge* permite indicar (em termos percentuais ou absolutos) quantos *Pods* podem ser criados adicionalmente ao número de réplicas atualmente configurado.
  • *maxUnavailable* permite indicar (em termos percentuais ou absolutos) quantos *Pods* podem ficar ‘indisponíveis’ durante a atualização, dependendo do número de réplicas configurado.

Dependendo da sua aplicação e do seu autoescalador, estas configurações permitirão garantir a Qualidade de Serviço (QoS) ou acelerar as implementações.

De seguida, vamos redimensionar os *pods* para 10 e alterar a *tag* da imagem Nginx para a mais recente.

kubectl scale deployment nginx-deployment --replicas=10

Note que temos 5 contêineres a serem criados e, de 10 *Pods*, temos 5 disponíveis.

Após alguns instantes, use o seguinte comando:

kubectl get all

Aqui pode ver que todos os *pods* foram criados e os contêineres estão em execução.

Removendo o seu Deployment

Para remover um *Deployment* do Kubernetes, pode usar os seguintes comandos:

kubectl delete deploy nginx-deployment 
kubectl delete deploy new_deployment.yaml

Helm: Simplificando as Implementações

Ao implementar uma aplicação complexa que utilize dezenas ou centenas de recursos do Kubernetes, a ferramenta kubectl pode tornar-se inadequada, sendo este o motivo pelo qual a ferramenta Helm foi desenvolvida. O Helm é um gestor de pacotes para o Kubernetes que complementa o kubectl, facilitando a implementação de aplicações.

No vocabulário do Helm, uma aplicação é designada por *release*. Esta está associada a um *chart*, que é uma coleção de arquivos de configuração em formato YAML, contendo variáveis globais e modelos que descrevem os recursos do Kubernetes.

Conclusão

O *Deployment* é um objeto essencial no Kubernetes. Dado que um grande poder implica uma grande responsabilidade, deve ter cuidado ao configurá-lo, sob pena de ter comportamentos inesperados. Para explorar as configurações do *Deployment* mais a fundo, consulte a documentação do Kubernetes.

Pode também explorar alguns dos melhores tutoriais do Kubernetes para aprender desde o início e tornar-se um especialista.