Implementa una aplicación web en contenedor

En este instructivo, se muestra cómo empaquetar una aplicación web en una imagen de contenedor de Docker y ejecutar esa imagen en un clúster de Google Kubernetes Engine (GKE). Deberás implementar la aplicación web como un conjunto de réplicas con balanceo de cargas que puede escalar según las necesidades de los usuarios.

Objetivos

  • Empaquetar una aplicación web de muestra en una imagen de Docker
  • Subir la imagen de Docker a Container Registry
  • Crear un clúster de GKE
  • Implementar la app de muestra en el clúster
  • Administrar el ajuste de escala automático para la implementación
  • Exponer la app de muestra a la Internet
  • Implementar una versión nueva de la app de muestra

Antes de comenzar

Sigue los pasos que se indican a continuación para habilitar la API de Kubernetes Engine:
  1. Consulta la página de Kubernetes Engine en Google Cloud Console.
  2. Crea o selecciona un proyecto.
  3. Espera a que la API y los servicios relacionados se habiliten. Esto puede tomar varios minutos.
  4. Asegúrate de que la facturación esté habilitada para tu proyecto de Cloud. Descubre cómo confirmar que tienes habilitada la facturación en un proyecto.

Opción A: Usa Cloud Shell

Puedes seguir este instructivo mediante Cloud Shell, que viene preinstalado con las herramientas de línea de comandos de gcloud, docker y kubectl que se usan en este instructivo. Si usas Cloud Shell, no necesitas instalar estas herramientas de línea de comandos en tu estación de trabajo.

Para usar Cloud Shell, sigue estos pasos:

  1. Dirígete a Google Cloud Console.
  2. Haz clic en el botón Activar Cloud Shell Botón de activar Shell que se encuentra en la parte superior de la ventana de Cloud Console.

    Se abrirá una sesión de Cloud Shell en un marco nuevo en la parte inferior de Cloud Console, que mostrará una ventana de la línea de comandos.

    Sesión de Cloud Shell

Opción B: Usa las herramientas de línea de comandos de manera local

Si prefieres seguir este instructivo en tu estación de trabajo, sigue estos pasos para instalar las herramientas necesarias.

  1. Instala el SDK de Google Cloud, que incluye la herramienta de línea de comandos de gcloud.

  2. Con la herramienta de línea de comandos de gcloud, instala la herramienta de línea de comandos deKubernetes. kubectl se usa para comunicarse con Kubernetes, que es el sistema de organización de clústeres de los clústeres de GKE:

    gcloud components install kubectl
  3. Instala la edición de la comunidad de Docker (CE) en tu estación de trabajo. Usarás esto a fin de compilar una imagen de contenedor para la aplicación.

  4. Instala la herramienta de control de fuente Git para obtener la aplicación de muestra de GitHub.

Paso 1: Compila la imagen de contenedor

En este instructivo, implementarás una aplicación web de muestra llamada hello-app, un servidor web escrito en Go que responde a todas las solicitudes con el mensaje Hello, World! en el puerto 8080.

GKE acepta imágenes de Docker como el formato de implementación de la aplicación. Antes de implementar hello-app en GKE, debes empaquetar el código fuente de hello-app como una imagen de Docker.

Para compilar una imagen de Docker, necesitas un código fuente y un Dockerfile. Un Dockerfile contiene instrucciones para compilar la imagen.

  1. Descarga el código fuente de hello-app y el Dockerfile mediante la ejecución de los siguientes comandos:

    git clone https://github.com/GoogleCloudPlatform/kubernetes-engine-samples
    cd kubernetes-engine-samples/hello-app
    
  2. Configura la variable de entorno PROJECT_ID como el ID del proyecto de Google Cloud (project-id). La variable PROJECT_ID se usará para asociar la imagen de contenedor con Container Registry del proyecto.

    export PROJECT_ID=project-id
    
  3. Compila y etiqueta la imagen de Docker para hello-app:

    docker build -t gcr.io/${PROJECT_ID}/hello-app:v1 .
    

    Con este comando, se le indica a Docker que compile la imagen mediante el Dockerfile en el directorio actual y que la etiquete con un nombre, como gcr.io/my-project/hello-app:v1. El prefijo gcr.io se refiere a Container Registry, donde se alojará la imagen. Ejecutar este comando no subirá la imagen todavía.

  4. Ejecuta el comando docker images a fin de verificar que la compilación se realizó de forma correcta:

    docker images
    
    Salida:
    REPOSITORY                     TAG                 IMAGE ID            CREATED             SIZE
    gcr.io/my-project/hello-app    v1                  25cfadb1bf28        10 seconds ago      54 MB
    

Paso 2: Ejecuta el contenedor de forma local (opcional)

  1. Prueba tu imagen de contenedor mediante el motor de Docker local:

    docker run --rm -p 8080:8080 gcr.io/${PROJECT_ID}/hello-app:v1
    
  2. Si usas Cloud Shell, haz clic en el botón Vista previa en la Web Botón Vista previa en la Web y selecciona el número de puerto 8080. GKE abre la URL de vista previa en su servicio de proxy en una nueva ventana del navegador.

  3. De lo contrario, abre una nueva ventana de la terminal (o una pestaña de Cloud Shell) y ejecuta para verificar si el contenedor funciona y responde a las solicitudes con “Hello, Word!”:

    curl http://localhost:8080

    Cuando obtengas una respuesta exitosa, puedes cerrar el contenedor mediante Ctrl+C en la pestaña en la que se ejecuta el comando docker run.

Paso 3: Envía la imagen de Docker a Container Registry

Debes subir la imagen de contenedor a un registro para que el clúster de GKE pueda descargarla y ejecutarla.

  1. Configura la herramienta de línea de comandos de Docker para que se autentique en Container Registry:

    gcloud auth configure-docker
    
  2. Envía la imagen de Docker que acabas de compilar a Container Registry:

    docker push gcr.io/${PROJECT_ID}/hello-app:v1
    

Paso 4: Crea un clúster de GKE

Ahora que la imagen de Docker está almacenada en Container Registry, debes crear un clúster de GKE para ejecutar hello-app. Un clúster de GKE consiste en un grupo de instancias de VM de Compute Engine que ejecutan Kubernetes, el sistema de organización de clústeres de código abierto que se usa en GKE.

Cloud Shell

  1. Configura las opciones del ID del proyecto y de la zona de Compute Engine para la herramienta de gcloud:

    gcloud config set project $PROJECT_ID
    gcloud config set compute/zone compute-zone
  2. Crea un clúster llamado hello-cluster:

    gcloud container clusters create hello-cluster
    

    La creación y la verificación de estado del clúster de GKE tomará unos minutos.

  3. Una vez que se complete el comando, ejecuta el siguiente comando para ver las tres instancias de VM de trabajador del clúster:

    gcloud compute instances list
    
    Resultado:
    NAME                                           ZONE        MACHINE_TYPE   PREEMPTIBLE  INTERNAL_IP  EXTERNAL_IP    STATUS
    gke-hello-cluster-default-pool-d8b498d3-0d6r  us-east1-b   e2-medium                   10.142.0.4   35.237.4.149   RUNNING
    gke-hello-cluster-default-pool-d8b498d3-k29m  us-east1-b   e2-medium                   10.142.0.3   34.75.248.193  RUNNING
    gke-hello-cluster-default-pool-d8b498d3-vcrj  us-east1-b   e2-medium                   10.142.0.2   35.196.51.235  RUNNING
    

Console

  1. Visita el menú de Google Kubernetes Engine en Cloud Console.

    Ir al menú Google Kubernetes Engine

  2. Haz clic en el botón Crear clúster.

  3. En la sección Conceptos básicos del clúster, ingresa el nombre hello-cluster.

  4. Para establecer la zona, elige una zona de Compute Engine en el menú desplegable.

  5. Haz clic en Crear. De esta forma, se creará un clúster de GKE con 3 nodos.

  6. Espera a que se cree el clúster. Cuando el clúster esté listo, aparecerá una marca de verificación verde junto al nombre del clúster.

Paso 5: Implementa la app de muestra en GKE

Ya estás listo para implementar la imagen de Docker que compilaste en el clúster de GKE.

Kubernetes representa las aplicaciones como Pods, que son unidades escalables que contienen uno o más contenedores. Un Pod es la unidad más pequeña que se puede implementar en Kubernetes. Por lo general, implementas los Pods como un conjunto de réplicas que se pueden escalar y distribuir juntas en el clúster. Una forma de implementar un conjunto de réplicas es mediante una implementación de Kubernetes.

Crearás una implementación de Kubernetes para ejecutar hello-app en el clúster. Esta implementación tendrá 3 réplicas (Pods). Un Pod de la implementación contendrá solo un contenedor: la imagen de Docker de hello-app. También crearás un recurso HorizontalPodAutoscaler que escalará la cantidad de Pods de 3 a un número entre 1 y 5, en función de la carga de CPU.

Cloud Shell

  1. Crea una implementación de Kubernetes para la imagen de Docker de hello-app.

    kubectl create deployment hello-app --image=gcr.io/${PROJECT_ID}/hello-app:v1
    
  2. Establece en 3 el número del modelo de referencia de las réplicas de la implementación.

    kubectl scale deployment hello-app --replicas=3
    
  3. Crea un recurso HorizontalPodAutoscaler para la implementación.

    kubectl autoscale deployment hello-app --cpu-percent=80 --min=1 --max=5
    
  4. Para ver los Pods creados, ejecuta el siguiente comando:

    kubectl get pods
    
    Salida:
    NAME                         READY   STATUS    RESTARTS   AGE
    hello-app-784d7569bc-hgmpx   1/1     Running   0          10s
    hello-app-784d7569bc-jfkz5   1/1     Running   0          10s
    hello-app-784d7569bc-mnrrl   1/1     Running   0          15s
    

Console

  1. Visita el menú Cargas de trabajo de Google Kubernetes Engine en Cloud Console.

    Visitar el menú Cargas de trabajo

  2. En el menú Cargas de trabajo, haz clic en Implementar.

  3. En la ventana Crear implementación que aparece, haz clic en Imagen de contenedor existente.

  4. En el menú desplegable, haz clic en la imagen de hello-app que enviaste a Container Registry.

  5. Haz clic en Ver YAML. De esta forma, se abrirá un archivo de configuración YAML que representa los dos recursos de la API de Kubernetes que se están por implementar en el clúster: una implementación y un HorizontalPodAutoscaler para la implementación.

  6. Haz clic en Implementar.

  7. Espera a que los Pods de la implementación estén listos. Verás ruedas giratorias azules mientras el clúster de GKE implementa los 3 Pods de hello-app y, luego, verás marcas de verificación verdes cuando los Pods se hayan implementado con éxito.

  8. Para esperar a que los Pods estén listos, navega a Kubernetes Engine y, luego, a Cargas de trabajo. Haz clic en hello-app y desplázate hacia abajo hasta la sección Pods administrados. Deberías ver 3 Pods de hello-app.

Paso 6: Expón la app de muestra a la Internet

Si bien los Pods tienen direcciones IP asignadas de forma individual, solo se puede acceder a estas desde el interior del clúster. Además, los Pods de GKE están diseñados para ser efímeros y disminuir o aumentar en función de las necesidades de escalamiento. Cuando un Pod falla debido a un error, GKE volverá a implementarlo de forma automática y le asignará una dirección IP nueva cada vez que esto suceda.

Esto significa que, en cualquier implementación, el conjunto de direcciones IP correspondiente al conjunto activo de Pods es dinámico. Necesitamos una forma de: 1) agrupar los Pods en un nombre de host estático y 2) exponer un grupo de Pods fuera del clúster a la Internet.

Los Servicios de Kubernetes resuelven estos dos problemas. Los servicios agrupan los Pods en una dirección IP estática, a la que se puede acceder desde cualquier Pod dentro del clúster. GKE también asigna un nombre de host de DNS a esa IP estática: por ejemplo, hello-app.default.svc.cluster.local.

El tipo de servicio predeterminado en GKE se llama ClusterIP. En este tipo, el servicio obtiene una dirección IP a la que solo se puede acceder desde interior del clúster. Para exponer un servicio de Kubernetes fuera del clúster, deberás crear un servicio de tipo LoadBalancer. Este tipo de servicio genera una IP del balanceador de cargas externo para un conjunto de Pods, a la que se puede acceder a través de Internet.

Ahora deberás exponer la implementación de hello-app a la Internet mediante el uso de un servicio de tipo LoadBalancer.

Cloud Shell

  1. Usa el comando kubectl expose a fin de generar un servicio de Kubernetes para la implementación de hello-app.

    kubectl expose deployment hello-app --name=hello-app-service --type=LoadBalancer --port 80 --target-port 8080
    

    Aquí, la marca --port especifica el número de puerto configurado en el balanceador de cargas y la marca --target-port especifica el número de puerto en el que escucha el contenedor de hello-app.

  2. Ejecuta el siguiente comando con el fin de obtener los detalles del servicio para hello-app-service.

    kubectl get service
    
    Salida:
    NAME                 CLUSTER-IP      EXTERNAL-IP     PORT(S)          AGE
    hello-app-service    10.3.251.122    203.0.113.0     80:30877/TCP     10s
    
  3. Copia la dirección EXTERNAL_IP en el portapapeles (por ejemplo, 203.0.113.0).

Console

  1. Visita el menú Cargas de trabajo de Google Kubernetes Engine en Cloud Console.

    Visitar el menú Cargas de trabajo

  2. Haz clic en hello-app.

  3. En la página detalles de la implementación, haz clic en Exponer.

  4. En el menú Exponer una implementación, establece el Puerto de destino en 8080. Este es el puerto en el que escucha el contenedor de hello-app.

  5. Haz clic en Exponer con el fin de generar un servicio de Kubernetes para hello-app, llamado hello-app-service.

  6. Espera a que se cree el balanceador de cargas externo. Verás una rueda giratoria azul en Google Cloud Console y, una vez que el balanceador de cargas esté listo, se te redireccionará a la página Detalles del servicio de hello-app-service.

  7. Desplázate hacia abajo hasta el campo Extremos externos y copia la dirección en el portapapeles.

Ahora que los Pods de hello-app están expuestos a la Internet a través de un servicio de Kubernetes, puedes abrir una pestaña nueva del navegador y navegar a la dirección IP del servicio que copiaste en el portapapeles. Deberías ver un mensaje Hello, World! junto con un campo Hostname. El Hostname corresponde a uno de los tres Pods de hello-app que entregan la solicitud HTTP al navegador.

Paso 7: Implementa una versión nueva de la app de muestra

En esta sección, deberás actualizar hello-app a una versión nueva mediante la compilación y la implementación de una imagen de Docker nueva en el clúster de GKE.

La función de actualización progresiva de GKE te permite actualizar las implementaciones sin tiempo de inactividad. Durante una actualización progresiva, el clúster de GKE reemplazará de forma incremental los Pods de hello-app existentes por Pods que contengan la imagen de Docker de la versión nueva. Durante la actualización, el servicio del balanceador de cargas enrutará el tráfico solo a los Pods disponibles.

  1. Regresa a Cloud Shell, donde clonaste el código fuente de hello-app y el Dockerfile. A fin de crear una versión nueva del código fuente de hello-app, actualiza main.go para informar una versión nueva, 2.0.0.

  2. Compila y etiqueta una nueva imagen de Docker de hello-app.

    docker build -t gcr.io/${PROJECT_ID}/hello-app:v2 .
    
  3. Envía la imagen a Container Registry.

    docker push gcr.io/${PROJECT_ID}/hello-app:v2
    

Ya estás listo para actualizar la implementación de Kubernetes de hello-app con el fin de usar una imagen de Docker nueva.

Cloud Shell

  1. Aplica una actualización progresiva a la implementación existente con una actualización de imagen:

    kubectl set image deployment/hello-app hello-app=gcr.io/${PROJECT_ID}/hello-app:v2
    
  2. Mira cómo finalizan los Pods en ejecución que ejecutan la imagen v1 y cómo inician los Pods nuevos que ejecutan la imagen v2.

    watch kubectl get pods
    
    Resultado:
    NAME                        READY   STATUS    RESTARTS   AGE
    hello-app-89dc45f48-5bzqp   1/1     Running   0          2m42s
    hello-app-89dc45f48-scm66   1/1     Running   0          2m40s
    
  3. En una pestaña diferente, vuelve a navegar a la IP externa hello-app-service. Ahora deberías ver la Version configurada como 2.0.0..

Console

  1. Visita el menú Cargas de trabajo de Google Kubernetes Engine en Cloud Console.

    Visitar el menú Cargas de trabajo

  2. Haz clic en hello-app.

  3. En Acciones, haz clic en Actualización progresiva.

  4. En la ventana que aparece, configura el campo Imagen como gcr.io/[YOUR_PROJECT_ID]/hello-app:v2.

  5. Haz clic en Actualizar para comenzar la actualización progresiva.

  6. Regresa a la vista Implementación de hello-app y, luego, desplázate hacia abajo hasta Revisiones activas. Ahora deberías ver dos revisiones: 1 y 2. La revisión 1 corresponde a la implementación inicial que creaste antes. La revisión 2 es la actualización progresiva que acabas de iniciar.

  7. Después de unos momentos, actualiza la página. En Pods administrados, deberías ver que, ahora, todas las réplicas de hello-app corresponden a la revisión 2.

  8. En una pestaña diferente, vuelve a navegar a la IP externa hello-app-service. Ahora deberías ver la Version configurada como 2.0.0..

Realiza una limpieza

Sigue estos pasos para evitar que se apliquen cargos a tu cuenta de Google Cloud Platform por los recursos que usaste en el instructivo:

  1. Borra el servicio: De este modo, se desasigna el balanceador de cargas de Cloud creado para él:

    kubectl delete service hello-app-service
  2. Borra el clúster: De este modo, se borran los recursos que conforman el clúster, como las instancias de procesamiento, los discos y los recursos de red:

    gcloud container clusters delete hello-cluster
  3. Borra la imagen de contenedor: Esto borra la imagen de Docker que enviaste a Container Registry.

     gcloud container images delete gcr.io/${PROJECT_ID}/hello-app:v1  --force-delete-tags --quiet
    

Próximos pasos