Microsserviços, parte 3: orquestração com Kubernetes
Conheça a arquitetura do Kubernetes, pratique com o kubectl (Deployments, Pods, Services, rótulos, escalabilidade e rolling updates) e implante os microsserviços de lembretes e o barramento de eventos no cluster com arquivos de configuração, imagens no Docker Hub e serviços NodePort e ClusterIP.
1. Visão geral
Este codelab é a parte 3 de 3 da apostila Arquiteturas de Sistemas Computacionais. Na parte 2, cada microsserviço da aplicação de lembretes passou a ser executado em um contêiner Docker. Agora você vai usar o Kubernetes para gerenciar esses contêineres.
O que você vai aprender
- O que é o Kubernetes e como é a sua arquitetura (control plane, nós, Pods)
- Como habilitar o Kubernetes no Docker Desktop ou instalar o Minikube
- Como usar o
kubectlpara criar Deployments, inspecionar Pods, ver logs e executar comandos em contêineres - Como usar Go templates para extrair informações da saída do
kubectl - O que são serviços (ClusterIP, NodePort e LoadBalancer), rótulos e seletores
- Como escalar uma aplicação, testar o balanceador de carga e fazer rolling updates e rollbacks
- Como definir Pods, Deployments e Services com arquivos de configuração YAML
- Como publicar imagens no Docker Hub e atualizar Deployments
- Como fazer microsserviços se comunicarem dentro do cluster
O que você vai precisar
- Ter concluído as partes 1 e 2 (codelabs
mss-microsservicos-parte-1emss-microsservicos-parte-2), com osDockerfiledos microsserviços prontos - Docker Desktop com Kubernetes habilitado (Windows) ou Minikube (Linux e MacOS)
- Uma conta gratuita no Docker Hub
- O Postman ou outro cliente HTTP, e o
curl
2. Kubernetes
O uso de contêineres traz as diversas vantagens mencionadas. Entretanto, gerenciar a sua execução, em particular em um ambiente distribuído em que a demanda por processamento varia significativamente, pode se tornar bastante trabalhoso. É aí que entra o uso do Kubernetes. Segundo a documentação oficial, que pode ser acessada em https://kubernetes.io/docs/concepts/overview/what-is-kubernetes/, o Kubernetes é uma plataforma para o gerenciamento de serviços que facilita a configuração declarativa e a automação.
A figura a seguir ilustra algumas das funcionalidades providas pelo Kubernetes.

O Kubernetes como "timoneiro" dos contêineres.
Quando colocamos o Kubernetes em execução, obtemos um cluster. Um cluster é um conjunto de máquinas trabalhadoras (do inglês worker machines) que executam aplicações em contêineres. Todo cluster possui, pelo menos, uma máquina trabalhadora.
Arquitetura do Kubernetes
A arquitetura do Kubernetes é composta por
- Uma máquina trabalhadora que executa Pods. Máquinas trabalhadoras são também chamadas de nós. Elas podem ser máquinas físicas ou virtuais.
- Um Pod é um conjunto de contêineres em execução.
- O control plane é a camada de orquestração que expõe uma API por meio da qual é possível implantar e gerenciar contêineres. Em ambiente de produção, a sua execução comumente é realizada por vários computadores, o que traz tolerância a falhas e alta disponibilidade.
Veja a figura a seguir.

Componentes do Kubernetes. Fonte: https://kubernetes.io/docs/concepts/overview/components/
Detalhes sobre o control plane
O control plane é constituído por
- kube-apiserver Desempenha o papel de front end do control plane, expondo a API do Kubernetes.
- etcd Mecanismo de armazenamento baseado em pares chave/valor. Usado para armazenar dados referentes ao funcionamento do cluster.
- kube-scheduler Responsável por detectar novos Pods para os quais um nó ainda não foi alocado e providenciar a alocação.
- kube-controller-manager Executa controllers. Um controller verifica constantemente o estado do cluster e executa ações necessárias para alterar seu estado atual, levando-o para o estado desejado. Um exemplo de controller é o Node controller. Ele é responsável por informar quando um nó se torna inoperante.
- cloud-controller-manager É um tipo de control plane que viabiliza a conexão entre o cluster do Kubernetes e um provedor de computação em nuvem. Ele separa os componentes que interagem com o provedor de nuvem daqueles que interagem somente com o cluster local.
Detalhes sobre os nós
Um nó ou máquina virtual, por sua vez, possui os seguintes componentes.
- kubelet Responsável por garantir que os contêineres estão em execução em um Pod, de acordo com especificações obtidas em PodSpecs. Um kubelet não se preocupa com contêineres em execução que eventualmente não tenham sido criados pelo Kubernetes.
- kube-proxy Implementa a ideia de Service do Kubernetes. Trata-se de uma maneira de expor um conjunto de Pods como um serviço em rede.
- Container runtime É o software responsável por executar os contêineres. Hoje o Docker é certamente o mais utilizado. Entretanto, qualquer um que implemente a especificação CRI pode ser utilizado.
3. Instalação do Kubernetes
Windows
A instalação do Kubernetes varia em função do sistema operacional utilizado. Para o Windows, basta instalar o Docker Desktop. Ele inclui uma implementação do Kubernetes que pode ser executada localmente. É preciso habilitar o uso do Kubernetes por meio da interface gráfica do Docker. Clique no ícone que fica na "system tray" do sistema operacional e então clique no botão Settings, como na figura a seguir.

Abrindo as configurações do Docker Desktop.
A seguir, clique na opção Kubernetes, marque a caixa Enable Kubernetes e clique Apply & Restart, como na figura a seguir.

Habilitando o Kubernetes no Docker Desktop.
O download da implementação do Kubernetes será iniciado e o Docker Desktop será reiniciado quando a instalação estiver concluída.
Linux e MacOS
Caso esteja utilizando Linux ou MacOS, uma opção é fazer a instalação do Minikube. O procedimento é muito simples. Há pacotes oficiais apropriados para os dois sistemas operacionais. Siga as instruções disponíveis em https://minikube.sigs.k8s.io/docs/start/.
4. Hello, Kubernetes!
Nesta seção utilizaremos diversos comandos do Kubernetes a fim de ilustrar o seu uso básico.
Checando versões
Use
Terminal
kubectl version
para verificar a versão do cliente e do servidor. O cliente é o próprio kubectl. Ele é um cliente de linha de comando que permite acesso a clusters Kubernetes. O servidor, por outro lado, é o cluster Kubernetes.
Visualizando máquinas trabalhadoras (nós)
Execute
Terminal
kubectl get nodes
para exibir os nós (máquinas trabalhadoras) disponíveis no cluster. Caso seja a sua primeira instalação do Kubernetes, provavelmente você verá um único nó, como mostra o resultado a seguir.
Terminal
C:\Users\rodri>kubectl get nodes
NAME STATUS ROLES AGE VERSION
docker-desktop Ready master 72m v1.19.7
Forma geral de uso do kubectl
Digite apenas
Terminal
kubectl
para ver as formas como o kubectl pode ser utilizado. A forma geral é
kubectl ação recurso
Para obter ajuda sobre um comando específico, use
Terminal
kubectl get nodes --help
Criando um Deployment
A fim de implantar uma aplicação usando o Kubernetes, criamos uma configuração de Deployment que o instrui sobre como criar e atualizar instâncias da aplicação. Uma vez criado um Deployment, o control plane produz instâncias da aplicação que serão executadas em diferentes nós. Um controller de Deployment monitora cada instância. Se algum nó ficar inoperante e comprometer o funcionamento de uma instância da aplicação, esse controller se encarrega de colocar em execução uma nova instância dela em outro nó disponível. Use
Terminal
kubectl create deployment meu-primeiro-deployment --image=gcr.io/google-samples/kubernetes-bootcamp:v1
para criar seu primeiro Deployment.
A seguir, verifique quais Deployments você possui com
Terminal
kubectl get deployments
O resultado deve ser parecido com o seguinte.
Terminal
C:\Users\rodri>kubectl get deployments
NAME READY UP-TO-DATE AVAILABLE AGE
meu-primeiro-deployment 1/1 1 1 7m9s
5. Pods: proxy, nomes, logs e comandos
Proxy para acesso aos Pods
A aplicação está em execução em um contêiner Docker. Cada contêiner sob controle do Kubernetes executa dentro de um Pod. Por padrão, Pods executam em uma rede privada, isolada do mundo externo. O kubectl pode criar um proxy entre a rede interna do cluster e o mundo externo com
Terminal
kubectl proxy
O resultado deve ser parecido com o seguinte.
Terminal
C:\Users\rodri>kubectl get deployments
NAME READY UP-TO-DATE AVAILABLE AGE
meu-primeiro-deployment 1/1 1 1 5h32m
C:\Users\rodri>kubectl proxy
Starting to serve on 127.0.0.1:8001
Abra o Postman e faça uma requisição na porta exibida (8001). A saída deve ser parecida com a figura a seguir.

A API do cluster acessível pelo proxy.
Cada linha do resultado é um endpoint para o qual requisições podem ser direcionadas. O Kubernetes gera um endpoint para cada Pod com base em seu nome.
Nomes de Pods com Go templates
Vamos extrair o nome do Pod existente e guardar em uma variável de ambiente para uso futuro. O comando kubectl get pods traz uma quantidade bastante grande de informações sobre os Pods. Use
Terminal
kubectl get pods -o json
(ou yaml, se preferir) para visualizar todos os campos disponíveis. A saída deve ser parecida com o que exibe a figura a seguir.

Saída do kubectl get pods em JSON.
Estude a estrutura do JSON e verifique que ele possui uma coleção associada à chave items. Cada item na lista é um Pod. Cada um deles possui um objeto JSON associado a uma chave chamada metadata. Entre muitas chaves, o objeto em questão possui uma chamada name. Ela está associada ao nome de cada Pod. Para extrair essa e outras informações de interesse em um formato específico, podemos utilizar um Go template. Veja a sua documentação oficial em https://golang.org/pkg/text/template/.
Antes de prosseguir, vejamos alguns exemplos de uso de Go templates envolvendo a saída do kubectl.
kubectl get pods -o go-template='"Hello, Go templates!"'- Ignora o que okubectlproduz e apenas mostra o texto especificado.kubectl get pods -o go-template='{{.apiVersion}}'- extrai o valor associado à chaveapiVersion, existente na saída produzida pelokubectl. O caractere.que precede o nome da propriedade é fundamental. Se ele for omitido,apiVersionserá considerada uma tentativa de chamada de função. Note que{{}}é usado para avaliar expressões.kubectl get pods -o go-template='{{.items}}'- extrai os dados de todos os itens de uma só vez.kubectl get pods -o go-template='{{range .items}}{{.metadata}}{{end}}'- usa a funçãorangepara iterar sobre a coleçãoitems. Exibe o objeto associado à chavemetadatade cada Pod.kubectl get pods -o go-template='{{range .items}}{{.metadata.name}}{{end}}'- Exibe o nome de cada Pod.{{end}}encerra a repetição criada porrange.
Como temos um único Pod no momento, vamos usar
Terminal
kubectl get pods -o go-template='{{range .items}}{{.metadata.name}}{{end}}'
set POD_NAME=nome_obtido_aqui //Windows
export POD_NAME=nome_obtido_aqui //Unix-like
echo %POD_NAME% //Windows, para testar
echo $POD_NAME //Unix-like, para testar
para guardar o seu nome em uma variável de ambiente.
Enviando requisições a um Pod
Execute
Terminal
curl http://localhost:8001/api/v1/namespaces/default/pods/%POD_NAME% //Windows
curl http://localhost:8001/api/v1/namespaces/default/pods/$POD_NAME //Unix-like
para obter detalhes do Pod. Também é possível fazer essa requisição usando o Postman ou o navegador.
Logs de um Pod
Use
Terminal
kubectl logs %POD_NAME% //Windows
kubectl logs $POD_NAME //Unix-like
para visualizar os logs do seu Pod.
Executando comandos "dentro" de um contêiner
Podemos executar comandos "dentro" de um contêiner com
Terminal
//Lista conteúdo no diretório atual
kubectl exec %POD_NAME% -- ls //Windows
kubectl exec $POD_NAME -- ls //Unix-like
// Exibe as variáveis de ambiente
kubectl exec %POD_NAME% -- env //Windows
kubectl exec $POD_NAME -- env //Unix-like
// Obtém a data
kubectl exec %POD_NAME% -- date //Windows
kubectl exec $POD_NAME -- date //Unix-like
A aplicação implantada: código-fonte e teste
A aplicação que implantamos está definida em um arquivo chamado server.js. Para visualizar o seu conteúdo e testá-la a partir do próprio contêiner em que se encontra, vamos abrir um terminal vinculado ao contêiner. Faça isso com
Terminal
kubectl exec -ti %POD_NAME% -- bash //Windows
kubectl exec -ti $POD_NAME -- bash //Unix-like
Para visualizar o conteúdo do arquivo server.js, no terminal vinculado ao contêiner, use
Terminal (dentro do contêiner)
cat server.js
Verifique que o servidor está em funcionamento com
Terminal (dentro do contêiner)
curl localhost:8080
6. Serviços
Considere a arquitetura retratada pela figura a seguir.

Cada Pod possui o seu próprio endereço IP.
Ela destaca um detalhe muito importante. Pods possuem IP próprio, mesmo aqueles executando no mesmo nó. Agora, suponha que uma aplicação deseja utilizar uma funcionalidade disponibilizada por contêineres executando no cluster. É possível que mais de um Pod esteja envolvido no atendimento a requisições feitas por ela. Eles são destacados na figura a seguir.

Vários Pods, em nós diferentes, atendendo ao mesmo cliente.
Quando um nó se torna inoperante, cabe ao Kubernetes colocar em execução novas instâncias dos Pods que estavam sob sua responsabilidade. Veja a figura a seguir.

Pods de um nó inoperante são recriados em outro nó.
É claro que esse tipo de alteração deve ser transparente para a aplicação cliente. Ela sequer deve saber que está sendo atendida por múltiplos Pods no cluster. É aí que entra o conceito de serviço. Um serviço é um agrupamento lógico de Pods. Quando um serviço é criado, ele pode ter um tipo. Cada tipo influencia a forma como o serviço é exposto para acesso a seus Pods.
- ClusterIP - O serviço é exposto somente dentro do próprio cluster.
- NodePort - Expõe o serviço externamente ao cluster usando a mesma porta de cada nó especificado. O padrão para acesso é
NodeIp:NodePort. - LoadBalancer - Cria um balanceador de carga e atribui a ele um único IP externo e fixo.
Um serviço agrupa Pods por meio de rótulos e seletores. Aplicamos rótulos a Pods que desejamos que façam parte daquele serviço e, na definição do serviço, especificamos aquele rótulo escolhido como seu seletor. Veja a figura a seguir.

Um serviço seleciona Pods por rótulo.
Comece verificando os serviços existentes com
Terminal
kubectl get services
A saída deve conter um único serviço, como mostra o resultado a seguir. Ele é criado por padrão pelo Kubernetes.
Terminal
C:\Users\rodri>kubectl get services
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 8d
Crie um serviço com
Terminal
kubectl expose deployment/meu-primeiro-deployment --type="NodePort" --port 8080
Execute
Terminal
kubectl get services
novamente. Para verificar a porta do nó (campo NodePort) que foi exposta, use
Terminal
kubectl describe services/meu-primeiro-deployment
Vamos armazená-la em uma variável de ambiente para uso futuro. Para obtê-la, use
Terminal
kubectl get services/meu-primeiro-deployment -o go-template="{{(index .spec.ports 0).nodePort}}"
set NODE_PORT=porta_obtida //Windows
export NODE_PORT=porta_obtida //Unix-like
echo %NODE_PORT% //Windows, para testar
echo $NODE_PORT //Unix-like, para testar
Obtenha o endereço IP da máquina com
Terminal
ipconfig //Windows
ifconfig //Unix-like
Faça um teste com
Terminal
curl ip_da_sua_maquina:%NODE_PORT% //Windows
curl ip_da_sua_maquina:$NODE_PORT //Unix-like
7. Rótulos e remoção de serviços
Manipulação de rótulos
Nosso Pod possui um rótulo que foi atribuído automaticamente quando criamos o Deployment. Use
Terminal
kubectl describe deployment
para visualizá-lo. Veja a figura a seguir.

O rótulo app=meu-primeiro-deployment atribuído automaticamente.
Podemos fazer uma busca por Pods e por serviços filtrando por rótulo. Para isso, use
Terminal
kubectl get pods -l chave=valor
kubectl get services -l chave=valor
Armazene o nome do Pod obtido com
Terminal
kubectl get pods -o go-template --template "{{range .items}}{{.metadata.name}}{{end}}"
set POD_NAME=nome_aqui //Windows
export POD_NAME=nome_aqui //Unix-like
Aplique um rótulo ao Pod com
Terminal
kubectl label pod %POD_NAME% versao=v1 //Windows
kubectl label pod $POD_NAME versao=v1 //Unix-like
Verifique que o novo rótulo foi aplicado com
Terminal
kubectl describe pods %POD_NAME%
A figura a seguir exibe parte do resultado esperado.

O Pod com o novo rótulo versao=v1.
A busca pode ser realizada usando qualquer rótulo existente no objeto de interesse. Use, por exemplo
Terminal
kubectl get pods -l versao=v1
Removendo serviços
Uma vez que não seja necessária a exposição causada por um serviço, ele pode ser removido. A sua remoção não implica na remoção dos Pods associados a ele. A remoção pode ser feita com
Terminal
kubectl delete service -l app=meu-primeiro-deployment
Verifique que o serviço já não está disponível com
Terminal
kubectl get services
Verifique também que não é mais possível realizar requisições usando a porta que havia sido exposta com
Terminal
curl ip_da_sua_maquina:%NODE_PORT% //Windows
curl ip_da_sua_maquina:$NODE_PORT //Unix-like
Observe, entretanto, que a aplicação permanece executando dentro do Pod. Use
Terminal
kubectl exec -ti %POD_NAME% -- curl localhost:8080 //Windows
kubectl exec -ti $POD_NAME -- curl localhost:8080 //Unix-like
para verificar. Ocorre que o Deployment está sob gerência do Kubernetes e ele garante uma instância da aplicação em execução. Para removê-la, seria necessário remover também o Deployment.
8. Escalabilidade e balanceamento de carga
Escalabilidade
Quando a demanda a funcionalidades de sua aplicação aumenta, é de interesse que novos recursos sejam alocados para mantê-la operando e com tempo de resposta aceitável. No Kubernetes, a escalabilidade é obtida aumentando-se o número de réplicas especificadas no Deployment. Quando requisições são atendidas por múltiplas instâncias da aplicação, é preciso distribuir a carga de trabalho de alguma forma. Os serviços possuem um balanceador de carga embutido que se encarrega de fazê-lo. Serviços também se encarregam de verificar esporadicamente se cada um de seus Pods está operando, garantindo que requisições sejam atendidas somente por aqueles que estejam. Veja a figura a seguir.

O serviço distribui a carga entre as réplicas.
Obtenha a sua lista de Deployments com
Terminal
kubectl get deployments
Cada Deployment possui um ReplicaSet. O propósito de um ReplicaSet é viabilizar a replicação de Pods. Um ReplicaSet possui alguns campos, tais como
- um seletor usado para especificar quais Pods fazem parte dele
- um número de réplicas que indica quantos Pods devem ser mantidos em execução.
Use
Terminal
kubectl get rs
para verificar seus ReplicaSets. As colunas DESIRED e CURRENT indicam quantas réplicas da aplicação são desejadas e quantas estão atualmente em funcionamento, respectivamente. Veja o resultado a seguir.
Terminal
C:\Users\rodri>kubectl get rs
NAME DESIRED CURRENT READY AGE
meu-primeiro-deployment-7cd85b47b7 1 1 1 88m
Podemos aumentar o número de réplicas desejadas com
Terminal
kubectl scale deployments/meu-primeiro-deployment --replicas=4
Verifique novamente a sua lista de Deployments com
Terminal
kubectl get deployments
Verifique também a sua lista de Pods com
Terminal
kubectl get pods //simples
kubectl get pods -o wide //mais detalhes
A figura a seguir destaca que cada Pod tem seu próprio endereço IP.

Cada réplica tem seu próprio endereço IP.
A descrição de objetos do Kubernetes, em geral, inclui os eventos que os envolveram ao longo do tempo. Ajustar o número de réplicas como fizemos é um evento que teve impacto no Deployment. Visualize isso com
Terminal
kubectl describe deployments/meu-primeiro-deployment
A figura a seguir destaca a lista de eventos.

O ajuste de réplicas registrado nos eventos do Deployment.
Testando o balanceador de carga
Quando uma requisição é enviada ao serviço, ele deve usar o seu balanceador de carga para distribuir a carga de trabalho entre os Pods que gerencia. Como removemos o serviço anterior, será necessário criar um novo para testar o balanceador de carga. Faça isso com
Terminal
kubectl expose deployment/meu-primeiro-deployment --type="NodePort" --port 8080
A seguir, obtenha a porta exposta com
Terminal
kubectl get service meu-primeiro-deployment -o go-template="{{(index .spec.ports 0).nodePort}}"
set NODE_PORT=porta //Windows
export NODE_PORT=porta //Unix-like
Execute
Terminal
curl ip_da_sua_maquina:%NODE_PORT% //Windows
curl ip_da_sua_maquina:$NODE_PORT //Unix-like
diversas vezes e verifique o resultado. A figura a seguir destaca o nome do Pod responsável pelo atendimento a cada requisição.

Requisições atendidas por Pods diferentes.
Para reduzir o número de réplicas, basta usar
Terminal
kubectl scale deployments/meu-primeiro-deployment --replicas=2
E para testar, use
Terminal
kubectl get deployments //simples
kubectl get deployments -o wide //Mais detalhes
Volte a utilizar quatro réplicas para os testes a seguir, com
Terminal
kubectl scale deployments/meu-primeiro-deployment --replicas=4
9. Implantando novas versões: rolling updates
Nos dias atuais, é muito comum que desenvolvedores entreguem muitos pequenos updates em um único dia e que muitos deles sejam implantados no mesmo dia. Trata-se de uma prática comum de DevOps. Idealmente, a atualização acontece sem que a aplicação passe por um período de indisponibilidade. No Kubernetes, isso é obtido por meio de Rolling Updates. Um rolling update funciona substituindo gradualmente cada Pod existente por um novo. Enquanto um Pod é substituído, os demais permanecem atendendo as requisições dos clientes. Veja a figura a seguir.

Rolling update: os Pods são substituídos gradualmente.
Há algumas considerações importantes ainda sobre os rolling updates.
- Por padrão, no máximo um Pod pode ficar indisponível durante um rolling update.
- Por padrão, no máximo um Pod pode ser criado por vez durante um rolling update.
- Ambos valores citados podem ser reconfigurados.
- O Kubernetes aplica uma versão (um identificador) automaticamente a cada atualização realizada.
- Uma vez que uma atualização tenha sido realizada, é possível voltar para qualquer uma que tenha sido implantada com sucesso no passado.
Para testar o funcionamento dos rolling updates, comece usando
Terminal
kubectl get deployments
para visualizar os Deployments que possui no momento. A seguir, visualize os seus Pods com
Terminal
kubectl get pods
Visualize a imagem que está sendo executada pelos Pods com
Terminal
kubectl describe pods
Para atualizar a imagem sendo executada pelos Pods, use
Terminal
kubectl set image deployments/meu-primeiro-deployment kubernetes-bootcamp=jocatalin/kubernetes-bootcamp:v2
Logo depois, execute
Terminal
kubectl get pods
diversas vezes. Deverá ser possível ver informações sobre a criação e remoção de Pods, como ilustra a figura a seguir.

Pods sendo criados e removidos durante o rolling update.
Para testar a atualização, use
Terminal
curl ip_da_sua_maquina:%NODE_PORT% //Windows
curl ip_da_sua_maquina:$NODE_PORT //Unix-like
A figura a seguir destaca múltiplos Pods atendendo requisições. Perceba que todos eles estão usando a versão mais recente.

Todos os Pods respondendo com a versão 2.
Também é possível verificar o status da atualização com
Terminal
kubectl rollout status deployments/meu-primeiro-deployment
A seguir, vamos fazer uma atualização utilizando uma imagem inexistente. Assim, será necessário voltar à versão anterior. Para atualizar os Pods com a nova imagem, use
Terminal
kubectl set image deployments/meu-primeiro-deployment kubernetes-bootcamp=gcr.io/google-samples/kubernetes-bootcamp:v10
Observe, no resultado a seguir, que o número de Pods prontos não é o total (coluna READY). Um deles ficou comprometido com a tentativa de atualização utilizando uma imagem inexistente.
Terminal
C:\Users\rodri>kubectl set image deployments/meu-primeiro-deployment kubernetes-bootcamp=gcr.io/google-samples/kubernetes-bootcamp:v10
deployment.apps/meu-primeiro-deployment image updated
C:\Users\rodri>kubectl get deployments
NAME READY UP-TO-DATE AVAILABLE AGE
meu-primeiro-deployment 3/4 2 3 3h50m
Execute
Terminal
kubectl get pods
kubectl describe pods
para visualizar mais informações sobre os Pods e entender o que houve. Podemos desfazer a última atualização realizada com
Terminal
kubectl rollout undo deployments/meu-primeiro-deployment
10. Arquivos de configuração: um Pod
Cada objeto ou recurso como Pods e Deployments que criamos até então pode também ser criado por meio da especificação de arquivos de configuração. Essa é a forma recomendada de fazê-lo por diferentes razões.
- Uma vez escritos, eles podem ser armazenados no sistema de controle de versão junto com o código-fonte. Conforme o sistema evolui, aquilo que é alocado para seu funcionamento também muda. Por isso, para cada versão, é importante saber quais objetos precisam ser alocados.
- Eles documentam aquilo que está sendo alocado no Kubernetes para o funcionamento da aplicação.
Arquivo de configuração para um Pod: microsserviço de lembretes
Vamos escrever um arquivo de configuração em que especificamos um Pod para execução do microsserviço de lembretes.
Abra um terminal vinculado ao diretório em que se encontra o Dockerfile do seu microsserviço de lembretes. Vamos criar uma nova imagem com uma nova tag com
Terminal (pasta lembretes)
docker build -t rodbossini/lembretes:0.0.1 .
Há uma informação muito importante para usuários Minikube. Por padrão, o Minikube possui o seu próprio ambiente Docker, como mostra a figura a seguir.

O cliente Docker, por padrão, conversa com o daemon da máquina host.
Entretanto, o cliente Docker, por padrão, se comunica com o Docker daemon da máquina host, como ilustra a figura. O Docker daemon é um processo servidor responsável por atender às requisições feitas pelo cliente Docker. As imagens, contêineres etc criados ficam disponíveis na máquina host. Quando o Minikube tenta fazer uso de uma imagem por meio de seu rótulo, ele a procura localmente, em seu próprio ambiente Docker, e não na máquina host. Desta forma, caso a imagem tenha sido criada na máquina host, o Minikube irá reportar um erro do tipo ErrImagePull. Para resolver esse problema, podemos instruir o cliente Docker a enviar requisições ao Docker daemon que executa no ambiente Docker do Minikube. Isso pode ser feito com
Terminal
eval $(minikube docker-env) //Unix-like
minikube docker-env | Invoke-Expression //Powershell, Windows 10
O efeito é destacado na figura a seguir.

O cliente Docker passa a conversar com o daemon do Minikube.
Para fazer com que o cliente Docker passe a se comunicar novamente com o Docker daemon da máquina host, use
Terminal
eval $(minikube docker-env -u) //Unix-like
minikube docker-env -u | Invoke-Expression //Powershell, Windows 10
Visite https://minikube.sigs.k8s.io/docs/handbook/pushing/ para mais detalhes.
Prosseguindo, crie uma pasta chamada implantacao e, dentro dela, uma outra chamada kubernetes, como ilustra a figura a seguir.

A pasta implantacao/kubernetes no workspace.
Na pasta kubernetes, crie um arquivo chamado lembretes.yaml. Seu conteúdo aparece a seguir. Ele especifica
- apiVersion - Qual versão da API do Kubernetes está sendo usada para criar esse objeto. Ocorre que podemos especificar objetos customizados além daqueles disponíveis por padrão. Quando usamos
v1, estamos dizendo que queremos criar objetos a partir da coleção padrão do Kubernetes. Quando criamos objetos customizados, eles fazem parte de uma nova versão que criamos e que pode ser especificada aqui. - kind - Qual o tipo do objeto.
- metadata - Dados sobre o objeto, como o seu nome e um identificador.
- spec - Descrição do estado desejado para o objeto.
implantacao/kubernetes/lembretes.yaml
apiVersion: v1
kind: Pod
metadata:
name: lembretes
spec:
containers:
- name: lembretes
image: rodbossini/lembretes:0.0.1
resources:
limits:
memory: 256Mi
cpu: 1
A seguir, a partir de um terminal vinculado à pasta em que se encontra o arquivo lembretes.yaml, use
Terminal (pasta implantacao/kubernetes)
kubectl apply -f lembretes.yaml
para criar o Pod. Verifique a sua existência com
Terminal
kubectl get pods/lembretes
kubectl describe pods/lembretes
11. Arquivos de configuração: um Deployment
Como vimos, Deployments podem ser utilizados para tarefas importantes envolvendo replicação de Pods, atualização de versão de imagem em uso nos Pods e assim por diante. Eles também podem ser criados com arquivos de configuração. Nesta seção iremos definir um Deployment usando um arquivo de configuração. Os Pods a que ele estará associado também serão definidos assim, por isso, comece removendo o arquivo lembretes.yaml. Ele não causa nenhum dano mas não será mais usado. A seguir, crie um arquivo chamado lembretes-deployment.yaml. Seu conteúdo aparece a seguir.
implantacao/kubernetes/lembretes-deployment.yaml
#deployments vem de apps/v1
apiVersion: apps/v1
#tipo
kind: Deployment
metadata:
#nome do deployment
name: lembretes-deployment
spec:
#quantas cópias
replicas: 1
#para especificar o rótulo
selector:
matchLabels:
#rótulo, app não tem nada de especial, pode ser qq coisa
#Deployment vai selecionar todo Pod que tiver esse rótulo
app: lembretes
#modelo que vai ser usado para construção dos Pods
template:
metadata:
labels:
#os Pods terão esse rótulo, assim,
#serão selecionados por esse deployment
app: lembretes
spec:
containers:
- name: lembretes
image: rodbossini/lembretes:0.0.1
resources:
limits:
memory: 256Mi
cpu: 1
Crie o Deployment com
Terminal (pasta implantacao/kubernetes)
kubectl apply -f lembretes-deployment.yaml
Verifique a existência de seu Deployment com
Terminal
kubectl get deployments
kubectl describe deployments
Verifique também que há um Pod em execução. Seu nome deve ser igual ao nome do Deployment seguido de um código gerado pelo Kubernetes. É interessante observar que um Deployment é uma configuração usada pelo Kubernetes para decidir quais Pods devem estar em execução. Se removermos o Pod, ele será recriado! Você pode testar isso com
Terminal
//use o nome do pod que foi gerado na sua máquina
kubectl delete pod lembretes-deployment-76767c559c-x9m7g
//aguarde alguns segundos
kubectl get pods
Você deverá ver um novo Pod cujo nome contém o nome do Deployment. Note que o código em seu nome é diferente do anterior.
12. Atualizando a imagem de um Deployment
Uma imagem sendo utilizada por um Deployment pode ser atualizada de formas diferentes. Uma delas consiste em
- Fazer as atualizações desejadas no código-fonte da aplicação.
- Gerar uma nova imagem Docker.
- Atualizar o arquivo de configuração em que o Deployment foi especificado para que ele use a nova versão.
- Usar
kubectl applypara informar o Kubernetes sobre a atualização.
Para testar essa possibilidade, abra o arquivo index.js do microsserviço de lembretes. Adicione a linha console.log('Nova versão'), como a seguir.
lembretes/index.js
...
app.listen(4000, () => {
console.log('Nova versão')
console.log("Lembretes. Porta 4000");
});
A seguir, em um terminal vinculado ao diretório em que se encontram os arquivos do microsserviço de lembretes, execute
Terminal (pasta lembretes)
docker build -t rodbossini/lembretes:0.0.2 .
para gerar a nova imagem. Atualize o arquivo que descreve o Deployment como a seguir (a imagem passa a ser a versão 0.0.2).
implantacao/kubernetes/lembretes-deployment.yaml
#deployments vem de apps/v1
apiVersion: apps/v1
#tipo
kind: Deployment
metadata:
#nome do deployment
name: lembretes-deployment
spec:
#quantas cópias
replicas: 1
#para especificar o rótulo
selector:
matchLabels:
#rótulo, app não tem nada de especial, pode ser qq coisa
#Deployment vai selecionar todo Pod que tiver esse rótulo
app: lembretes
#modelo que vai ser usado para construção dos Pods
template:
metadata:
labels:
#os Pods terão esse rótulo, assim,
#serão selecionados por esse deployment
app: lembretes
spec:
containers:
- name: lembretes
image: rodbossini/lembretes:0.0.2
Passe a utilizar o novo Deployment com
Terminal (pasta implantacao/kubernetes)
kubectl apply -f lembretes-deployment.yaml
Ao executar
Terminal
kubectl get pods
você deverá visualizar um novo Pod com tempo de vida de apenas alguns segundos. Copie o nome dele e use
Terminal
kubectl logs lembretes-deployment-85968d5ff6-n2w9f //Use o nome do seu pod aqui
para visualizar seu log. O método que utilizamos pode se tornar mais difícil ao longo do tempo, especialmente quando os arquivos .yaml se tornarem maiores e mais complexos. Usando este método, toda vez que houver alguma alteração na aplicação, teremos de abrir o arquivo .yaml correspondente e atualizar a versão, como fizemos atualizando de 0.0.1 para 0.0.2. Em outras palavras, violamos o princípio aberto/fechado. Além disso, podemos digitar o número errado da versão. Uma segunda possibilidade de implantação consiste nos seguintes passos.
- Deixar de especificar a versão explicitamente, o que instrui o Kubernetes a utilizar a última versão disponível. Podemos simplesmente não especificar coisa alguma ou escrever a palavra
latestno lugar da versão. Dá na mesma. - Atualizar o código-fonte da aplicação conforme desejado.
- Gerar uma nova versão da imagem com o Docker.
- Enviar a imagem para o Docker Hub.
- Aplicar a nova versão com
kubectl rollout.
Comece atualizando o arquivo lembretes-deployment.yaml como a seguir (a imagem fica sem versão).
implantacao/kubernetes/lembretes-deployment.yaml
#deployments vem de apps/v1
apiVersion: apps/v1
#tipo
kind: Deployment
metadata:
#nome do deployment
name: lembretes-deployment
spec:
#quantas cópias
replicas: 1
#para especificar o rótulo
selector:
matchLabels:
#rótulo, app não tem nada de especial, pode ser qq coisa
#Deployment vai selecionar todo Pod que tiver esse rótulo
app: lembretes
#modelo que vai ser usado para construção dos Pods
template:
metadata:
labels:
#os Pods terão esse rótulo, assim,
#serão selecionados por esse deployment
app: lembretes
spec:
containers:
- name: lembretes
image: rodbossini/lembretes
A seguir, atualize o arquivo index.js do microsserviço de lembretes como a seguir.
lembretes/index.js
...
app.listen(4000, () => {
console.log("Nova versão");
console.log("Agora usando o Docker Hub");
console.log("Lembretes. Porta 4000");
});
O próximo passo é gerar uma nova imagem com o Docker. Com um terminal vinculado à pasta em que se encontra o arquivo index.js do microsserviço de lembretes, use
Terminal (pasta lembretes)
docker build -t rodbossini/lembretes .
Execute
Terminal
docker images
e verifique que a tag da nova imagem é latest, como no trecho de saída a seguir.
Terminal
REPOSITORY TAG
rodbossini/lembretes latest
Para enviar a imagem para o Docker Hub, faça login na sua conta com
Terminal
docker login
A seguir, execute
Terminal
docker push rodbossini/lembretes
para enviar a imagem para um repositório público do seu Docker Hub.
Para atualizar a imagem utilizada no Deployment, use
Terminal
kubectl rollout restart deployment lembretes-deployment
Verifique novamente a sua lista de Deployments com
Terminal
kubectl get deployments
Verifique também a sua lista de Pods com
Terminal
kubectl get pods
Como destaca o resultado a seguir, deve haver um novo Pod com poucos segundos de tempo de vida.
Terminal
NAME READY STATUS RESTARTS AGE
lembretes-deployment-6557d596fd-9rp7q 1/1 Running 0 7s
lembretes-deployment-75b97c596f-dd7tv 0/1 Terminating 0 4m55s
Anote o nome do novo Pod e use
Terminal
//use o nome do seu pod
kubectl logs lembretes-deployment-6557d596fd-9rp7q
para visualizar os logs do contêiner executando no novo Pod. O resultado deve ser parecido com o seguinte.
Terminal
[nodemon] 2.0.7
[nodemon] to restart at any time, enter `rs`
[nodemon] watching path(s): *.*
[nodemon] watching extensions: js,mjs,json
[nodemon] starting `node index.js`
Nova versão
Agora usando o Docker Hub
Lembretes. Porta 4000
Exemplo: Pod que usa somente imagens locais
apiVersion: v1
kind: Pod
metadata:
name: lembretes
spec:
containers:
- name: lembretes
image: rodbossini/lembretes
imagePullPolicy: Never
resources:
limits:
memory: 256Mi
cpu: 1
13. Serviço para acessar o microsserviço de lembretes
Nesta seção, vamos criar um serviço que irá viabilizar o acesso à aplicação que implantamos. Assim como os demais objetos, serviços também podem ser criados por meio de arquivos de configuração. Comece criando um arquivo chamado lembretes-service.yaml na pasta implantacao/kubernetes. Seu conteúdo aparece a seguir.
implantacao/kubernetes/lembretes-service.yaml
apiVersion: v1
kind: Service
metadata:
name: lembretes-service
spec:
#Ip externo, acessível fora do cluster
type: NodePort
selector:
#todo Pod que tiver essa tag
#fará parte desse serviço
app: lembretes
ports:
- name: lembretes
protocol: TCP
#o nó recebe requisições nessa porta
port: 4000
# e direciona para essa porta do Pod
targetPort: 4000
Para criar o serviço use
Terminal (pasta implantacao/kubernetes)
kubectl apply -f lembretes-service.yaml
Verifique a sua existência com
Terminal
kubectl get services
kubectl describe service lembretes-service
A figura a seguir destaca a porta aleatória que foi associada ao serviço. Esta é a porta que deve ser usada externamente. O cliente envia requisições para esta porta. Internamente, o serviço as redireciona para a porta 4000 do nó que, por sua vez, as entrega ao contêiner em sua porta 4000.

A porta aleatória (aqui, 32143) associada ao serviço NodePort.
Use o Postman para fazer uma requisição em http://localhost:sua_porta/lembretes.
14. Comunicação interna: serviços ClusterIP
Até então, os microsserviços utilizam o endereço IP da máquina host para se comunicarem. Isso já não será possível uma vez que sejam executados por instâncias de Pods do Kubernetes. Para viabilizar a comunicação interna entre microsserviços executando em uma instância do Kubernetes, usamos serviços do tipo Cluster IP.
Deployment e serviço ClusterIP para o barramento de eventos e para o microsserviço de lembretes
Começamos colocando o barramento de eventos em funcionamento e viabilizando a sua comunicação com o microsserviço de lembretes. Isso será feito da seguinte forma.
- Construir uma imagem Docker para o barramento de eventos.
- Enviar a imagem para o Docker Hub.
- Criar um Deployment para o barramento de eventos.
- Criar um serviço do tipo Cluster IP para o barramento de eventos e para o microsserviço de lembretes.
Para criar a imagem Docker para o barramento de eventos, vá até o diretório em que se encontra o respectivo arquivo Dockerfile e use
Terminal (pasta barramento-de-eventos)
docker build -t rodbossini/barramento-de-eventos .
Envie a imagem para o Docker Hub com
Terminal (pasta barramento-de-eventos)
docker push rodbossini/barramento-de-eventos
Repita o procedimento para a imagem Docker do microsserviço de lembretes. Crie uma nova com
Terminal (pasta lembretes)
docker build -t rodbossini/lembretes .
e envie para o Docker Hub com
Terminal (pasta lembretes)
docker push rodbossini/lembretes
Crie um arquivo chamado barramento-de-eventos-deployment.yaml na pasta implantacao/kubernetes. Seu conteúdo aparece a seguir.
implantacao/kubernetes/barramento-de-eventos-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: barramento-de-eventos-deployment
spec:
replicas: 1
selector:
matchLabels:
app: barramento-de-eventos
template:
metadata:
labels:
app: barramento-de-eventos
spec:
containers:
- name: barramento-de-eventos
image: rodbossini/barramento-de-eventos
Para criar o novo Deployment, use
Terminal (pasta implantacao/kubernetes)
kubectl apply -f barramento-de-eventos-deployment.yaml
Execute
Terminal
kubectl get pods
para verificar se há um novo Pod em funcionamento. O prefixo de seu nome deve ser barramento-de-eventos. Seu tempo de vida deve ser de alguns segundos. O serviço do tipo Cluster IP para disponibilização interna do barramento de eventos também será criado no arquivo barramento-de-eventos-deployment.yaml, depois de um separador ---. Veja o arquivo completo a seguir.
implantacao/kubernetes/barramento-de-eventos-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: barramento-de-eventos-deployment
spec:
replicas: 1
selector:
matchLabels:
app: barramento-de-eventos
template:
metadata:
labels:
app: barramento-de-eventos
spec:
containers:
- name: barramento-de-eventos
image: rodbossini/barramento-de-eventos
---
apiVersion: v1
kind: Service
metadata:
name: barramento-de-eventos-service
spec:
selector:
app: barramento-de-eventos
#ip interno ao cluster
type: ClusterIP
ports:
- name: barramento-de-eventos
protocol: TCP
port: 10000
targetPort: 10000
Para confirmar a criação do serviço, use
Terminal (pasta implantacao/kubernetes)
kubectl apply -f barramento-de-eventos-deployment.yaml
O novo serviço criado pode ser visualizado com
Terminal
kubectl get services
O resultado deve ser parecido com aquele exibido pela figura a seguir.

O serviço ClusterIP do barramento de eventos.
A criação do serviço de tipo Cluster IP para o microsserviço de lembretes é semelhante. Abra o arquivo lembretes-deployment.yaml e adicione o conteúdo a partir do separador ---, como a seguir.
implantacao/kubernetes/lembretes-deployment.yaml
#deployments vem de apps/v1
apiVersion: apps/v1
#tipo
kind: Deployment
metadata:
name: lembretes-deployment #nome do deployment
spec:
#quantas cópias
replicas: 1
#para especificar o rótulo
selector:
matchLabels:
#rótulo, app não tem nada de especial, pode ser qq coisa
#Deployment vai selecionar todo Pod que tiver esse rótulo
app: lembretes
#modelo que vai ser usado para construção dos Pods
template:
metadata:
labels:
#os Pods terão esse rótulo, assim,
#serão selecionados por esse deployment
app: lembretes
spec:
containers:
- name: lembretes
image: rodbossini/lembretes
---
apiVersion: v1
kind: Service
metadata:
#nome diferente do outro de tipo NodePort
#que havíamos criado
name: lembretes-clusterip-service
spec:
selector:
app: lembretes
ports:
- name: lembretes
protocol: TCP
port: 4000
targetPort: 4000
O barramento de eventos tenta se comunicar com todos os microsserviços. Vamos manter a sua comunicação somente com o microsserviço de lembretes para depois fazer os ajustes necessários. Veja o código a seguir.
barramento-de-eventos/index.js
const eventos = [];
app.post("/eventos", (req, res) => {
const evento = req.body;
eventos.push(evento);
//envia o evento para o microsserviço de lembretes
axios.post("http://localhost:4000/eventos", evento);
//envia o evento para o microsserviço de observações
//axios.post("http://localhost:5000/eventos", evento);
//envia o evento para o microsserviço de consulta
// axios.post("http://localhost:6000/eventos", evento).catch((err) => {
// console.log("err", err);
// });
//envia o evento para o microsservico de classificacao
//axios.post("http://localhost:7000/eventos", evento);
res.status(200).send({ msg: "ok" });
});
Nossos microsserviços estão fazendo requisições direcionadas a localhost, o que já não funciona já que eles estão sob coordenação dos serviços Kubernetes que criamos. É preciso substituir a constante localhost usando os nomes dos serviços criados. Os nomes dos serviços são aqueles especificados nos arquivos .yaml. Também é possível obtê-los com
Terminal
kubectl get services
Veja o resultado na figura a seguir.

Os nomes dos serviços, usados no lugar de localhost.
Comece ajustando o microsserviço de lembretes. Em seu arquivo index.js, substitua a constante localhost pelo nome do serviço Kubernetes que dá acesso ao barramento de eventos. Veja o código a seguir.
lembretes/index.js
...
//era assim
//await axios.post("http://localhost:10000/eventos", {
//fica assim
await axios.post("http://barramento-de-eventos-service:10000/eventos", {
tipo: "LembreteCriado",
dados: {
contador,
texto,
},
});
res.status(201).send(lembretes[contador]);
});
Faça o mesmo ajuste para o barramento de eventos. Faça com que ele use o nome do serviço Kubernetes que dá acesso interno ao microsserviço de lembretes, como no código a seguir.
barramento-de-eventos/index.js
app.post("/eventos", (req, res) => {
const evento = req.body;
eventos.push(evento);
//envia o evento para o microsserviço de lembretes
//era assim
//axios.post("http://localhost:4000/eventos", evento);
//fica assim
axios.post("http://lembretes-clusterip-service:4000/eventos", evento);
//envia o evento para o microsserviço de observações
//axios.post("http://localhost:5000/eventos", evento);
//envia o evento para o microsserviço de consulta
// axios.post("http://localhost:6000/eventos", evento).catch((err) => {
// console.log("err", err);
// });
//envia o evento para o microsservico de classificacao
//axios.post("http://localhost:7000/eventos", evento);
res.status(200).send({ msg: "ok" });
});
Feitas as atualizações, precisamos gerar novas imagens Docker. Vá até a pasta em que se encontra o arquivo Dockerfile do barramento de eventos e execute
Terminal (pasta barramento-de-eventos)
docker build -t rodbossini/barramento-de-eventos .
para gerar a nova imagem. A seguir, use
Terminal (pasta barramento-de-eventos)
docker push rodbossini/barramento-de-eventos
para enviá-la para o Docker Hub. Repita o procedimento para o microsserviço de lembretes. Na pasta em que se encontra o seu arquivo Dockerfile, execute
Terminal (pasta lembretes)
docker build -t rodbossini/lembretes .
A seguir, envie a imagem para o Docker Hub com
Terminal (pasta lembretes)
docker push rodbossini/lembretes
A seguir, precisamos atualizar os Deployments. Use
Terminal
kubectl get deployments
caso precise se lembrar de seus nomes. Veja o resultado a seguir.
Terminal
NAME READY UP-TO-DATE AVAILABLE AGE
barramento-de-eventos-deployment 1/1 1 1 6d20h
lembretes-deployment 1/1 1 1 7d12h
A atualização dos Deployments pode ser feita com
Terminal
kubectl rollout restart deployment barramento-de-eventos-deployment
e
Terminal
kubectl rollout restart deployment lembretes-deployment
Execute
Terminal
kubectl get pods
e verifique os novos Pods criados. Eles devem ter poucos segundos de tempo de vida. É possível que você ainda veja os antigos sendo destruídos, caso execute este comando logo após a atualização dos Deployments. Veja o resultado a seguir (colunas STATUS e AGE).
Terminal
NAME READY STATUS RESTARTS AGE
barramento-de-eventos-deployment-6cb889765b-7xzjj 1/1 Running 0 23s
lembretes-deployment-6557d596fd-tzx55 0/1 Terminating 1 6d19h
lembretes-deployment-74f46c9b87-lzcp4 1/1 Running 0 8s
15. Testando a comunicação interna
Neste instante já deve ser possível testar a comunicação interna entre o microsserviço de lembretes e o barramento de eventos. Para isso, precisamos utilizar um cliente HTTP (como o Postman) para enviar uma requisição ao cluster Kubernetes. A requisição partirá de um ambiente externo ao cluster, por isso precisamos usar uma porta que tenha sido aberta previamente. Lembre-se que isso é feito utilizando um serviço Kubernetes do tipo NodePort ou LoadBalancer. O serviço Kubernetes do tipo NodePort que criamos anteriormente pode ser visualizado com
Terminal
kubectl get services
Veja o resultado na figura a seguir. Note que é possível visualizar a porta que foi aberta para o ambiente externo.

A porta externa do serviço NodePort (aqui, 30686).
O endereço IP a ser utilizado para fazer a requisição é aquele associado ao ambiente em que o cluster está em execução. Caso esteja utilizando o Docker for Desktop, basta utilizar a constante localhost. Usuários do Minikube podem obter o seu endereço IP com
Terminal
minikube ip
Abra o Postman e faça uma requisição PUT como ilustra a figura a seguir. Lembre-se de substituir localhost pelo IP apropriado, caso esteja utilizando o Minikube.

Criando um lembrete no cluster pela porta do serviço NodePort.
A seguir, faça também um GET, como na figura a seguir.

Obtendo os lembretes do microsserviço executado no cluster.
Para ter certeza de que tudo deu certo, verifique os logs do Pod que executa o microsserviço de lembretes. Ele deve ter recebido um evento do barramento de eventos e exibido na saída padrão. Pegue o nome do Pod com
Terminal
kubectl get pods
Veja o resultado a seguir.
Terminal
NAME READY STATUS RESTARTS AGE
barramento-de-eventos-deployment-6cb889765b-7xzjj 1/1 Running 0 28m
lembretes-deployment-78dc5fd895-lg9xr 1/1 Running 0 3m13s
A seguir, use
Terminal
kubectl logs nome_do_seu_pod
para visualizar seus logs. A saída deve ser parecida com a seguinte; a última linha mostra o evento recebido.
Terminal
[nodemon] 2.0.7
[nodemon] to restart at any time, enter `rs`
[nodemon] watching path(s): *.*
[nodemon] watching extensions: js,mjs,json
[nodemon] starting `node index.js`
Testando no Windows
Nova versão
Agora usando o Docker Hub
Lembretes. Porta 4000
Evento recebido: LembreteCriado
Caso a sua saída não exiba uma mensagem assim, pode ser que o seu microsserviço de lembretes não esteja registrando cada evento que recebe. Você pode ajustar isso como mostra o código a seguir. Estamos no arquivo index.js do microsserviço de lembretes.
lembretes/index.js
...
app.post("/eventos", (req, res) => {
console.log("Evento recebido: " + req.body.tipo);
res.status(200).send({ msg: "ok" });
});
...
16. Exercício e encerramento
Exercício
Crie novos serviços Kubernetes do tipo Cluster IP e coloque os demais microsserviços em funcionamento. Faça um teste completo e certifique-se de que a solução está completamente funcional.
Parabéns!
Você concluiu as três partes da apostila. Ao longo delas você:
- estudou arquitetura de software e a arquitetura baseada em microsserviços;
- construiu os microsserviços de lembretes, observações, consulta e classificação, ligados por um barramento de eventos próprio;
- executou cada microsserviço em um contêiner Docker;
- usou o Kubernetes para criar Deployments, Pods e Services, escalar, atualizar versões e fazer os microsserviços se comunicarem dentro do cluster.
Referências
- L. Bass, P. Clements e R. Kazman. Software Architecture in Practice. 3ª ed. Addison-Wesley Professional, 2012.
- Dahl, R. Node.js. Disponível em: https://nodejs.org/en/. Acesso em abril de 2021.
- A. Fox e D. Patterson. Engineering Software as a Service - An Agile Approach Using Cloud Computing. 1ª ed. Strawberry Canyon LLC, 2018.
- Martin Fowler. Who Needs an Architect? Disponível em: https://martinfowler.com/ieeeSoftware/whoNeedsArchitect.pdf. Acesso em fevereiro de 2021.
- TJ Holowaychuk. Express - Node.js web application framework. Disponível em: https://expressjs.com. Acesso em abril de 2021.