1. Visão geral
Sobre a Micronaut
O Micronaut é um framework de pilha completa moderno baseado em JVM para a criação de aplicativos sem servidor e microsserviços modulares e facilmente testáveis. A Micronaut tem como objetivo oferecer um ótimo tempo de inicialização, capacidade de processamento rápida e um consumo mínimo de memória. Os desenvolvedores podem desenvolver com o Micronaut em Java, Groovy ou Kotlin.
O Micronaut oferece:
- Inicialização rápida e Baixo consumo de memória: frameworks de IoC baseados em reflexões carregam e armazenam em cache os dados de reflexão para cada campo, método e construtor no seu código, enquanto que, com o Micronaut, o tempo de inicialização e o consumo de memória do aplicativo não estão vinculados ao tamanho da sua base de código.
- Cliente HTTP declarativo, reativo e em tempo de compilação: crie clientes HTTP reativos de forma declarativa, que são implementados no momento da compilação, reduzindo o consumo de memória.
- Servidor HTTP sem bloqueios integrado ao Netty: com uma curva de aprendizado suave, o servidor HTTP da Micronaut facilita ao máximo a exposição de APIs que podem ser consumidas por clientes HTTP.
- Testes rápidos e fáceis: ative com facilidade servidores e clientes nos seus testes de unidade e execute-os instantaneamente.
- Injeção eficiente de dependências no tempo de compilação e AOP: o Micronaut oferece uma API de programação simples orientada a aspectos em tempo de compilação que não usa reflexão.
- Criar apps totalmente reativos e sem bloqueio: o Micronaut oferece suporte a qualquer framework que implemente streams reativos, incluindo RxJava e Reactor.
Para mais informações, acesse o site da Micronaut.
Sobre o Kubernetes
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 locais e de máquinas virtuais a bare metal.
Neste laboratório, você vai implantar um microsserviço simples baseado no Groovy no Kubernetes em execução no Kubernetes Engine.
O objetivo deste codelab é executar o microsserviço como um serviço replicado em execução no Kubernetes. Você pega o código que desenvolveu em sua máquina, o transforma em uma imagem de contêiner do Docker e, em seguida, executa essa imagem no Kubernetes Engine.
Veja um diagrama das várias partes deste codelab para ajudar você a entender como as peças se encaixam. Use-o como referência ao longo do codelab. tudo deverá fazer sentido quando você chegar ao fim (mas sinta-se à vontade para ignorar isso por enquanto).
Para os fins deste codelab, o uso de um ambiente gerenciado como o Kubernetes Engine (uma versão hospedada pelo Google do Kubernetes em execução no Compute Engine) permite que você se concentre mais em testar o Kubernetes, em vez de configurar a infraestrutura subjacente.
Se você estiver interessado em executar o Kubernetes no computador, como um laptop de desenvolvimento, conheça o Minikube. Ele oferece uma configuração simples de um cluster do Kubernetes de nó único para desenvolvimento e teste. Se quiser, use o Minikube para fazer este codelab.
Sobre o Jib
Jib é uma ferramenta de código aberto que permite criar imagens Docker e OCI para aplicativos Java. Ela está disponível como plug-ins para Maven e Gradle e como uma biblioteca Java.
O objetivo do Jib é:
- Rápido: implante as alterações rapidamente. Ela separa seu aplicativo em várias camadas, dividindo as dependências das classes. Agora você não precisa esperar que o Docker recrie todo o seu aplicativo Java, basta implantar as camadas que mudaram.
- Reprodutível: recriar a imagem do contêiner com o mesmo conteúdo sempre gera a mesma imagem. Nunca mais acione uma atualização desnecessária.
- Daemonless: reduza suas dependências de CLI. Crie sua imagem Docker no Maven ou Gradle e envie por push para qualquer registro de sua escolha. Chega de escrever Dockerfiles e chamar build/push do Docker.
Saiba mais sobre o Jib na página do projeto do GitHub.
Sobre este tutorial
Neste tutorial, usamos o exemplo de código da ferramenta Jib para criar contêineres para aplicativos Java.
O exemplo é um serviço hello world simples que usa o framework Micronaut e a linguagem de programação Apache Groovy (links em inglês).
O que você vai aprender
- Como empacotar um aplicativo Java simples como um contêiner do Docker usando o Jib
- Como criar um cluster do Kubernetes no Kubernetes Engine.
- Como implantar um serviço do Micronaut no Kubernetes com o Kubernetes Engine
- Como escalonar verticalmente o serviço e fazer um upgrade
- Como acessar o painel gráfico do Kubernetes.
O que é necessário
- Um projeto do Google Cloud Platform
- Um navegador, como o Chrome ou o Firefox
- Conhecer os editores de texto padrão do Linux, como vim, emacs ou nano
Como você usará este tutorial?
Como você classificaria sua experiência com a criação de apps da Web HTML/CSS?
Como você classificaria sua experiência com o uso dos serviços do Google Cloud Platform?
2. Configuração e requisitos
Configuração de ambiente autoguiada
- Faça login no Console do Cloud e crie um novo projeto ou reutilize um existente. Crie uma se você ainda não tiver uma conta do Gmail ou do G Suite.
Lembre-se do código do projeto, um nome exclusivo em todos os projetos do Google Cloud. O nome acima já foi escolhido e não servirá para você. Faremos referência a ele mais adiante neste codelab como PROJECT_ID
.
- Em seguida, será necessário ativar o faturamento no Console do Cloud para usar os recursos do Google Cloud.
A execução deste codelab não será muito cara, se for o caso. Siga todas as instruções na seção "Limpeza", que orienta você sobre como encerrar recursos para não incorrer em cobranças além deste tutorial. Novos usuários do Google Cloud estão qualificados para o programa de US$ 300 de avaliação sem custos.
3. Fazer o download do código-fonte de amostra do Micronaut
Depois que o Cloud Shell for iniciado, use a linha de comando para clonar o código-fonte de exemplo no diretório principal e use cd no diretório que contém o serviço de exemplo:
$ git clone https://github.com/GoogleContainerTools/jib.git
$ cd jib/examples/micronaut/
4. Uma rápida olhada no código
Nosso serviço simples do Micronaut é composto por um controlador que emite a infame mensagem Hello World:
@Controller("/hello") class HelloController { @Get("/") String index() { "Hello World" } }
O controlador HelloController
está respondendo a solicitações no caminho /hello
, e o método index()
aceita as solicitações HTTP GET.
Uma classe de teste Spock também está disponível para verificar se a mensagem correta foi enviada na saída.
class HelloControllerSpec extends Specification { @Shared @AutoCleanup EmbeddedServer embeddedServer = ApplicationContext.run(EmbeddedServer) @Shared @AutoCleanup RxHttpClient client = embeddedServer.applicationContext.createBean(RxHttpClient, embeddedServer.getURL()) void "test hello world response"() { when: HttpRequest request = HttpRequest.GET('/hello') String rsp = client.toBlocking().retrieve(request) then: rsp == "Hello World" } }
Mais do que um simples teste de unidade, o teste executa a mesma pilha de servidores Micronaut (com base no framework Netty) que é executada na produção. Portanto, o comportamento do código será o mesmo no produto e nos testes.
Execute o comando a seguir para verificar se está tudo bem:
./gradlew test
5. execute o aplicativo no local
Inicie o serviço Micronaut normalmente com o seguinte comando do Gradle:
$ ./gradlew run
Depois que o aplicativo for iniciado, abra outra instância do Cloud Shell graças ao pequeno ícone "+" e use o comando curl para conferir se o resultado esperado é o resultado esperado:
$ curl localhost:8080/hello
E vai aparecer um simples "Hello World" aparecer.
6. Empacotar o aplicativo como um contêiner do Docker com o Jib
Em seguida, prepare o aplicativo para ser executado no Kubernetes. Para isso, vamos aproveitar o Jib e fazer o trabalho pesado para nós, já que não precisamos tocar em uma Dockerfile
.
Vamos executar o comando para criar o contêiner:
$ ./gradlew jibDockerBuild
Você verá esta saída:
Tagging image with generated image reference micronaut-jib:0.1. If you'd like to specify a different tag, you can set the jib.to.image parameter in your build.gradle, or use the --im age=<MY IMAGE> commandline flag. Containerizing application to Docker daemon as micronaut-jib:0.1... warning: Base image 'gcr.io/distroless/java' does not use a specific image digest - build may not be reproducible Getting base image gcr.io/distroless/java... Building dependencies layer... Building resources layer... Building classes layer... Finalizing... Container entrypoint set to [java, -cp, /app/resources:/app/classes:/app/libs/*, example.micronaut.Application] Loading to Docker daemon... Built image to Docker daemon as micronaut-jib:0.1
Agora que a imagem foi criada, vamos conferir se a mensagem de boas-vindas aparece. Para isso, execute a imagem Docker na primeira guia do Cloud Shell:
$ docker run -it -p 8080:8080 micronaut-jib:0.1 16:57:20.255 [main] INFO i.m.context.env.DefaultEnvironment - Established active environments: [cloud, gcp] 16:57:23.203 [main] INFO io.micronaut.runtime.Micronaut - Startup completed in 2926ms. Server Running: http://97b7d76ccf3f:8080
Como o serviço está em execução, inicie o comando curl na segunda guia do Cloud Shell para conferir se ele está funcionando conforme o esperado:
$ curl localhost:8080/hello Hello World
Para interromper o contêiner, pressione Ctrl+C
no Cloud Shell.
7. Como enviar nosso serviço conteinerizado para o registro
Agora que a imagem funciona conforme o esperado, envie-a para o Google Container Registry, um repositório particular para suas imagens do Docker acessível a partir de todos os projetos do Google Cloud, mas também de fora do Google Cloud Platform.
Antes de enviar para o registro, confira se o Container Registry está ativado no nosso projeto. Acesse Tools > Container Registry. Se ela não estiver ativada, você verá a caixa de diálogo a seguir. Clique em Ativar API Container Registry. para ativá-lo:
Quando o registro estiver pronto, envie a imagem para ele executando os seguintes comandos:
$ gcloud auth configure-docker $ docker tag micronaut-jib:0.1 \ gcr.io/$GOOGLE_CLOUD_PROJECT/micronaut-jib:0.1 $ docker push gcr.io/$GOOGLE_CLOUD_PROJECT/micronaut-jib:0.1
Os comandos acima permitem que o SDK da gcloud configure e autorize o Docker a enviar imagens para sua instância do Container Registry, marcar a imagem para apontar para o local dela no registro e, em seguida, enviá-la para o registro.
Se tudo correr bem e depois de um tempo, você verá a imagem do contêiner listada no console: Tools > Container Registry. Agora você tem uma imagem do Docker disponível para todo o projeto que pode ser acessada e orquestrada pelo Kubernetes, como você verá em alguns minutos.
8. Crie o cluster
Agora está tudo pronto para criar o cluster do Kubernetes Engine. Antes disso, acesse a seção "Google Kubernetes Engine" no console da Web e aguarde a inicialização do sistema. Leva só alguns segundos.
Um cluster consiste em um servidor de API mestre do Kubernetes administrado pelo Google e um conjunto de nós de trabalho. Os nós de trabalho são máquinas virtuais do Compute Engine. Use a CLI gcloud
da sessão do Cloud Shell para criar um cluster com dois nós do n1-standard-1
. Esse processo leva alguns minutos:
$ gcloud container clusters create hello-cluster \ --num-nodes 2 \ --machine-type n1-standard-1 \ --zone us-central1-c
No final, você verá o cluster criado.
Creating cluster hello-cluster in us-central1-c...done. Created [https://container.googleapis.com/v1/projects/mn-gke-test/zones/us-central1-c/clusters/hello-cluster]. To inspect the contents of your cluster, go to: https://console.cloud.google.com/kubernetes/workload_/gcloud/us-central1-c/hello-cluster?project=mn-gke-test kubeconfig entry generated for hello-cluster. NAME LOCATION MASTER_VERSION MASTER_IP MACHINE_TYPE NODE_VERSION NUM_NODES STATUS hello-cluster us-central1-c 1.9.7-gke.7 35.239.224.115 n1-standard-1 1.9.7-gke.7 2 RUNNING
Agora você tem um cluster do Kubernetes totalmente funcional com a tecnologia do Google Kubernetes Engine:
Agora é hora de implantar o aplicativo em um contêiner no cluster do Kubernetes. De agora em diante, você usará a linha de comando kubectl
, que já está configurada no ambiente do Cloud Shell. O restante deste 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.
9. Implantar o aplicativo no Kubernetes
Uma implantação do Kubernetes pode criar, gerenciar e escalonar várias instâncias do aplicativo usando a imagem de contêiner recém-criada. Crie uma implantação do aplicativo no Kubernetes usando o comando kubectl create deployment
:
$ kubectl create deployment hello-micronaut \ --image=gcr.io/$GOOGLE_CLOUD_PROJECT/micronaut-jib:0.1
Para ver a implantação que você acabou de criar, execute:
$ kubectl get deployments NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE hello-micronaut 1 1 1 1 5m
Para ver as instâncias do aplicativo criadas pela implantação, execute este comando:
$ kubectl get pods NAME READY STATUS RESTARTS AGE hello-micronaut-5647fb98c5-lh5h7 1/1 Running 0 5m
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.
10. permitir o tráfego externo
Por padrão, o pod é acessível somente do seu IP interno dentro do cluster. Para tornar o contêiner hello-micronaut
acessível de fora da rede virtual do Kubernetes, é necessário expor o pod como um serviço do Kubernetes.
No Cloud Shell, é possível expor o pod à Internet pública com o comando kubectl expose
combinado com a sinalização --type=LoadBalancer
. A sinalização é obrigatória para a criação de um IP acessível externamente:
$ kubectl expose deployment hello-micronaut --type=LoadBalancer --port=8080
O sinalizador usado nesse comando especifica que você usará o balanceador de carga fornecido pela infraestrutura subjacente (nesse caso, o balanceador de carga do Compute Engine). Você expôs a implantação, não o pod diretamente. 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 (nesse caso, apenas um pod, mas você adicionará mais réplicas posteriormente).
O mestre do Kubernetes cria o balanceador de carga e as regras de encaminhamento do Compute Engine relacionadas, pools de destino e regras de firewall para tornar o serviço totalmente acessível de fora do Google Cloud Platform.
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 TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE hello-micronaut LoadBalancer 10.39.243.251 aaa.bbb.ccc.ddd 8080:30354/TCP 1m kubernetes ClusterIP 10.39.240.1 <none> 443/TCP 31m
Há dois endereços IP listados para seu serviço, ambos usando a porta 8080
. Um é o IP interno que é visível apenas dentro da sua rede virtual na nuvem. Outro é o IP com balanceamento de carga externo. Neste exemplo, o endereço IP externo é aaa.bbb.ccc.ddd
.
Agora, você deve conseguir acessar o serviço ao apontar seu navegador para este endereço: http://<EXTERNAL_IP>
:8080
/hello
11. escalonar o serviço verticalmente
Um dos poderosos recursos oferecidos pelo Kubernetes é a facilidade de escalonar seu aplicativo. Suponha que, de repente, você precise de mais capacidade para seu aplicativo. você pode simplesmente dizer ao controlador de replicação para gerenciar um novo número de réplicas para suas instâncias de aplicativo:
$ kubectl scale deployment hello-micronaut --replicas=3 deployment.extensions "hello-micronaut" scaled $ kubectl get deployment NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE hello-micronaut 3 3 3 3 16m
Observe a abordagem declarativa aqui. Em vez de iniciar ou interromper novas instâncias, declare quantas instâncias precisam estar em execução ao mesmo tempo. Os loops de reconciliação do Kubernetes simplesmente garantem que a realidade corresponda ao que você solicitou e tomam medidas, se necessário.
12. implementar uma atualização no serviço
Em algum momento, o aplicativo implantado na produção exigirá correções de bugs ou recursos adicionais. O Kubernetes ajuda você a implantar uma nova versão na produção sem afetar seus usuários.
Primeiro, vamos modificar o aplicativo. Abra o editor de código no Cloud Shell.
Navegue até /jib/examples/micronaut/src/main/groovy/example/micronaut/HelloController.groovy
e atualize o valor da resposta:
@Controller("/hello") class HelloController { @Get("/") String index() { "Hello Kubernetes World" } }
Em /jib/examples/micronaut/build.gradle
, vamos fazer o upgrade da versão da nossa imagem de 0.1 para 0.2 atualizando esta linha:
version '0.2'
Em seguida, recrie e empacote o aplicativo com as alterações mais recentes:
$ ./gradlew jibDockerBuild
Adicione uma tag e envie a imagem ao registro de imagens do contêiner:
$ docker tag micronaut-jib:0.2 \ gcr.io/$GOOGLE_CLOUD_PROJECT/micronaut-jib:0.2 $ docker push gcr.io/$GOOGLE_CLOUD_PROJECT/micronaut-jib:0.2
Agora já está tudo pronto para o Kubernetes atualizar o controlador de replicação para a nova versão do aplicativo. Para mudar o rótulo da imagem do contêiner em execução, é necessário editar o hello-micronaut deployment
atual e mudar a imagem de gcr.io/PROJECT_ID/micronaut-jib:0.1
para gcr.io/PROJECT_ID/micronaut-jib:0.2
.
É possível usar o comando kubectl set image
para pedir que o Kubernetes implante a nova versão do aplicativo em todo o cluster, uma instância por vez, com a atualização gradual:
$ kubectl set image deployment/hello-micronaut \ micronaut-jib=gcr.io/$GOOGLE_CLOUD_PROJECT/micronaut-jib:0.2 deployment.apps "hello-micronaut" image updated
Acesse http://EXTERNAL_IP:8080 de novo para conferir se a nova resposta está sendo retornada.
13. Reverter
Ops! Você cometeu um erro com uma nova versão do aplicativo? Talvez a nova versão contenha um erro e você precise reverter rapidamente. Com o Kubernetes, é possível reverter para o estado anterior facilmente. Reverta o aplicativo executando:
$ kubectl rollout undo deployment/hello-micronaut
Se você observar a saída do serviço, voltaremos para a versão inicial do "Hello World" mensagem.
14. Resumo
Nesta etapa, você configurou um serviço "Hello World" do Micronaut simples baseado no Apache Groovy e o executou diretamente no Cloud Shell. Em seguida, você o empacotou como um contêiner com o Jib e o implantou no Google Kubernetes Engine.
15. Parabéns!
Você aprendeu a criar e implantar um novo microsserviço baseado na Web no Apache Groovy / Micronaut no Kubernetes no Google Kubernetes Engine.
Saiba mais
- Documentação e exemplos do Jib: https://github.com/GoogleContainerTools/jib/
- Site do Micronaut: http://micronaut.io/ (em inglês)
- Java no Google Cloud Platform: https://cloud.google.com/java/
- Para exemplos do Java: https://cloud.google.com/java/samples
- Para conferir um tutorial mais longo e completo do Kubernetes, consulte bit.ly/k8s-lab, que mostra como implantar um aplicativo de pilha completa.
Licença
Este conteúdo está sob a licença Atribuição 2.0 Genérica da Creative Commons.