Una de las funciones más populares de Heroku es su solución de Review Apps, que crea un entorno y una instancia desechables de la app durante un pull request (PR) y, al fusionarlo, destruye el entorno temporal.
Inspirado en este concepto y en una reunión reciente con un cliente de DoiT International, me propuse recrear ese comportamiento sobre Google Cloud Platform (GCP) con un enfoque nativo de la nube y herramientas open source populares.
Experiencia del desarrollador (demo de 20 minutos)
Si te apegas a los principios de GitOps, tu equipo de desarrollo solo se preocupa por escribir código: cuando crean un PR, en cuestión de segundos o minutos tienen disponible online una versión lista para revisar de su código más reciente.
Los commits posteriores van actualizando la review app hasta que los revisores o testers queden conformes y aprueben o fusionen el PR. Una vez que la app pasa a un entorno superior, la review app se destruye, y el ciclo se repite con cada feature.
Demo de review app al estilo Heroku y pipeline de CI/CD con GitOps (20 minutos)
Componentes involucrados
- Github — control de código fuente
- Kustomize — gestión de configuración nativa de Kubernetes
- Argo CD — CD declarativo basado en GitOps para Kubernetes
- Kong Ingress Controller — API gateway
- Google Kubernetes Engine (GKE) — Kubernetes administrado
- Google Cloud Build — servidor de CI
- Google Container Registry (GCR) — registro privado de imágenes de contenedor
- Google Secret Manager — gestión centralizada de secretos
- Google Cloud DNS — servicio de DNS con API ( opcional)
Arquitectura
La funcionalidad principal de las review apps es la siguiente: cuando un desarrollador crea un pull request (PR) en el control de código, el pipeline de despliegue construye una copia de la app y la aloja en un entorno aislado con una URL única para que otros la revisen.

El PR del desarrollador crea la Review App
La funcionalidad adicional consiste en promover la aplicación a producción tras fusionar el PR y eliminar la review app.

El merge del revisor o admin promueve y elimina la Review App
TL;DR
Para que todo funcione tal como se muestra, hay que seguir estos pasos:
- Crear repositorios separados de App y Config en Github
- Habilitar las APIs de Google y hacer bootstrap del cluster de GKE y de Argo CD
- Instalar Kong API Gateway (ingress controller) desde el repo de C onfig
- Crear un registro DNS A apuntando a la IP externa de kong-proxy
- Conectar Cloud Build con tu repositorio de Github
- Crear una clave privada y guardarla en Google Secret Manager
- Agregar la clave pública al repo Config de Github
- Crear 3 triggers de Cloud Build ( push, PR, merge)
- Autorizar a la cuenta de servicio de Cloud Build para acceder a Secrets
- Agregar los archivos de configuración de Cloud Build al repo App
- Agregar los manifiestos de Kubernetes y los overlays de Kustomize al repo Config
Crear los repositorios fuente en Github
Los siguientes repositorios son ejemplos funcionales; en las próximas secciones te explico cómo armarlos paso a paso.
- Demo App — Dockerfile y scripts de CI de Cloud Build
- Demo App Config — scripts de configuración y manifiestos de Kubernetes para Argo CD
Habilitar APIs, hacer bootstrap de GKE y Argo CD
En el siguiente script habilité las APIs de servicios de Google Cloud y levanté un cluster de Kubernetes.
En un artículo anterior presenté el concepto del patrón app of apps, que utiliza incluso el equipo de desarrollo de Argo en Intuit. Al diseñar esta solución, la creación y eliminación dinámica de una "Application" encaja perfectamente con nuestro caso de uso de crear y destruir review apps.
Instalar Kong API Gateway (ingress controller)
Para Kong, basta con agregar un archivo kong.yaml en la carpeta /apps del repositorio Config. Argo CD detecta y monitorea cualquier repo o carpeta a la que lo apuntes. Elegí Kong porque cada Ingress que creo configura un host, lo que lo hace ideal para generar dinámicamente nuevas URLs de host para review apps.
Agrega los archivos de configuración de Kong en esa carpeta de destino y se instalará en tu cluster de Kubernetes (repite el proceso con cualquier app que necesites).
Fíjate en el source.path (kong): es la carpeta del repo donde estarán los manifiestos YAML que Argo CD instalará. Creé un archivo en el repo llamado 01-install.yaml a partir del propio manifiesto único de Kong, en la carpeta /kong del repo Config. ( https://bit.ly/k4k8s apunta a la configuración más reciente de Kong )
curl https://raw.githubusercontent.com/Kong/kubernetes-ingress-controller/master/deploy/single/all-in-one-dbless.yaml --output kong/01-install.yaml
Crear el registro DNS A para Kong Proxy
Después de instalarse en tu cluster, Kong crea un load balancer TCP externo (Service) con una IP externa.

Servicio load balancer de Kong Proxy en el cluster de Kubernetes
Lo que querrás es apuntar tu dominio a esa IP, lo cual puedes hacer manualmente desde tu proveedor. Para mi demo inicial solo configuré el registro A y algunos alias CNAME como los de abajo.

Entradas de DNS configuradas manualmente
Otra alternativa es usar Google Cloud DNS para administrar tu dominio. Habría que apuntar a los nameservers de Google y, a partir de ahí, podrías crear dinámicamente URLs de review app basadas en el número de PR (lo ideal). Tras el bootstrap de GKE y Kong, puedes usar los siguientes comandos para configurarlo.
Conectar Cloud Build con Github
Normalmente detesto los artículos que te mandan a otros artículos, pero por brevedad, sigue estos dos pasos para conectar Cloud Build con Github y agregar una llave SSH a Secret Manager. Están bien explicados en estos dos artículos de Google:
- Conectar Cloud Build con Github
- Agregar la llave y el secreto para acceder a repos privados — ten en cuenta que conviene habilitar la casilla de "commit" en el repo Config para que tu pipeline de build de la App pueda hacer commits con cambios en la versión del tag de la imagen Docker.
Crear 3 triggers de Cloud Build
Técnicamente, para simular el comportamiento deseado solo necesitaríamos crear los triggers de PR y merge con sus respectivos archivos de configuración, pero normalmente también querrás builds y despliegues de app para los desarrolladores, así que incluí un tercer trigger de push a la rama develop.

Triggers de Cloud Build
Fíjate que en las configuraciones de abajo agrego variables de entorno definidas por el usuario (al final de cada página). Con eso, los archivos de configuración pueden referenciar el nombre de la app y, si quieres, sumar pasos condicionales según el stage.
Por simplicidad creé 3 triggers y 3 archivos de configuración por separado (próxima sección), pero podrías consolidarlos usando estas funciones.

La rama develop hace build y deploy de la imagen Docker en cada push

Pull request desde otra rama hacia master (prod)

Merge del PR a la rama master (prod)
Agregar los archivos de configuración de Cloud Build al repo App
La parte inicial de los archivos de configuración de build es bastante simple: construye una imagen Docker y la sube a Google Container Registry (GCR). Los pasos siguientes usan el secreto de Secret Manager para clonar el repo de configuración, modificar archivos y hacer push de un commit. Eso dispara a Argo CD para que sincronice los últimos cambios y actualice las apps en tu cluster de GKE.
Fíjate que en este archivo el sed -i ... es donde se actualiza el tag de la imagen al último build subido a GCR.
En la etapa de PR usamos v$_PR_NUMBER para etiquetar las imágenes, de modo que se puedan actualizar en commits posteriores durante la revisión del PR (puede que esto lo cambie en algún momento). Otro detalle particular es que copiamos desde /templates/demo-app-review.yaml hacia la carpeta /apps para que Argo CD comience a monitorear la ruta de destino.
Lo más particular aquí es la parte de "Removing review app…", donde ejecutamos rm apps/demo-app-review.yaml. Como activamos autoSync y prune en nuestra configuración de Application, ArgoCD lo detecta y elimina la review app del cluster de GKE.
Agregar manifiestos de Kubernetes y overlays de Kustomize
Podríamos (y deberíamos) tener otro post de blog dedicado solo a Kustomize y a cómo permite la gestión de configuración nativa de Kubernetes. Tradicionalmente empaquetas tus apps con charts de Helm, o con herramientas tipo "sonnet" usando código, pero yo prefiero mantenerlo simple y extensible con Kustomize.
El repo Config está organizado de forma que cada app, en nuestro caso /demo-app/base, incluye sus manifiestos y un archivo kustomization.yaml.
- namespace.yaml — namespace personalizado
- ingress.yaml — configuración de Ingress que Kong detecta y agrega como ruta
- service.yaml — "wrapper" de red para los pods backend
- deployment.yaml — tu app real (apuntando a la imagen)
- kustomization.yaml — configuración de Kustomize
Después agregamos overlays para representar nuestros entornos; estas configuraciones reemplazan o parchean los archivos YAML con valores específicos del entorno: el sufijo del nombre de la app, el namespace o el host del Ingress (para habilitar URLs dinámicas de review app).
/overlays/develop— configuraciones del entorno develop/overlays/review— configuraciones del entorno de review app/overlays/production— configuraciones del entorno de producción
Puedes verlas en el repo de configuración de ejemplo en Github; abajo dejo un ejemplo de configuración de overlay y archivo de patch para crear URLs específicas por entorno en el Ingress.
Fíjate que la propiedad patchesStrategicMerge apunta a un archivo. Kustomize fusionará el contenido de ese archivo (o archivos) para sobrescribir valores personalizados como el nombre del host del Ingress de abajo, y así habilitar una URL personalizada por entorno.
URLs dinámicas opcionales para cada PR
Para mi demo inicial usé siempre la misma URL, pero si trabajas con Cloud DNS, agrega otro paso a tu archivo cloudbuild-pr.yaml como el de abajo para que las URLs sean dinámicas. Al momento de escribir esto aún no lo he probado, pero pienso actualizar mis nameservers y probarlo también.
Tendrías que agregar otro comando sed -i ... en el script de configuración para reemplazar dinámicamente el archivo de patch ingress-host.yaml en cada deploy de PR.
Súmate a mi equipo
Súmate a DoiT International y crea tus propios descubrimientos increíbles como este; visita nuestra página de carreras
- https://careers.doit-intl.com (puestos remotos en zonas horarias cercanas)
Aunque este post tiene bastante contenido, el proceso en general no es demasiado complicado: aprovechando los repositorios de ejemplo que compartí, tú también puedes darle a tus Engineers la libertad de enfocarse menos en la infraestructura y más en lo que mejor saben hacer.

Pipeline de CI/CD exitoso usando GitOps y Review Apps al estilo Heroku durante el PR