Implantar um app Java do Spring Boot no Kubernetes no Google Kubernetes Engine

1. Antes de começar

O Kubernetes é um projeto de código aberto que pode ser executado em diversos ambientes, de laptops a clusters com vários nós de alta disponibilidade, de nuvens públicas a implantações no local e de instâncias de máquina virtual (VM) a bare metal.

Neste codelab, você vai implantar um app da Web simples do Spring Boot em Java no Kubernetes do GKE para executar seu app da Web como um aplicativo replicado no Kubernetes. Você vai transformar o código desenvolvido na sua máquina em uma imagem de contêiner do Docker e executá-la no GKE.

Você vai usar o GKE, um serviço Kubernetes totalmente gerenciado no Google Cloud, para se concentrar mais em testar o Kubernetes, em vez de configurar a infraestrutura subjacente.

Se você quiser executar o Kubernetes na sua máquina local, como em um laptop de desenvolvimento, confira o Minikube, que oferece uma configuração simples de um cluster do Kubernetes de nó único para fins de desenvolvimento e teste. Você pode usar o Minikube para fazer o codelab, se quiser.

O codelab usará o exemplo de código do guia sobre Como criar um app com o Spring Boot.

Pré-requisitos

  • Conhecer a linguagem de programação e as ferramentas Java
  • Conhecimento sobre editores de texto padrão do Linux, como Vim, Emacs e nano.

O que você aprenderá

  • Empacotar um app Java simples como um contêiner do Docker
  • Crie seu cluster do Kubernetes no GKE.
  • Implante o app Java no Kubernetes no GKE.
  • Escalone verticalmente seu serviço e lance um upgrade.
  • Access Dashboard, uma interface do usuário do Kubernetes baseada na Web.

O que é necessário

2. Configuração e requisitos

Configuração de ambiente autoguiada

  1. Faça login no Console do Google Cloud e crie um novo projeto ou reutilize um existente. Crie uma conta do Gmail ou do Google Workspace, se ainda não tiver uma.

b35bf95b8bf3d5d8.png

a99b7ace416376c4.png

bd84a6d3004737c5.png

  • O Nome do projeto é o nome de exibição para os participantes do projeto. É uma string de caracteres não usada pelas APIs do Google e pode ser atualizada quando você quiser.
  • O ID do projeto precisa ser exclusivo em todos os projetos do Google Cloud e não pode ser mudado após a definição. O console do Cloud gera automaticamente uma string exclusiva. Em geral, não importa o que seja. Na maioria dos codelabs, é necessário fazer referência ao ID do projeto, normalmente identificado como PROJECT_ID. Se você não gostar do ID gerado, crie outro aleatório. Se preferir, teste o seu e confira se ele está disponível. Ele não pode ser mudado após essa etapa e permanece durante o projeto.
  • Para sua informação, há um terceiro valor, um Número do projeto, que algumas APIs usam. Saiba mais sobre esses três valores na documentação.
  1. Em seguida, ative o faturamento no console do Cloud para usar os recursos/APIs do Cloud. A execução deste codelab não vai ser muito cara, se tiver algum custo. Para encerrar os recursos e evitar cobranças além deste tutorial, exclua os recursos criados ou exclua o projeto. Novos usuários do Google Cloud estão qualificados para o programa de US$ 300 de avaliação sem custos.

Ativar o Cloud Shell

  1. No Console do Cloud, clique em Ativar o Cloud Shell853e55310c205094.png.

55efc1aaa7a4d3ad.png

Se você estiver iniciando o Cloud Shell pela primeira vez, verá uma tela intermediária com a descrição dele. Se aparecer uma tela intermediária, clique em Continuar.

9c92662c6a846a5c.png

Leva apenas alguns instantes para provisionar e se conectar ao Cloud Shell.

9f0e51b578fecce5.png

Essa máquina virtual tem todas as ferramentas de desenvolvimento necessárias. Ela oferece um diretório principal persistente de 5 GB, além de ser executada no Google Cloud. Isso aprimora o desempenho e a autenticação da rede. Grande parte do trabalho neste codelab, se não todo, pode ser feito em um navegador.

Depois de se conectar ao Cloud Shell, você verá sua autenticação e o projeto estará configurado com o ID do seu projeto.

  1. Execute o seguinte comando no Cloud Shell para confirmar se a conta está autenticada:
gcloud auth list

Resposta ao comando

 Credentialed Accounts
ACTIVE  ACCOUNT
*       <my_account>@<my_domain.com>

To set the active account, run:
    $ gcloud config set account `ACCOUNT`
  1. Execute o seguinte comando no Cloud Shell para confirmar que o comando gcloud sabe sobre seu projeto:
gcloud config list project

Resposta ao comando

[core]
project = <PROJECT_ID>

Se o projeto não estiver configurado, configure-o usando este comando:

gcloud config set project <PROJECT_ID>

Resposta ao comando

Updated property [core/project].

3. Encontrar o código-fonte

Depois que o Cloud Shell for iniciado, use a linha de comando para clonar o código-fonte de exemplo no diretório principal.

$ git clone https://github.com/spring-guides/gs-spring-boot.git
$ cd gs-spring-boot/complete

4. Executar o app localmente

  1. Verifique se JAVA_HOME está definido com a versão correta:
$ export JAVA_HOME=/usr/lib/jvm/java-1.17.0-openjdk-amd64
  1. É possível iniciar o app Spring Boot normalmente com o plug-in Spring Boot.
$ ./mvnw -DskipTests spring-boot:run
  1. Depois que o app for iniciado, clique em Visualização na Web 1a94d5bd10bfc072.pngna barra de ferramentas do Cloud Shell e selecione Visualizar na porta 8080.

6252b94905f3f7bd.png

Uma guia será aberta no navegador, conectando você ao servidor que acabou de iniciar.

9b6c29059957bd0.jpeg

5. Empacotar o app Java como um contêiner do Docker

Em seguida, você precisa preparar o app para ser executado no Kubernetes. O primeiro passo é definir o contêiner e o conteúdo dele.

  1. Crie o JAR implantável para o app.
$ ./mvnw -DskipTests package
  1. Ative a API Artifact Registry para armazenar a imagem do contêiner que você vai criar.
$ gcloud services enable artifactregistry.googleapis.com
  1. Crie um novo repositório do Docker, se não houver um. É necessário criar um repositório antes de enviar imagens para ele:
$ gcloud artifacts repositories create codelabrepo     --repository-format=docker --location=us-central1 
  1. A imagem estará no formato:

{LOCATION}-docker.pkg.dev/{PROJECT-ID}/{REPOSITORY}/{IMAGE-NAME}

Por exemplo, se você criou o repositório no local us-central1 chamado codelabrepo e quer nomear sua imagem como hello-java:v1, ela será:

us-central1-docker.pkg.dev/{PROJECT-ID}/codelabrepo/hello-java:v1

  1. Use o Jib para criar a imagem do contêiner e enviá-la para o Artifact Registry.
$ export GOOGLE_CLOUD_PROJECT=`gcloud config list --format="value(core.project)"`

$ ./mvnw -DskipTests com.google.cloud.tools:jib-maven-plugin:build -Dimage=us-central1-docker.pkg.dev/${GOOGLE_CLOUD_PROJECT}/codelabrepo/hello-java:v1
  1. Para conferir a imagem do contêiner listada no console, acesse a página Imagens do Artifacts Registry no console do Cloud. Agora você tem uma imagem Docker para todo o projeto disponível, que o Kubernetes pode acessar e orquestrar, como você verá em alguns minutos.
  2. (Opcional) Após a conclusão, que levará algum tempo para fazer o download e extrair tudo, teste a imagem com o comando a seguir, que executará um contêiner do Docker como um daemon na porta 8080 usando a imagem do contêiner recém-criada. Se você tiver problemas de permissões, execute o gcloud auth configure-docker us-central1-docker.pkg.dev primeiro:
$ docker run -ti --rm -p 8080:8080 \
  us-central1-docker.pkg.dev/$GOOGLE_CLOUD_PROJECT/codelabrepo/hello-java:v1
  1. Mais uma vez, aproveite o recurso de visualização da Web do Cloud Shell.

6252b94905f3f7bd.png

  1. A página padrão vai aparecer em uma nova guia. Depois de verificar se o app está em execução localmente em um contêiner do Docker, pressione Control+C para interromper esse contêiner.

6. Crie o cluster

Você já pode criar o cluster do GKE. Um cluster consiste em um servidor da API Kubernetes gerenciado pelo Google e um conjunto de nós de trabalho. Os nós de trabalho são VMs do Compute Engine.

  1. Primeiro, verifique se os recursos de API relacionados estão ativados.
$ gcloud services enable compute.googleapis.com container.googleapis.com
  1. Crie um cluster com dois nós n1-standard-1 (esse processo vai levar alguns minutos).
$ gcloud container clusters create hello-java-cluster \
  --num-nodes 2 \
  --machine-type n1-standard-1 \
  --zone us-central1-c

No final, você verá o cluster criado.

Creating cluster hello-java-cluster...done.
Created [https://container.googleapis.com/v1/projects/...].
kubeconfig entry generated for hello-dotnet-cluster.
NAME                  ZONE            MASTER_VERSION  
hello-java-cluster  us-central1-c  ...

Agora você tem um cluster do Kubernetes totalmente funcional com a tecnologia do GKE.

758c7fca14f70623.png

Agora é hora de implantar o app conteinerizado no cluster do Kubernetes. A partir de agora, você usará a linha de comando kubectl, que já está configurada no ambiente do Cloud Shell. O restante do codelab exige que o cliente e o servidor do Kubernetes sejam a 1.2 ou mais recente. kubectl version vai mostrar a versão atual do comando.

7. Implantar o app no Kubernetes

  1. Uma implantação do Kubernetes pode criar, gerenciar e escalonar várias instâncias do seu app usando a imagem de contêiner que você criou. Implante uma instância do app no Kubernetes usando o comando kubectl run.
$ kubectl create deployment hello-java --image=us-central1-docker.pkg.dev/$GOOGLE_CLOUD_PROJECT/codelabrepo/hello-java:v1
  1. Para ver a implantação que você criou, basta executar o seguinte comando:
$ kubectl get deployments

NAME         DESIRED   CURRENT   UP-TO-DATE   AVAILABLE   AGE
hello-java   1         1         1            1           37s
  1. Para ver as instâncias de apps criadas pela implantação, execute o seguinte comando:
$ kubectl get pods

NAME                         READY     STATUS    RESTARTS   AGE
hello-java-714049816-ztzrb   1/1       Running   0          57s

Neste ponto, o contêiner já deve estar em execução sob o controle do Kubernetes, mas você ainda precisa torná-lo acessível ao mundo exterior.

8. permitir o tráfego externo

Por padrão, o pod só pode ser acessado pelo IP interno dentro do cluster. Para tornar o contêiner hello-java acessível de fora da rede virtual do Kubernetes, exponha o pod como um serviço do Kubernetes.

  1. No Cloud Shell, é possível expor o pod à Internet pública criando um serviço LoadBalancer do Kubernetes.
$ kubectl create service loadbalancer hello-java --tcp=8080:8080

Observe que você expõe diretamente a implantação, não o pod. Isso fará com que o serviço resultante faça o balanceamento de carga do tráfego em todos os pods gerenciados pela implantação. Neste caso, é apenas um pod, mas você vai adicionar mais réplicas depois.

O mestre do Kubernetes cria o balanceador de carga e as regras de encaminhamento, pools de destino e regras de firewall do Compute Engine para tornar o serviço totalmente acessível de fora do Google Cloud.

  1. Para encontrar o endereço IP publicamente acessível do serviço, basta solicitar que kubectl liste todos os serviços de cluster.
$ kubectl get services

NAME         CLUSTER-IP     EXTERNAL-IP      PORT(S)    AGE
hello-java   10.3.253.62    aaa.bbb.ccc.ddd  8080/TCP    1m
kubernetes   10.3.240.1     <none>           443/TCP    5m
  1. Agora você deve conseguir acessar o serviço apontando o navegador para http://<EXTERNAL_IP>:8080.

9. Escalone seu serviço

Um dos recursos avançados oferecidos pelo Kubernetes é a facilidade de escalonar seu app. Suponha que, de repente, você precise de mais capacidade para seu app. Basta dizer ao controlador de replicação para gerenciar um novo número de réplicas para as instâncias do seu app.

$ kubectl scale deployment hello-java --replicas=3

deployment "hello-java" scaled

$ kubectl get deployment
NAME         DESIRED   CURRENT   UP-TO-DATE   AVAILABLE   AGE
hello-java   3         3         3            3           22m

Observe a abordagem declarativa. Em vez de iniciar ou interromper novas instâncias, você declara quantas instâncias precisam estar em execução o tempo todo. Os loops de reconciliação do Kubernetes simplesmente garantem que a realidade corresponde ao que você solicitou e tomam medidas, se necessário.

10. implementar uma atualização no serviço

Em algum momento, o app implantado na produção exigirá correções de bugs ou recursos adicionais. O Kubernetes pode ajudar você a implantar uma nova versão na produção sem afetar seus usuários.

  1. Clique em Abrir editor 2109d75686c889a.pngno menu do Cloud Shell para abrir o editor de código.
  2. Navegue até src/main/java/com/example/springboot/HelloController.java e atualize o valor da resposta.
package com.example.springboot;

import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.bind.annotation.RequestMapping;

@RestController
public class HelloController {

    @RequestMapping("/")
    public String index() {
        return "Greetings from Google Kubernetes Engine!";
    }
}
  1. Use o Jib para criar e enviar uma nova versão da imagem do contêiner. A criação e o envio da imagem atualizada serão muito mais rápidos quando você aproveitar plenamente o armazenamento em cache.
$ ./mvnw -DskipTests package com.google.cloud.tools:jib-maven-plugin:build -Dimage=us-central1-docker.pkg.dev/$GOOGLE_CLOUD_PROJECT/codelabrepo/hello-java:v2

Está tudo pronto para o Kubernetes atualizar facilmente seu controlador de replicação para a nova versão do app.

  1. Para mudar o rótulo da imagem do contêiner em execução, é necessário editar a implantação hello-java atual e mudar a imagem de us-central1-docker.pkg.dev/PROJECT_ID/codelabrepo/hello-java:v1

para us-central1-docker.pkg.dev/PROJECT_ID/codelabrepo/hello-java:v2

  1. Use o comando kubectl set image para pedir que o Kubernetes implante a nova versão do app em todo o cluster, uma instância por vez, com atualizações graduais.
$ kubectl set image deployment/hello-java hello-java=us-central1-docker.pkg.dev/$GOOGLE_CLOUD_PROJECT/codelabrepo/hello-java:v2

deployment "hello-java" image updated
  1. Verifique http://EXTERNAL_IP:8080 novamente para ver se ele está retornando a nova resposta.

11. Reverter

Ops! Você cometeu um erro com uma nova versão do aplicativo? Talvez a nova versão contenha um erro e você precise revertê-la rapidamente. Com o Kubernetes, é fácil revertê-lo ao estado anterior. Reverta o app executando o seguinte comando:

$ kubectl rollout undo deployment/hello-java

Você verá a resposta antiga quando verificar http://EXTERNAL_IP:8080 novamente.

12. Parabéns

Você aprendeu a criar e implantar um novo app da Web baseado em Java no Kubernetes no GKE.

Limpeza

$ gcloud container clusters delete hello-java-cluster --zone us-central1-c

$ gcloud container images delete us-central1-docker.pkg.dev/$GOOGLE_CLOUD_PROJECT/codelabrepo/hello-java:v1 us-central1-docker.pkg.dev/$GOOGLE_CLOUD_PROJECT/codelabrepo/hello-java:v2

Saiba mais