1. Descripción general
Acerca de Micronaut
Micronaut es un framework moderno de pila completa basado en JVM para crear microservicios modulares y aplicaciones sin servidores que se pueden probar fácilmente. Micronaut tiene como objetivo ofrecer un excelente tiempo de inicio, una capacidad de procesamiento rápida y una huella de memoria mínima. Los desarrolladores pueden desarrollar con Micronaut en Java, Groovy o Kotlin.
Micronaut proporciona lo siguiente:
- Tiempo de inicio rápido y bajo consumo de memoria: Los frameworks de IoC basados en la reflexión cargan y almacenan en caché los datos de reflexión para cada campo, método y constructor de tu código, mientras que, con Micronaut, el tiempo de inicio y el consumo de memoria de tu aplicación no están vinculados al tamaño de tu base de código.
- Cliente HTTP declarativo, reactivo y de tiempo de compilación: Crea de forma declarativa clientes HTTP reactivos que se implementan en el tiempo de compilación, lo que reduce el consumo de memoria.
- Servidor HTTP no bloqueante compilado en Netty: Con una curva de aprendizaje fluida, el servidor HTTP de Micronaut facilita al máximo la exposición de APIs que pueden consumir los clientes HTTP.
- Pruebas rápidas y sencillas: Inicia servidores y clientes fácilmente en tus pruebas de unidades, y ejecútalos de forma instantánea.
- Inyección de dependencias y AOP eficientes en tiempo de compilación: Micronaut proporciona una API de programación orientada a aspectos simple en tiempo de compilación que no usa la reflexión.
- Crea apps completamente reactivas y no bloqueantes: Micronaut admite cualquier framework que implemente Reactive Streams, incluidos RxJava y Reactor.
Para obtener más información, visita el sitio web de Micronaut.
Acerca de Kubernetes
Kubernetes es un proyecto de código abierto que se puede ejecutar en muchos entornos distintos, desde laptops hasta clústeres de varios nodos de alta disponibilidad; desde nubes públicas hasta implementaciones locales; desde máquinas virtuales hasta equipos físicos.
En este lab, implementarás un microservicio simple de Micronaut basado en Groovy en Kubernetes, que se ejecuta en Kubernetes Engine.
El objetivo de este codelab es que ejecutes tu microservicio como un servicio replicado que se ejecuta en Kubernetes. Convertirás el código que hayas desarrollado en tu máquina en una imagen de contenedor de Docker y, luego, la ejecutarás en Kubernetes Engine.
Este es un diagrama de las distintas partes que están en juego en este codelab. Lo ayudará a entender cómo encajan las piezas. Úselo como referencia a medida que avanza en el codelab. Todo debería tener sentido cuando llegue al final (pero puede ignorarlo por el momento).

A los fines de este codelab, utilizar un entorno administrado como Kubernetes Engine (una versión de Kubernetes alojada en Google que se ejecuta en Compute Engine) te permite concentrarte en experimentar con Kubernetes, en vez de configurar la infraestructura subyacente.
Si le interesa ejecutar Kubernetes en su máquina local, como una laptop de desarrollo, le recomendamos que obtenga información sobre Minikube. Esta herramienta ofrece una configuración sencilla de un clúster de Kubernetes de un solo nodo para fines de desarrollo y pruebas. Si lo deseas, puedes usar Minikube durante este codelab.
Acerca de Jib
Jib es una herramienta de código abierto que te permite compilar imágenes de Docker y OCI para tus aplicaciones de Java. Está disponible como complementos para Maven y Gradle, y como biblioteca de Java.
Jib tiene como objetivo ser lo siguiente:
- Rápido: Implementa tus cambios rápidamente. Jib separa tu aplicación en varias capas y divide las dependencias de las clases. Ahora no tienes que esperar a que Docker vuelva a compilar toda tu aplicación Java, sino que solo debes implementar las capas que cambiaron.
- Reproducible: Si vuelves a compilar tu imagen de contenedor con el mismo contenido, siempre se generará la misma imagen. Nunca más se activará una actualización innecesaria.
- Sin daemon: Reduce las dependencias de la CLI. Compila tu imagen de Docker desde Maven o Gradle y envíala a cualquier registro que elijas. Ya no es necesario escribir Dockerfiles ni llamar a docker build/push.
Puedes encontrar más información sobre Jib en la página del proyecto de GitHub.
Acerca de este instructivo
En este instructivo, se usa el código de muestra de la herramienta Jib para compilar contenedores para aplicaciones de Java.
La muestra es un servicio simple de hello world que usa el framework de Micronaut y el lenguaje de programación de Apache Groovy.
Qué aprenderás
- Cómo empaquetar una aplicación simple de Java como un contenedor de Docker con Jib
- Cómo crear tu clúster de Kubernetes en Kubernetes Engine
- Cómo implementar tu servicio de Micronaut en Kubernetes en Kubernetes Engine
- Cómo escalar su servicio verticalmente e implementar una actualización
- Cómo acceder al panel gráfico de Kubernetes
Requisitos
- Un proyecto de Google Cloud Platform
- Un navegador como Chrome o Firefox
- Se recomienda estar familiarizado con editores de texto estándares de Linux, como Vim, Emacs o Nano.
¿Cómo usarás este instructivo?
¿Cómo calificarías tu experiencia con la compilación de aplicaciones web con HTML/CSS?
¿Cómo calificarías tu experiencia con el uso de los servicios de Google Cloud Platform?
2. Configuración y requisitos
Configuración del entorno de autoaprendizaje
- Accede a la consola de Cloud y crea un proyecto nuevo o reutiliza uno existente. (Si todavía no tienes una cuenta de Gmail o de G Suite, debes crear una).
Recuerde el ID de proyecto, un nombre único en todos los proyectos de Google Cloud (el nombre anterior ya se encuentra en uso y no lo podrá usar). Se mencionará más adelante en este codelab como PROJECT_ID.
- A continuación, deberás habilitar la facturación en la consola de Cloud para usar los recursos de Google Cloud recursos.
Ejecutar este codelab no debería costar mucho, tal vez nada. Asegúrate de seguir las instrucciones de la sección “Realiza una limpieza”, en la que se aconseja cómo cerrar recursos para que no se te facture más allá de este instructivo. Los usuarios nuevos de Google Cloud son aptos para participar en el programa Prueba gratuita de $300.
3. Obtén el código fuente de muestra de Micronaut
Después de que se inicie Cloud Shell, podrás utilizar la línea de comandos para clonar el código fuente de ejemplo en el directorio principal y cambiar al directorio que contiene nuestro servicio de ejemplo:
$ git clone https://github.com/GoogleContainerTools/jib.git
$ cd jib/examples/micronaut/
4. Un vistazo rápido al código
Nuestro servicio simple de Micronaut se compone de un controlador que genera el infame mensaje Hello World:
@Controller("/hello")
class HelloController {
@Get("/")
String index() {
"Hello World"
}
}
El controlador HelloController responde a las solicitudes en la ruta /hello, y el método index() acepta las solicitudes HTTP GET.
También hay disponible una clase de prueba Spock para verificar que se muestre el mensaje correcto en el resultado.
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"
}
}
Más que una simple prueba de unidades, esta prueba ejecuta la misma pila de servidores de Micronaut (basada en el framework Netty) que se ejecuta en producción. Por lo tanto, el comportamiento de tu código será el mismo en el producto que en tus pruebas.
Para ejecutar las pruebas, puedes ejecutar el siguiente comando y verificar que todo esté bien:
./gradlew test
5. Ejecuta la aplicación de manera local
Puedes iniciar el servicio de Micronaut de forma normal con el siguiente comando de Gradle:
$ ./gradlew run
Una vez que se inicie la aplicación, puedes abrir una instancia adicional de Cloud Shell gracias al pequeño ícono de signo más y, luego, verificar con curl que obtengas el resultado esperado:
$ curl localhost:8080/hello
Deberías ver un mensaje simple de "Hello World".
6. Empaqueta la aplicación como un contenedor de Docker con Jib
A continuación, prepare su aplicación para que se ejecute en Kubernetes. Para ello, aprovecharemos Jib para que haga el trabajo pesado por nosotros, ya que no tendremos que tocar un Dockerfile nosotros mismos.
Ejecutemos el comando para compilar nuestro contenedor:
$ ./gradlew jibDockerBuild
Este es el resultado que deberías ver:
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
Ahora que nuestra imagen está compilada, comprobemos si podemos ver nuestro mensaje de saludo ejecutando nuestra imagen de Docker en la primera pestaña de 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
Nuestro servicio se está ejecutando, por lo que ahora podemos iniciar nuestro comando curl en la segunda pestaña de Cloud Shell para ver si funciona según lo esperado:
$ curl localhost:8080/hello Hello World
Puedes detener el contenedor presionando Ctrl+C en Cloud Shell.
7. Envía nuestro servicio en contenedores al registro
Ahora que la imagen funciona como debe, puedes enviarla a Google Container Registry, un repositorio privado para tus imágenes de Docker al que puedes acceder desde cada proyecto de Google Cloud (y también desde fuera de Google Cloud Platform).
Antes de poder enviar elementos al registro, asegúrate de que Container Registry esté habilitado para tu proyecto. Para ello, ve a Tools > Container Registry. Si no está habilitada, deberías ver el siguiente diálogo. Luego, haz clic en "Habilita la API de Container Registry" para habilitarla:

Una vez que el registro esté listo, ejecuta los siguientes comandos para enviar la imagen al registro:
$ 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
Los comandos anteriores permiten que el SDK de gcloud configure y autorice Docker para enviar imágenes a tu instancia de Container Registry, etiquetar la imagen para que apunte a su ubicación en el registro y, luego, enviarla al registro.
Si todo sale bien, después de un tiempo, deberías poder ver la imagen de contenedor en la consola: Herramientas > Container Registry. Ahora tiene una imagen de Docker disponible para todo el proyecto, y Kubernetes puede acceder a ella y organizarla, como verá en unos minutos.

8. Cree su clúster
De acuerdo. Ahora puedes crear tu clúster de Kubernetes Engine, pero antes de eso, navega a la sección de Google Kubernetes Engine de la consola web y espera a que se inicialice el sistema (solo debería tardar unos segundos).

Un clúster consiste en un servidor de API de instancia principal de Kubernetes que administra Google y un conjunto de nodos trabajadores. Los nodos trabajadores son máquinas virtuales de Compute Engine. Usemos la CLI de gcloud desde tu sesión de Cloud Shell para crear un clúster con dos nodos n1-standard-1 (esto tardará unos minutos en completarse):
$ gcloud container clusters create hello-cluster \ --num-nodes 2 \ --machine-type n1-standard-1 \ --zone us-central1-c
Cuando el proceso se complete, debería ver que se creó el clúster.
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
Ahora deberías tener un clúster de Kubernetes completamente funcional con la tecnología de Google Kubernetes Engine:

Llegó la hora de implementar su propia aplicación en contenedores en el clúster de Kubernetes. A partir de ahora, usarás la línea de comandos kubectl (que ya está configurada en tu entorno de Cloud Shell). Para el resto de este codelab, se requiere que la versión del cliente de Kubernetes y del servidor sea la 1.2 o una posterior. kubectl version te mostrará la versión actual del comando.
9. Implementa tu aplicación en Kubernetes
Una implementación de Kubernetes puede crear, administrar y escalar varias instancias de tu aplicación con la imagen de contenedor que acabas de crear. Creemos una implementación de tu aplicación en Kubernetes con el comando kubectl create deployment:
$ kubectl create deployment hello-micronaut \ --image=gcr.io/$GOOGLE_CLOUD_PROJECT/micronaut-jib:0.1
Para ver la implementación que acabas de crear, simplemente ejecuta el siguiente comando:
$ kubectl get deployments NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE hello-micronaut 1 1 1 1 5m
Para ver las instancias de la aplicación creadas por la implementación, ejecuta este comando:
$ kubectl get pods NAME READY STATUS RESTARTS AGE hello-micronaut-5647fb98c5-lh5h7 1/1 Running 0 5m
En este punto, deberías tener tu contenedor ejecutándose bajo el control de Kubernetes, pero aún tienes que hacerlo accesible para otras personas.
10. Permite el tráfico externo
Según la configuración predeterminada, el Pod únicamente es accesible a través de su IP interna dentro del clúster. Para que se pueda acceder al contenedor hello-micronaut desde fuera de la red virtual de Kubernetes, tienes que exponer el pod como un servicio de Kubernetes.
Desde Cloud Shell, puedes exponer el pod a la Internet pública con el comando kubectl expose combinado con la marca --type=LoadBalancer. Esta marca es necesaria para crear una IP accesible de forma externa:
$ kubectl expose deployment hello-micronaut --type=LoadBalancer --port=8080
La marca utilizada en este comando especifica que usarás el balanceador de cargas proporcionado por la infraestructura subyacente (en este caso, el balanceador de cargas de Compute Engine). Tenga en cuenta que se expone la implementación, y no el pod directamente. Esto hará que el servicio resultante balancee la carga de tráfico en todos los Pods administrados por la implementación (en este caso, solo 1 Pod, pero luego podrás agregar más réplicas).
La instancia principal de Kubernetes crea el balanceador de cargas y las reglas de reenvío, las reglas de firewall y los grupos de destino de Compute Engine relacionados para que se pueda acceder al servicio completamente desde fuera de Google Cloud Platform.
Para encontrar la dirección IP accesible de forma pública del servicio, solo debes solicitar que kubectl muestre todos los servicios del clúster:
$ 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
Observa que se muestran 2 direcciones IP para tu servicio, y ambas entregan contenido al puerto 8080. Una es la IP interna que solo es visible dentro de su red virtual de Cloud; la otra es la IP externa de balanceo de cargas. En este ejemplo, la dirección IP externa es aaa.bbb.ccc.ddd.
Ahora deberías poder acceder al servicio dirigiendo tu navegador a esta dirección: http://<EXTERNAL_IP>:8080/hello
11. Escala tu servicio verticalmente
Una de las características avanzadas que ofrece Kubernetes es la gran facilidad para escalar tu aplicación. Supongamos que, de repente, necesitas más capacidad para tu aplicación. Simplemente puedes indicarle al controlador de replicación que administre una nueva cantidad de réplicas para las instancias de tu aplicación:
$ 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
Observa el enfoque declarativo que usamos aquí: en lugar de iniciar o detener nuevas instancias, debes declarar cuántas instancias deberían estar en ejecución constantemente. Los bucles de conciliación de Kubernetes simplemente se aseguran de que la realidad coincida con lo que solicitaste y, de ser necesario, ejecutan acciones.
12. Implementa una actualización para tu servicio
En algún momento, la aplicación que implementó en producción requerirá la corrección de errores o funciones adicionales. Kubernetes lo ayudará a implementar una versión nueva en producción sin afectar a sus usuarios.
Primero, modifiquemos la aplicación. Abre el editor de código desde Cloud Shell.

Navega a /jib/examples/micronaut/src/main/groovy/example/micronaut/HelloController.groovy y actualiza el valor de la respuesta:
@Controller("/hello")
class HelloController {
@Get("/")
String index() {
"Hello Kubernetes World"
}
}
En /jib/examples/micronaut/build.gradle, actualizaremos la versión de nuestra imagen de 0.1 a 0.2 actualizando esta línea:
version '0.2'
Luego, vuelve a compilar y empaquetar la aplicación con los cambios más recientes:
$ ./gradlew jibDockerBuild
Etiqueta y envía la imagen al registro de imágenes de contenedor:
$ 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
Ahora está listo para que Kubernetes actualice sin problemas su controlador de replicación a una versión nueva de la aplicación. Para cambiar la etiqueta de la imagen de tu contenedor en ejecución, debes editar el hello-micronaut deployment existente y cambiar la imagen de gcr.io/PROJECT_ID/micronaut-jib:0.1 a gcr.io/PROJECT_ID/micronaut-jib:0.2.
Puedes usar el comando kubectl set image para solicitarle a Kubernetes que implemente la versión nueva de tu aplicación en todo el clúster, una instancia a la vez, con una actualización progresiva:
$ kubectl set image deployment/hello-micronaut \
micronaut-jib=gcr.io/$GOOGLE_CLOUD_PROJECT/micronaut-jib:0.2
deployment.apps "hello-micronaut" image updated
Vuelve a verificar http://EXTERNAL_IP:8080 para ver que muestre la nueva respuesta.
13. Revertir
¿Cometiste un error con una versión nueva de la aplicación? Quizás la nueva versión contenía un error y necesitas revertirla rápidamente. Con Kubernetes, puedes revertir al estado anterior con facilidad. Ejecuta el siguiente comando para revertir la aplicación:
$ kubectl rollout undo deployment/hello-micronaut
Si observas el resultado del servicio, volveremos a nuestro mensaje inicial "Hello World".
14. Resumen
En este paso, configuraste un servicio simple de Hello World de Micronaut basado en Apache Groovy y lo ejecutaste directamente desde Cloud Shell, lo empaquetaste como un contenedor con Jib y lo implementaste en Google Kubernetes Engine.
15. ¡Felicitaciones!
Aprendiste a compilar e implementar un nuevo microservicio basado en la Web de Apache Groovy / Micronaut en Kubernetes en Google Kubernetes Engine.
Más información
- Documentación y muestras de Jib: https://github.com/GoogleContainerTools/jib/
- Sitio web de Micronaut: http://micronaut.io/
- Java en Google Cloud: https://cloud.google.com/java/
- Para ver ejemplos de Java, consulta https://cloud.google.com/java/samples
- Para ver un instructivo más largo y completo de Kubernetes, consulta bit.ly/k8s-lab, en el que se te guiará para implementar una aplicación de pila completa.
Licencia
Este trabajo cuenta con una licencia Atribución 2.0 Genérica de Creative Commons.