En este ejemplo avanzado se muestra cómo compilar una app de libro de registro que usa Node.js para su frontend y MySQL para su backend. Además, la plantilla crea y conecta un balanceador de cargas HTTP que hace el balanceo de cargas en dos zonas y un escalador automático destinado a escalar automáticamente la aplicación.
En este ejemplo se da por sentado que estás familiarizado con los contenedores de Docker, como con los recursos de Compute Engine, especialmente el balanceo de cargas HTTP, el ajuste de escala automático, los grupos de instancias administrados y las plantillas de instancias.
Para obtener más instructivos de introducción, consulta la Guía de introducción o la Guía paso a paso.
Antes de comenzar
- Si deseas usar los ejemplos de línea de comandos de esta guía, instala la herramienta de línea de comandos de gcloud.
- Si deseas usar los ejemplos de la API en esta guía, configura el acceso a la API.
- Familiarízate con el balanceo de cargas HTTP de Compute Engine.
- Familiarízate con los contenedores de Docker.
Crea tus plantillas
En este ejemplo se inicia una implementación con diferentes tipos de recursos. Para comenzar, crearás plantillas que definan estos recursos por separado. Luego, utilizarás estas plantillas en tu configuración final.
Al final de este ejemplo, tendrás una implementación que contiene los siguientes recursos:
- Una instancia única de Compute Engine para la máquina virtual MySQL del backend
- Una plantilla de instancias que utiliza una imagen de Docker
- Dos grupos de instancias administrados de escala automática en dos zonas diferentes, que ejecutan el servicio node.js frontend
- Otro grupo de dos instancias administrado de escala automática que entrega datos estáticos
- Una verificación de estado y un balanceador de cargas HTTP que distribuye tráfico entre los grupos de instancias administrados respectivos
Crea las plantillas de backend
El backend de esta aplicación es una instancia única de Compute Engine que ejecuta un contenedor MySQL Docker. Crea una plantilla que defina una instancia de Compute Engine que use una imagen optimizada para el contenedor. Asígnale un nombre al archivo container_vm.[py|jinja]
:
Jinja
Python
La plantilla define la cantidad de variables, como containerImage
y manifest
, que se completarán cuando definas tu configuración. Esta plantilla por sí sola simplemente crea una única instancia de máquina virtual.
Cuando usas imágenes de contenedor en instancias de Compute Engine, también debes proporcionar un archivo de manifiesto (diferente del manifiesto de Deployment Manager) a fin de describir a Compute Engine qué imagen de contenedor debe usar. Crea un método auxiliar llamado container_helper.[py|jinja]
para definir de forma dinámica el manifiesto del contenedor:
Jinja
Python
Crea las plantillas frontend
El frontend de esta app ejecuta Node.js y permite que los usuarios publiquen mensajes en la página web. Habrá dos grupos de instancias administrados que contendrán dos instancias cada uno: un grupo de instancias administradas principal y un grupo de instancias administradas secundario para el balanceo de cargas.
Para crear estas plantillas de frontend, sigue las siguientes instrucciones.
Crea una plantilla de instancias.
Necesitas un recurso de plantilla de instancias para crear un grupo de instancias administrado, es decir, un grupo de instancias de VM idénticas, administradas centralmente. En este ejemplo se crea un grupo de instancias administrado para las instancias node.js frontend, pero, primero, debes crear la plantilla de la instancia.
Define un archivo llamado
container_instance_template.[py|jinja]
:Jinja
Python
Crea un grupo de instancias administrado con ajuste de escala automático.
Ahora que ya tienes una plantilla de instancias, puedes definir una plantilla que utilice la plantilla de instancia a fin de crear un grupo de instancias administrado y con escala automática. Crea un nuevo archivo llamado
autoscaled_group.[py|jinja]
con los siguientes contenidos:Jinja
Python
Crea el archivo de esquema correspondiente:
Jinja
Python
Crea recursos mediante estas plantillas.
Hasta este momento, definiste plantillas base que determinan las propiedades de tus recursos. Mediante estas plantillas, define la configuración de tu frontend. Crea un nuevo archivo llamado
service.[py|jinja]
con los siguientes contenidos:Jinja
Python
Crea el archivo de esquema correspondiente:
Jinja
Python
Veamos en detalle lo que crea esta plantilla:
Dos grupos de instancias administrados, uno principal y otro secundario.
En la plantilla, se usa la plantilla
autoscaled_group.[py|jinja]
para crear un grupo de instancias administrado de escala automática principales y secundarias.A continuación, la plantilla crea un servicio de backend y verificación de estado. Se requiere un servicio de backend para el balanceo de cargas HTTP, que define la capacidad de servicio de los grupos de instancias en ese servicio de backend. En este caso, los grupos de instancias administrados principales y secundarios son parte de este backend y se aplican las propiedades predeterminadas del servicio de backend.
De forma predeterminada, un servicio de backend realiza el balanceo de cargas en función del uso de CPU por parte de los grupos de instancias relacionados, pero también puedes realizar el balanceo de cargas en función de la solicitud por segundo (RPS).
Nota: Siempre es obligatorio contar con una verificación de estado cuando se crea un servicio de backend.
Crea una plantilla unificadora
Por último, crea una plantilla unificadora que combine las plantillas de backend y de frontend. Crea un archivo nuevo llamado application.[py|jinja]
:
Jinja
Python
Crea un archivo con el esquema correspondiente:
Jinja
Python
Además del frontend y backend, la plantilla también define algunos recursos adicionales:
Un servicio estático, con grupos de instancias administrados principales y secundarios. Este servicio estático entrega a una página web ubicada en la ruta de acceso
/static
en tu aplicación.Un recurso de mapa de URL. El balanceo de cargas HTTP requiere un mapa de URL a fin de asignar las diferentes URL con las rutas correctas. En este caso, la ruta de acceso predeterminada, indicada mediante la propiedad
defaultService
, es el servicio de backend que creaste antes. Si un usuario navega hasta/static
, el mapa de la URL asignará la ruta de acceso con el servicio estático, como se define en la secciónpathMatchers
.Una regla de reenvío global y un Proxy HTTP de destino. Dado que a la aplicación se le están balanceando las cargas en dos zonas separadas, necesitarás una regla de reenvío global que entregue a una sola dirección IP externa. Además, se requiere un Proxy HTTP de destino para la configuración del balanceo de cargas HTTP.
Una regla de firewall que permite el tráfico a través del puerto 8080.
Crea tu configuración
Ahora que tus plantillas y tus esquemas relacionados están listos, puedes crear una configuración que implemente estos recursos. Crea un archivo de configuración llamado application.yaml
con los siguientes contenidos y reemplaza ZONE_TO_RUN
y SECONDARY_ZONE_TO_RUN
con las zonas principal y secundaria que elijas.
Jinja
Python
Implementando la configuración
Implementemos tus recursos. Con Google Cloud CLI, ejecuta el siguiente comando y, si lo deseas, elige reemplazar advanced-configuration-l7
con el nombre de implementación que quieras. Ten en cuenta que el nombre de la implementación se usará automáticamente para nombrar los recursos.
En este ejemplo, el nombre de implementación es advanced-configuration-l7
. Si decides cambiar el nombre de la implementación, asegúrate de usar ese nombre en todos los siguientes ejemplos.
gcloud deployment-manager deployments create advanced-configuration-l7 --config application.yaml
La respuesta debería ser similar a los siguientes recursos:
Waiting for create operation-1469468950934-5387966d431f0-49b11bc4-1421b2f0...done. Create operation operation-1469468950934-5387966d431f0-49b11bc4-1421b2f0 completed successfully. NAME TYPE STATE ERRORS advanced-configuration-l7-application-fw compute.v1.firewall COMPLETED [] advanced-configuration-l7-application-l7lb compute.v1.globalForwardingRule COMPLETED [] advanced-configuration-l7-application-targetproxy compute.v1.targetHttpProxy COMPLETED [] advanced-configuration-l7-application-urlmap compute.v1.urlMap COMPLETED [] advanced-configuration-l7-backend compute.v1.instance COMPLETED [] advanced-configuration-l7-frontend-bes compute.v1.backendService COMPLETED [] advanced-configuration-l7-frontend-hc compute.v1.httpHealthCheck COMPLETED [] advanced-configuration-l7-frontend-it compute.v1.instanceTemplate COMPLETED [] advanced-configuration-l7-frontend-pri-as compute.v1.autoscaler COMPLETED [] advanced-configuration-l7-frontend-pri-igm compute.v1.instanceGroupManager COMPLETED [] advanced-configuration-l7-frontend-sec-as compute.v1.autoscaler COMPLETED [] advanced-configuration-l7-frontend-sec-igm compute.v1.instanceGroupManager COMPLETED [] advanced-configuration-l7-static-service-bes compute.v1.backendService COMPLETED [] advanced-configuration-l7-static-service-hc compute.v1.httpHealthCheck COMPLETED [] advanced-configuration-l7-static-service-it compute.v1.instanceTemplate COMPLETED [] advanced-configuration-l7-static-service-pri-as compute.v1.autoscaler COMPLETED [] advanced-configuration-l7-static-service-pri-igm compute.v1.instanceGroupManager COMPLETED [] advanced-configuration-l7-static-service-sec-as compute.v1.autoscaler COMPLETED [] advanced-configuration-l7-static-service-sec-igm compute.v1.instanceGroupManager COMPLETED []
Agrega etiquetas de servicio
A continuación, especifica las etiquetas de servicio adecuadas para tus grupos de instancias administrados. Las etiquetas de servicio son metadatos utilizados por el servicio de balanceo de cargas para agrupar recursos.
A fin de agregar etiquetas de servicio, ejecuta los siguientes comandos, haciendo coincidir las zonas principales y secundarias que seleccionaste en tu archivo de configuración de implementación:
gcloud compute instance-groups unmanaged set-named-ports advanced-configuration-l7-frontend-pri-igm \
--named-ports http:8080,httpstatic:8080 \
--zone [PRIMARY_ZONE]
gcloud compute instance-groups unmanaged set-named-ports advanced-configuration-l7-frontend-sec-igm \
--named-ports http:8080,httpstatic:8080 \
--zone [SECONDARY_ZONE]
Prueba la configuración
A fin de probar tu configuración, obtén la dirección IP externa que está enviando tráfico; para ello, consulta la regla de reenvío:
gcloud compute forwarding-rules list | grep advanced-configuration-l7-l7lb advanced-configuration-l7-l7lb 107.178.249.126 TCP advanced-configuration-l7-targetproxy
En este caso, la IP externa es 107.178.249.126
.
En un navegador, visita la dirección IP externa en el puerto 8080. Por ejemplo, si tu IP externa es 107.178.249.126
, la URL sería la siguiente:
http://107.178.249.126:8080
Deberías ver una página en blanco. A continuación, publica un mensaje en la página. Ve a la siguiente URL:
http://107.178.249.126:8080?msg=hello_world!
Verás una confirmación de que se agregó tu mensaje. Navega nuevamente a la URL principal; ahora, la página debería tener el siguiente mensaje:
hello_world!
Además, puedes visitar la página estática que creaste, o verificar el estado de tu aplicación; para ello, visita las siguientes URL:
# Static web page
http://107.178.249.126:8080/static
# Health check
http://107.178.249.126:8080/_ah/health
Felicitaciones, has implementado tu configuración correctamente.
Crea imágenes de Docker (opcional)
Docker te permite automatizar y ejecutar software dentro de contenedores. Los contenedores te permiten aislar diferentes servicios dentro de contenedores que pueden ejecutarse todos en una única instancia de Linux.
En este ejemplo se usaron algunas imágenes existentes de Docker, pero también puedes crear tus propias versiones de estas imágenes de Docker. Puedes encontrar las instrucciones para crear imágenes backend MySQL y las imágenes de frontend de Node.js en la sección Crea tus plantillas de recursos.
A fin de crear una imagen de Docker que entregue a la página web estática, sigue estos pasos:
Crea una nueva instancia de VM con una imagen optimizada para el contenedor:
gcloud compute instances create docker-playground \ --image-family container-vm \ --image-project google-containers \ --zone us-central1-a \ --machine-type f1-micro
Conéctate a la instancia:
gcloud compute ssh --zone us-central1-a docker-playground
Crea un archivo llamado
Dockerfile
con los siguientes contenidos:FROM node:latest RUN mkdir /var/www/ ADD service.js /var/www/service.js WORKDIR /var/www/ RUN npm install mysql CMD ["node", "service.js"]
Crea un archivo llamado
service.js
con el siguiente contenido:var http = require('http'); var url = require('url'); console.log('Started static node server') http.createServer(function (req, res) { reqUrl = url.parse(req.url, true); res.useChunkedEncodingByDefault = false; res.writeHead(200, {'Content-Type': 'text/html'}); if (reqUrl.pathname == '/_ah/health') { res.end('ok'); } else if (reqUrl.pathname == '/exit') { process.exit(-1) } else { res.end('static server'); } }).listen(8080, '0.0.0.0'); console.log('Static server running at http://127.0.0.1:8080/');
Compila la imagen de Docker y reemplaza
username
con tu nombre de usuario de Docker Hub. Si no tienes un nombre de usuario de Docker Hub, crea uno antes de compilar la imagen de Docker.sudo docker build --no-cache -t username/nodejsservicestatic .
Envía las imágenes al repositorio de Docker:
sudo docker push username/nodejsservicestatic
Ahora tienes las imágenes de Docker necesarias para ejecutar node.js y MySQL. Puedes ver estas imágenes en el repositorio si buscas los nombres de las imágenes. Para probar las imágenes, puedes reemplazar todas las instancias de gcr.io/deployment-manager-examples/mysql
y gcr.io/deployment-manager-examples/nodejsservice
con tus imágenes respectivas.
Próximos pasos
Una vez que hayas completado este ejemplo, podrás hacer lo siguiente:
- Continuar compilando este ejemplo; para ello, crea una página web más sólida o agrega más servicios al servidor web
- Obtén más información acerca de las configuraciones o las implementaciones.
- Intentar crear tus propias configuraciones