Cloud Intelligence™Cloud Intelligence™

Cloud Intelligence™

Entornos de desarrollo nativos de la nube [Parte 2 — Cómo]

By Yarel MamanJun 18, 202110 min read

Esta página también está disponible en English, Deutsch, Français, Italiano, 日本語 y Português.

¡Muy bien! Si llegaste hasta acá, lo más probable es que ya hayas leído la Parte 1 (El porqué) y quieras saber más sobre cómo montar correctamente entornos de desarrollo nativos de la nube. ¡Genial!

Veamos el ejemplo de un equipo de proyecto real y cómo podemos mejorar su flujo de desarrollo.

Esta guía está pensada para GCP (Google Cloud Platform), pero los mismos conceptos también aplican a AWS.

Foto de Jason Richard en Unsplash

📖 Caso de estudio

Una empresa llamada MajesticFantastic tiene varios productos relacionados con pagos 💸

El equipo del proyecto de billing está a cargo del desarrollo de una aplicación de facturación.

Se compone de lo siguiente:

  • Algunos microservicios desplegados como contenedores en GKE 🛳
  • Servicios de GCP utilizados: Pub/Sub, Cloud SQL (PostgreSQL), Cloud Monitoring, Container Registry.
  • Entornos actuales: Dev, Prod.
  • Un equipo de 2 Engineers: David y Martha. Muy pronto se sumarán Ezekiel y algunos Engineers más, ya que la empresa está en plena fase de crecimiento. ¡Tiempos emocionantes! 🚀

Prueba de concepto

Vamos a introducir un nuevo tipo de entorno. Lo llamaremos "el entorno Personal".

Para el entorno personal, nuestro POC consistirá en:

  • Un proyecto de GCP que actuará como proyecto Host. Este proyecto alojará el cluster de GKE, la instancia de Cloud SQL y las imágenes de contenedor en GCR.
  • Varios proyectos personales de GCP — uno por cada Engineer. Cada proyecto contendrá los recursos no compartidos, acotados por Engineer. Por ejemplo, en nuestro caso de uso, alojará los topics y las suscripciones de Pub/Sub.
  • Una Shared VPC. Su host será el proyecto Host, y cada proyecto Personal actuará como un proyecto de servicio de la Shared VPC.

Cluster de GKE multi-tenant

Asignaremos un namespace de K8s por cada entorno (por ejemplo, el entorno de David tendrá el namespace david-env, el de Martha será martha-env, y así sucesivamente).

Cada entorno deberá acceder únicamente a su propio namespace, sin depender de recursos que residan en los namespaces de otros entornos.

Nota: por ahora no aplicaremos nada a nivel de seguridad. Las medidas de seguridad pueden incorporarse después; hablaremos más sobre eso al final del artículo.

Cloud SQL multi-tenant

Cloud SQL admite Users y Databases, así que podemos asignar un User y un Database por entorno (Nota: ¡estamos usando una sola instancia de Cloud SQL y solo se nos cobra por una!).

Crearemos una única instancia privada de Cloud SQL y la "conectaremos" a nuestra Shared VPC mediante private service access.

¡Llega la parte práctica! 👩‍🔧

El repositorio developer-envs contiene todo el código relevante de IaC y GitOps.

Infrastructure-as-Code (IaC)

No hace falta hacer esto a mano. Usaremos Terraform como Infrastructure-as-Code para que se encargue del bootstrap. ¡Muéstrame el código!

Usaremos el Terraform Kubernetes Provider para configurar el namespace de K8s por entorno, y también para crear ConfigMaps generales con parámetros de infraestructura (por ejemplo, el nombre del topic de PubSub, el GCP Project ID, etc.).

Utilicé los Terraform Modules de Google dentro del Cloud Foundation Toolkit a lo largo de la solución y me parecieron bastante fáciles de usar. Además incorporan varias buenas prácticas de Google, así que vale la pena revisarlos.

Usar una herramienta de infra-as-code (como Terraform) es fundamental para este enfoque, porque la idea es justamente reducir y automatizar el trabajo manual propenso a errores y mantener todas las configuraciones alineadas a medida que escalas. Un poco más de trabajo ahora a cambio de mucho menos trabajo después.

GitOps

A continuación, usaremos también ArgoCD para controlar y desplegar nuestros distintos entornos en K8s. ArgoCD es una herramienta popular de continuous delivery basada en GitOps que, en mi opinión, encaja muy bien con nuestro caso de uso multi-tenant. ¡Muéstrame el código!

Definiremos la mayoría de nuestros recursos de K8s como archivos YAML y usaremos Kustomize para personalizar la configuración.

Kustomize es una herramienta de configuración que te permite definir una configuración "base" y muchos "overlays" sobre ella, todos compartiendo la configuración base (una especie de herencia versión austera). Es ideal cuando tienes varios entornos y quieres que todos compartan un ancestro común de configuración.

Por suerte para nosotros, nuestra solución de CD, ArgoCD, se integra con Kustomize.

Creo que Kustomize es simple y fácil de usar, pero por supuesto, puedes optar por otra herramienta (como Helm).

Microservicios de ejemplo

Vamos a desplegar dos microservicios bastante sencillos escritos en Go.

El microservicio env-producer publicará periódicamente eventos de pago en un topic de Pub/Sub cada 10 segundos.

El microservicio env-consumer consumirá los mensajes de "eventos de pago" desde Pub/Sub y los persistirá en una tabla de PostgreSQL.

Lo importante de estos servicios es que la configuración multi-entorno es transparente para ellos, ya que exponemos los detalles del entorno como variables de entorno. Separar la configuración del código es una práctica clave de Twelve-Factor que conviene tener presente.

En esencia, estos microservicios se ejecutan por separado en cada entorno e integran únicamente con los recursos específicos de ese entorno.

Manos a la obra 🏃🏻‍♂️

Para poner esto en marcha, clona el repositorio de ejemplo y sigue las instrucciones del README.md.

Después de eso, la consola de ArgoCD debería verse así.

Esto te sirve como un punto único desde donde puedes hacer seguimiento de todos tus entornos en un solo dashboard. Como es lógico, querrás añadir aquí también tus otros entornos (como dev y prod), tal vez en un "proyecto" distinto de ArgoCD.

Fíjate que hay una aplicación llamada argocd-config que se encarga de auto-sincronizar la configuración y los archivos de instalación de ArgoCD, además de 2 aplicaciones adicionales: una por cada Engineer.

Cómo desplegar cambios en tu entorno

Hiciste un cambio en uno de los servicios y quieres desplegarlo en tu entorno. ¿Qué opciones tienes?

Opción 1: construir una imagen personalizada

Puedes hacer un cambio en el código fuente y luego construir una nueva imagen de contenedor. Después, basta con modificar el tag de la imagen en su aplicación dentro de ArgoCD para desplegar la nueva imagen en cuestión de segundos.

Información de la aplicación en ArgoCD donde un Engineer puede cambiar el tag de una imagen y hacer clic en Save.

Esto se puede hacer manualmente o de forma automática a través de un pipeline de CI o scripts personalizados. (ArgoCD también tiene una CLI que puede usarse para automatizarlo).

Opción 2: ejecutarlo localmente

Espera… ¿Qué? ¿No es contraintuitivo respecto a lo que estamos intentando hacer?

Te presento Telepresence. Telepresence es una de las herramientas más interesantes que he descubierto últimamente. La he usado muchas veces y me ha ayudado a aumentar mi productividad como Engineer.

Es un poco difícil de explicar en una sola frase, pero lo intentaré. Aquí va una descripción que tomé de su sitio web:

Telepresence sustituye tu pod normal que se ejecuta en el cluster de Kubernetes por un proxy de red bidireccional. Este pod hace de proxy de los datos de tu entorno de Kubernetes (por ejemplo, conexiones TCP, variables de entorno, volúmenes) hacia el proceso local. La red del proceso local se sobrescribe de forma transparente para que las llamadas DNS y las conexiones TCP se enruten a través del proxy hacia el cluster remoto de Kubernetes.

O en términos más simples: te permite ejecutar tu servicio localmente, en tu máquina, mientras hace de proxy para las conexiones entrantes y salientes, las variables de entorno y los volúmenes hacia el cluster de K8s. ¡Genial! 👍

Entonces, supongamos que hiciste un cambio en el microservicio env-consumer y quieres probarlo. Ejecutas:

Y en cuestión de segundos, está desplegado y corriendo con tu nuevo cambio.

En esencia, lo que hace es reemplazar el pod de tu servicio por un pod proxy, y luego ejecuta tu servicio localmente mientras se comunica con ese pod proxy.

Lo interesante acá es que estás ejecutando una app local, ¡pero en realidad estás conectado a PubSub y a Cloud SQL (PostgreSQL) de forma remota!

Y todo esto se logra sin cambiar el código de la aplicación ni configurar certificados ni claves secretas. ¡El mismo código en el entorno personal y en producción!

Cuando termino, presiono Ctrl+C y la imagen vuelve al estado anterior. ¡Una maravilla! 🤩

Una demo de cómo ejecutar nuestro servicio de ejemplo usando telepresence.

Ahora imagínate corrigiendo un bug, ejecutando Telepresence, esperando unos segundos y dándote cuenta de que rompiste el servicio. Ah, sí… lo arreglas otra vez. ¡El ciclo de feedback es bastante rápido! 😁

Fíjate que no construí ninguna imagen Docker acá. Estoy compilando el código fuente modificado y ejecutando el binario localmente. También puedes hacer que construya la imagen Docker y la reemplace en su lugar.

Entornos personales y onboarding

¡Ezekiel acaba de unirse al equipo como Engineer! ¡Bienvenido! Ya recibió su laptop y algo de merchandising. ¡Yay! 🥳

Como parte de su onboarding, te piden que prepares un entorno personal para Ezekiel, así puede experimentar con la aplicación y la infraestructura, y tal vez hacer pequeños cambios para ver su impacto.

Cómo lograrlo:

  1. Edita el archivo tf/personal.tfvars y añade a Ezekiel a la lista de tenants:

2. Aplica el cambio ejecutando terraform apply -f personal.tfvars.

3. Añade una aplicación de ArgoCD para el entorno de Ezekiel agregando el siguiente fragmento en argo/apps/applications.yaml; luego haz commit y push del cambio.

¡Eso es todo! Como ArgoCD está sincronizado para hacer seguimiento de la carpeta apps, detectará automáticamente que se añadió ezekiel-env y dejará el entorno listo. Seguro que Ezekiel queda contento.

Entornos personales y offboarding

¡Oh, no! ¡David se va del equipo para explorar nuevas oportunidades!

Qué pena, lo vamos a extrañar. ⭐️ 😩

Pero bueno, ahora podemos ver lo fácil que es limpiar su entorno personal. 😌

Solo dirígete a argo/apps/applications.yaml, elimina la definición de la aplicación david-env, haz commit y push. Como ArgoCD está sincronizado para hacer seguimiento de la carpeta apps, detectará automáticamente que se eliminó david-env y borrará el entorno.

Después, debes eliminar la infraestructura del entorno borrando a david de la lista de tenants en tf/personal.tfvars y ejecutando terraform apply -f personal.tfvars.

¡Listo! No queda rastro de David 💀

👣 Próximos pasos

Si quieres adaptar esto a tu organización, adelante. Pero tendrás que tener en cuenta otras consideraciones, como:

Es solo un POC

Como ya se mencionó, esto es un POC y está pensado a modo de ejemplo y para dar los primeros pasos. Algunas partes de la implementación se simplificaron por brevedad. Por favor, no la tomes como una referencia de buenas prácticas y siéntete libre de ajustarla a tus requisitos y preferencias.

Seguridad

Como mencioné en el capítulo anterior, la seguridad puede ser un punto a considerar en esta solución. Existen varias formas de mejorar la seguridad y el aislamiento partiendo de esta base (por ejemplo, RBAC, Network Policies, Resource Quotas, Pod anti-affinity. Consulta esto para más información).

Multi-tenancy

Acá se dieron ejemplos de multi-tenancy para servicios cloud como GKE, Pub/Sub y Cloud SQL; sin embargo, también puedes adaptar estos conceptos a otros servicios cloud.

Proyecto GCP por Engineer

El alcance actual del proyecto GCP por Engineer es bastante acotado. Esta es una base para extenderlo y mejorarlo. Por ejemplo, puedes configurar el enrutamiento para que los logs y métricas específicos de un namespace se envíen al proyecto GCP de un Engineer en particular. Otro ejemplo: el proyecto GCP del Engineer puede usarse para lanzar recursos personalizados que no formen parte del flujo principal del proyecto, con el fin de validar que las cosas funcionan como se espera. El proyecto GCP por Engineer no es un requisito, sino más bien una posibilidad, así que puedes omitirlo si lo prefieres.

Shared VPC

Estamos usando una Shared VPC, que les permite a tus distintos proyectos personales de GCP compartir la misma red VPC. Esto tiene algunos requisitos de IAM que debes considerar. Por ejemplo, el usuario IAM de tu Engineer debe tener el rol compute.networkUser en el proyecto Host para poder crear recursos en la Shared VPC.

Soluciones alternativas

Las siguientes alternativas también buscan ofrecer una solución. Algunas no son gratuitas. Hasta donde sé, no proporcionan una solución "full-stack" cuando se trata de adaptar la infraestructura a la configuración de despliegue, como sí lo hace nuestro POC. Más bien están enfocadas principalmente en la parte de Kubernetes. Cada una tiene sus pros y contras según tu contexto, así que conviene tenerlos en cuenta.

¡Eso es todo! Espero que lo hayas disfrutado 🙂

En DoiT International, los Architects y Engineers siempre buscamos cerrar la brecha entre la Infraestructura y el Desarrollo de Software, ya que creemos que ambos lados comparten un objetivo común: la productividad y la confiabilidad.

¡Gracias por leer! Para mantenerte conectado, síguenos en el DoiT Engineering Blog, el canal de LinkedIn de DoiT y el canal de Twitter de DoiT. Para explorar oportunidades laborales, visita https://careers.doit-intl.com.