1. Descripción general
Acerca de Micronaut
Micronaut es un framework moderno de pila completa basado en JVM para compilar aplicaciones sin servidores y microservicios que se pueden probar fácilmente y de forma modular. El objetivo de Micronaut es ofrecer un tiempo de inicio excelente, una capacidad de procesamiento rápida y una huella mínima en la memoria. Los desarrolladores pueden desarrollar con Micronaut en Java, Groovy o Kotlin.
Micronaut proporciona:
- Tiempo de inicio rápido y Bajo consumo de memoria: Los frameworks de IoC basados en reflexiones cargan y almacenan en caché los datos de reflexión de cada campo, método y constructor en 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 reactivo, declarativo y en tiempo de compilación: Compila clientes HTTP reactivos de manera declarativa, que se implementan en el tiempo de compilación, lo que reduce el consumo de memoria.
- Servidor HTTP sin bloqueo compilado en Netty: Con una curva de aprendizaje fluida, el servidor HTTP de Micronaut facilita al máximo la exposición de las APIs que pueden consumir clientes HTTP.
- Pruebas rápidas y sencillas: Inicia servidores y clientes con facilidad en las pruebas de unidades y ejecútalas de forma instantánea.
- Inyección de dependencias en tiempo de compilación y AOP eficientes: Micronaut proporciona una API de programación simple en tiempo de compilación orientada al aspecto que no usa reflexión.
- Compila apps completamente reactivas y sin bloqueo: Micronaut admite cualquier framework que implemente transmisiones reactivas, 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 de Micronaut simple 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. Toma el código que desarrollaste en tu máquina, lo conviertes en una imagen de contenedor de Docker y, luego, ejecutas esa imagen en Kubernetes Engine.
A continuación, se muestra un diagrama de las distintas partes que están en juego en este codelab para ayudarte a comprender cómo encajan las piezas. Usa esto como referencia a medida que avances en el codelab. Todo debería tener sentido cuando llegues al final (pero puedes ignorarlo por ahora).
A los efectos de este codelab, usar un entorno administrado como Kubernetes Engine (una versión de Kubernetes alojada en Google que se ejecuta en Compute Engine) te permite enfocarte más en experimentar Kubernetes en lugar 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 para realizar este codelab.
Acerca de Jib
Jib es una herramienta de código abierto que te permite compilar imágenes de Docker y de OCI para tus aplicaciones de Java. Está disponible como complementos para Maven y Gradle, y como biblioteca de Java.
Jib pretende ser:
- Rápida: Implementa tus cambios con rapidez. Jib separa la aplicación en varias capas y divide las dependencias de las clases. Ya no tienes que esperar a que Docker vuelva a compilar toda tu aplicación de Java; solo implementa las capas que cambiaron.
- Reproducible: La recompilación de la imagen de contenedor con el mismo contenido siempre genera la misma imagen. Nunca vuelvas a 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 obtener más información sobre Jib en la página del proyecto de GitHub.
Acerca de este instructivo
En este instructivo, se utiliza el código de muestra de la herramienta Jib a fin de compilar contenedores para aplicaciones de Java.
La muestra es un servicio simple de Hello World que usa el framework Micronaut y el lenguaje de programación 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 el 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 creación de aplicaciones web HTML/CSS?
¿Cómo calificarías tu experiencia en 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 no incurrir en facturación 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, puedes usar 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 muestra:
$ git clone https://github.com/GoogleContainerTools/jib.git
$ cd jib/examples/micronaut/
4. Un vistazo rápido al código
Nuestro servicio simple 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 de acceso /hello
, y el método index()
acepta las solicitudes HTTP GET.
También hay una clase de prueba Spock disponible 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 en realidad la misma pila de servidor Micronaut (basada en el framework Netty) que se ejecuta en producción. Por lo tanto, el comportamiento del código será el mismo en el producto que en las pruebas.
Para ejecutar las pruebas, puedes ejecutar el siguiente comando y comprobar que todo esté bien:
./gradlew test
5. Ejecuta la aplicación de manera local
Puedes iniciar el servicio de Micronaut normalmente con el siguiente comando de Gradle:
$ ./gradlew run
Una vez que se inició la aplicación, puedes abrir una instancia adicional de Cloud Shell gracias al ícono pequeño del signo + y, luego, verificar con curl que obtienes el resultado esperado:
$ curl localhost:8080/hello
Deberías ver un simple “Hello World” .
6. Empaquetar la aplicación como un contenedor de Docker con Jib
A continuación, prepare su aplicación para que se ejecute en Kubernetes. Con ese fin, aprovecharemos Jib para hacer el trabajo difícil por nosotros, ya que no tendremos que tocar un Dockerfile
.
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 se compiló la imagen, verifiquemos si podemos ver nuestro mensaje amigable:
$ 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, así que ahora podemos iniciar el comando curl en la segunda pestaña de Cloud Shell para ver si funciona como se esperaba:
$ curl localhost:8080/hello Hello World
Para detener el contenedor, presiona Ctrl+C
en Cloud Shell.
7. Envío de nuestro servicio alojado en contenedores al registro
Ahora que la imagen funciona según lo previsto, puedes enviarla a Google Container Registry, un repositorio privado para tus imágenes de Docker al que se puede acceder desde cada proyecto de Google Cloud (pero también desde fuera de Google Cloud Platform).
Antes de poder hacer envíos al registro, asegurémonos de que Container Registry esté habilitado para nuestro proyecto. Para ello, vamos a Herramientas > Container Registry. Si no está habilitada, deberías ver el siguiente diálogo y, luego, hacer clic en “Habilitar la API de Container Registry”. para habilitarlo:
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 a Docker a 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 va bien y, después de un tiempo, deberías poder ver la imagen del 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
Ya está todo listo para crear tu clúster de Kubernetes Engine, pero antes de eso, navega a la sección Google Kubernetes Engine de la consola web y espera a que el sistema se inicialice (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
de 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 de kubectl
(que ya está configurada en tu entorno de Cloud Shell). En el resto de este codelab, se requiere que tanto el cliente de Kubernetes como la versión del servidor sean la versión 1.2 o 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 lo siguiente:
$ 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 que creó 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 ejecutar tu contenedor bajo el control de Kubernetes, pero debes hacerlo accesible para todo el mundo.
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 de hello-micronaut
desde fuera de la red virtual de Kubernetes, debes 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 que se usa en este comando especifica que se usará el balanceador de cargas que proporciona 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 conocer la dirección IP de acceso público del servicio, solo debes solicitar a kubectl
que enumere 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
Ten en cuenta 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 si diriges el 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. 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
Ten en cuenta el enfoque declarativo que se aplica aquí: en lugar de iniciar o detener instancias nuevas, declaras cuántas instancias deberían estar en ejecución en todo momento. Los bucles de conciliación de Kubernetes simplemente se aseguran de que la realidad coincida con lo que solicitó y, de ser necesario, toman medidas.
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 de 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 con esta línea:
version '0.2'
Luego, vuelve a compilar y empaqueta la aplicación con los cambios más recientes:
$ ./gradlew jibDockerBuild
Etiqueta y envía la imagen al registro de imágenes del 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 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 pedirle a Kubernetes que implemente la versión nueva de tu aplicación en todo el clúster, de a 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
Verifica http://EXTERNAL_IP:8080 nuevamente para ver que devuelve la nueva respuesta.
13. Revertir
¡Vaya! ¿Cometiste un error con la nueva versión de la aplicación? Es posible que la nueva versión haya tenido un error y debas hacer una reversión con rapidez. Con Kubernetes, puedes revertir fácilmente al estado anterior. Ejecute el siguiente comando para revertir la aplicación:
$ kubectl rollout undo deployment/hello-micronaut
Si observas el resultado del servicio, volveremos a la versión inicial de "Hello World" mensaje.
14. Resumen
En este paso, configuraste un Service Micronaut de Hello World sencillo 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 Platform: https://cloud.google.com/java/
- Para ver ejemplos de Java, consulta https://cloud.google.com/java/samples
- Para obtener un instructivo más largo y completo de Kubernetes, consulta bit.ly/k8s-lab, donde te enseñará a implementar una aplicación de pila completa.
Licencia
Este trabajo cuenta con una licencia Atribución 2.0 Genérica de Creative Commons.