Introducción al curso

Este libro reúne el material de Arquitectura de Nube en GCP de la Universidad Austral.

Usá las secciones del índice para avanzar en este orden:

  1. Clases: conceptos base y decisiones de arquitectura.
  2. Labs: ejercicios guiados para practicar en Google Cloud.
  3. Ejemplos: implementaciones Terraform agrupadas por tipo de recurso.

La idea no es copiar comandos sin entenderlos: primero entendé el servicio, después practicá el lab y recién ahí mirá cómo se modela como infraestructura.

Introducción

Regiones y Zonas

  • Los servidores de GCP se manejan por Regiones y Zonas.
  • Las regiones se manejan a nivel ciudad. Existen data centers dentro de estas.
    • Por el SLA que firmó GCP, en cada región tiene que haber al menos 3 data centers para los servicios ofrecidos: 1 para ofrecer el servicio y 2 de respaldo/réplica
  • Las zonas representan un data center concreto; no son todas iguales.
    • Difieren a nivel acceso y a nivel latencia
  • Existe lo que se llaman Points of Presence (PoP), que son lugares donde ya hay datos guardados para poder distribuirlos mejor.
  • No todos los servidores son iguales: el costo de mantenimiento claramente difiere según la zona geográfica.
    • Por lo general, EE.UU es mucho más barato; hasta 10 veces menos que Brasil
    • No tiene sentido, estando en Argentina, pagar un servicio en Europa, porque no tenemos un cable físico de fibra que vaya directo; entonces tiene que hacer el salto con latencia agregada a EE.UU o a la región más cercana.

Van a haber más concentración de recursos en los lugares donde más consumo haya, claramente. Por eso hay tantos PoP en EE.UU y en Europa.

GCP Map

Existen también servicios (principalmente los relacionados al almacenamiento) que pueden ser multi-región (replicándolos en varias regiones), pero incurre en costos extra.

Billing

  • Se crea una organización por empresa, que administra todos los departamentos, con fines de gobernanza (acceso, monitoreo, aplicación de políticas)
    • Puedo tener el depto. de contabilidad, de ingeniería, cada uno con sus carpetas o folders
      • Dentro de la folder, puedo tener proyectos
  • A cada proyecto se le asignan recursos por los que se le va a cobrar a la Billing Account
  • Una org puede tener B.A y c/u puede tener proyectos asignados, que pueden a diferentes folders

Formas de interactuar con GCP

  • Cloud Platform: interfaz web, que te deja hacer de todo
    • Crear y asignar recursos
    • Administrar proyectos
    • Monitorear uso y controlar costos
    • Dentro de esto, existe Cloud Shell, que es una terminal configurada con todo lo necesario para permitirnos usar el Cloud SDK
  • Cloud SDK: nos permite interactuar con la plataforma con cualquier terminal/lenguaje (con sus respectivos clientes)
    • En el caso de los lenguajes, wrappean los llamados a las APIs a través de métodos de los clientes
  • Cloud APIs: todos los servicios exponen una API que permite que nuestros servicios use la plataforma, incluso si el lenguaje particular no posee un SDK que la wrappee
  • Cloud MobileApp: es más que nada para monitoreo y control

Recursos de cómputo

Compute Resources

  • De derecha a izquierda vamos más desde IaaS hasta PaaS
  • También crece el nivel de abstracción que se nos ofrece para interactuar con dichos recursos

Compute Engine

  • Alternativa de GCP a EC2 de Amazon o las VM de Azure
  • Ofrece máquinas virtuales completamente configurables, con SLAs y precios acordes al mercado
  • Se organizan en familias, series y tipos concretos para que sea lo más fácil posible elegir la configuración que se adapte a nuestras necesidades
    • Una E2-medium es un tipo concreto
    • La familia es General-Purpose

Familias

Familias

  • Storage-optimized: la uso para workloads pesados de almacenamiento
    • Guardado de datos para streaming
    • Bases de datos (SQL, NoSQL y vectoriales)
    • Data warehouses (almacenes con grandes volúmenes de datos organizados)
  • Memory-optimized: hasta 12TB de RAM. La uso para trabajos pesados en memoria
    • Simulaciones
    • Bases de datos de alta performance (SQL Server, MySQL)
    • Data stores en memoria (ej: )
  • Compute-optimized: tienen un CPU característico y potente. La uso para trabajos de procesamiento pesados.
    • Servers para juegos
    • Sistemas de salud
    • Sistemas meteorológicos
  • Accelerator-optimized: tengo acceso a GPUs de todo tipo.
    • Un uso actual muy latente es AI/ML
  • General-purpose: te dan buen valor por lo que estás pagando, pero no les pidas mucho
    • No son para grandes servidores. Sirven para "iniciar" un negocio
    • Dentro de las General Purpose hay distintas categorías con distinto propósito y optimizaciones particulares:
      • Familia de las N: relación precio-performance bastante alta
        • Microservicios containerizados
        • Escritorios virtuales
        • Batch processing

Preguntas

  • Diferencias entre N2 y N4, y para qué elegimos c/u
    • N2 tiene 2 arquitecturas diferentes (Ice Lake, de 2019; Cascade Lake, de 2023). Se usa para workloads que aprovechen la alta frecuencia de reloj
    • N4 es más nueva. Tiene una performance 40% mejor que su predecesor (N2). Es más caro porque hay más demanda y menos disponibilidad.
  • Qué significa que una máquina tenga en su nombre -lssd? Y qué representan otras versiones de esta variación?
    • Tienen un SSD físico local asociado. Si pierdo la máquina, pierdo el disco. No están en rack, por ende no se persiste necesariamente.
    • Mover memoria virtual a estos discos es bastante generoso
    • Sus variaciones son: normal, standard y high.
  • Qué significa que una serie termine en A o en D? Qué implica eso?
    • Cambia la arquitectura del procesador
      • D es AMD (x86) y A es ARM. Si no tiene modificador, viene un Intel (x86)
      • Con ARM se reduce la compatibilidad con ciertos programas, además de que baja el consumo.
      • x86 es más barato

Consumo

  • GCP te cobra el CPU cuando la maquina está RUNNING o en PENDING_STOP
  • También te cobra por la memoria cuando la máquina está RUNNING, en PENDING_STOP, SUSPENDING o SUSPEND
  • Los recursos adjuntables (attachable resources) sobreviven a la máquina si pasa a TERMINATED y nos siguen cobrando por su uso (si corresponde). No puedo dettachear la CPU ni la RAM.
    • Ejemplos de attachables:
      • Interfaz de Red
      • GPU
      • Disco (SALVO el lssd, ya que no es dettachable. No puedo mover un SSD entre máquinas)

Modelos de aprovisionamiento

  • Estándar: reservo la máquina, me dan los recursos y me cobran según el estado de la máquina. Yo lo administro, y puedo determinar cuándo la freno/arranco.
  • Spot: te las pueden sacar en cualquier momento con previo aviso, dependiendo de la disponibilidad de los recursos de GCP. "Dame lo que tengas barato y disponible".
    • Suelen ser entre 40-50% más barato que las estándar. En el mejor de los casos llega a 92%
    • No podés controlar cuándo se paran ni cuándo se eliminan, pero podés recuperar la configuración y el estado de la máquina.
    • Se usa bastante para procesos que pueden persistir el estado
  • Flex-start: la inversa de Spot, "se levanta cuando puede". Tiene un tiempo máximo de 2hs para levantar el recurso. Es bastante más barata que las estándar.
    • Tenés control sobre la máquina.
    • Suele ser para trabajo de batch-processing, porque podés albergar la máquina por un máximo de 7 días
  • Reservation-bound: es para cuando vos sabés que vas a tener un workload por un tiempo prolongado, entonces lo reservás con antelación.

No todas las máquinas pueden acceder a todos los modelos de provisioning

Managed Instance Groups (MIGs)

Son análogos a los grupos de Auto-Scaling de AWS. Escalás horizontalmente en función del consumo, agregando máquinas de manera automática. MIGs

  • Ante cierto de uso de CPU o de memoria, levanto una nueva instancia.
  • Se define un mínimo y un máximo de máquinas a tener en el MIG

Son máquinas virtuales exactamente iguales administradas como un conjunto, siendo todas idénticas. Ofrece:

  • Alta disponibilidad: nos ofrece automatic repairs basados en la salud de la VM y en la salud de la aplicación. Además, nos da soporte regional para el deployment de las VMs, de forma de que si falla una zona, nuestro servicio sigue funcionando. Con esta estructura podemos usar un load balancer y distribuir la demanda.
  • Escalabilidad automática: ante ciertos escenarios, el sistema puede levantar instancias nuevas para responder a picos de demanda
  • Automatic Updates: podemos hacer rollouts de diferentes versiones de nuestra aplicación

Recursos de Cómputo - Continuación

Las VMs y los MIGs toman bastante tiempo...

  • Cuando creamos una Vm sen casi todos los casos el provisioning se hace según el mejor esfuerzo (en unga unga, cuando pueda). Configurar y encender la VM también toma tiempo
  • Un MIG responde a subas y bajas de demanda con una ventana de por lo menos 10 mins. entre lo que se conoce como el initialization process y el stabilization process
    • Por cierta cantidad de tiempo (desde que creo la máquina a partir de la regla de auto-scaling hasta que efectivamente está corriendo), no miro el consumo de recursos para decidir si levanto una instancia nueva
      • Puedo estar inicializando la máquina, clonando un repo (según la config), instalando todas las dependencias, ejecutando algún proceso que consuma mucha CPU, etc.
    • En esos 10 minutos entre inicialización y estabilización, me cobran ($$).
      • El proceso de inicialización puede tener una duración configurable
      • Si $T_{init} > T_{stab} \Longrightarrow T_{stab} = 0$ . Es decir, no tengo tiempo de estabilización
  • Puede haber un caso extremo en donde tengo un servicio que responde una request cada 10 mins.
    • En este caso, termino teniendo un MIG o un server dedicado para no hacer nada la mayor parte del tiempo. Es decir, terminás teniendo infraestructura ociosa

No existe el MIG sin instancias. No podés configurar un MIG vacío, porque un Load Balancer no puede existir por sí solo.

Para evitar estos problemas de infra ociosa, podemos trasladarnos a una solución serverless.

App Engine

Es un framework serverless donde montamos nuestro código (con una estructura particular). Nos perdemos ciertos aspectos de configurabilidad (como interactuar con el S.O de la máquina sobre la que está montado nuestro servicio serverless), además de que estamos limitados a ciertos lenguajes.

Es un PaaS, no tengo ni idea de la infraestructura como tal, me abstraigo de muchas de las configuraciones necesarias. A partir de ahora, nos cobran sólo por tiempo de ejecución. Nos administran sólo por tiempo de ejecución.

Cloud Run Functions

Esta es la solución FaaS (Function as a Service), que también es serverless.

  • Corre ante eventos concretos, sobre Cloud Run Service.
  • Funcionan con Functions Framework, un SDK disponible para algunos lenguajes y una cierta estructura (ej: un main.py y un requirements.txt en )
  • La primera generación era más limitada (límites de vCPU, RAM y timeout de ejecución)
    • El timeout era de aprox. 15 minutos.
    • Tenían límites de concurrencia
  • Las de 2da gen son mucho más óptimas

Cloud Run Service

  • Puedo publicar y compartir imágenes (artefactos) que contienen la config del O.S, alas dependencias y el contexto necesario disponible.
  • GCP crea contenedores en una fracción del tiempo porque se ahorra los pasos de provisioning y la inicialización es mucho menos compleja
  • Obvio que no todas las imágenes son iguales y GCP tiene mejores prácticas

Ventajas

El container tarda muchísimo menos en levantarse que las VM, por cómo funcionan los contenedores en sí.

  • La ventaja de usar containers es la portabilidad/inter-operabilidad: me abstraigo del lenguaje y del ambiente.
    • Mismo si mañana me quiero cambiar de Cloud Provider, y el otro también tiene un servicio de Container Running, me llevo mis imágenes y pum para casa

Límites

  • El Build System de tiene que tener acceso a mi imagen
  • Las imágenes no pueden pesar más de 10GB
  • Hay un límite de consumo de recursos de los containers en ejecución
    • Pasado este límite, te cobran
  • Si tarda más de $4 \text{ minutos}$ en levantarse, no puedo correr el container
  • No se pueden usar imágenes basadas sobre . Sí o sí tiene que ser a partir de alguna distro de

Cobro

Request-based billing

Te cobran por:

  • Cantidad de requests
  • $\frac{\text{Cantidad de CPU}}{\text{unidad de tiempo}}$
  • $\frac{\text{Cantidad de memoria}}{\text{unidad de tiempo}}$ En los últimos 2 me cobran por el tiempo de inactividad. En cuanto a la CPU, es 10 veces menos que el tiempo de actividad (claramente la CPU es más cara)

Instance-based billing

Existe también el billing basado en instancias, que también te cobra por los últimos 2 anteriores, pero se le agrega el tipo de GPU usado, y su uso por unidad de tiempo.

Almacenamiento

Aclaración respecto del Lab: una Service Account es una cuenta de un usuario artificial que tiene permisos para realizar operaciones de manera automática sobre los distintos recursos de GCP. Operan como un proceso aparte.

Qué es un dato? una representación de información que puede ser almacenada, procesada y transmitida por un sistema.

Google ofrece una cantidad muy amplia de soluciones de almacenamiento en la nube, pero nos vamos a enfocar en 3 particulares:

  • Cloud Storage
  • Cloud SQL
  • Cloud Firestore

Google File System: es un FS que SÓLO appendea. Es rapidísimo para escribir.

Cloud Storage (GCS)

(2010) Es un bucket, una solución object store, parecido a un network file system en la nube, casi "infinito". Usa una interfaz REST. La diferencia clave con un file system es que los tiempos de lectura a esa escala son incompatibles con este: en un file system real es imposible tener una lectura de esa cantidad de archivos.

En sí, hacen una serie de operaciones sobre los archivos que guardamos:

  • Replicación
  • Partición y reconstrucción
  • Guarda metadata particular del archivo

La interfaz que le dan al usuario la hace ver similar a un FS.

Tiene una durabilidad altísima (11 nueves), haciendo casi imposible que un archivo se pierda a lo largo del tiempo. Se logra justamente con mecanismos de reconstrucción (si mi archivo se rompe o pierde, lo puedo recuperar), replicación geográfica de los datos (al menso 2 zonas, con posibilidad de multiregión) y validaciones constantes de los datos.

Está construido sobre Colossus, sucesor de GFS, permitiendo capacidad infinita. Es administrado por Spanner, garantizando consistencia fuerte de la metadata.

Por el cliente, yo interactúo con la metadata del archivo, no con el archivo en sí. El Blob es todo lo que conoce

Pricing

Bucket Pricing

  • Region no te cobra el outbound data transfer porque lees datos dentro de la misma región.
  • Multi-región es más caro que región, pero más barato que dual-region, porque Google no te deja elegir dónde guardarlo
    • Justamente por esto es que tanto acá como en dual-region te cobran por outbound data transfer, porque te movés afuera de la región
    • Te cobran la replicación por escribir un archivo
  • Elijo zona porque tengo muy poca latencia y muchísimo ancho de banda.
    • Este es el más caro justamente por esto.

Tipos de buckets

  • Rapid storage: el zonal, funciona a los piques. Se usa para AI/ML, análisis de datos, etc.
  • Standard storage: es ideal para lectura frecuente de un conjunto de archivos.
  • Nearline, Coldline, Storage: en este orden, el costo de almacenamiento es cada vez más barato
    • El costo de escritura es caro de manera creciente, según el orden anterior
    • El compromiso del tiempo de vida es también creciente (30, 90 y 365 días, respectivamente)

Cloud SQL

(2015)

  • Es un servicio de bases de datos relacionales. No lo administrás vos, sino que directamente lo usás.
  • Maneja por sí solo:
    • Updates
    • Parches
    • Vertical Scaling
    • Auto-resizing del disco on-the-fly
  • Por lo general, tiene una disponibilidad alta por el uso de 2 instancias (una primaria y otra standby), una en cada zona.
    • Si falla la primaria, la standby la reemplaza. Se van replicando entre sí y cuando la primaria está disponible la vuelve a reemplazar.
    • Son 2 discos a nivel zonal, 1 a nivel regional.
    • Tiene chequeos automáticos (a nivel Persistent Disk) para revisar qué tan sincronizadas están.
  • Tiene backups automatizados periódicos, pudiendo recuperarnos en un click de un DELETE FROM erróneo. Son incrementales.
  • Podés asignar réplicas de lectura para alivianar la carga de la instancia primaria.

Firestore

(2017)

  • BD NoSQL orientada a documentos
    • Los documentos son JSON con un encodeo binario más eficiente que el JSON común, que pueden pesar hasta 1 MB
  • 2 modos de operación: Native y Datastore.
    • Native te permite usarlo como BaaS, con límites de 10k escrituras/segundo
    • Datastore se usa cuando tenemos un backend que interactúa con nuestra instancia. Sin límites ni features de BaaS
  • Solo nos deja hacer queries si tenemos índices para hacerla. El índice de un solo field lo hace automático, pero el complejo hay que armarlo manual
  • Es serverless, no te cobran por nada que no sea read/write ni almacenamiento. Las escrituras consideran el mantenimiento de los índices
  • Hay costo por GiB
  • Los datos se organizan en splits.
    • Split es una implementación de sharding pero completamente administrado por Firestore. Nosotros tenemos que elegir la sharding key, y Firestore se encarga de manejar los splits por tamaño o por frecuencia de lectura, además de juntar los datos que se suelen consultar juntos en los mismos splits
      • No hay que usar keys secuenciales porque sino corremos el riesgo de sobrecargar nodos
      • Autobalancea la carga en un mismo shard, creando subparticiones
    • Nos permite escalar prácticamente de forma infinita sin degradación de performance.

Sharding: particionar datos a partir de una clave.

VPC

NIC: Network Interface Controller. Es la interfaz de red con la que una máquina se conecta a una red. Vamos a limitarnos a tomar una NIC por máquina. En la vida real se puede tener más de una.

Tengo que tener una forma de identificar a mi máquina. Vamos a trabajar con IPv4 mayoritariamente. El problema de escalabilidad que tiene es que son direcciones de 32 bits, con cantidad finita de IPs posibles (aproximadamente )

Antes usábamos máscaras, ahora usamos una notación para agurpar IPs llamada CIDR. Ej: 10.0.1.0/24. El /24 indica que los primeros 24 bits de la dirección son fijos. El resto son variables.

  • Por ende, tengo 256 direcciones libres

Se pueden tener 2 subredes cubiertas por el mismo rango, pero no se debe. No siempre tengo un router central que se encarga de manejar todos los otros routers (y por ende todas las otras redes).

A la hora de definir una topología de red no es menor ni trivial definir el CIDR.

Dentro de una red se pueden definir reglas de tráfico. No suelen ser complejas, pero tienen que estar bien configuradas.

Puedo poner reglas a nivel máquina y a nivel router.

Un firewall dedicado es un aparato físico, una pieza de un rack. Tiene una capacidad enorme de procesamiento de tráfico.

RFC

El RFC 1918 es la razón por la que no nos quedamos sin IPs de IPv4, porque dice que tenemos rangos específicos según el lugar donde nos encontremos. Ej: 10.0.0.0/8 (grande/corpo), 172.16.0.0/12 (mediano/GCP) 192.168.0.0/16 (hogareño/chico).

GCP Networking

Sobre estos conceptos anteriores Google construye Andrómeda, el SDN (Software Defined Network), que es un sistema compuesto por 2 partes:

  • Control Plane: definimos reglas
  • Data Plane: ejecuta las reglas definidas en el Control Plane Las reglas se aplican a nivel host (máquina con máquinas virtuales) y no pasan por un router central. Las reglas se distribuyen entre los hosts de manera dinámica y son estos los que filtran el tráfico antes de mandarlo a la red física.

Básicamente se hizo todo el control de red sobre todas las máquinas dentro del host a nivel software.

Es independiente a la topología física/real de la red.

VPC

VPC: Virtual Private Cloud. Es una red virtual privada en la nube.

  • Nosotros podemos armar una computadora y nunca conectarla a una red. En GCP esto no puede pasar nunca, ya que toda VM debe a una VPC, no puede sin una red asociada.
  • Si no configuramos nada previamente Google siempre tiene la VPC default lista para nosotros, que se crea con cada proyecto, en algo llamado Auto-Mode.
  • Este Auto-Mode crea una subred automática.
    • Por default tiene configuraciones muy laxas:
      • Tráfico interno ilimitado entre VMs
      • Tráfico SSH, RDP, ICMP sin límite
        • Ojo con esto
    • Claramente no es una configuración de producción, es para tener algo rápido funcionando.
  • Las VPC son globales, mientras que las subredes son regionales.
  • Se pueden crear las VPCs en modo custom, con configuraciones más robustas pero que tenemos que setear manualmente. Network = VPC para simplicidad.

Toda VPC vive dentro de un proyecto, que tiene un componente llamado VPC Routing.

Firewall

¿Cómo hacemos seguridad con todo lo que tenemos configurado, con los grupos lógicos que armamos? Por medio de reglas de Firewall

  • Nos dejan armar reglas de ingreso y egreso de tráfico. Si permitimos que entre una request automáticamente permitimos la respuesta de salida.
  • En general tenemos que definir dirección (entrada/salida), prioridad (la resolución de conflictos entre reglas se desempata por la prioridad), acción (permitir/denegar), filtro de origen/destino según la dirección, y la combinación de protocolo:puerto. GCP siempre asigna una red.
  • Los firewalls se asignan a nivel VPC y dentro de la VPC se asignan a nivel tag. A c/máquina que tenga un tag específico se le aplica una regla. En el caso de que no haya un tag definida se aplica todas las VMs, pero no es lo ideal.
    • Es más rico hacerlo por tag porque es más seguro y prolijo, más fácil de manejar la asignación (por el bajo acoplamiento).
  • Se aplica Deny by Default (cerrar todo de entrada) y Least Privilege Principle (abrimos solo lo necesario)

¿Me interesa que 2 VPCs se comuniquen? Depende de si es necesario y si se puede permitir por temas de privacidad de datos.

Por lo general queremos que 1 proyecto tenga 1 sola VPC

Andromeda aplica todas las reglas de Firewall a nivel NIC (que en este caso es virtual).

IPs externas

  • Google tiene un pool de IPs públicas gigantesco. Cuando creamos una máquina nos puede asignar (por default si) un IP externo para que a través de Internet nos podamos comunicar con esa máquina.
  • Llega una request a uno de los routers de borde de Google y se redireccionan a partir de un NAT (Network Address Translation) para llegar a la VM dentro de GCP
  • Google nos cobra muy muy poco por tener una IP externa fija reservada siempre y cuando la estemos usando. Si dejamos de usarla, te cobran mucho más.
    • No lo estás usando (según ellos) si no lo tenés asignado a ningún recurso.

Costos

Google te cobra por los siguientes recursos de red:

  • Direcciones IPs reservadas
  • Cloud Load Balancing
  • NAT Gateways
    • El público es para salir a Internet
    • El privado es para conectar 2 VPCs/máquinas/recursos de GCP.
      • Si querés todas con todas usás VPC Peering. Si querés un líder de grupo de VPCs usás este recurso.
  • Tráfico

IAM

IAM: Identity and Access Management. Nos dice quién puede hacer qué sobre qué recurso dentro de GCP.

Google separa bastante bien dos preguntas:

  • Authentication: ¿soy realmente quien digo ser?
  • Authorization: una vez autenticado, ¿qué permisos tengo y sobre qué recurso?

La seguridad de GCP no vive aislada. Se apoya sobre la jerarquía de recursos y desde ahí hereda permisos y políticas.

Jerarquía de recursos de GCP

Jerarquía de recursos

Toda la seguridad de GCP cae sobre una jerarquía. Google la documenta acá.

  • Organización: es el nodo raíz. Suele representar a la empresa completa.
  • Folders: agrupan por ambientes, equipos o dominios de negocio (Prod, Dev, RRHH, etc.)
  • Projects: suelen ser la frontera de confianza, costos, cuotas y facturación.
  • Resources: son los recursos concretos que consumimos, como VMs, buckets, datasets de BigQuery, etc.
  • Propiedad: el ciclo de vida de un recurso queda atado a su superior inmediato.
    • Si un empleado se va, el proyecto no desaparece porque no le "pertenece" a esa persona, sino a la organización.
  • Herencia: tanto los permisos como las políticas de organización fluyen hacia abajo en la jerarquía.

Fundamentos de IAM

Fundamentos de IAM

IAM le permite a los administradores autorizar quién puede tomar acciones sobre recursos específicos.

  • Pensarlo en 3 ejes ayuda mucho:
    • Who: la identidad
    • Can do what: el rol/permisos
    • On which resource: el recurso objetivo
  • En criollo: Member + Role + Resource.

Miembros (Members)

Members en IAM

La parte del who en IAM es el member.

  • Un member puede ser:
    • una Google Account o un usuario de Cloud Identity
    • una service account
    • un Google Group
    • un dominio de Cloud Identity / Google Workspace
  • En general la identidad se representa con un identificador estilo email.

Service Accounts

Las service accounts son cuentas asignadas a aplicaciones o cargas de trabajo. Sus identificadores tienen formato email, por ejemplo nombre-sa@proyecto.iam.gserviceaccount.com.

  • No tienen contraseña: no están pensadas para que una persona se loguee en la consola web.
  • Son un recurso y una identidad:
    • puedo darle permisos a una SA para que actúe sobre otros recursos
    • y también puedo darle permisos a un usuario para que administre esa SA
  • Autenticación: usan pares de claves públicas/privadas para validar identidad frente a las APIs de Google.

Puedo tanto usar una JSON key como crear un recurso y attachear una S.A a ese recurso.

  • La diferencia está en que la primera la administramos nosotros y la 2da la administra Google.

Tipos de service accounts

Tipos de service accounts

  • Default Service Accounts:
    • GCP las crea automáticamente (por ejemplo al habilitar Compute Engine)
    • el peligro clásico es dejarlas con permisos demasiado amplios, tipo Editor
  • User-managed Service Accounts:
    • las crea el arquitecto según la necesidad
    • permiten aplicar mejor el Principio de Menor Privilegio
  • Google-managed Service Accounts:
    • las usa internamente GCP para que sus servicios interactúen entre sí
    • por ejemplo, para que Cloud Run pueda hablar con otros recursos

Autorización: ¿qué? ¿dónde?

Autorización en IAM

La autorización la resolvemos combinando roles con recursos.

  • Un permiso es una acción puntual sobre una API o recurso
    • por ejemplo compute.instances.start
  • Un rol es un paquete de permisos
  • El rol responde qué puedo hacer
  • El recurso responde dónde lo puedo hacer
  • Ejemplo: roles/compute.instanceAdmin agrupa varios permisos administrativos sobre instancias de Compute Engine

Roles en Cloud IAM

Los roles de IAM se dividen en 3 familias:

  • Primitivos (básicos):
    • son roles muy genéricos, con permisos amplios
    • no se recomienda usarlos en producción
    • a veces sirven en desarrollo o para salir del paso
  • Predefinidos:
    • tienen mucha más granularidad
    • los crea y mantiene GCP para casos de uso comunes
  • Custom:
    • los creamos nosotros para necesidades muy específicas
    • acá la responsabilidad de mínimo privilegio y segregación de funciones es totalmente nuestra

Roles primitivos

Entre los roles primitivos más conocidos están:

  • Owner: puede administrar miembros, borrar proyectos, etc.
  • Editor: puede desplegar aplicaciones, modificar configuraciones y operar servicios.
  • Viewer: acceso de solo lectura.
  • Billing Admin: administra la parte de facturación, no necesariamente el resto de los recursos.

IAM Policies

IAM Policies

Una IAM Policy es el documento que vincula un role con uno o varios members sobre un recurso.

  • El modelo mental es: una policy es un conjunto de bindings
  • Cada binding dice algo como:
    • a estos members
    • dales este role
  • En formato mental:
    • bindings: [{ role, members }]

Los accesos resultantes de un usuario son la suma de todas las políticas aplicadas sobre este.

  • Si tengo una política que me da acceso a 7 recursos distintos y tengo otra que me da acceso a otros 21 recursos diferentes a los anteriores (por poner un ejemplo), termino teniendo acceso a todos esos 28.

Herencia y propagación en IAM

Herencia y propagación en IAM

Las policies de IAM se heredan desde la organización hacia abajo.

  • Un rol otorgado a nivel Organización también aplica en carpetas, proyectos y recursos inferiores.
  • El acceso efectivo de un usuario es la unión de:
    • la policy definida sobre el recurso
    • más todas las policies heredadas
  • En el modelo de allow que vimos en clase, un permiso dado arriba no lo "sacás" abajo con otra policy de IAM.
  • Por eso conviene aplicar el Principio de Menor Privilegio desde el nivel más alto posible.

Si quiero que un usuario opere sobre algún recurso para el que necesita algún privilegio, puedo darle los permisos a una Service Account y asignarle esa S.A al usuario particular.

Políticas de Organización (Guardrails)

Las Organization Policies son restricciones configurables (constraints) que se aplican sobre los recursos, no sobre las identidades.

Políticas de Organización

  • Definen qué está permitido hacer en la infraestructura.
  • Habitualmente se configuran en el nodo raíz (la organización) y fluyen hacia abajo.
  • Son el equivalente a poner barandas de seguridad sobre toda la plataforma.

Ejemplos clásicos:

  • Restricción de ubicación: impedir que se creen recursos fuera de una región determinada, por ejemplo solo southamerica-east1
  • Desactivar IPs externas: evitar que las VMs salgan con IP pública por default
  • Restringir dominios: permitir que solo miembros de cierto dominio reciban roles en IAM

Terraform

IaC: Infrastructure as Code. Describir la infraestructura en archivos versionables y aplicarla de forma automatizada, en vez de apretar botones a mano en la consola.

Las arquitecturas productivas se vuelven complicadas rápido: redes, VMs, buckets, functions, bases de datos, IAM. Llevar registro de todos los componentes y su estado configurándolos a mano tiene varios problemas:

  • Baja velocidad: cada cambio depende de que alguien se acuerde del paso a paso.
  • Errores: la consola te deja hacer cosas inconsistentes entre ambientes.
  • Downtime: si rehacés algo mal, lo notan los usuarios.
  • Sin auditoría: no queda registro claro de quién cambió qué ni por qué.

La idea de IaC es resolver todo esto describiendo la infraestructura como código. Un simple script que levante recursos ya es una forma (rudimentaria) de IaC: se puede versionar, correr varias veces y revisar en un PR.

De Cloudformation a Terraform

  • En 2011 AWS creó CloudFormation: permitía declarar en JSON (hoy también YAML) cómo tenía que verse la infraestructura de un proyecto.
    • A partir de esa declaración AWS podía replicar toda la infra en segundos.
    • La limitación: solo habla con AWS.
  • En 2014 Hashicorp publica Terraform, inicialmente open-source y hoy source-available (BSL).
    • Usa HCL (HashiCorp Configuration Language), más legible que JSON.
    • Es agnóstico de cloud: hay providers para GCP, AWS, Azure, Kubernetes, GitHub, Datadog, etc.
    • Adopción altísima, hoy es prácticamente el estándar de la industria para IaC multi-cloud.

Terraform CLI

Terraform es una herramienta de línea de comandos con 4 comandos centrales que conviene tener presentes.

terraform init

Prepara el ambiente local.

  • Descarga los providers declarados (por ejemplo hashicorp/google).
  • Trae los módulos externos referenciados.
  • Deja todo preparado en .terraform/ para poder armar planes.
  • Es el primer comando que corremos en un proyecto nuevo o después de agregar un provider/módulo.

terraform plan

Compara la declaración actual contra el estado real y propone qué hacer.

  • Lee los .tf, consulta el state y habla con la API del cloud.
  • Devuelve un plan con todas las acciones en un orden específico.
  • Hay 4 operaciones válidas:
    • Create: recurso nuevo.
    • Update: cambios in-place.
    • Delete: borrar un recurso existente.
    • Replace: destruir y volver a crear (típico cuando tocás un campo inmutable).
  • Se puede persistir con -out para aplicarlo después:
    • terraform plan -out=tfplan

terraform apply

Aplica el plan.

  • Si le pasás un plan guardado (terraform apply tfplan), lo ejecuta tal cual.
  • Si no, genera uno al vuelo, te lo muestra y pide confirmación.
  • Ejecuta las operaciones respetando las dependencias del grafo de recursos.

terraform destroy

Elimina todos los recursos gestionados por el proyecto.

  • Lo hace en el orden inverso al de creación: primero las VMs, después las subnets, al final la VPC (al revés no es válido).
  • Útil para tirar abajo ambientes de prueba sin dejar recursos huérfanos.

El archivo .tf

La declaración vive en archivos con extensión .tf y usa HCL. Un ejemplo mínimo para GCP:

provider "google" {
  project = "my-81bd"
  region  = "us-central1"
  zone    = "us-central1-c"
}

resource "google_compute_instance" "vm_instance" {
  name         = "terraform-instance"
  machine_type = "e2-micro"

  boot_disk {
    initialize_params {
      image = "debian-cloud/debian-11"
    }
  }

  network_interface {
    network = "default"
    access_config {
      # Asigna una IP externa efímera
    }
  }
}
  • El bloque provider configura el cloud destino y credenciales/región por defecto.
  • Cada bloque resource "<tipo>" "<nombre>" describe un recurso concreto. El <nombre> es un identificador local del código, no el nombre del recurso en GCP.
  • Los bloques anidados (boot_disk, network_interface) reflejan la estructura del recurso en la API.

Cómo arma el plan Terraform

Terraform tiene la inteligencia de mirar la declaración y el estado, y proponer un plan para ir del estado actual al deseado.

Pero la forma en la que llega a ese plan no siempre es la que queremos o anticipamos. El flujo mental es algo así:

Flujo de armado de plan en Terraform

  • Lee el archivo de configuración (.tf).
  • Lee el state.
  • Por cada recurso decide:
    • si no existe en el state ⇒ Create()
    • si existe ⇒ Read() contra la API y chequea conflictos
    • si está planeado para destrucción ⇒ Delete()
    • si no ⇒ Update()
  • Con todas esas decisiones arma el plan final.

Cuidado con los replace

  • Un recreate no es gratuito si el estado actual del recurso importa.
    • Una VM con discos, datos locales o configuración manual se pierde.
    • Un bucket con objetos adentro no se puede recrear sin borrar todo.
  • Muchos cambios parecen inofensivos pero tocan un campo inmutable (por ejemplo el machine_type de una VM en algunos escenarios, o el nombre de ciertos recursos).
  • Terraform no conserva data dentro del recurso: si hay que hacer replace, destruye y crea uno nuevo, limpio.
  • Por eso: siempre leer el plan antes de aplicar.

State

El state es la representación que Terraform tiene de la infraestructura actual. Es un JSON que mapea los recursos declarados con los recursos reales en el cloud.

  • Todo plan depende del state: Terraform no vuelve a escanear todo el cloud cada vez, confía en el state.
  • Si trato de aplicar un plan armado sobre un state viejo inválido (que no refleja el estado real), Terraform lo detecta y frena.
    • Ej: si tengo 2 VMs creadas y declaradas en mi main.tf, pero borro una a manopla, cuando quiera re-aplicar el plan, no voy a poder. Va a reventar todo por los aires.

La desviación entre el estado de Terraform con el estado real se conoce como drift

State local vs remoto

  • Local: terraform.tfstate en el directorio del proyecto.
    • Funciona para jugar solo, rompe rápido en equipo.
    • Si dos personas tienen estados locales distintos, cada una va a proponer cambios inconsistentes.
  • Remoto: el state vive en un backend compartido (por ejemplo un bucket de GCS, S3, Terraform Cloud).
    • Todos trabajan sobre el mismo state.
    • Se puede combinar con locking para impedir dos escrituras simultáneas tanto al state como al cloud real.
  • Incluso con state remoto, sin locking podés tener condiciones de carrera entre dos apply corriendo al mismo tiempo.

Buenas prácticas

  • Nunca apliquen un plan sin revisarlo antes.
    • El plan es la herramienta de seguridad principal de Terraform.
    • Mirar especialmente los - (destroy) y los -/+ (replace).
  • Versionar los .tf en Git y revisar cambios por PR.
  • Usar state remoto con locking apenas hay más de una persona tocando el proyecto.
  • Separar ambientes (dev, stg, prod) en workspaces, carpetas o proyectos distintos.
  • No editar recursos administrados por Terraform desde la consola: drift asegurado.

La mayoría de las herramientas de IaC son transaccionales. Si falla una operación, no se hace ninguna dentro del plan de la IaC tool.

Monitoreo y Alertas

Monitoreo

Recopilación, procesamiento, agregación y visualización de datos cuantitativos en tiempo real sobre un sistema. Ejemplos de lo que monitoreás: recuento y tipos de consultas, recuento y tipos de errores, tiempos de procesamiento, tiempo de vida de los servidores.

El monitoreo se basa en métricas, no en historias. Una métrica es un valor numérico que representa el estado del sistema en un momento dado a lo largo del tiempo. Me permite entender la salud del sistema ahora mismo, incluso cuando no hay ninguna alerta disparada.

Me da la capacidad de detectar incidentes y también de prevenirlos.

La pirámide del monitoreo

El monitoreo es la base de todo lo demás. Sin visibilidad sobre el sistema, no podés hacer nada de lo que está arriba:

          Product
        Developing
      Capacity planning
          Testing
  Postmortems / root cause
      Incident response
         Monitoring        ← base

No tiene sentido hablar de capacity planning o de mejoras al producto si el monitoreo está roto.

Observabilidad

Es la capacidad de entender el estado interno de un sistema complejo basándose únicamente en los datos que este genera hacia el exterior.

La observabilidad me debería permitir ser consciente de qué pasa en mi sistema en todo momento, no solo para hacer troubleshooting, sino también para forensics. Depende de tres pilares:

  • Métricas: valores numéricos medidos en el tiempo. Son ideales para detectar anomalías y ver tendencias (CPU, memoria, tasa de errores).
  • Logs: registros de eventos discretos. Cada evento que sucede debería generar uno.
  • Traces: muestran el recorrido de una request a través de todos los componentes del sistema (microservicios, bases de datos, APIs externas).

El monitoreo es una de las funciones necesarias para que un sistema sea observable.

Rendimiento y confiabilidad

Las cuatro métricas clave para saber si un sistema está medianamente monitoreado (los "Four Golden Signals"):

  • Latencia: tiempo en procesar una request. Hay que diferenciar la latencia de los errores de la de las respuestas exitosas.
  • Tráfico: la demanda que está soportando el sistema (requests por segundo, conexiones, lecturas a disco).
  • Errores: pueden ser explícitos (HTTP 500), implícitos (HTTP 200 con contenido incorrecto) o por incumplimiento de un SLO de latencia.
  • Saturación: qué tan lleno está el recurso más limitante del sistema (memoria, CPU, disco).

Herramientas de observabilidad

  • Cloud Monitoring: recolecta métricas de rendimiento y estado de salud de la infraestructura y las aplicaciones para generar dashboards y alertas.
  • Cloud Logging: almacena, busca y analiza logs de los servicios para auditorías y resolución de problemas.
  • Error Reporting: agrupa automáticamente los errores de aplicaciones en ejecución para notificar y ayudar a priorizar su solución.
  • Cloud Trace: rastrea el camino de las solicitudes a través de sistemas distribuidos para encontrar cuellos de botella y latencia entre microservicios.
  • Cloud Profiler: analiza continuamente el consumo de recursos (CPU, memoria) a nivel de código para optimizar el rendimiento y reducir costos de computación.

Cloud Monitoring

El scope default del monitoreo de Google es el proyecto. Se puede ampliar a nivel organización.

Tiene cuatro capacidades principales:

  • Métricas: datos numéricos medidos a lo largo del tiempo (CPU, memoria, latencia de red).
  • Dashboards: visualizaciones gráficas para identificar tendencias o picos de uso de un vistazo.
  • Umbrales y alertas: definís una regla y Cloud Monitoring la vigila. Ej: "Si el uso de CPU supera el 80% durante 5 minutos, mandar un email".
  • Uptime checks: verificaciones externas para saber si una aplicación es accesible desde distintas partes del mundo.

Cómo funciona por dentro

El flujo tiene tres etapas:

  1. Metric Collection: los 100+ servicios de GCP mandan métricas automáticamente. GKE puede usar Prometheus u OpenTelemetry. Compute Engine necesita el Ops Agent. También soporta Hybrid/Multi-Cloud.
  2. Metric Storage: todo se guarda en Cloud Monitoring Storage y se accede vía API.
  3. Visualization and Analysis: desde ahí se arman dashboards, uptime checks, alert policies y notificaciones. Para exportar a terceros (ej: Grafana) también hay soporte.

Cloud Logging

Los logs pasan por cuatro etapas:

  1. Ingesta: servicios de GCP y agentes envían logs.
  2. Router de Logs: filtra, enruta y excluye registros. Acá podés decidir qué logs guardás, adónde van y cuáles descartás.
  3. Buckets: almacenamiento en _Default o _Required (o buckets propios).
  4. Análisis: Logs Explorer con lenguaje LQL para consultar y filtrar.

Además de guardarse en buckets, los logs se pueden exportar a BigQuery para análisis más complejos.

Tipos de logs

  • Logs de plataforma: los provistos por Google, sobre sus propios servicios (ej: VPC Flow Logs).
  • Logs de componentes: generados por software que corre sobre la infra de Google pero que no es 100% administrado (GKE, el SO de una VM).
  • Logs de seguridad: ¿quién hizo qué, dónde y cuándo? Son críticos para auditoría y análisis forense.
  • Logs de usuario: los que vos escribís en el código para seguir la lógica del negocio.
  • Logs multi-cloud: registros de AWS, Azure o servidores on-premise centralizados en GCP para tener un panel único de observabilidad.

Propiedades importantes

  • Inmutabilidad: los registros son definitivos. Una vez escritos, no se pueden editar ni borrar individualmente.
  • Bloqueo de buckets: podés fijar políticas de retención para compliance normativo y auditorías forenses.
  • Logs de auditoría: registro inmutable de toda actividad administrativa y de acceso a datos en la plataforma.
  • Métricas basadas en logs: podés generar métricas de monitoreo a partir de patrones de texto en los registros. Eso habilita armar dashboards y alertas sobre eventos que no tienen una métrica nativa.

De logs a métricas

El flujo es: tus recursos emiten logs → Cloud Logging los recibe → definís un filtro LQL (ej: resource.type="gce_instance" AND severity=ERROR) → cada vez que un log coincide, se genera un punto de datos numérico → Cloud Monitoring lo trata como cualquier otra métrica → podés graficarlo y disparar alertas.

El log original sigue su camino normal hacia el almacenamiento; la métrica es una capa paralela encima.

Error Reporting

Identifica, contabiliza, analiza y agrupa las caídas de servicios en ejecución. Lo útil es que no te tira un log por cada error — agrupa errores similares y te muestra el stack trace, lo que hace mucho más fácil priorizar qué arreglar.

Recibe alertas cuando aparece en producción un error nuevo o uno existente empieza a dispararse con alta frecuencia. Mucho más manejable que revisar logs crudos.

Cloud Trace

Sigue el viaje de una request a través de múltiples contenedores y servicios para encontrar cuellos de botella. Usa un Trace ID único por petición, y un span por cada microservicio o componente que la procesa. Los spans se acumulan, lo que te permite ver exactamente dónde está la latencia.

Lo valioso es que no solo ve los servicios propios — también identifica latencias ocultas en llamadas a APIs externas y consultas a bases de datos.

Cloud Profiler

Hace muestreo de la pila de llamadas mediante snapshots separados por pocos milisegundos. Con esas fotos arma un perfil estadístico de uso de recursos. Dependiendo del lenguaje puede analizar: uso de memoria, CPU, uso de pila, pila asignada y tiempo total de ejecución de una función.

Ayuda a encontrar qué proceso consume más de un recurso particular sin tener que instrumentar nada manualmente.

Alertas

Se definen a partir de umbrales sobre métricas o sobre logs. Para cada alerta hay que definir:

  • Canal de notificación: correo electrónico o mensajería (Slack, PagerDuty, etc.).
  • Ciclo de vida: hay que registrar la gestión del incidente desde Open hasta Closed para asegurar trazabilidad. Si una alerta se abre y no se cierra, no sabés si alguien la atendió.
  • Higiene de alertas: usar Muting Rules durante mantenimientos y ventanas de alineación para evitar la fatiga del equipo técnico. Si tenés una cantidad descomunal de alertas que nadie lee, no tenés ni idea del estado real del sistema.
  • Alertas basadas en logs: para notificación inmediata ante eventos críticos específicos que no tienen métrica nativa (ej: detección de intrusiones, errores de auditoría).

Las alertas de performance las atás a un período de tiempo. Por lo general, los objetivos que disparan las alertas se basan en el SLO definido con el cliente.

SLI (Service Level Indicator): la métrica con la que medís.

SLO (Service Level Objective): el valor objetivo de esa métrica — lo que acordaste en el SLA.

Observabilidad

Es la capacidad de entender el estado interno de un sistema complejo basándose únicamente en los datos que este genera hacia el exterior.

Depende de tres tipos de datos:

  • Métricas: valores numéricos medidos en el tiempo. Son ideales para detectar anomalías y ver tendencias (CPU, memoria, tasa de errores).
  • Logs: registros de eventos discretos.
  • Traces: muestran el recorrido de una request a través de todos los componentes del sistema (microservicios, bases de datos, APIs externas).

Observabilidad en GCP

Varios servicios emiten métricas y logs de forma nativa, sin necesitar configuración adicional: App Engine, GKE, Cloud Run y Cloud Run Functions. Todos mandan sus datos directamente a la Cloud Logging API y la Cloud Monitoring API.

Para VMs con Compute Engine, en cambio, necesitás instalar el Ops Agent.

Monitoreo en GKE

GKE se integra nativamente con Cloud Logging y Cloud Monitoring. También se puede integrar con GC Managed Prometheus:

  • Funciona con un modelo de extracción (pull): scrapea métricas de la aplicación a intervalos regulares (ej: cada 15 segundos).
  • La aplicación expone un endpoint /metrics con las métricas en formato Prometheus.
  • Los datos se almacenan en Cloud Monarch (el repositorio global de métricas de Google) y se visualizan en Cloud Monitoring.

Ops Agent

Agente unificado de Google Cloud para Compute Engine que combina la recolección de logs y métricas en un solo proceso:

  • Hace scraping de métricas de Prometheus y las envía directo al Global Data Store (Monarch). No hace falta instalar servidores de Prometheus completos en cada VM.
  • Simplifica el Service Discovery dentro del entorno de Compute Engine — básicamente te dice qué tenés corriendo.
  • Tiene soporte oficial para las distros de Linux más usadas y Windows.

Open Telemetry

Proyecto open source de la CNCF que da APIs, SDKs y herramientas para recolectar datos de telemetría. La pieza central es el collector, que orquesta la recolección, el procesamiento y la exportación:

  • Receivers: capturan datos en distintos formatos.
  • Processors: transforman, filtran y enriquecen los datos.
  • Exporters: envían los datos a uno o más destinos (Datadog, Elastic, New Relic).

En GCP se conecta con tres servicios:

  • Cloud Trace: visualización de latencias en microservicios distribuidos mediante trazas propagadas por OTel.
  • Cloud Monitoring: ingesta de métricas personalizadas y del sistema mediante Monarch.
  • Managed Prometheus: colección de métricas compatibles con Prometheus usando el collector de OpenTelemetry.

Incorporar métricas propias a Cloud Monitoring

Dependiendo de dónde corra la aplicación, el camino es distinto:

  • GKE (Managed Service for Prometheus): exponés un endpoint /metrics con librerías estándar de Prometheus. El Managed Service hace el scraping automático, almacena en Monarch y visualizás en Cloud Monitoring. Lo usás cuando la métrica no es parte del set prefabricado de Cloud Monitoring — es decir, cuando necesitás una métrica custom.
  • VMs (Ops Agent): configurás el agente en la instancia, él captura las métricas y las manda a la API de Cloud Monitoring.
  • Instrumentación directa (OpenTelemetry SDKs): integrás el SDK de OTel en el código (Java, Go, Python, .NET) y enviás los datos a un OTel Collector centralizado.

Monitoreo de red

Cuando monitoreás la red de GCP, no lo hacés a nivel del dispositivo físico — lo hacés a nivel de la interfaz de red de cada VM.

VPC Flow Logs

Registran los metadatos de las conexiones de red. Se basan en 5 elementos clave (el "5-tuple"):

  • IP de origen y destino
  • Puerto de origen y destino
  • Protocolo

Los logs se capturan dentro de la interfaz de red de la VM, no en el cable físico ni en el router central. Esto tiene una implicancia importante:

  • Tráfico saliente (Egress): si una regla de firewall bloquea la salida de una VM, el log sí registra el intento.
  • Tráfico entrante (Ingress): si una regla de firewall bloquea un paquete que viene de afuera, no queda registrado en el log.

Se habilitan por subred y se puede configurar el intervalo de agregación, la tasa de muestreo y qué metadatos incluir (ID de la VM, ID del endpoint). Ver formato completo del registro.

Logs del firewall

Los logs de firewall no están activos por defecto — hay que editar cada regla para incluirla en los logs.

Cada registro tiene:

  • action: Allow o Deny.
  • rule_details: el nombre de la regla que se aplicó.
  • connection: IP de origen, puerto de destino y protocolo.
  • disposition: indica si la regla es de prioridad más alta o si se aplicó por defecto.

La diferencia entre los dos tipos de log es clara: el Firewall Log te dice qué regla actuó. El VPC Flow Log te da la estadística del tráfico (bytes, paquetes).

Logs de load balancers

Cada tipo de balanceador registra cosas distintas:

  • Application Load Balancers: status codes HTTP, URLs exactas y latencias. Permiten ver exactamente qué experimentó el usuario final en el navegador.
  • Network Load Balancers: conectividad pura — flujos de paquetes, IPs y puertos.
  • Proxy Load Balancers: terminación de la conexión del cliente e inicio de la conexión al backend. Útiles para diagnosticar problemas de negociación SSL/TLS.

Reliability

Todo lo que se ve esta clase está basado en un libro de SRE (Site Reliability Engineering) publicado por Google en 2016.

La confiabilidad es la característica más fundamental de cualquier producto. Si una persona no puede confiar en un servicio, ese servicio falló.

Reliability: la capacidad de un sistema de ejecutar su función prevista de manera consistente, bajo condiciones variables, durante un período de tiempo determinado.

El problema del sysadmin

Hace algunos años el perfil dominante para operar sistemas era el sysadmin: una persona o equipo que administraba producción de forma manual o semiautomática (mantenimiento, actualizaciones, deploys).

Dos problemas concretos de ese modelo:

  • Escala lineal: a medida que el sistema crece, necesitás más y más gente operándolo.
  • Tensión estructural: los developers quieren llevar cambios a producción lo antes posible. Los sysadmins quieren minimizar cambios porque el cambio introduce errores. Son objetivos opuestos.

Site Reliability Engineering (SRE)

Ben Treynor Sloss crea el concepto en 2003 cuando le asignan liderar un equipo de sysadmins en Google. Durante 13 años desarrollaron métodos para reducir esa tensión entre dev y ops, automatizando y reduciendo fricción en el mantenimiento y despliegue.

En 2016 Google publica el libro Site Reliability Engineering con todas sus prácticas. Hoy es adoptado en empresas de software de todo tipo y tamaño.

Tolerancia al riesgo

La confiabilidad extrema es costosa: ya sea por hardware redundante o por dedicar esfuerzo de ingeniería a mejorar confiabilidad en vez de sacar features.

El punto clave: la diferencia entre 99.9% y 99.99% de disponibilidad requiere muchísimo esfuerzo, y muchas veces la mejora percibida por los usuarios es mínima o nula, porque otra parte del sistema es menos confiable (GCS es mucho más confiable que la conexión de red del celular del usuario).

Por eso hay que construir un consenso entre producto e ingeniería para definir cuál es la disponibilidad que realmente necesitamos.

DisponibilidadDowntime / AñoDowntime / MesDowntime / SemanaDowntime / Día
99.999%5.256 min0.438 min0.101 min0.014 min
99.990%52.56 min4.38 min1.011 min0.144 min
99.900%8.76 hs43.8 min10.108 min1.44 min
99.500%43.8 hs3.65 hs50.538 min7.2 min
99.000%87.6 hs7.3 hs101.077 min14.4 min

SLI, SLO y SLA

  • Service Level Indicator (SLI): la métrica con la que medís. Lo primero que hay que preguntarse es qué vamos a medir. Existen infinitas variables de un sistema que podemos monitorear; un subconjunto reducido de ellas nos va a servir para entender qué tan bien funciona el sistema.
  • Service Level Objective (SLO): el valor objetivo de esa métrica. Una vez que podés medir algo, podés establecer umbrales: si estás por debajo del umbral tiene que sonar una alarma que te haga focalizar en mejorar la confiabilidad en vez de sacar nueva funcionalidad.
  • Service Level Agreement (SLA): el acuerdo legal con el cliente, que puede tener implicancias financieras. El SLA tiene que ser más relajado que el SLO — si ya sonaron las alarmas internas (SLO) antes de violar el acuerdo, tenés margen para actuar.

Error Budget

Concepto creado por el equipo de Treynor Sloss para poder determinar de manera objetiva si el equipo tiene que trabajar en confiabilidad o en features nuevas.

  • Se mide con una rolling window de X días: se toma el conjunto de métricas del período y se lo compara con el SLO.
  • Si el resultado da que estás por debajo del SLO → congelás features y trabajás en confiabilidad.
  • Si tenés presupuesto disponible → usarlo para sacar funcionalidad nueva que mejore la experiencia o atraiga usuarios.

Ej: si tengo un SLO de 95% de availability y actualmente tengo 99%, mi Error Budget es de 4%. Si bajo de 95%, hay que parar y arreglar.

Toil

Trabajo asociado con correr un servicio en prod que suele ser manual, repetitivo, automatizable, táctico, que no ofrece valor que perdura en el tiempo y escala linealmente.

  • Táctico: reactivo, se ejecuta ante una interrupción o alerta. No es estratégico ni proactivo.
  • Valor perdurable: un cambio o mejora en el proceso que es repetible y reduce fricción o costos. Automatizar algún paso del despliegue, por ejemplo.

La idea es reducir este trabajo porque consume tiempo de personas del equipo en algo que no suma tanto valor, y además es desgastante por el estrés de potencialmente generar un error.

Un caso super típico es el deploy manual de una aplicación.

Four Golden Signals

Las cuatro métricas genéricas y mínimas para determinar que un sistema está medianamente monitoreado:

  • Latencia: el tiempo en procesar una request. Es necesario diferenciar la latencia entre errores y respuestas exitosas — una respuesta de error rápida no es lo mismo que una respuesta exitosa lenta.
  • Tráfico: la demanda que está soportando el sistema. Se puede medir en requests por segundo, conexiones concurrentes o lecturas a disco, dependiendo del tipo de sistema.
  • Errores: pueden ser explícitos (HTTP 500), implícitos (HTTP 200 con contenido incorrecto) o que fallen algún requerimiento no funcional (respuesta correcta pero demasiado lenta).
  • Saturación: el uso de los recursos del sistema. Lo mejor es medir el recurso por el que el sistema está limitado (memoria, disco, CPU). La saturación afecta rápidamente a la latencia.

MTBF y MTTR

  • Mean Time Between Failures (MTBF): el tiempo promedio que pasa entre dos errores en el sistema. Es imposible que sea infinito, pero hay que apuntar a que sea lo más alto posible con mecanismos que identifiquen bugs lo antes posible.
  • Mean Time To Repair (MTTR): el promedio de tiempo desde que encontramos un bug en producción hasta que lo solucionamos. Puede ser cero si capturamos los bugs en etapas de testing previas. Si el error ya está en producción, un canary release y herramientas de rollback ayudan a identificar y mitigar el impacto.

CI/CD Pipelines

  • Un pipeline de CI (Continuous Integration) reduce muchísimo las chances de mandar código roto a producción.
    • También te permite generar un artefacto testeado de manera mucho más sencilla y reproducible.
  • Un pipeline de CD puede ser:
    • Continuous Delivery: automatiza hasta dejar el artefacto listo para deployar, con un paso manual de aprobación.
    • Continuous Deployment: automatiza el deploy completo, sin intervención humana.

AI y BigQuery

BigQuery

Es un servicio serverless de data warehousing: te deja correr SQL sobre volúmenes masivos de datos sin administrar infraestructura. Está construido sobre bases de datos columnares, que son mucho más eficientes que las relacionales clásicas para queries analíticos.

No solemos cargar datos desde nuestra máquina. Lo típico es traerlos desde una fuente que ya los tenga — un bucket de GCS, un data lake externo, o bien derivarlos de tablas que ya están en BigQuery.

Para cargar datos hay tres caminos:

MétodoAutomatizableCuándo usarlo
Console (CSV upload)NoExploración rápida, datasets chicos
CLI bq load desde GCSPipelines batch repetibles
DDL CREATE TABLE AS SELECTDerivar tablas ya en BQ

BigQuery ML

Podés entrenar modelos de ML directamente en SQL, sin mover los datos. El trade-off es que tenés menos opciones de modelos que Vertex AI, pero los datos nunca salen de BigQuery — no hay infra de ML que gestionar.

-- Entrenás el modelo con SQL, sobre datos que ya están en BQ
CREATE OR REPLACE MODEL nyctaxi.fare_model
OPTIONS(model_type='linear_reg', input_label_cols=['fare_amount']) AS
SELECT fare_amount, trip_distance, passenger_count,
  EXTRACT(HOUR FROM pickup_datetime) AS pickup_hour
FROM nyctaxi.2018trips
WHERE fare_amount > 0 AND trip_distance > 0;

-- Y predecís también con SQL
SELECT * FROM ML.PREDICT(MODEL nyctaxi.fare_model,
  (SELECT 5.0 AS trip_distance, 2 AS passenger_count, 18 AS pickup_hour));

AI en GCP

Agent Platform (antes Vertex AI, renombrado en 2026) es la plataforma unificada de ML/AI. Dentro tiene Model Garden, Agent Builder, RAG Engine, Notebooks y la Gemini API.

Agent Studio (antes Vertex AI Studio) es la UI para prototipar con modelos generativos sin escribir código.

Hay tres niveles de abstracción según cuánto control necesitás:

  • APIs pre-entrenadas (Vision AI, Speech-to-Text, Document AI, Translation): hacés una llamada a la API y listo. Minutos de setup, el más barato.
  • Modelos generativos (Gemini, Imagen, Chirp): le pasás un prompt con configuración. También minutos de setup, más caro que las APIs pero mucho más flexible.
  • Modelo propio (Vertex AI Training, AutoML, BigQuery ML): traés tu propio dataset y entrenás. Horas o días, el más costoso.

La regla práctica es empezar siempre desde el nivel más simple. No tiene sentido entrenar un modelo propio si una API ya resuelve el problema.

¿Cuándo uso cada cosa?

  • Si la tarea es estándar y bien definida (OCR, traducción, transcripción de audio) → API pre-entrenada.
  • Si necesitás razonamiento, lenguaje natural o algo creativo → modelo generativo.
  • Si tenés datos tabulares y querés predecir un número a escala → modelo propio o BigQuery ML.

Por ejemplo: para extraer texto de 50.000 facturas, Document AI es más barato y más rápido que Gemini. Para un chatbot que responda sobre tus productos, Gemini con Grounding es la opción correcta. Para detectar fraude en transacciones, Gemini no sirve — necesitás un modelo entrenado con tus datos.

Gemini: Flash vs Pro

Ambos son de Google, pero tienen trade-offs muy distintos:

FlashPro
Latencia~0.5s~2–5s
Costo~1.25 / 1M tokens (25x más caro)
RazonamientoBuenoSignificativamente mejor

Flash para el 80% de los casos. Pro cuando la calidad del razonamiento lo justifica.


¿Cómo le doy conocimiento al modelo?

El modelo base no sabe nada de tu empresa. Hay tres formas de dárselo, de más simple a más costoso:

Grounding

Conectás el modelo a fuentes externas en tiempo de inferencia — Google Search o tus propios documentos. No reentrenás nada; el modelo consulta la fuente al momento de responder y cita las fuentes.

Útil para información dinámica (precios, noticias, disponibilidad). Setup en minutos.

from google import genai
from google.genai.types import GenerateContentConfig, Tool, GoogleSearch

client = genai.Client(vertexai=True, project="my-project", location="global")
response = client.models.generate_content(
    model="gemini-2.5-flash",
    contents="¿Cuál es la cotización del dólar en Argentina hoy?",
    config=GenerateContentConfig(tools=[Tool(google_search=GoogleSearch())]),
)

Sin Grounding el modelo inventa un número. Con Grounding busca en Google y cita de dónde sacó el dato.

RAG — Retrieval Augmented Generation

Procesás tus documentos, los convertís en embeddings, y armás un índice de búsqueda vectorial. Cuando el usuario pregunta algo, el sistema busca los fragmentos más relevantes y se los pasa al modelo como contexto.

Tus docs → chunks → embeddings → Vector Search
Pregunta → embedding → chunks similares → LLM responde con ese contexto

Más control que Grounding sobre qué se recupera y cómo. Setup en horas. Se usa cuando querés buscar patrones o hacer búsqueda semántica sobre tu propio contenido.

Fine-tuning

Reentrenás el modelo con pares de input/output propios. A diferencia de RAG, no le estás dando información nueva — le estás cambiando el comportamiento. Es carísimo y tarda bastante. Usarlo solo cuando Grounding y RAG ya no alcanzan.


¿Chatbot o Agente?

Un chatbot genera texto. Un agente ejecuta acciones.

La diferencia no es que el agente "acceda" a tus sistemas directamente — el modelo genera un pedido estructurado (ej: create_booking("CBA", "2026-06-06")), tu aplicación lo recibe, lo ejecuta, y le devuelve el resultado al modelo para que genere la respuesta final.

def get_weather(location: str) -> dict:
    """Devuelve el clima actual de una ubicación."""
    ...

def book_flight(origin: str, destination: str, date: str) -> dict:
    """Reserva un vuelo entre dos ciudades."""
    ...

response = client.models.generate_content(
    model="gemini-2.5-flash",
    contents="Necesito volar de Buenos Aires a Córdoba el viernes. ¿Cómo va a estar el clima allá?",
    config=GenerateContentConfig(tools=[get_weather, book_flight]),
)

Gemini decide qué función usar leyendo el nombre, los type hints y el docstring. El SDK convierte eso a un JSON schema automáticamente. Ver Function Calling.


Prompt Engineering

Antes de cambiar de modelo, agregar RAG o hacer fine-tuning: mejorar el prompt es gratis.

  • System Instructions: definís el rol y el comportamiento base del modelo. Ej: "Sos un analista financiero. Respondé solo con datos, nunca especules."
  • Output Structuring: le pedís un formato específico. Ej: "Respondé en JSON con keys: risk_level, factors, recommendation."
  • Few-shot: le das 2–3 ejemplos de input→output antes del input real. Mejora mucho la precisión en tareas estructuradas.
  • Chain of Thought: "Antes de responder, razoná paso a paso." Útil para problemas complejos.

Temperature

El modelo predice el siguiente token calculando probabilidades para cada palabra posible. Temperature escala esas probabilidades:

  • Temp 0: siempre elige el token más probable → siempre la misma respuesta.
  • Temp baja (0.1–0.3): los tokens probables se vuelven aún más probables → enfocado y predecible.
  • Temp alta (> 1): tokens menos probables ganan chances → respuestas más variadas, pero más erráticas.

Para extracción de datos usás temperatura baja. Para creatividad, alta. Para Q&A, algo en el medio.


Responsible AI

No es solo ética — son restricciones concretas que afectan cómo diseñás el sistema.

  • Los datos del cliente no se usan para entrenar modelos de Google.
  • Los Safety Filters están activos por default y pueden rechazar inputs legítimos — hay que manejar ese caso.
  • Las alucinaciones son siempre posibles, incluso con modelos buenos. Por eso Grounding y RAG muestran fuentes: el usuario puede verificar.
  • No hay determinismo garantizado: la misma pregunta no siempre da la misma respuesta.
  • SynthID: watermark invisible que Google embebe en el contenido generado por IA para que sea identificable.

Cloud Shell

Es un recurso análogo al CLI de AWS. Básicamente te permite interactuar con todos los recursos de GCP pero desde una terminal.

Prerrequisitos

  • Tener, justamente, la herramienta instalada en tu sistema. Si no la tenés, buscala acá

Ejemplos

He aquí algunos ejemplos de lo que se puede hacer:

Verificar la cuenta activa

gcloud auth list

Listar los proyectos existentes a los cuales la cuenta tiene acceso

gcloud config list project

Setear la región default

gcloud config set compute/region <REGION>

Crear una instancia de una VM en una zona particular

gcloud compute instances create gcelab2 --machine-type e2-medium --zone=$ZONE
  • Notar que se crea con el nombre gcelab2 y es de tipo e2-medium

Conectarte por SSH a una instancia ya creada

gcloud compute ssh gcelab2 --zone=<ZONE>
  • Hay que pasarle la zona por parámetro

Crear un cluster de máquinas y asignarlas a una Target Pool

Vamos a crear máquinas con los nombres www1, www2 y www3.

  gcloud compute instances create www1 \
    --zone=$ZONE \
    --tags=network-lb-tag \
    --machine-type=e2-small \
    --image-family=debian-11 \
    --image-project=debian-cloud \
    --metadata=startup-script='#!/bin/bash
      apt-get update
      apt-get install apache2 -y
      service apache2 restart
      echo "
<h3>Web Server: www1</h3>" | tee /var/www/html/index.html'
  gcloud compute instances create www2 \
    --zone=$ZONE \
    --tags=network-lb-tag \
    --machine-type=e2-small \
    --image-family=debian-11 \
    --image-project=debian-cloud \
    --metadata=startup-script='#!/bin/bash
      apt-get update
      apt-get install apache2 -y
      service apache2 restart
      echo "
<h3>Web Server: www2</h3>" | tee /var/www/html/index.html'
  gcloud compute instances create www3 \
    --zone=$ZONE \
    --tags=network-lb-tag \
    --machine-type=e2-small \
    --image-family=debian-11 \
    --image-project=debian-cloud \
    --metadata=startup-script='#!/bin/bash
      apt-get update
      apt-get install apache2 -y
      service apache2 restart
      echo "
<h3>Web Server: www3</h3>" | tee /var/www/html/index.html'

Para poder usarlas, tenemos que crear una regla de firewall para poder permitir el tráfico hacia estas máquinas:

gcloud compute firewall-rules create www-firewall-network-lb \
    --target-tags network-lb-tag --allow tcp:80

Ahora, necesitamos crear una target pool y asignar esas instancias para que el NLB pueda accederlas

  • Crear la target pool
gcloud compute target-pools create www-pool \
  --region Region --http-health-check basic-check
  • Asignar las instancias a esa pool
gcloud compute target-pools add-instances www-pool \
    --instances www1,www2,www3

Por último, para poder interactuar con esas instancias a través del NLB, necesitamos agregar una forwarding rule:

gcloud compute forwarding-rules create www-rule \
    --region  Region \
    --ports 80 \
    --address network-lb-ip-1 \
    --target-pool www-pool

Definir reglas de firewall

gcloud compute firewall-rules create allow-ssh-clase \
  --direction=INGRESS \
  --priority=1000 \
  --network=default \
  --action=ALLOW \
  --rules=tcp:22 \
  --source-ranges=181.20.10.5/32 \ # solo los admins pueden conectarse por SSH desde esta IP
  --target-tags=ssh-admin
gcloud compute firewall-rules create allow-http-public \
  --direction=INGRESS \
  --priority=1000 \
  --network=tu-vpc-pro \ # Esto es una red particular
  --action=ALLOW \
  --rules=tcp:80 \
  --source-ranges=0.0.0.0/0 \ # permito todo el tráfico HTTP
  --target-tags=web-frontend
gcloud compute firewall-rules create block-attacker \
  --direction=INGRESS \
  --priority=100 \
  --network=default \
  --action=DENY \
  --rules=all \
  --source-ranges=190.0.0.0/8 # bloqueo todo el tráfico dentro de este source range

¿Por qué elijo un Cloud Provider sobre otro?

Se elige uno sobre otro dependiendo de lo que quieras hacer:

  • AWS es bastante más generalista. Tiene una oferta más amplia de recursos
  • GCP es más orientado a datos (análisis, ML, etc.)

Uno elige profundizar más en una que en otra por ya estar ahí y por la portabilidad que ofrece.

Cuanto más me caso con un proveedor, más me hundo en él, y más costoso es salir

Hay costos de egreso e ingreso al pasar datos entre nubes.

Prácticas de infraestructura (src/examples)

En esta carpeta vas a encontrar prácticas de infraestructura pensadas para acompañar los labs del curso, con foco en Terraform y buenas prácticas (variables reutilizables, outputs, estructura clara por caso de uso, etc.).

Qué incluye hoy

  • cloud-run/cloud-run-functions-qwik-start/
    • Ejemplo Terraform basado en el lab Cloud Run Functions Qwik Start.
    • Cubre APIs, Cloud Run Functions (gen2), triggers y recursos asociados.
  • cloud-run/pubsub-with-cloud-run/
    • Ejemplo Terraform basado en el lab Cloud Pub Sub With Cloud Run.
    • Cubre servicios Cloud Run, topic/subscription de Pub/Sub, service account e IAM.
  • iam/configuring-iam-with-gcloud/
    • Ejemplo Terraform basado en el lab Configuring IAM Permissions with gcloud.
    • Cubre rol custom, bindings IAM para un segundo usuario, service account y una VM con identidad adjunta.
  • iam/exploring-iam/
    • Ejemplo Terraform basado en el lab Exploring IAM.
    • Cubre bucket de prueba, grants IAM acotados, service account y VM demoiam.
  • load-balancer/create-nlb/
    • Ejemplo Terraform para crear un Network Load Balancer.
  • load-balancer/application-load-balancer/
    • Ejemplo Terraform para un Application Load Balancer con autoscaling (MIG + autoscaler).
  • network/configuring-vpc/
    • Ejemplo Terraform basado en el lab Configuring VPC Firewalls.
    • Cubre VPC auto mode, VMs de demo y reglas de firewall ingress/egress.
  • network/controlling-access/
    • Ejemplo Terraform basado en el lab VPC Networks - Controlling Access.
    • Cubre VMs web, firewall taggeado y service account para probar permisos de red.
  • network/multiple-vpc/
    • Ejemplo Terraform basado en el lab Multiple VPC Networks.
    • Cubre VPCs custom/auto mode, VMs y una appliance con múltiples interfaces de red.
  • network/vpc-flow-logs/
    • Ejemplo Terraform basado en el lab Analyzing Network Traffic with VPC Flow Logs.
    • Cubre VPC custom con Flow Logs, firewall, VM Apache, log sink a BigQuery y permisos IAM del sink.
  • network/build-secure-network-challenge/
    • Ejemplo Terraform basado en el lab Build a Secure Network - Challenge.
    • Cubre bastion sin IP pública vía IAP, juice-shop con HTTP, y reglas de firewall restrictivas por tags/subred.
  • storage/buckets/
    • Ejemplo Terraform basado en el lab Cloud Storage (versioning, lifecycle y objetos de muestra).
  • storage/cloud-sql/
    • Ejemplo Terraform basado en el lab Implementing Cloud SQL (Cloud SQL, peering privado y VMs de demo).
  • terraform/automating-infrastructure-deployment/
    • Ejemplo Terraform basado en el lab Automating the Deployment of Infrastructure Using Terraform.
    • Cubre VPC auto mode, firewall ICMP/SSH/HTTP/RDP y dos VM instances en zonas distintas.
  • virtual-machines/create-vm/
    • Ejemplo Terraform para crear una VM en Compute Engine.
  • terraform/build-iac-with-terraform/
    • Ejemplo Terraform basado en el lab Build IaC with Terraform.
    • Cubre import de Compute Engine, bucket para estado remoto, VPC con módulo del registry y firewall.
  • storage/cloud-storage/bucket/
    • Ejemplo del SDK de Cloud Storage en Python (google-cloud-storage): funciones upload_blob/download_blob. No es Terraform.
  • observability/ops-agent-monitoring/
    • Ejemplo Terraform basado en el lab Monitoring a Compute Engine by using Ops Agent.
    • Cubre VM con Apache + Ops Agent preconfigurado vía startup script, firewall HTTP, canal de notificación y alerting policy opcionales.
  • observability/cloud-trace/
    • Ejemplo Terraform basado en el lab View application latency with Cloud Trace.
    • Cubre cluster GKE con scopes para Cloud Trace; la app demo Python + OpenTelemetry se despliega con el script oficial.
  • observability/alerting-in-gcp/
    • Ejemplo Terraform basado en el lab Alerting in Google Cloud.
    • Cubre App Engine application y un alert policy de Cloud Monitoring (latencia 99th percentile) con notification channel opcional.
  • observability/service-monitoring/
    • Ejemplo Terraform basado en el lab Service Monitoring.
    • Cubre App Engine application, un SLO de disponibilidad (rolling window) para el servicio default y un alert policy por burn rate del error budget (notification channel opcional).
  • observability/log-analytics/
    • Ejemplo Terraform basado en el lab Log Analytics on Google Cloud (GSP1088).
    • Cubre GKE, log bucket con Log Analytics habilitado, linked dataset en BigQuery y log sink para enrutar logs k8s_container.
  • observability/monitoring-apps-in-gcp/
    • Ejemplo Terraform basado en el lab Monitoring Applications in Google Cloud.
  • cicd/devops-pipeline/
    • Ejemplo Terraform basado en el lab Building a DevOps Pipeline (curso 41).
    • Cubre Cloud Build trigger + Artifact Registry conectado a GitHub.

Cómo usar estas prácticas

  1. Entrá a la carpeta del ejemplo que quieras.
  2. Inicializá Terraform con terraform init.
  3. Definí variables (por ejemplo en terraform.tfvars).
  4. Revisá cambios con terraform plan.
  5. Aplicá con terraform apply.

Recomendaciones

  • No hardcodear project_id, región o nombres sensibles: usá variables.
  • Usar terraform fmt y, si podés, terraform validate antes de aplicar.
  • Si estás probando en un proyecto temporal, al terminar corré terraform destroy.

Carpeta remota en GitHub

Cloud Run

Prácticas Terraform para servicios serverless y flujos event-driven sobre Cloud Run.

PrácticaDescripción
Cloud Run Functions Qwik StartFunción HTTP serverless básica con Cloud Run Functions
Cloud Pub/Sub with Cloud RunIntegración event-driven entre Pub/Sub y dos servicios Cloud Run
PDF Converter con Cloud RunPipeline de conversión de archivos a PDF usando LibreOffice + Cloud Storage + Pub/Sub

Terraform Example: Cloud Run Functions Qwik Start

Este ejemplo replica los recursos principales del lab Cloud Run Functions Qwik Start usando Terraform.

Qué despliega

  • Habilitación de APIs necesarias (cloudfunctions, run, eventarc, pubsub, etc.).
  • Bucket de Cloud Storage para eventos.
  • Permisos IAM requeridos para integración de eventos.
  • Funciones de Cloud Run Functions (gen2):
    • nodejs-http-function
    • nodejs-storage-function
    • gce-vm-labeler
    • hello-world-colored
    • slow-function
    • slow-concurrent-function

Importante

Las funciones se despliegan desde ZIPs en Cloud Storage. Tenés que subir previamente esos artefactos al bucket definido en source_bucket_name.

Uso rápido

  1. Inicializá:
terraform init
  1. Creá terraform.tfvars:
project_id         = "tu-project-id"
region             = "us-central1"
source_bucket_name = "tu-bucket-con-zips"

source_objects = {
  nodejs_http              = "nodejs-http-function.zip"
  nodejs_storage           = "nodejs-storage-function.zip"
  gce_vm_labeler           = "gce-vm-labeler.zip"
  hello_world_colored      = "hello-world-colored.zip"
  slow_function            = "slow-function.zip"
  slow_concurrent_function = "slow-concurrent-function.zip"
}
  1. Plan y apply:
terraform plan
terraform apply

Link al lab

Recursos identificados

  • APIs: artifactregistry.googleapis.com, cloudfunctions.googleapis.com, cloudbuild.googleapis.com, eventarc.googleapis.com, run.googleapis.com, logging.googleapis.com, pubsub.googleapis.com.
  • Cloud Run Functions (gen2):
    • nodejs-http-function (HTTP)
    • nodejs-storage-function (evento de Cloud Storage)
    • gce-vm-labeler (evento de Cloud Audit Logs)
    • hello-world-colored (HTTP con variable de entorno)
    • slow-function (HTTP, prueba de cold start)
    • slow-concurrent-function (HTTP, min instances y concurrencia)
  • Cloud Storage bucket para eventos: gcf-gen2-storage-<PROJECT_ID>.
  • IAM bindings:
    • roles/pubsub.publisher para la Cloud Storage service account.
    • roles/eventarc.eventReceiver para la Compute Engine default service account.
  • Compute Engine VM de prueba: instance-1 (creacion y borrado para test de Audit Logs).
  • Cloud Run service revisions (via consola) para pruebas de color, min instances y concurrencia.

Comandos ejecutados

Verificar la cuenta activa en Cloud Shell

Se usa para confirmar con que identidad estas autenticado.

gcloud auth list

Verificar el proyecto activo

Se usa para validar el PROJECT_ID que usara gcloud.

gcloud config list project

Habilitar APIs necesarias del lab

Se usa para activar servicios base de Cloud Run Functions, build, eventos y logs.

gcloud services enable \
  artifactregistry.googleapis.com \
  cloudfunctions.googleapis.com \
  cloudbuild.googleapis.com \
  eventarc.googleapis.com \
  run.googleapis.com \
  logging.googleapis.com \
  pubsub.googleapis.com

Habilitar Gemini for Google Cloud API

Se usa para permitir Gemini Code Assist en el entorno del lab.

gcloud services enable cloudaicompanion.googleapis.com

Crear carpeta base de la funcion HTTP

Se usa para inicializar el directorio de trabajo y entrar en el.

mkdir ~/hello-http && cd $_

Crear archivo de codigo de la funcion HTTP

Se usa para crear index.js.

touch index.js

Crear manifiesto de dependencias de la funcion HTTP

Se usa para crear package.json.

touch package.json

Desplegar funcion HTTP en Cloud Run Functions (gen2)

Se usa para publicar la funcion nodejs-http-function.

gcloud functions deploy nodejs-http-function \
  --gen2 \
  --runtime nodejs22 \
  --entry-point helloWorld \
  --source . \
  --region {{{project_0.default_region|Region}}} \
  --trigger-http \
  --timeout 600s \
  --max-instances 1

Probar la funcion HTTP desplegada

Se usa para invocar la funcion y validar la respuesta.

gcloud functions call nodejs-http-function \
  --gen2 \
  --region {{{project_0.default_region|Region}}}

Obtener el numero de proyecto

Se usa para guardar el PROJECT_NUMBER en una variable.

PROJECT_NUMBER=$(gcloud projects list --filter="project_id:{{{ project_0.project_id | PROJECT_ID }}}" --format='value(project_number)')

Obtener service account de Cloud Storage para KMS

Se usa para guardar la cuenta de servicio requerida en una variable.

SERVICE_ACCOUNT=$(gsutil kms serviceaccount -p $PROJECT_NUMBER)

Asignar rol pubsub.publisher a Cloud Storage

Se usa para permitir que eventos de Cloud Storage publiquen en Pub/Sub.

gcloud projects add-iam-policy-binding {{{ project_0.project_id | PROJECT_ID }}} \
  --member serviceAccount:$SERVICE_ACCOUNT \
  --role roles/pubsub.publisher

Crear carpeta base de la funcion de Cloud Storage

Se usa para inicializar el directorio de trabajo y entrar en el.

mkdir ~/hello-storage && cd $_

Crear archivo de codigo de la funcion de Cloud Storage

Se usa para crear index.js.

touch index.js

Crear manifiesto de dependencias de la funcion de Cloud Storage

Se usa para crear package.json.

touch package.json

Definir nombre del bucket en variable

Se usa para reutilizar el bucket en comandos posteriores.

BUCKET="gs://gcf-gen2-storage-{{{ project_0.project_id | PROJECT_ID }}}"

Crear bucket de Cloud Storage

Se usa para generar eventos que disparen la funcion.

gsutil mb -l {{{project_0.default_region|Region}}} $BUCKET

Desplegar funcion disparada por bucket

Se usa para publicar nodejs-storage-function con trigger de Cloud Storage.

gcloud functions deploy nodejs-storage-function \
  --gen2 \
  --runtime nodejs22 \
  --entry-point helloStorage \
  --source . \
  --region {{{project_0.default_region|Region}}} \
  --trigger-bucket $BUCKET \
  --trigger-location {{{project_0.default_region|Region}}} \
  --max-instances 1

Crear archivo de prueba local

Se usa para tener un objeto a subir al bucket.

echo "Hello World" > random.txt

Subir archivo al bucket

Se usa para disparar el evento de Cloud Storage.

gsutil cp random.txt $BUCKET/random.txt

Leer logs de la funcion de Cloud Storage

Se usa para confirmar que la funcion recibio el CloudEvent.

gcloud functions logs read nodejs-storage-function \
  --region {{{project_0.default_region|Region}}} \
  --gen2 \
  --limit=100 \
  --format "value(log)"

Asignar rol eventarc.eventReceiver a Compute Engine default SA

Se usa para habilitar recepcion de eventos de Audit Logs via Eventarc.

gcloud projects add-iam-policy-binding {{{ project_0.project_id | PROJECT_ID }}} \
  --member serviceAccount:$PROJECT_NUMBER-compute@developer.gserviceaccount.com \
  --role roles/eventarc.eventReceiver

Ir al home de Cloud Shell

Se usa para posicionarse donde se clonara el repositorio.

cd ~

Clonar repositorio de ejemplo de Eventarc

Se usa para obtener el codigo de gce-vm-labeler.

git clone https://github.com/GoogleCloudPlatform/eventarc-samples.git

Entrar al directorio del ejemplo nodejs

Se usa para desplegar desde el path correcto.

cd ~/eventarc-samples/gce-vm-labeler/gcf/nodejs

Desplegar funcion basada en Cloud Audit Logs

Se usa para etiquetar VMs creadas segun filtros de evento.

gcloud functions deploy gce-vm-labeler \
  --gen2 \
  --runtime nodejs22 \
  --entry-point labelVmCreation \
  --source . \
  --region {{{project_0.default_region|Region}}} \
  --trigger-event-filters="type=google.cloud.audit.log.v1.written,serviceName=compute.googleapis.com,methodName=beta.compute.instances.insert" \
  --trigger-location {{{project_0.default_region|Region}}} \
  --max-instances 1

Describir VM para verificar etiqueta creator

Se usa para comprobar que la funcion aplico labels.

gcloud compute instances describe instance-1 --zone {{{project_0.default_zone | "Zone"}}}

Eliminar VM de prueba

Se usa para limpieza de recursos.

gcloud compute instances delete instance-1 --zone {{{project_0.default_zone | "Zone"}}}

Crear carpeta base para funcion con revisiones

Se usa para preparar proyecto Python.

mkdir ~/hello-world-colored && cd $_

Crear codigo de funcion Python

Se usa para crear main.py.

touch main.py

Crear archivo de dependencias Python

Se usa para crear requirements.txt.

touch requirements.txt

Definir variable de color inicial

Se usa para pasarla como env var en el deploy.

COLOR=orange

Desplegar revision inicial de funcion coloreada

Se usa para publicar hello-world-colored con color naranja.

gcloud functions deploy hello-world-colored \
  --gen2 \
  --runtime python311 \
  --entry-point hello_world \
  --source . \
  --region {{{project_0.default_region|Region}}} \
  --trigger-http \
  --allow-unauthenticated \
  --update-env-vars COLOR=$COLOR \
  --max-instances 1

Crear carpeta base para prueba de cold start

Se usa para preparar proyecto Go.

mkdir ~/min-instances && cd $_

Crear codigo de funcion Go

Se usa para crear main.go.

touch main.go

Crear modulo Go

Se usa para crear go.mod.

touch go.mod

Desplegar funcion lenta sin min instances

Se usa para observar cold start inicial.

gcloud functions deploy slow-function \
  --gen2 \
  --runtime go123 \
  --entry-point HelloWorld \
  --source . \
  --region {{{project_0.default_region|Region}}} \
  --trigger-http \
  --allow-unauthenticated \
  --max-instances 4

Primera invocacion de la funcion lenta

Se usa para medir latencia con cold start.

gcloud functions call slow-function \
  --gen2 \
  --region {{{project_0.default_region|Region}}}

Segunda invocacion de la funcion lenta

Se usa para comparar latencia posterior al warm-up.

gcloud functions call slow-function \
  --gen2 \
  --region {{{project_0.default_region|Region}}}

Instalar herramienta de carga hey

Se usa para enviar requests concurrentes.

sudo apt install hey

Obtener URL de la funcion lenta

Se usa para guardarla en SLOW_URL.

SLOW_URL=$(gcloud functions describe slow-function --region {{{project_0.default_region|Region}}} --gen2 --format="value(serviceConfig.uri)")

Ejecutar prueba de concurrencia sin ajuste de concurrency

Se usa para observar tiempos altos por escalado/cold start.

hey -n 10 -c 10 $SLOW_URL

Eliminar servicio slow-function

Se usa para limpiar antes del siguiente despliegue.

gcloud run services delete slow-function --region {{{project_0.default_region | "Region"}}}

Desplegar funcion con min instances para prueba de concurrency

Se usa para publicar slow-concurrent-function.

gcloud functions deploy slow-concurrent-function \
  --gen2 \
  --runtime go123 \
  --entry-point HelloWorld \
  --source . \
  --region {{{project_0.default_region|Region}}} \
  --trigger-http \
  --allow-unauthenticated \
  --min-instances 1 \
  --max-instances 4

Obtener URL de la funcion concurrente

Se usa para guardarla en SLOW_CONCURRENT_URL.

SLOW_CONCURRENT_URL=$(gcloud functions describe slow-concurrent-function --region {{{project_0.default_region|Region}}} --gen2 --format="value(serviceConfig.uri)")

Ejecutar prueba de concurrencia con servicio ajustado

Se usa para validar mejora de tiempos con concurrencia alta.

hey -n 10 -c 10 $SLOW_CONCURRENT_URL

Terraform Example: Pub/Sub with Cloud Run

Este ejemplo implementa la arquitectura del lab Cloud Pub Sub With Cloud Run con Terraform.

Qué despliega

  • APIs necesarias (run, pubsub, iam).
  • Cloud Run store-service (público).
  • Cloud Run order-service (privado).
  • Topic de Pub/Sub ORDER_PLACED.
  • Subscription push hacia order-service.
  • Service account invocadora + IAM bindings requeridos.

Uso rápido

  1. Inicializá:
terraform init
  1. Creá terraform.tfvars:
project_id = "tu-project-id"
region     = "us-central1"
  1. Plan y apply:
terraform plan
terraform apply

Salidas útiles

El ejemplo expone por outputs:

  • URL de store-service
  • URL de order-service
  • nombre del topic
  • nombre de la subscription
  • email de la service account invocadora

Link al lab

Recursos identificados

  • APIs: run.googleapis.com (y uso de pubsub.googleapis.com en operaciones de Pub/Sub).
  • Cloud Run services: store-service (público), order-service (privado).
  • Pub/Sub: topic ORDER_PLACED, subscription push order-service-sub.
  • IAM service account: pubsub-cloud-run-invoker.
  • IAM bindings:
    • roles/run.invoker sobre order-service para la service account invocadora.
    • roles/iam.serviceAccountTokenCreator para la Pub/Sub service agent del proyecto.
  • Integración push autenticada Pub/Sub -> Cloud Run con --push-auth-service-account.

Comandos ejecutados

Verificar la cuenta activa en Cloud Shell

Se usa para confirmar con que identidad estas autenticado.

gcloud auth list

Verificar el proyecto activo

Se usa para validar el PROJECT_ID que usara gcloud.

gcloud config list project

Habilitar la API de Cloud Run

Se usa para poder desplegar servicios en Cloud Run.

gcloud services enable run.googleapis.com

Definir region en variable de entorno

Se usa para reutilizar la misma region en todo el lab.

LOCATION={{{project_0.default_region|REGION}}}

Configurar region por defecto de gcloud

Se usa para evitar pasar la region manualmente en cada comando.

gcloud config set compute/region $LOCATION

Desplegar servicio publico store-service

Se usa para publicar el productor accesible sin autenticacion.

gcloud run deploy store-service \
  --image gcr.io/qwiklabs-resources/gsp724-store-service \
  --region $LOCATION \
  --allow-unauthenticated

Desplegar servicio privado order-service

Se usa para publicar el consumidor solo para cuentas autenticadas.

gcloud run deploy order-service \
  --image gcr.io/qwiklabs-resources/gsp724-order-service \
  --region $LOCATION \
  --no-allow-unauthenticated

Crear topic de Pub/Sub

Se usa para recibir eventos de ordenes creadas.

gcloud pubsub topics create ORDER_PLACED

Crear service account invocadora

Se usa para que Pub/Sub pueda invocar order-service.

gcloud iam service-accounts create pubsub-cloud-run-invoker \
  --display-name "Order Initiator"

Listar service account creada

Se usa para confirmar que la cuenta existe.

gcloud iam service-accounts list --filter="Order Initiator"

Asignar rol Cloud Run Invoker al service account

Se usa para permitir invocar order-service.

gcloud run services add-iam-policy-binding order-service \
  --region $LOCATION \
  --member=serviceAccount:pubsub-cloud-run-invoker@$GOOGLE_CLOUD_PROJECT.iam.gserviceaccount.com \
  --role=roles/run.invoker \
  --platform managed

Obtener numero de proyecto

Se usa para guardarlo en la variable PROJECT_NUMBER.

PROJECT_NUMBER=$(gcloud projects list \
  --filter="qwiklabs-gcp" \
  --format='value(PROJECT_NUMBER)')

Permitir creacion de tokens para Pub/Sub

Se usa para que la service account administrada de Pub/Sub firme tokens.

gcloud projects add-iam-policy-binding $GOOGLE_CLOUD_PROJECT \
  --member=serviceAccount:service-$PROJECT_NUMBER@gcp-sa-pubsub.iam.gserviceaccount.com \
  --role=roles/iam.serviceAccountTokenCreator

Obtener URL de order-service

Se usa para guardarla en ORDER_SERVICE_URL.

ORDER_SERVICE_URL=$(gcloud run services describe order-service \
  --region $LOCATION \
  --format="value(status.address.url)")

Crear suscripcion push hacia order-service

Se usa para conectar el topic con el endpoint privado usando autenticacion.

gcloud pubsub subscriptions create order-service-sub \
  --topic ORDER_PLACED \
  --push-endpoint=$ORDER_SERVICE_URL \
  --push-auth-service-account=pubsub-cloud-run-invoker@$GOOGLE_CLOUD_PROJECT.iam.gserviceaccount.com

Obtener URL de store-service

Se usa para guardarla en STORE_SERVICE_URL.

STORE_SERVICE_URL=$(gcloud run services describe store-service \
  --region $LOCATION \
  --format="value(status.address.url)")

Enviar payload de prueba al productor

Se usa para publicar una orden y validar el flujo completo.

curl -X POST -H "Content-Type: application/json" -d @test.json $STORE_SERVICE_URL

Sistema asíncrono resiliente con Cloud Run y Pub/Sub

Practica basada en el lab GSP650. Despliega un sistema de fan-out donde un productor publica reportes en Pub/Sub y dos consumidores independientes (email y SMS) los procesan en paralelo via push subscriptions autenticadas.

Arquitectura

lab-report-service (público)
        │
        ▼
  Pub/Sub topic: new-lab-report
        │
   ┌────┴────┐
   ▼         ▼
email-service  sms-service
(privado)     (privado)

Pre-requisito: construir imágenes

Los servicios usan código del repositorio rosera/pet-theory. Construir y pushear las imágenes antes de aplicar Terraform:

git clone https://github.com/rosera/pet-theory
cd pet-theory/lab05/lab-service && npm install
gcloud builds submit --tag gcr.io/$PROJECT_ID/lab-report-service

cd ../email-service && npm install
gcloud builds submit --tag gcr.io/$PROJECT_ID/email-service

cd ../sms-service && npm install
gcloud builds submit --tag gcr.io/$PROJECT_ID/sms-service

Uso

terraform init

terraform apply -var="project_id=<PROJECT_ID>" \
  -var="lab_report_service_image=gcr.io/<PROJECT_ID>/lab-report-service" \
  -var="email_service_image=gcr.io/<PROJECT_ID>/email-service" \
  -var="sms_service_image=gcr.io/<PROJECT_ID>/sms-service"

Probar el flujo

LAB_URL=$(terraform output -raw lab_report_service_url)

curl -X POST \
  -H "Content-Type: application/json" \
  -d '{"id": 12, "status": "pending"}' \
  $LAB_URL/v1/report

Los logs de email-service y sms-service en Cloud Logging deben mostrar el mensaje recibido.

Variables requeridas

VariableDescripción
project_idID del proyecto GCP
lab_report_service_imageURI de imagen del productor
email_service_imageURI de imagen del consumidor email
sms_service_imageURI de imagen del consumidor SMS

Link al lab

Recursos identificados

  • APIs: run.googleapis.com, pubsub.googleapis.com, iam.googleapis.com.
  • Cloud Run services:
    • lab-report-service (público) — productor, recibe reportes y los publica en Pub/Sub.
    • email-service (privado) — consumidor, envía notificaciones por email.
    • sms-service (privado) — consumidor, envía notificaciones por SMS.
  • Pub/Sub topic: new-lab-report.
  • Pub/Sub subscriptions push:
    • email-service-sub → push autenticado a email-service.
    • sms-service-sub → push autenticado a sms-service.
  • IAM service account: pubsub-cloud-run-invoker.
  • IAM bindings:
    • roles/run.invoker sobre email-service para pubsub-cloud-run-invoker.
    • roles/run.invoker sobre sms-service para pubsub-cloud-run-invoker.
    • roles/iam.serviceAccountTokenCreator para el service agent de Pub/Sub del proyecto.
  • Código fuente: repositorio rosera/pet-theory.

Comandos ejecutados

Verificar la cuenta activa

gcloud auth list

Verificar el proyecto activo

gcloud config list project

Habilitar la API de Cloud Run

gcloud services enable run.googleapis.com

Clonar repositorio pet-theory

git clone https://github.com/rosera/pet-theory

Crear topic de Pub/Sub

gcloud pubsub topics create new-lab-report

Desplegar lab-report-service (productor público)

Se construye la imagen localmente y se despliega como servicio público.

gcloud run deploy lab-report-service \
  --image gcr.io/$GOOGLE_CLOUD_PROJECT/lab-report-service \
  --platform managed \
  --region us-central1 \
  --allow-unauthenticated \
  --max-instances=1

Desplegar email-service (consumidor privado)

gcloud run deploy email-service \
  --image gcr.io/$GOOGLE_CLOUD_PROJECT/email-service \
  --platform managed \
  --region us-central1 \
  --no-allow-unauthenticated \
  --max-instances=1

Desplegar sms-service (consumidor privado)

gcloud run deploy sms-service \
  --image gcr.io/$GOOGLE_CLOUD_PROJECT/sms-service \
  --platform managed \
  --region us-central1 \
  --no-allow-unauthenticated \
  --max-instances=1

Crear service account invocadora

gcloud iam service-accounts create pubsub-cloud-run-invoker \
  --display-name "PubSub Cloud Run Invoker"

Asignar rol run.invoker sobre email-service

gcloud run services add-iam-policy-binding email-service \
  --member=serviceAccount:pubsub-cloud-run-invoker@$GOOGLE_CLOUD_PROJECT.iam.gserviceaccount.com \
  --role=roles/run.invoker \
  --region us-central1 \
  --platform managed

Asignar rol run.invoker sobre sms-service

gcloud run services add-iam-policy-binding sms-service \
  --member=serviceAccount:pubsub-cloud-run-invoker@$GOOGLE_CLOUD_PROJECT.iam.gserviceaccount.com \
  --role=roles/run.invoker \
  --region us-central1 \
  --platform managed

Obtener número de proyecto

PROJECT_NUMBER=$(gcloud projects list \
  --filter="qwiklabs-gcp" \
  --format='value(PROJECT_NUMBER)')

Permitir creación de tokens para el service agent de Pub/Sub

gcloud projects add-iam-policy-binding $GOOGLE_CLOUD_PROJECT \
  --member=serviceAccount:service-$PROJECT_NUMBER@gcp-sa-pubsub.iam.gserviceaccount.com \
  --role=roles/iam.serviceAccountTokenCreator

Obtener URL de email-service

EMAIL_SERVICE_URL=$(gcloud run services describe email-service \
  --platform managed \
  --region us-central1 \
  --format="value(status.address.url)")

Crear suscripción push hacia email-service

gcloud pubsub subscriptions create email-service-sub \
  --topic new-lab-report \
  --push-endpoint=$EMAIL_SERVICE_URL \
  --push-auth-service-account=pubsub-cloud-run-invoker@$GOOGLE_CLOUD_PROJECT.iam.gserviceaccount.com

Obtener URL de sms-service

SMS_SERVICE_URL=$(gcloud run services describe sms-service \
  --platform managed \
  --region us-central1 \
  --format="value(status.address.url)")

Crear suscripción push hacia sms-service

gcloud pubsub subscriptions create sms-service-sub \
  --topic new-lab-report \
  --push-endpoint=$SMS_SERVICE_URL \
  --push-auth-service-account=pubsub-cloud-run-invoker@$GOOGLE_CLOUD_PROJECT.iam.gserviceaccount.com

Obtener URL de lab-report-service

LAB_REPORT_SERVICE_URL=$(gcloud run services describe lab-report-service \
  --platform managed \
  --region us-central1 \
  --format="value(status.address.url)")

Probar el flujo completo enviando un reporte

curl -X POST \
  -H "Content-Type: application/json" \
  -d '{"id": 12, "status": "pending"}' \
  $LAB_REPORT_SERVICE_URL/v1/report

REST API con Go y Cloud Run

Practica basada en el lab GSP761. Despliega una REST API escrita en Go que expone datos de clientes desde Firestore, junto con el bucket de Cloud Storage usado para la importacion inicial de datos.

Arquitectura

cliente HTTP
     │
     ▼
Cloud Run: rest-api (público)
  GET /v1/customer/{id}
     │
     ▼
Firestore: coleccion customers / treatments

Pre-requisito: construir la imagen

La imagen se construye desde el repositorio rosera/pet-theory, subdirectorio lab08:

git clone https://github.com/rosera/pet-theory.git
cd pet-theory/lab08

go build -o server

gcloud builds submit \
  --tag gcr.io/$PROJECT_ID/rest-api:0.2

Uso

terraform init

terraform apply \
  -var="project_id=<PROJECT_ID>" \
  -var="rest_api_image=gcr.io/<PROJECT_ID>/rest-api:0.2"

Importar datos de clientes a Firestore

Después del apply, importar el dataset de Qwiklabs:

gsutil cp -r gs://spls/gsp645/2019-10-06T20:10:37_43617 gs://<PROJECT_ID>-customer

gcloud beta firestore import gs://<PROJECT_ID>-customer/2019-10-06T20:10:37_43617/

Probar el endpoint

API_URL=$(terraform output -raw rest_api_url)

# Health check
curl $API_URL/v1/

# Consultar cliente por ID
curl $API_URL/v1/customer/22521

Variables requeridas

VariableDescripción
project_idID del proyecto GCP
rest_api_imageURI de la imagen construida con Cloud Build

Link al lab

Recursos identificados

  • APIs: run.googleapis.com, cloudbuild.googleapis.com, firestore.googleapis.com.
  • Cloud Run service: rest-api (público, dos versiones: 0.1 y 0.2).
  • Cloud Storage bucket: $PROJECT_ID-customer (importación de datos a Firestore).
  • Firestore: base de datos en modo nativo, ubicación nam5.
  • Código fuente: repositorio rosera/pet-theory, subdirectorio lab08.
  • Imagen construida con Cloud Build y almacenada en Container Registry.

Comandos ejecutados

Configurar el proyecto activo

gcloud config set project $GOOGLE_CLOUD_PROJECT

Habilitar APIs necesarias

gcloud services enable run.googleapis.com
gcloud services enable cloudbuild.googleapis.com

Clonar repositorio pet-theory e ir a lab08

git clone https://github.com/rosera/pet-theory.git
cd pet-theory/lab08

Construir el binario Go (v0.1)

El main.go inicial expone solo un endpoint /v1/ que devuelve {status: 'running'}.

go build -o server

Enviar imagen v0.1 a Container Registry con Cloud Build

gcloud builds submit \
  --tag gcr.io/$GOOGLE_CLOUD_PROJECT/rest-api:0.1

Desplegar v0.1 en Cloud Run (público)

gcloud run deploy rest-api \
  --image gcr.io/$GOOGLE_CLOUD_PROJECT/rest-api:0.1 \
  --platform managed \
  --region $REGION \
  --allow-unauthenticated \
  --max-instances=2

Crear bucket de Cloud Storage para importar datos de clientes

gsutil mb -c standard -l $REGION gs://$GOOGLE_CLOUD_PROJECT-customer

Copiar dataset de clientes al bucket

El dataset viene de un bucket público de Qwiklabs.

gsutil cp -r gs://spls/gsp645/2019-10-06T20:10:37_43617 gs://$GOOGLE_CLOUD_PROJECT-customer

Crear base de datos Firestore en modo nativo

gcloud firestore databases create --location nam5

Importar datos de clientes desde Cloud Storage a Firestore

gcloud beta firestore import gs://$GOOGLE_CLOUD_PROJECT-customer/2019-10-06T20:10:37_43617/

Construir el binario Go (v0.2)

El main.go actualizado conecta con Firestore y expone /v1/customer/{id} para consultar tratamientos.

go build -o server

Enviar imagen v0.2 a Container Registry con Cloud Build

gcloud builds submit \
  --tag gcr.io/$GOOGLE_CLOUD_PROJECT/rest-api:0.2

Desplegar v0.2 en Cloud Run

gcloud run deploy rest-api \
  --image gcr.io/$GOOGLE_CLOUD_PROJECT/rest-api:0.2 \
  --platform managed \
  --region $REGION \
  --allow-unauthenticated \
  --max-instances=2

Conversor de PDFs con Go y Cloud Run

Practica basada en el lab GSP762. Despliega un servicio Cloud Run que convierte documentos a PDF usando LibreOffice, implementado en Go. El flujo es event-driven: subir un archivo al bucket de upload dispara automáticamente la conversión.

Arquitectura

gsutil cp archivo.docx gs://<PROJECT_ID>-upload/
        │
        ▼ OBJECT_FINALIZE
  Pub/Sub topic: new-doc
        │ push autenticado
        ▼
  Cloud Run: pdf-converter (privado, 2Gi)
        │
        ▼
  gs://<PROJECT_ID>-processed/<archivo>.pdf

Diferencia con el lab pdf-converter (GSP644): mismo patrón de arquitectura, pero la implementación del servidor usa Go en lugar de Node.js, y el código fuente es Deleplace/pet-theory lab03.

Pre-requisito: construir la imagen

git clone https://github.com/Deleplace/pet-theory.git
cd pet-theory/lab03

go build -o server

gcloud builds submit \
  --tag gcr.io/$PROJECT_ID/pdf-converter

Uso

terraform init

terraform apply \
  -var="project_id=<PROJECT_ID>" \
  -var="pdf_converter_image=gcr.io/<PROJECT_ID>/pdf-converter"

Probar el flujo

# Subir un documento al bucket de upload
gsutil cp mi-documento.docx gs://$(terraform output -raw upload_bucket)/

# Verificar que el PDF apareció en el bucket de procesados
gsutil ls gs://$(terraform output -raw processed_bucket)/

Variables requeridas

VariableDescripción
project_idID del proyecto GCP
pdf_converter_imageURI de la imagen construida con Cloud Build

Nota sobre memoria

LibreOffice requiere al menos 2Gi de RAM. La variable cloud_run_memory tiene ese valor como default — no reducirlo o el servicio fallará con OOM.

Link al lab

Recursos identificados

  • APIs: run.googleapis.com, cloudbuild.googleapis.com, storage-component.googleapis.com.
  • Cloud Run service: pdf-converter (privado, 2Gi RAM, variable de entorno PDF_BUCKET).
  • Cloud Storage:
    • bucket $PROJECT_ID-upload — recibe archivos subidos, dispara notificaciones Pub/Sub.
    • bucket $PROJECT_ID-processed — destino de los PDFs convertidos.
  • Pub/Sub topic: new-doc (creado via notificación de GCS).
  • Pub/Sub subscription push: pdf-conv-subpdf-converter.
  • IAM service account: pubsub-cloud-run-invoker.
  • IAM bindings:
    • roles/run.invoker sobre pdf-converter para pubsub-cloud-run-invoker.
    • roles/iam.serviceAccountTokenCreator para el service agent de Pub/Sub del proyecto.
  • Código fuente: repositorio Deleplace/pet-theory, subdirectorio lab03. Implementación en Go con LibreOffice para la conversión.

Comandos ejecutados

Habilitar APIs necesarias

gcloud services enable cloudbuild.googleapis.com
gcloud services enable storage-component.googleapis.com
gcloud services enable run.googleapis.com

Verificar cuenta activa

gcloud auth list --filter=status:ACTIVE --format="value(account)"

Clonar repositorio e ir al subdirectorio

git clone https://github.com/Deleplace/pet-theory.git
cd pet-theory/lab03

Construir el binario Go

El server.go implementa la conversión de documentos a PDF usando LibreOffice.

go build -o server

Enviar imagen a Container Registry con Cloud Build

gcloud builds submit \
  --tag gcr.io/$GOOGLE_CLOUD_PROJECT/pdf-converter

Desplegar pdf-converter en Cloud Run (privado)

El servicio requiere 2Gi de RAM por LibreOffice. Máximo 3 instancias simultáneas.

gcloud run deploy pdf-converter \
  --image gcr.io/$GOOGLE_CLOUD_PROJECT/pdf-converter \
  --platform managed \
  --region $REGION \
  --memory=2Gi \
  --no-allow-unauthenticated \
  --set-env-vars PDF_BUCKET=$GOOGLE_CLOUD_PROJECT-processed \
  --max-instances=3

Crear notificación Pub/Sub en el bucket de upload

Cada OBJECT_FINALIZE en el bucket dispara un mensaje al topic new-doc.

gsutil notification create \
  -t new-doc \
  -f json \
  -e OBJECT_FINALIZE \
  gs://$GOOGLE_CLOUD_PROJECT-upload

Crear service account invocadora

gcloud iam service-accounts create pubsub-cloud-run-invoker \
  --display-name "PubSub Cloud Run Invoker"

Asignar rol run.invoker sobre pdf-converter

gcloud run services add-iam-policy-binding pdf-converter \
  --member=serviceAccount:pubsub-cloud-run-invoker@$GOOGLE_CLOUD_PROJECT.iam.gserviceaccount.com \
  --role=roles/run.invoker \
  --region $REGION \
  --platform managed

Obtener número de proyecto

PROJECT_NUMBER=$(gcloud projects list \
  --format="value(PROJECT_NUMBER)" \
  --filter="$GOOGLE_CLOUD_PROJECT")

Permitir creación de tokens para el service agent de Pub/Sub

gcloud projects add-iam-policy-binding $GOOGLE_CLOUD_PROJECT \
  --member=serviceAccount:service-$PROJECT_NUMBER@gcp-sa-pubsub.iam.gserviceaccount.com \
  --role=roles/iam.serviceAccountTokenCreator

Obtener URL del servicio

SERVICE_URL=$(gcloud run services describe pdf-converter \
  --platform managed \
  --region $REGION \
  --format "value(status.url)")

Crear suscripción push hacia pdf-converter

gcloud pubsub subscriptions create pdf-conv-sub \
  --topic new-doc \
  --push-endpoint=$SERVICE_URL \
  --push-auth-service-account=pubsub-cloud-run-invoker@$GOOGLE_CLOUD_PROJECT.iam.gserviceaccount.com

Terraform Example: PDF Converter con Cloud Run

Este ejemplo implementa la arquitectura del lab Build a Serverless App with Cloud Run that Creates PDF Files (GSP644) con Terraform.

Qué despliega

  • APIs necesarias (run, pubsub, cloudbuild, storage).
  • Bucket de upload (<project_id>-upload) con notificacion Pub/Sub en OBJECT_FINALIZE.
  • Bucket de procesados (<project_id>-processed) donde se guardan los PDFs.
  • Topic de Pub/Sub new-doc.
  • Cloud Run pdf-converter (privado, 2 GB RAM, variable PDF_BUCKET).
  • Service account pubsub-cloud-run-invoker + bindings IAM.
  • Suscripcion push pdf-conv-sub con autenticacion OIDC.

Pre-requisito: construir la imagen

Terraform no construye la imagen. Antes de hacer apply, ejecutá desde el directorio pet-theory/lab03:

git clone https://github.com/rosera/pet-theory.git
cd pet-theory/lab03
gcloud builds submit --tag gcr.io/<PROJECT_ID>/pdf-converter

Uso rápido

  1. Inicializá:
terraform init
  1. Creá terraform.tfvars:
project_id          = "tu-project-id"
region              = "us-central1"
pdf_converter_image = "gcr.io/tu-project-id/pdf-converter"
  1. Plan y apply:
terraform plan
terraform apply

Salidas útiles

El ejemplo expone por outputs:

  • URL del servicio pdf-converter
  • Nombre del bucket de upload
  • Nombre del bucket de procesados
  • Nombre del topic y la suscripcion Pub/Sub
  • Email de la service account invocadora

Link al lab

Recursos identificados

  • APIs: run.googleapis.com, pubsub.googleapis.com, cloudbuild.googleapis.com, storage.googleapis.com.
  • Cloud Run service: pdf-converter (privado, con variable de entorno PDF_BUCKET).
  • Artifact Registry: imagen gcr.io/$GOOGLE_CLOUD_PROJECT/pdf-converter construida con Cloud Build.
  • Cloud Storage: bucket de upload ($GOOGLE_CLOUD_PROJECT-upload), bucket de procesados ($GOOGLE_CLOUD_PROJECT-processed).
  • Pub/Sub: topic new-doc, suscripcion push pdf-conv-sub.
  • IAM service account: pubsub-cloud-run-invoker.
  • IAM bindings:
    • roles/run.invoker sobre pdf-converter para la service account invocadora.
    • roles/iam.serviceAccountTokenCreator para la Pub/Sub service agent del proyecto.
  • Notificacion de Cloud Storage sobre evento OBJECT_FINALIZE → Pub/Sub topic new-doc.

Comandos ejecutados

Clonar el repositorio de Pet Theory

Se usa para obtener el codigo fuente del lab.

git clone https://github.com/rosera/pet-theory.git
cd pet-theory/lab03

Instalar dependencias Node.js

Se usan para el servidor Express y la integracion con Cloud Storage.

npm install express
npm install body-parser
npm install child_process
npm install @google-cloud/storage

Construir la imagen del contenedor (primera version)

Se usa para empaquetar la app Node.js y subirla a Artifact Registry.

gcloud builds submit \
  --tag gcr.io/$GOOGLE_CLOUD_PROJECT/pdf-converter

Desplegar la primera revision del servicio

Se usa para exponer el endpoint privado del convertidor de PDFs.

gcloud run deploy pdf-converter \
  --image gcr.io/$GOOGLE_CLOUD_PROJECT/pdf-converter \
  --platform managed \
  --region $REGION \
  --no-allow-unauthenticated \
  --max-instances=1

Obtener la URL del servicio

Se usa para guardar el endpoint en una variable de entorno.

SERVICE_URL=$(gcloud beta run services describe pdf-converter \
  --platform managed \
  --region $REGION \
  --format="value(status.url)")
echo $SERVICE_URL

Verificar que el acceso anonimo esta bloqueado

Se espera un error 403, lo cual confirma que el servicio es privado.

curl -X POST $SERVICE_URL

Invocar el servicio como usuario autenticado

Se usa para verificar que el servicio responde correctamente con credenciales validas.

curl -X POST -H "Authorization: Bearer $(gcloud auth print-identity-token)" $SERVICE_URL

Crear el bucket de upload

Se usa como staging area para los archivos a convertir.

gsutil mb gs://$GOOGLE_CLOUD_PROJECT-upload

Crear el bucket de procesados

Se usa para almacenar los PDFs generados por el servicio.

gsutil mb gs://$GOOGLE_CLOUD_PROJECT-processed

Configurar notificacion de Pub/Sub sobre el bucket de upload

Se usa para que Cloud Storage publique un evento en el topic new-doc al finalizar cada upload.

gsutil notification create \
  -t new-doc \
  -f json \
  -e OBJECT_FINALIZE \
  gs://$GOOGLE_CLOUD_PROJECT-upload

Crear la service account invocadora

Se usa para que Pub/Sub pueda invocar el servicio Cloud Run de forma autenticada.

gcloud iam service-accounts create pubsub-cloud-run-invoker \
  --display-name "PubSub Cloud Run Invoker"

Asignar rol de invoker al service account

Se usa para autorizar a la service account a llamar al servicio pdf-converter.

gcloud beta run services add-iam-policy-binding pdf-converter \
  --member=serviceAccount:pubsub-cloud-run-invoker@$GOOGLE_CLOUD_PROJECT.iam.gserviceaccount.com \
  --role=roles/run.invoker \
  --platform managed \
  --region $REGION

Obtener el numero de proyecto

Se usa para construir el email de la service agent administrada de Pub/Sub.

gcloud projects list
PROJECT_NUMBER=[project number]

Habilitar Cloud Pub/Sub API

Se usa para activar la API si no estaba habilitada.

gcloud services enable pubsub.googleapis.com --project=$GOOGLE_CLOUD_PROJECT

Permitir que Pub/Sub genere tokens de autenticacion

Se usa para que la service agent de Pub/Sub firme tokens OIDC al hacer push.

gcloud projects add-iam-policy-binding $GOOGLE_CLOUD_PROJECT \
  --member=serviceAccount:service-$PROJECT_NUMBER@gcp-sa-pubsub.iam.gserviceaccount.com \
  --role=roles/iam.serviceAccountTokenCreator

Crear la suscripcion push hacia el servicio

Se usa para conectar el topic new-doc con el endpoint del convertidor, con autenticacion OIDC.

gcloud beta pubsub subscriptions create pdf-conv-sub \
  --topic new-doc \
  --push-endpoint=$SERVICE_URL \
  --push-auth-service-account=pubsub-cloud-run-invoker@$GOOGLE_CLOUD_PROJECT.iam.gserviceaccount.com

Copiar archivos de prueba al bucket de upload

Se usa para disparar el flujo de conversion y verificar el comportamiento end-to-end.

gsutil -m cp gs://spls/gsp644/* gs://$GOOGLE_CLOUD_PROJECT-upload

Limpiar el bucket de upload

Se usa para preparar la siguiente iteracion de pruebas.

gsutil -m rm gs://$GOOGLE_CLOUD_PROJECT-upload/*

Construir la imagen con LibreOffice (version final)

Se usa para agregar el paquete libreoffice al contenedor y habilitar la conversion real de archivos.

gcloud builds submit \
  --tag gcr.io/$GOOGLE_CLOUD_PROJECT/pdf-converter

Desplegar la revision final con LibreOffice y variable de entorno

Se usa para actualizar el servicio con 2 GB de RAM y la variable PDF_BUCKET que indica donde guardar los PDFs.

gcloud run deploy pdf-converter \
  --image gcr.io/$GOOGLE_CLOUD_PROJECT/pdf-converter \
  --platform managed \
  --region $REGION \
  --memory=2Gi \
  --no-allow-unauthenticated \
  --max-instances=1 \
  --set-env-vars PDF_BUCKET=$GOOGLE_CLOUD_PROJECT-processed

Verificar el servicio actualizado

Se usa para confirmar que la nueva revision responde correctamente.

curl -X POST -H "Authorization: Bearer $(gcloud auth print-identity-token)" $SERVICE_URL

Script para copiar archivos con delay y verificar conversion

Se usa para subir los archivos uno a uno con pausa de 5 segundos y observar la conversion en tiempo real.

cat <<'EOF' > copy_files.sh
#!/bin/bash
SOURCE_BUCKET="gs://spls/gsp644"
DESTINATION_BUCKET="gs://${GOOGLE_CLOUD_PROJECT}-upload"
DELAY=5
files=$(gsutil ls "$SOURCE_BUCKET")
for file in $files; do
  gsutil cp "$file" "$DESTINATION_BUCKET"
  if [ $? -eq 0 ]; then
    echo "Copied: $file to $DESTINATION_BUCKET"
  else
    echo "Failed to copy: $file"
  fi
  sleep $DELAY
done
echo "All files copied!"
EOF

bash copy_files.sh

Máquinas Virtuales

Prácticas Terraform para recursos de cómputo en Compute Engine.

PrácticaDescripción
Crear una VMInstancia básica de Compute Engine con disco de arranque y red default

Terraform Example: Crear una VM en Compute Engine

Ejemplo mínimo de Infraestructura como Código para crear una instancia de Compute Engine, equivalente a crear una VM desde la consola o con gcloud compute instances create.

Qué despliega

  • Una google_compute_instance (my-vm, n1-standard-1) con imagen Ubuntu en la zona configurada.
  • Disco de arranque inicializado con la imagen.
  • Interfaz de red sobre la red default con access_config (IP externa efímera).

Uso rápido

terraform init
terraform plan -var="project_id=<PROJECT_ID>"
terraform apply -var="project_id=<PROJECT_ID>"

El nombre y las IPs (interna y externa) de la instancia quedan expuestos en los outputs.

Recomendaciones

  • No hardcodear project_id, región ni imagen: usá variables (ya parametrizadas).
  • Corré terraform destroy al terminar para evitar costos.

Redes

Prácticas Terraform para VPCs, reglas de firewall, segmentación y tráfico de red.

Terraform Example: Configuring VPC

Este ejemplo implementa una versión Terraform del lab Configuring VPC Firewalls.

Qué crea

  • API necesaria: compute.googleapis.com.
  • VPC auto mode mynetwork.
  • 2 VMs de prueba:
    • mynet-vm-1
    • mynet-vm-2
  • Reglas de firewall equivalentes al escenario final del lab:
    • SSH desde una IP/CIDR puntual hacia instancias taggeadas con lab-ssh
    • ICMP interno permitido dentro de 10.128.0.0/9
    • deny ICMP ingress con prioridad 2000
    • deny ICMP egress con prioridad 10000

Uso rápido

  1. Inicializá:
terraform init
  1. Definí terraform.tfvars:
project_id      = "tu-project-id"
region          = "us-central1"
zone_1          = "us-central1-a"
zone_2          = "us-central1-b"
ssh_source_cidr = "203.0.113.10/32"
  1. Plan y apply:
terraform plan
terraform apply

Notas

  • Para replicar el comportamiento del lab, usá en ssh_source_cidr la IP pública de tu Cloud Shell en formato CIDR /32.
  • Este ejemplo modela el estado final útil del lab. La inspección manual de la red default y su eliminación quedan fuera de Terraform a propósito.

Link al lab

Recursos identificados

  • APIs habilitadas: compute.googleapis.com.
  • Red principal: VPC auto mode mynetwork, con subnetworks automáticas por región dentro del rango 10.128.0.0/9.
  • Instancias usadas en el lab: default-vm-1, mynet-vm-1 y mynet-vm-2.
  • Firewall rules observadas o creadas: reglas default-allow-* de la red default, mynetwork-ingress-allow-ssh-from-cs, mynetwork-ingress-allow-icmp-internal, mynetwork-ingress-deny-icmp-all y mynetwork-egress-deny-icmp-all.
  • Etiquetas relevantes: lab-ssh para limitar el acceso SSH a las VMs objetivo.
  • IAM relevante: no se crea IAM explícito; el lab usa las credenciales temporales del proyecto y los permisos ya otorgados.
  • Integraciones: Cloud Shell como cliente SSH, curl a api.ipify.org para descubrir la IP pública y resolución DNS interna entre VMs.

Comandos ejecutados

En los comandos siguientes, reemplazá <ZONE_1>, <ZONE_2> y <EXTERNAL_IP_MYNET_VM_2> por los valores de tu lab.

Verificar autenticación y proyecto activo

gcloud auth list
gcloud config list project

Crear la VPC auto mode del lab

gcloud compute networks create mynetwork --subnet-mode=auto

Crear las instancias de prueba

gcloud compute instances create default-vm-1 \
  --machine-type e2-micro \
  --zone=<ZONE_1> \
  --network=default

gcloud compute instances create mynet-vm-1 \
  --machine-type e2-micro \
  --zone=<ZONE_1> \
  --network=mynetwork

gcloud compute instances create mynet-vm-2 \
  --machine-type e2-micro \
  --zone=<ZONE_2> \
  --network=mynetwork

Probar SSH sin reglas personalizadas

gcloud compute ssh qwiklabs@mynet-vm-2 --zone <ZONE_2>

Obtener la IP pública de Cloud Shell

ip=$(curl -s https://api.ipify.org)
echo "My External IP address is: $ip"

Permitir SSH desde Cloud Shell

gcloud compute firewall-rules create \
  mynetwork-ingress-allow-ssh-from-cs \
  --network mynetwork \
  --action ALLOW \
  --direction INGRESS \
  --rules tcp:22 \
  --source-ranges $ip \
  --target-tags=lab-ssh

Asociar el tag lab-ssh a las VMs

gcloud compute instances add-tags mynet-vm-2 \
  --zone <ZONE_2> \
  --tags lab-ssh

gcloud compute instances add-tags mynet-vm-1 \
  --zone <ZONE_1> \
  --tags lab-ssh

Validar conectividad SSH luego de abrir el firewall

gcloud compute ssh qwiklabs@mynet-vm-2 --zone <ZONE_2>
exit
gcloud compute ssh qwiklabs@mynet-vm-1 --zone <ZONE_1>

Probar ping interno entre VMs

ping mynet-vm-2.<ZONE_2>

Permitir ICMP interno dentro de la VPC

gcloud compute firewall-rules create \
  mynetwork-ingress-allow-icmp-internal \
  --network mynetwork \
  --action ALLOW \
  --direction INGRESS \
  --rules icmp \
  --source-ranges 10.128.0.0/9

Repetir la prueba de ping interno

ping mynet-vm-2.<ZONE_2>

Verificar que el ping a la IP externa siga bloqueado

ping <EXTERNAL_IP_MYNET_VM_2>

Crear una regla deny de ICMP con prioridad mayor

gcloud compute ssh qwiklabs@mynet-vm-1 --zone <ZONE_1>
ping mynet-vm-2.<ZONE_2>

gcloud compute firewall-rules create \
  mynetwork-ingress-deny-icmp-all \
  --network mynetwork \
  --action DENY \
  --direction INGRESS \
  --rules icmp \
  --priority 500

ping mynet-vm-2.<ZONE_2>

Bajar la prioridad de la regla deny

gcloud compute firewall-rules update \
  mynetwork-ingress-deny-icmp-all \
  --priority 2000

ping mynet-vm-2.<ZONE_2>

Inspeccionar las reglas de firewall de la red

gcloud compute firewall-rules list --filter="network:mynetwork"

Bloquear ICMP saliente

gcloud compute firewall-rules create \
  mynetwork-egress-deny-icmp-all \
  --network mynetwork \
  --action DENY \
  --direction EGRESS \
  --rules icmp \
  --priority 10000

gcloud compute firewall-rules list --filter="network:mynetwork"
ping mynet-vm-2.<ZONE_2>

Terraform Example: VPC Controlling Access

Este ejemplo implementa una versión Terraform del lab VPC Networks - Controlling Access.

Qué crea

  • APIs necesarias: compute.googleapis.com, iam.googleapis.com.
  • 2 web servers en la red default:
    • blue con tag web-server
    • green sin tag
  • Instalación automática de nginx-light y página diferenciada en cada servidor.
  • Firewall rule allow-http-web-server para exponer tcp:80 e icmp solo a instancias con el tag web-server.
  • VM test-vm para validar conectividad.
  • Service account network-admin adjunta a test-vm, con:
    • roles/compute.networkAdmin
    • roles/compute.securityAdmin opcional según variable

Uso rápido

  1. Inicializá:
terraform init
  1. Definí terraform.tfvars:
project_id           = "tu-project-id"
region               = "us-central1"
zone                 = "us-central1-a"
network_name         = "default"
subnetwork_name      = "default"
grant_security_admin = true
  1. Plan y apply:
terraform plan
terraform apply

Notas

  • Este ejemplo asume que existe la red default y que conserva la regla default-allow-internal, igual que en el lab original.
  • Para reproducir la progresión del lab, podés aplicar primero con grant_security_admin = false y verificar que desde test-vm se pueden listar firewall rules pero no borrarlas; después cambiás a true y volvés a aplicar.
  • El lab original usa una clave JSON subida manualmente a la VM. Acá se evita esa práctica y se adjunta la service account directamente a test-vm.

Link al lab

Recursos identificados

  • APIs habilitadas o implícitas: compute.googleapis.com, iam.googleapis.com.
  • Red usada por el lab: VPC default.
  • Instancias principales: blue, green y test-vm.
  • Firewall rules relevantes: default-allow-internal, allow-http-web-server.
  • Tags relevantes: web-server aplicado a blue.
  • IAM relevante: service account Network-admin, rol Compute Network Admin, luego Compute Security Admin.
  • Integraciones: acceso por SSH a VMs, curl para validar HTTP interno/externo y activación de credenciales de service account con archivo credentials.json.

Comandos ejecutados

En los comandos siguientes, reemplazá <ZONE>, <BLUE_INTERNAL_IP>, <GREEN_INTERNAL_IP>, <BLUE_EXTERNAL_IP> y <GREEN_EXTERNAL_IP> por los valores de tu lab.

Verificar autenticación y proyecto activo

gcloud auth list
gcloud config list project

Instalar nginx en blue

sudo apt-get install nginx-light -y
sudo nano /var/www/html/index.nginx-debian.html
cat /var/www/html/index.nginx-debian.html
exit

Instalar nginx en green

sudo apt-get install nginx-light -y
sudo nano /var/www/html/index.nginx-debian.html
cat /var/www/html/index.nginx-debian.html
exit

Crear la VM de prueba

gcloud compute instances create test-vm --machine-type=e2-micro --subnet=default --zone=<ZONE>

Probar conectividad HTTP interna

curl <BLUE_INTERNAL_IP>
curl -c 3 <GREEN_INTERNAL_IP>

Probar conectividad HTTP externa

curl <BLUE_EXTERNAL_IP>
curl -c 3 <GREEN_EXTERNAL_IP>

Verificar permisos insuficientes con la service account por defecto

gcloud compute firewall-rules list
gcloud compute firewall-rules delete allow-http-web-server

Activar la service account subida manualmente al VM

gcloud auth activate-service-account --key-file credentials.json

Verificar permisos con Compute Network Admin

gcloud compute firewall-rules list
gcloud compute firewall-rules delete allow-http-web-server

Verificar permisos con Compute Security Admin

gcloud compute firewall-rules list
gcloud compute firewall-rules delete allow-http-web-server

Confirmar que el acceso HTTP externo deja de funcionar tras borrar la regla

curl -c 3 <BLUE_EXTERNAL_IP>

Terraform Example: Multiple VPC Networks

Este ejemplo implementa una versión Terraform del lab Multiple VPC Networks.

Qué crea

  • API necesaria: compute.googleapis.com.
  • 3 redes para reproducir el escenario completo:
    • managementnet como custom mode
    • privatenet como custom mode
    • mynetwork como auto mode
  • Subredes:
    • managementsubnet-1
    • privatesubnet-1
    • privatesubnet-2
    • subredes automáticas de mynetwork en region_1 y region_2
  • Firewall rules para permitir icmp, tcp:22 y tcp:3389 en las tres redes necesarias.
  • VMs simples:
    • managementnet-vm-1
    • privatenet-vm-1
    • mynet-vm-1
    • mynet-vm-2
  • VM vm-appliance con 3 interfaces:
    • privatesubnet-1
    • managementsubnet-1
    • subred automática de mynetwork en region_1

Uso rápido

  1. Inicializá:
terraform init
  1. Definí terraform.tfvars:
project_id = "tu-project-id"
region_1   = "us-central1"
region_2   = "us-east1"
zone_1     = "us-central1-a"
zone_2     = "us-east1-b"
  1. Plan y apply:
terraform plan
terraform apply

Notas

  • El lab original asume que mynetwork, mynet-vm-1 y mynet-vm-2 ya existen. En este ejemplo se crean también para que la práctica sea autocontenida.
  • La vm-appliance instala net-tools para que puedas correr ifconfig como en el lab.
  • La conectividad esperada replica la idea central del ejercicio: vm-appliance llega a subredes directamente conectadas, pero no necesariamente a otras subredes remotas de mynetwork sin policy routing adicional.

Link al lab

Recursos identificados

  • APIs habilitadas o implícitas: compute.googleapis.com.
  • Redes principales: managementnet y privatenet como custom mode; mynetwork ya preexistente en el lab.
  • Subredes creadas o usadas:
    • managementsubnet-1 en managementnet con 10.130.0.0/20
    • privatesubnet-1 en privatenet con 172.16.0.0/24
    • privatesubnet-2 en privatenet con 172.20.0.0/20
    • subredes automáticas de mynetwork en las regiones del lab
  • Firewall rules relevantes:
    • managementnet-allow-icmp-ssh-rdp
    • privatenet-allow-icmp-ssh-rdp
    • reglas preexistentes en mynetwork
  • Instancias creadas o usadas:
    • managementnet-vm-1
    • privatenet-vm-1
    • mynet-vm-1
    • mynet-vm-2
    • vm-appliance con múltiples NICs
  • IAM relevante: no se crea IAM específico en este lab.
  • Integraciones: SSH a VMs, resolución DNS interna entre instancias, múltiples interfaces de red y análisis de rutas con ip route.

Comandos ejecutados

En los comandos siguientes, reemplazá <REGION_1>, <REGION_2>, <ZONE_1>, <MYNET_VM_2_EXTERNAL_IP>, <MANAGEMENT_VM_EXTERNAL_IP>, <PRIVATE_VM_EXTERNAL_IP>, <MYNET_VM_2_INTERNAL_IP>, <MANAGEMENT_VM_INTERNAL_IP>, <PRIVATE_VM_INTERNAL_IP>, <PRIVATE_VM_1_INTERNAL_IP>, <MYNET_VM_1_INTERNAL_IP> y <MYNET_VM_2_INTERNAL_IP> por los valores de tu lab.

Verificar autenticación y proyecto activo

gcloud auth list
gcloud config list project

Crear la red privatenet

gcloud compute networks create privatenet --subnet-mode=custom
gcloud compute networks subnets create privatesubnet-1 --network=privatenet --region=<REGION_1> --range=172.16.0.0/24
gcloud compute networks subnets create privatesubnet-2 --network=privatenet --region=<REGION_2> --range=172.20.0.0/20

Listar redes y subredes disponibles

gcloud compute networks list
gcloud compute networks subnets list --sort-by=NETWORK

Crear el firewall de privatenet

gcloud compute firewall-rules create privatenet-allow-icmp-ssh-rdp --direction=INGRESS --priority=1000 --network=privatenet --action=ALLOW --rules=icmp,tcp:22,tcp:3389 --source-ranges=0.0.0.0/0

Listar firewall rules

gcloud compute firewall-rules list --sort-by=NETWORK

Crear la VM privatenet-vm-1

gcloud compute instances create privatenet-vm-1 --zone=<ZONE_1> --machine-type=e2-micro --subnet=privatesubnet-1

Listar instancias

gcloud compute instances list --sort-by=ZONE

Probar ping a IPs externas

ping -c 3 '<MYNET_VM_2_EXTERNAL_IP>'
ping -c 3 '<MANAGEMENT_VM_EXTERNAL_IP>'
ping -c 3 '<PRIVATE_VM_EXTERNAL_IP>'

Probar ping a IPs internas desde mynet-vm-1

ping -c 3 '<MYNET_VM_2_INTERNAL_IP>'
ping -c 3 '<MANAGEMENT_VM_INTERNAL_IP>'
ping -c 3 '<PRIVATE_VM_INTERNAL_IP>'

Inspeccionar interfaces dentro de vm-appliance

sudo ifconfig

Probar conectividad desde vm-appliance

ping -c 3 '<PRIVATE_VM_1_INTERNAL_IP>'
ping -c 3 privatenet-vm-1
ping -c 3 '<MANAGEMENT_VM_INTERNAL_IP>'
ping -c 3 '<MYNET_VM_1_INTERNAL_IP>'
ping -c 3 '<MYNET_VM_2_INTERNAL_IP>'

Ver tabla de ruteo en vm-appliance

ip route

VPC Flow Logs — Análisis de tráfico de red

Práctica Terraform basada en el lab Analyzing Network Traffic with VPC Flow Logs.

Crea una VPC custom con Flow Logs habilitados, una VM web-server con Apache, un log sink a BigQuery, y los permisos necesarios para que el sink pueda escribir en el dataset.

Recursos creados

RecursoNombre
VPC customvpc-net
Subred con Flow Logsvpc-subnet (10.1.3.0/24)
Firewallallow-http-ssh (tcp:22,80)
VMweb-server (e2-micro, Apache)
BigQuery datasetbq_vpcflows
Log sinkvpc-flows → BigQuery

Uso rápido

terraform init

terraform apply \
  -var="project_id=TU_PROJECT_ID"

Variables requeridas

VariableDescripción
project_idID del proyecto GCP

Las demás variables tienen defaults razonables; ver variables.tf.

Generar tráfico para análisis

Una vez aplicado:

export MY_SERVER=$(terraform output -raw web_server_external_ip)
for ((i=1;i<=50;i++)); do curl $MY_SERVER; done

Esperá unos minutos para que los logs se exporten a BigQuery, luego ejecutá la query de análisis desde la consola de BigQuery:

#standardSQL
SELECT
  jsonPayload.src_vpc.vpc_name,
  SUM(CAST(jsonPayload.bytes_sent AS INT64)) AS bytes,
  jsonPayload.src_vpc.subnetwork_name,
  jsonPayload.connection.src_ip,
  jsonPayload.connection.src_port,
  jsonPayload.connection.dest_ip,
  jsonPayload.connection.dest_port,
  jsonPayload.connection.protocol
FROM
  `TU_PROJECT_ID.bq_vpcflows.compute_googleapis_com_vpc_flows_*`
GROUP BY
  jsonPayload.src_vpc.vpc_name,
  jsonPayload.src_vpc.subnetwork_name,
  jsonPayload.connection.src_ip,
  jsonPayload.connection.src_port,
  jsonPayload.connection.dest_ip,
  jsonPayload.connection.dest_port,
  jsonPayload.connection.protocol
ORDER BY bytes DESC
LIMIT 15

Notas

  • El sink usa unique_writer_identity = true, lo que crea una service account dedicada. El recurso google_bigquery_dataset_iam_member le otorga automáticamente roles/bigquery.dataEditor.
  • No se puede validar runtime real sin un proyecto activo con billing habilitado.

Link al lab

Recursos identificados

  • APIs habilitadas: compute.googleapis.com, logging.googleapis.com, bigquery.googleapis.com.
  • Red: VPC custom mode vpc-net, subred vpc-subnet (10.1.3.0/24) con VPC Flow Logs habilitados (intervalo 5 s, sampling 50%, metadata completa).
  • Instancia: web-server (e2-micro, Debian, tag http-server) en vpc-subnet.
  • Firewall: allow-http-ssh — permite tcp:22 y tcp:80 desde 0.0.0.0/0 a VMs con tag http-server.
  • Log sink: vpc-flows exporta logs compute.googleapis.com/vpc_flows a BigQuery.
  • BigQuery dataset: bq_vpcflows — recibe los registros de flujo para análisis SQL.
  • IAM: la service account writer del sink recibe roles/bigquery.dataEditor sobre el dataset.

Comandos ejecutados

En los comandos siguientes, reemplazá <ZONE> y <EXTERNAL_IP> por los valores de tu lab.

Verificar autenticación y proyecto activo

gcloud auth list
gcloud config list project

Crear la VPC custom y la subred con Flow Logs

gcloud compute networks create vpc-net \
  --subnet-mode=custom \
  --bgp-routing-mode=regional

gcloud compute networks subnets create vpc-subnet \
  --network=vpc-net \
  --region=us-central1 \
  --range=10.1.3.0/24 \
  --enable-flow-logs \
  --logging-aggregation-interval=interval-5-sec \
  --logging-flow-sampling=0.5 \
  --logging-metadata=include-all

Crear la regla de firewall

gcloud compute firewall-rules create allow-http-ssh \
  --direction=INGRESS \
  --priority=1000 \
  --network=vpc-net \
  --action=ALLOW \
  --rules=tcp:22,tcp:80 \
  --source-ranges=0.0.0.0/0 \
  --target-tags=http-server

Crear la VM web-server

gcloud compute instances create web-server \
  --zone=<ZONE> \
  --machine-type=e2-micro \
  --subnet=vpc-subnet \
  --tags=http-server \
  --image-family=debian-12 \
  --image-project=debian-cloud

Instalar Apache en la VM (via SSH)

sudo apt-get update
sudo apt-get install apache2 -y
echo '<!doctype html><html><body><h1>Hello World!</h1></body></html>' | sudo tee /var/www/html/index.html
exit

Generar tráfico desde Cloud Shell

export MY_SERVER=<EXTERNAL_IP>
for ((i=1;i<=50;i++)); do curl $MY_SERVER; done

Crear el log sink hacia BigQuery (Console)

Esta tarea se realiza desde la consola: Logging → Explorador de logs → Más acciones → Crear receptor.

  • Nombre del receptor: vpc-flows
  • Destino: BigQuery dataset bq_vpcflows (crear nuevo)

Consultar los logs en BigQuery

#standardSQL
SELECT
  jsonPayload.src_vpc.vpc_name,
  SUM(CAST(jsonPayload.bytes_sent AS INT64)) AS bytes,
  jsonPayload.src_vpc.subnetwork_name,
  jsonPayload.connection.src_ip,
  jsonPayload.connection.src_port,
  jsonPayload.connection.dest_ip,
  jsonPayload.connection.dest_port,
  jsonPayload.connection.protocol
FROM
  `<PROJECT_ID>.bq_vpcflows.compute_googleapis_com_vpc_flows_*`
GROUP BY
  jsonPayload.src_vpc.vpc_name,
  jsonPayload.src_vpc.subnetwork_name,
  jsonPayload.connection.src_ip,
  jsonPayload.connection.src_port,
  jsonPayload.connection.dest_ip,
  jsonPayload.connection.dest_port,
  jsonPayload.connection.protocol
ORDER BY bytes DESC
LIMIT 15

Ajustar la agregación de Flow Logs (Console)

VPC network → vpc-net → vpc-subnet → Editar → Configurar logs

  • Intervalo de agregación: 30 segundos
  • Tasa de muestreo: 25 %

Terraform Example: Build a Secure Network - Challenge

Este ejemplo modela en Terraform una versión reproducible del challenge Build a Secure Google Cloud Network (GSP322).

Qué crea

  • APIs:
    • compute.googleapis.com
    • iap.googleapis.com
  • Red:
    • VPC acme-vpc (custom mode).
    • Subred acme-mgmt-subnet para administración.
    • Subred acme-web-subnet para juice-shop.
  • Firewall:
    • allow-ssh-iap-ingress: permite SSH solo desde rango IAP (35.235.240.0/20) hacia bastion.
    • allow-http-ingress: permite HTTP (tcp:80) desde Internet a juice-shop.
    • allow-ssh-internal-ingress: permite SSH interno desde la subnet de management hacia juice-shop.
  • Compute Engine:
    • VM bastion sin public IP (acceso por IAP).
    • VM juice-shop con public IP y nginx como placeholder de workload HTTP.

Uso rápido

  1. Inicializá:
terraform init
  1. Definí variables en terraform.tfvars:
project_id = "tu-project-id"
region     = "us-central1"
zone       = "us-central1-b"
  1. Plan y apply:
terraform plan
terraform apply

Notas

  • Este ejemplo representa el estado objetivo del challenge con reglas de firewall restrictivas y tags explícitos.
  • No incluye recursos temporales del laboratorio administrado por Skills Boost (grading/checkpoints).
  • Para limpieza, corré:
terraform destroy

Link al lab Fuente pública utilizada para extraer comandos (por requerir login): Build and Secure Networks in Google Cloud: Challenge Lab (DEV Community).

Recursos identificados

  • APIs/servicios GCP:
    • Compute Engine API (compute.googleapis.com).
    • Identity-Aware Proxy API (iap.googleapis.com) para SSH vía IAP TCP forwarding.
  • Recursos principales:
    • Red acme-vpc.
    • Subred de gestión acme-mgmt-subnet (CIDR usado para SSH interno).
    • VM bastion (sin public IP en el escenario objetivo).
    • VM juice-shop (exposición HTTP pública y SSH interno restringido).
    • Reglas de firewall: open-access (a eliminar), regla SSH vía IAP, regla HTTP pública, regla SSH interna.
  • IAM:
    • Uso de permisos para administrar firewall/tagging en Compute Engine.
    • Acceso operativo vía IAP (normalmente con rol como roles/iap.tunnelResourceAccessor para usuarios operadores).
  • Integraciones:
    • IAP TCP forwarding -> SSH a bastion.
    • bastion -> SSH interno a juice-shop.
    • Exposición HTTP de juice-shop mediante regla ingress acotada a tcp:80.

Comandos ejecutados

gcloud compute firewall-rules delete open-access
gcloud compute instances start bastion --zone=us-central1-b
gcloud compute firewall-rules create ssh-ingress --allow=tcp:22 --source-ranges 35.235.240.0/20 --target-tags [NETWORK_TAG_1] --network acme-vpc
gcloud compute instances add-tags bastion --tags=[NETWORK_TAG_1] --zone=us-central1-b
gcloud compute firewall-rules create http-ingress --allow=tcp:80 --source-ranges 0.0.0.0/0 --target-tags [NETWORK_TAG_2] --network acme-vpc
gcloud compute instances add-tags juice-shop --tags=[NETWORK_TAG_2] --zone=us-central1-b
gcloud compute firewall-rules create internal-ssh-ingress --allow=tcp:22 --source-ranges 192.168.10.0/24 --target-tags [NETWORK_TAG_3] --network acme-vpc
gcloud compute instances add-tags juice-shop --tags=[NETWORK_TAG_3] --zone=us-central1-b
ssh <internal-IP-of-juice-shop>

Balanceadores de carga

Prácticas Terraform para exponer servicios con balanceadores de carga en Google Cloud.

PrácticaDescripción
Network Load BalancerBalanceador de capa 4 (TCP) con target pool, health check y forwarding rule
Application Load Balancer con AutoscalingBalanceador de capa 7 con grupo de instancias administrado (MIG) y autoscaler

Terraform Example: Network Load Balancer

Este ejemplo implementa la arquitectura del lab Set Up a Network Load Balancer con Terraform: un conjunto de VMs detrás de un Network Load Balancer (capa 4, TCP) que distribuye el tráfico HTTP entre ellas.

Qué despliega

  • VMs google_compute_instance (Apache vía startup script) creadas con for_each a partir de instance_names.
  • Regla de firewall que permite el puerto HTTP sobre el tag de red de las instancias.
  • google_compute_http_health_check para chequear la salud de las VMs.
  • google_compute_target_pool que agrupa las instancias y usa el health check.
  • google_compute_address regional (IP externa del balanceador).
  • google_compute_forwarding_rule (EXTERNAL, TCP) que mapea el puerto HTTP de la IP hacia el target pool.

Un Load Balancer en GCP no es un único recurso: es la combinación de forwarding rule + target pool + health check.

Uso rápido

terraform init
terraform plan -var="project_id=<PROJECT_ID>"
terraform apply -var="project_id=<PROJECT_ID>"

La IP pública del balanceador queda expuesta en el output load_balancer_ip.

Recomendaciones

  • No hardcodear project_id, región ni nombres: usá variables.
  • Corré terraform destroy al terminar para evitar costos.

Set Up a NLB (Network Load Balancer)

Link al Lab

El Lab trata de crear un cluster de máquinas e2-small y ponerlas detrás de un NLB para poder redirigr el tráfico entre ellas.

Para ello, hay que seguir una serie de pasos, detallados en el subitem Crear un cluster de máquinas y asignarlas a una Target Pool del archivo de Cloud Shell.

Aparece el concepto de Forwarding Rule, que entiendo que son las reglas de mappeo para redirigir tráfico. En el caso del lab, mappea el puerto 80 de la IP del NLB hacia la pool de instancias con el argumento target-pool. Esta pool de instancias sería el cluster de máquinas entre el cual queremos distribuir el tráfico.

Los Load Balancers no se crean como un componente per se, sino que son un conjunto de 2 componentes.

Terraform Example: Application Load Balancer with Autoscaling

Este ejemplo implementa una versión Terraform del lab Application Load Balancer with Autoscaling.

Qué crea

  • Firewall rule para health checks.
  • Cloud Router + Cloud NAT en las regiones de backend.
  • Instance template para servidores web.
  • 2 Managed Instance Groups (uno en us-central1 y otro en europe-west1).
  • Autoscaler para cada MIG.
  • Application Load Balancer HTTP global (EXTERNAL_MANAGED) con:
    • backend service
    • URL map
    • target HTTP proxy
    • forwarding rule IPv4
    • forwarding rule IPv6 opcional

Uso rápido

  1. Inicializá:
terraform init
  1. Definí variables en terraform.tfvars:
project_id     = "tu-project-id"
default_region = "us-central1"
network_name   = "default"
  1. Plan y apply:
terraform plan
terraform apply

Notas

  • El lab original usa una imagen custom (mywebserver). Este ejemplo usa una imagen Debian por defecto + startup script.
  • Si querés replicar más fielmente el lab, podés cambiar instance_image por tu imagen custom.

Link al lab

Recursos identificados

  • APIs/servicios involucrados: Compute Engine, Cloud NAT, Cloud Router, Cloud Load Balancing.
  • Red y seguridad:
    • regla de firewall para health checks (130.211.0.0/22, 35.191.0.0/16).
    • red default.
  • Cómputo e imágenes:
    • VM base webserver.
    • imagen custom mywebserver.
    • instance template mywebserver-template.
    • managed instance groups multi-región (us-central1, europe-west1) con autoscaling.
  • Health checks y balanceo:
    • health check http-health-check.
    • Application Load Balancer HTTP global (IPv4/IPv6) con backend services sobre MIG.
  • Testing:
    • verificación de disponibilidad con curl.
    • stress test con ab (ApacheBench) desde VM stress-test.

Comandos ejecutados

Crear firewall rule para health checks

Permite que los health checks del load balancer lleguen a las VMs backend por tcp:80.

gcloud compute --project=qwiklabs-gcp-04-1059d35c6e27 firewall-rules create fw-allow-health-checks --direction=INGRESS --priority=1000 --network=default --action=ALLOW --rules=tcp:80 --source-ranges=130.211.0.0/22,35.191.0.0/16 --target-tags=allow-health-checks

Actualizar paquetes en la VM webserver

Prepara la VM base antes de instalar Apache.

sudo apt-get update

Iniciar Apache en la VM webserver

Levanta el servicio HTTP para validar la imagen base.

sudo service apache2 start

Verificar respuesta local de Apache

Confirma que el servidor web responde en localhost.

curl localhost

Habilitar Apache al boot

Deja Apache habilitado para que inicie automáticamente.

sudo update-rc.d apache2 enable

Crear imagen custom desde disco de la VM

Genera mywebserver para usarla en el instance template.

gcloud compute images create mywebserver --project=qwiklabs-gcp-04-1059d35c6e27 --source-disk=webserver --source-disk-zone=us-central1-a --storage-location=us

Crear instance template para los MIG

Define configuración homogénea de las instancias backend sin IP pública.

gcloud compute instance-templates create mywebserver-template --project=qwiklabs-gcp-04-1059d35c6e27 --machine-type=f1-micro --network-interface=network=default,no-address --metadata=enable-oslogin=true --maintenance-policy=MIGRATE --provisioning-model=STANDARD --service-account=425659184878-compute@developer.gserviceaccount.com --scopes=https://www.googleapis.com/auth/devstorage.read_only,https://www.googleapis.com/auth/logging.write,https://www.googleapis.com/auth/monitoring.write,https://www.googleapis.com/auth/servicecontrol,https://www.googleapis.com/auth/service.management.readonly,https://www.googleapis.com/auth/trace.append --tags=allow-health-checks --create-disk=auto-delete=yes,boot=yes,device-name=mywebserver-template,image=projects/qwiklabs-gcp-04-1059d35c6e27/global/images/mywebserver,mode=rw,size=10,type=pd-balanced --no-shielded-secure-boot --shielded-vtpm --shielded-integrity-monitoring --reservation-affinity=any

Crear health check TCP para los MIG

Define el check usado para determinar backends saludables.

gcloud beta compute health-checks create tcp http-health-check --project=qwiklabs-gcp-04-1059d35c6e27 --port=80 --proxy-header=NONE --no-enable-logging --check-interval=5 --timeout=5 --unhealthy-threshold=2 --healthy-threshold=2

Definir la IP del Load Balancer para pruebas

Guarda la IP pública del LB en una variable de entorno.

LB_IP=34.111.70.232

Esperar hasta que el LB responda tráfico HTTP

Hace polling con curl hasta obtener respuesta válida.

while [ -z "$RESULT" ] ;
do
  echo "Waiting for Load Balancer";
  sleep 5;
  RESULT=$(curl -m1 -s $LB_IP | grep Apache);
done

Definir variable de entorno con IP/URL del LB

Prepara la VM de stress test para enviar tráfico al balanceador.

export LB_IP=http://34.111.70.232/

Redefinir variable LB_IP en formato host

Normaliza la variable para usarla con ab.

export LB_IP=34.111.70.232

Verificar variable LB_IP

Confirma que la variable quedó seteada correctamente.

echo $LB_IP

Ejecutar stress test con ApacheBench

Simula alta carga para observar balanceo y autoscaling.

ab -n 500000 -c 1000 http://$LB_IP/

Almacenamiento

Prácticas Terraform para recursos de almacenamiento y bases de datos administradas.

PrácticaDescripción
Cloud StorageBuckets con versioning, lifecycle y objetos de muestra
Cloud SQLInstancia Cloud SQL con peering privado y VMs de demo
SDK Cloud Storage en PythonEjemplo del SDK google-cloud-storage (upload/download de blobs) — no es Terraform

Terraform Example: Cloud Storage Lab

Este ejemplo implementa una práctica Terraform basada en el lab Cloud Storage.

Qué crea

  • Bucket de Cloud Storage con nombre único global.
  • Versioning habilitable (enable_versioning).
  • Lifecycle rule para borrar objetos por edad (lifecycle_delete_age_days).
  • Objetos de ejemplo (setup.html, setup2.html, setup3.html) opcionales.
  • Opción de acceso público de lectura por IAM (make_sample_public).

Uso rápido

  1. Inicializá:
terraform init
  1. Definí variables en terraform.tfvars:
project_id                = "tu-project-id"
region                    = "us-central1"
bucket_name_prefix        = "cloud-storage-lab"
enable_versioning         = true
lifecycle_delete_age_days = 31
upload_sample_objects     = true
make_sample_public        = false
  1. Plan y apply:
terraform plan
terraform apply

Notas

  • El lab original usa ACLs y CSEK operados manualmente con gsutil + .boto.
  • Este ejemplo prioriza prácticas IaC estándar con IAM y configuración declarativa del bucket.
  • Si necesitás reproducir CSEK manual exacto, conviene mantenerlo en un paso operativo fuera de Terraform.

Link al lab

Recursos identificados

  • Servicio principal: Cloud Storage.
  • Recursos de storage:
    • bucket principal (BUCKET_NAME_1).
    • objetos (setup.html, setup2.html, setup3.html y versiones).
  • Seguridad y acceso:
    • ACLs de objeto (private, AllUsers:R).
    • CSEK (Customer-supplied encryption keys) vía .boto.
    • rotación de claves CSEK.
  • Gobierno del dato:
    • lifecycle policy (delete por edad).
    • versioning de bucket.
  • Operaciones de datos:
    • sincronización recursiva con gsutil rsync.

Comandos ejecutados

Definir nombre de bucket en variable

Se usa para reutilizar el nombre del bucket durante todo el lab.

export BUCKET_NAME_1=<enter bucket name 1 here>

Verificar variable del bucket

Se usa para confirmar que BUCKET_NAME_1 quedó bien seteada.

echo $BUCKET_NAME_1

Descargar archivo de muestra

Se usa para bajar setup.html y trabajar con objetos de prueba.

curl \
https://hadoop.apache.org/docs/current/\
hadoop-project-dist/hadoop-common/\
ClusterSetup.html > setup.html

Crear copias locales del archivo

Se usa para tener múltiples objetos para pruebas de cifrado/versionado.

cp setup.html setup2.html
cp setup.html setup3.html

Subir archivo al bucket

Se usa para cargar el primer objeto al bucket.

gcloud storage cp setup.html gs://$BUCKET_NAME_1/

Exportar ACL actual del objeto

Se usa para inspeccionar permisos actuales del objeto.

gsutil acl get gs://$BUCKET_NAME_1/setup.html > acl.txt
cat acl.txt

Forzar ACL privada en el objeto

Se usa para restringir acceso a modo privado y validar resultado.

gsutil acl set private gs://$BUCKET_NAME_1/setup.html
gsutil acl get gs://$BUCKET_NAME_1/setup.html > acl2.txt
cat acl2.txt

Hacer objeto público por ACL

Se usa para habilitar lectura pública del objeto.

gsutil acl ch -u AllUsers:R gs://$BUCKET_NAME_1/setup.html
gsutil acl get gs://$BUCKET_NAME_1/setup.html > acl3.txt
cat acl3.txt

Borrar archivo local

Se usa para validar recuperación desde bucket.

rm setup.html

Listar archivos locales

Se usa para verificar que setup.html fue eliminado.

ls

Recuperar objeto desde bucket

Se usa para copiar nuevamente setup.html al entorno local.

gcloud storage cp gs://$BUCKET_NAME_1/setup.html setup.html

Generar clave CSEK

Se usa para crear una clave AES-256 base64 para cifrado del lado cliente.

python3 -c 'import base64; import os; print(base64.encodebytes(os.urandom(32)))'

Abrir configuración gsutil (.boto)

Se usa para configurar encryption_key y/o decryption_key.

ls -al
nano .boto

Subir archivos cifrados con CSEK

Se usa para cargar objetos que queden cifrados con la clave configurada.

gsutil cp setup2.html gs://$BUCKET_NAME_1/
gsutil cp setup3.html gs://$BUCKET_NAME_1/

Borrar archivos locales de setup

Se usa para forzar nueva descarga y validar descifrado.

rm setup*

Descargar archivos setup desde bucket

Se usa para recuperar y validar acceso a objetos cifrados.

gsutil cp gs://$BUCKET_NAME_1/setup* ./

Mostrar contenido de archivos recuperados

Se usa para comprobar que los archivos se pudieron descifrar.

cat setup.html
cat setup2.html
cat setup3.html

Abrir .boto para rotación de claves

Se usa para mover clave vieja a decryption_key1 y preparar nueva clave.

nano .boto

Generar nueva clave CSEK para rotación

Se usa para actualizar encryption_key.

python3 -c 'import base64; import os; print(base64.encodebytes(os.urandom(32)))'

Reabrir .boto para setear la nueva clave

Se usa para pegar nueva encryption_key.

nano .boto

Reescribir objeto para rotar cifrado

Se usa para volver a cifrar setup2.html con la nueva clave.

gsutil rewrite -k gs://$BUCKET_NAME_1/setup2.html

Abrir .boto para desactivar decryption_key vieja

Se usa para simular cierre de rotación de claves.

nano .boto

Descargar objeto ya rotado

Se usa para validar que setup2.html sigue siendo legible.

gsutil cp gs://$BUCKET_NAME_1/setup2.html recover2.html

Intentar descargar objeto no rotado

Se usa para demostrar fallo esperado en objeto con clave vieja.

gsutil cp gs://$BUCKET_NAME_1/setup3.html recover3.html

Ver lifecycle policy actual

Se usa para inspeccionar la configuración vigente del bucket.

gsutil lifecycle get gs://$BUCKET_NAME_1

Crear archivo de policy lifecycle

Se usa para definir reglas de borrado automático por edad.

nano life.json

Aplicar lifecycle policy al bucket

Se usa para activar la política definida en life.json.

gsutil lifecycle set life.json gs://$BUCKET_NAME_1

Verificar lifecycle policy aplicada

Se usa para confirmar que la policy quedó activa.

gsutil lifecycle get life.json gs://$BUCKET_NAME_1

Consultar estado de versioning

Se usa para verificar si el bucket tiene versionado habilitado.

gsutil versioning get gs://$BUCKET_NAME_1

Habilitar versioning en bucket

Se usa para conservar versiones históricas de objetos.

gsutil versioning set on gs://$BUCKET_NAME_1

Revalidar versioning

Se usa para confirmar que el versionado quedó encendido.

gsutil versioning get gs://$BUCKET_NAME_1

Revisar tamaño del archivo actual

Se usa como referencia antes de crear nuevas versiones.

ls -al setup.html

Editar archivo para cambiar contenido

Se usa para generar una nueva versión del objeto.

nano setup.html

Subir versión nueva del objeto

Se usa para crear una versión adicional en el bucket.

gcloud storage cp -v setup.html gs://$BUCKET_NAME_1

Editar nuevamente archivo para otra versión

Se usa para producir una tercera variante del objeto.

nano setup.html

Subir otra versión del objeto

Se usa para tener varias versiones recuperables.

gcloud storage cp -v setup.html gs://$BUCKET_NAME_1

Listar todas las versiones del objeto

Se usa para obtener el VERSION_NAME histórico.

gcloud storage ls -a gs://$BUCKET_NAME_1/setup.html

Guardar versión objetivo en variable

Se usa para facilitar la descarga de una versión específica.

export VERSION_NAME=<Enter VERSION name here>

Verificar VERSION_NAME

Se usa para confirmar que la variable contiene el path versionado completo.

echo $VERSION_NAME

Recuperar versión histórica del objeto

Se usa para restaurar una versión antigua en recovered.txt.

gcloud storage cp $VERSION_NAME recovered.txt

Comparar tamaños entre versión actual y recuperada

Se usa para verificar que se recuperó contenido anterior.

ls -al setup.html
ls -al recovered.txt

Crear estructura de directorios de prueba

Se usa para preparar un escenario de sincronización recursiva.

mkdir firstlevel
mkdir ./firstlevel/secondlevel
cp setup.html firstlevel
cp setup.html firstlevel/secondlevel

Sincronizar directorio local al bucket

Se usa para copiar recursivamente estructura y archivos.

gsutil rsync -r ./firstlevel gs://$BUCKET_NAME_1/firstlevel

Listado recursivo de objetos sincronizados

Se usa para comparar estructura en bucket vs local.

gcloud storage ls -r gs://$BUCKET_NAME_1/firstlevel

Salir de Cloud Shell

Se usa para terminar la sesión del lab.

exit

Terraform Example: Cloud SQL

Este ejemplo implementa una práctica Terraform basada en el lab Implementing Cloud SQL.

Qué crea

  • APIs necesarias: compute, sqladmin, servicenetworking.
  • Peering privado para Cloud SQL (google_service_networking_connection).
  • Instancia Cloud SQL MySQL (wordpress-db) con:
    • Public IP habilitada.
    • Private IP en la VPC seleccionada.
  • Base de datos wordpress.
  • 2 VMs de apoyo:
    • wordpress-proxy
    • wordpress-private-ip
  • Firewall para exponer HTTP en las VMs de demo.

Uso rápido

  1. Inicializá:
terraform init
  1. Definí terraform.tfvars:
project_id        = "tu-project-id"
region            = "us-central1"
zone              = "us-central1-a"
network_name      = "default"
sql_root_password = "cambiame-por-una-password-segura"
  1. Plan y apply:
terraform plan
terraform apply

Comandos útiles post-deploy

Con la salida sql_instance_connection_name, en wordpress-proxy podés correr:

wget https://dl.google.com/cloudsql/cloud_sql_proxy.linux.amd64 -O cloud_sql_proxy && chmod +x cloud_sql_proxy
export SQL_CONNECTION=<connection_name>
./cloud_sql_proxy -instances=$SQL_CONNECTION=tcp:3306 &

Notas

  • Este ejemplo crea infraestructura base y conectividad; la instalación guiada de WordPress (UI) se hace manual como en el lab.
  • El password root se maneja por variable sensible; no lo hardcodees en código versionado.

Link al lab

Recursos identificados

  • Servicio principal: Cloud SQL (instancia MySQL wordpress-db).
  • Red y conectividad:
    • conexión por proxy (cloud_sql_proxy) sobre 127.0.0.1:3306.
    • conexión por Private IP (internal IP de Cloud SQL).
  • Compute Engine:
    • VM wordpress-proxy.
    • VM wordpress-private-ip.
  • Base de datos:
    • DB wordpress.
  • Aplicación:
    • WordPress conectado a Cloud SQL por dos métodos (proxy e internal IP).

Comandos ejecutados

Descargar Cloud SQL Auth Proxy y dar permisos de ejecución

Se usa para instalar el binario del proxy en la VM wordpress-proxy.

wget https://dl.google.com/cloudsql/cloud_sql_proxy.linux.amd64 -O cloud_sql_proxy && chmod +x cloud_sql_proxy

Guardar el connection name de Cloud SQL en variable

Se usa para reutilizar el identificador de instancia en los comandos del proxy.

export SQL_CONNECTION=[SQL_CONNECTION_NAME]

Verificar la variable SQL_CONNECTION

Se usa para confirmar que la variable quedó correctamente seteada.

echo $SQL_CONNECTION

Iniciar Cloud SQL Proxy en background

Se usa para abrir un túnel local seguro hacia la instancia Cloud SQL.

./cloud_sql_proxy -instances=$SQL_CONNECTION=tcp:3306 &

Obtener external IP de la VM desde metadata server

Se usa para abrir WordPress en el navegador y completar configuración inicial.

curl -H "Metadata-Flavor: Google" http://169.254.169.254/computeMetadata/v1/instance/network-interfaces/0/access-configs/0/external-ip && echo

Ejemplo SDK: Cloud Storage en Python

A diferencia del resto de las prácticas de esta carpeta, este ejemplo no es un lab ni Terraform: es un módulo de Python que muestra cómo interactuar con Cloud Storage usando el SDK oficial (google-cloud-storage).

Qué incluye

  • main.py — funciones upload_blob y download_blob que suben y descargan objetos de un bucket usando storage.Client().
  • pyproject.toml / uv.lock — dependencias gestionadas con uv.

Cómo correrlo

# Autenticación local (Application Default Credentials)
gcloud auth application-default login

# Instalar dependencias con uv
uv sync

# Usar las funciones desde un REPL o script
uv run python -c "from main import upload_blob; upload_blob('<BUCKET>', 'local.txt', 'remoto.txt')"

Recomendaciones

  • El SDK usa Application Default Credentials: asegurate de estar autenticado y con el proyecto correcto.
  • upload_blob usa if_generation_match=0, por lo que falla si el objeto ya existe (subida idempotente de primera escritura).

IAM

Prácticas Terraform para permisos, roles, bindings y service accounts.

Terraform Example: Configuring IAM with gcloud

Este ejemplo implementa una version Terraform de la parte reproducible del lab Configuring IAM Permissions with gcloud, enfocada en el segundo proyecto del escenario.

Que crea

  • APIs necesarias: compute.googleapis.com, iam.googleapis.com.
  • Rol custom devops con los permisos de Compute Engine usados en el lab.
  • Bindings IAM para user2:
    • roles/viewer
    • roles/iam.serviceAccountUser
    • projects/<project>/roles/devops
  • Service account devops.
  • Bindings IAM para la service account:
    • roles/iam.serviceAccountUser
    • roles/compute.instanceAdmin
  • VM lab-3 con la service account adjunta.

Uso rapido

  1. Inicializa Terraform:
terraform init
  1. Defini un terraform.tfvars:
project_id      = "tu-project-id"
user2_email     = "usuario2@example.com"
region          = "us-central1"
zone            = "us-central1-a"
network_name    = "default"
subnetwork_name = "default"
  1. Revisa y aplica:
terraform plan
terraform apply

Verificaciones manuales

  • Revisar el rol custom:
gcloud iam roles describe devops --project <PROJECT_ID>
  • Revisar bindings del usuario secundario:
gcloud projects get-iam-policy <PROJECT_ID> \
  --flatten="bindings[].members" \
  --filter="bindings.members:user:<USER2_EMAIL>" \
  --format="table(bindings.role)"
  • Confirmar la service account adjunta en la VM:
gcloud compute instances describe lab-3 \
  --zone <ZONE> \
  --format="value(serviceAccounts.email)"

Notas

  • El ejemplo asume que ya existe una VPC y subred, igual que en el lab original. Por default usa default/default, pero se puede apuntar a otra red cambiando variables.
  • No modela el paso interactivo de gcloud auth login, gcloud init ni el cambio entre configuraciones locales (default y user2), porque Terraform trabaja contra una identidad ya autenticada.
  • La VM usa el scope cloud-platform por default y limita acceso real via roles IAM, que es la recomendacion actual en lugar de depender solo de scopes legacy.
  • Los custom roles tienen soft-delete en GCP. Si ya existio un rol con el mismo custom_role_id, puede hacer falta cambiar el nombre o esperar a que quede disponible otra vez.

Link al lab

Recursos identificados

  • Contexto del lab:
    • 2 proyectos temporales (PROJECTID1, PROJECTID2).
    • 2 identidades humanas (Username1, Username2).
    • 2 configuraciones locales de gcloud: default y user2.
  • APIs/servicios principales:
    • Compute Engine
    • Identity and Access Management (IAM)
    • políticas IAM a nivel proyecto
  • Recursos de compute:
    • VM existente centos-clean
    • VMs creadas o probadas durante el lab: lab-1, lab-2, lab-3, lab-4
    • red y subred por defecto del proyecto/lab
  • Recursos IAM en el segundo proyecto:
    • binding roles/viewer para Username2
    • rol custom projects/$PROJECTID2/roles/devops
    • binding roles/iam.serviceAccountUser para Username2
  • Recursos de service account:
    • service account devops
    • binding roles/iam.serviceAccountUser para la service account
    • binding roles/compute.instanceAdmin para la service account
    • VM lab-3 con la service account adjunta
  • Archivos/config local usados durante la práctica:
    • ~/.config/gcloud/configurations/config_default
    • ~/.bashrc para exportar PROJECTID2, USERID2 y SA

Comandos ejecutados

Verificar que gcloud ya esta instalado

Se usa para confirmar el entorno inicial dentro de la VM centos-clean.

gcloud --version

Autenticar gcloud y definir region/zona por defecto

Se usa para iniciar sesion y dejar seteada la ubicacion por defecto del primer proyecto.

gcloud auth login
gcloud config set compute/region <REGION_1>
gcloud config set compute/zone <ZONE_1>

Crear la primera VM del lab

Se usa para crear lab-1 en el proyecto inicial.

gcloud compute instances create lab-1 \
  --zone <ZONE_1> \
  --machine-type=e2-standard-2

Revisar configuracion activa y zonas disponibles

Se usa para inspeccionar defaults actuales y elegir otra zona en la misma region.

gcloud config list
gcloud compute zones list

Cambiar la zona por defecto

Se usa para demostrar que gcloud persiste configuraciones locales.

gcloud config set compute/zone <ZONE_MISMA_REGION>
gcloud config list

Inspeccionar el archivo de configuracion local

Se usa para validar que la configuracion se guarda como texto plano.

cat ~/.config/gcloud/configurations/config_default

Crear una segunda configuracion de gcloud

Se usa para preparar un contexto separado para Username2.

gcloud init --no-launch-browser

Probar acceso de solo lectura con user2

Se usa para comprobar que user2 puede listar instancias pero no crearlas todavia.

gcloud compute instances list
gcloud compute instances create lab-2 \
  --zone <ZONE_2> \
  --machine-type=e2-standard-2
gcloud config configurations activate default

Listar roles IAM disponibles

Se usa para revisar roles predefinidos desde CLI.

gcloud iam roles list | grep "name:"

Inspeccionar permisos del rol compute.instanceAdmin

Se usa para identificar el set minimo de permisos que despues se reutiliza en el rol custom.

gcloud iam roles describe roles/compute.instanceAdmin

Cambiar a user2 y apuntar al segundo proyecto

Se usa para mostrar que inicialmente user2 no tiene acceso sobre PROJECTID2.

gcloud config configurations activate user2
echo "export PROJECTID2=<PROJECT_ID_2>" >> ~/.bashrc
. ~/.bashrc
gcloud config set project $PROJECTID2

Volver a la configuracion admin e instalar jq

Se usa para volver al usuario con permisos y preparar utilidades locales.

gcloud config configurations activate default
sudo yum -y install epel-release
sudo yum -y install jq

Exportar USERID2 y dar rol Viewer en el segundo proyecto

Se usa para habilitar acceso de lectura de Username2 sobre PROJECTID2.

echo "export USERID2=<USERNAME_2>" >> ~/.bashrc
. ~/.bashrc
gcloud projects add-iam-policy-binding $PROJECTID2 \
  --member user:$USERID2 \
  --role=roles/viewer

Validar acceso Viewer de user2 en el segundo proyecto

Se usa para comprobar que puede listar recursos pero sigue sin poder crear VMs.

gcloud config configurations activate user2
gcloud config set project $PROJECTID2
gcloud compute instances list
gcloud compute instances create lab-2 \
  --zone <ZONE_2> \
  --machine-type=e2-standard-2
gcloud config configurations activate default

Crear un rol custom para el equipo DevOps

Se usa para encapsular permisos de administracion de instancias en un rol propio del proyecto.

gcloud iam roles create devops \
  --project $PROJECTID2 \
  --permissions "compute.instances.create,compute.instances.delete,compute.instances.start,compute.instances.stop,compute.instances.update,compute.disks.create,compute.subnetworks.use,compute.subnetworks.useExternalIp,compute.instances.setMetadata,compute.instances.setServiceAccount"

Dar a user2 el rol iam.serviceAccountUser

Se usa para permitir que user2 pueda crear instancias con una service account adjunta.

gcloud projects add-iam-policy-binding $PROJECTID2 \
  --member user:$USERID2 \
  --role=roles/iam.serviceAccountUser

Vincular el rol custom devops a user2

Se usa para completar el set de permisos necesarios para operar Compute Engine en PROJECTID2.

gcloud projects add-iam-policy-binding $PROJECTID2 \
  --member user:$USERID2 \
  --role=projects/$PROJECTID2/roles/devops

Verificar que user2 ahora puede crear lab-2

Se usa para confirmar que los nuevos bindings IAM ya tienen efecto.

gcloud config configurations activate user2
gcloud compute instances create lab-2 \
  --zone <ZONE_2> \
  --machine-type=e2-standard-2
gcloud compute instances list

Volver al usuario admin y crear la service account devops

Se usa para preparar el escenario de automatizacion con service accounts.

gcloud config configurations activate default
gcloud config set project $PROJECTID2
gcloud iam service-accounts create devops --display-name devops
gcloud iam service-accounts list --filter "displayName=devops"
SA=$(gcloud iam service-accounts list --format="value(email)" --filter "displayName=devops")

Dar iam.serviceAccountUser a la service account

Se usa para permitir que la service account pueda asociarse a instancias.

gcloud projects add-iam-policy-binding $PROJECTID2 \
  --member serviceAccount:$SA \
  --role=roles/iam.serviceAccountUser

Dar compute.instanceAdmin a la service account

Se usa para que la identidad de servicio pueda administrar instancias.

gcloud projects add-iam-policy-binding $PROJECTID2 \
  --member serviceAccount:$SA \
  --role=roles/compute.instanceAdmin

Crear lab-3 con la service account adjunta

Se usa para montar una VM que hereda permisos via IAM de la service account.

gcloud compute instances create lab-3 \
  --zone <ZONE_2> \
  --machine-type=e2-standard-2 \
  --service-account $SA \
  --scopes "https://www.googleapis.com/auth/compute"

Conectarse a lab-3 y probar permisos de la service account

Se usa para validar desde dentro de la VM que la identidad adjunta puede operar sobre Compute Engine.

gcloud compute ssh lab-3 --zone <ZONE_2>
gcloud config list
gcloud compute instances create lab-4 \
  --zone <ZONE_2> \
  --machine-type=e2-standard-2
gcloud compute instances list

Terraform Example: Exploring IAM

Este ejemplo implementa una version Terraform del lab Exploring IAM.

Que crea

  • APIs necesarias: compute.googleapis.com, iam.googleapis.com, storage.googleapis.com.
  • Bucket de Cloud Storage multi-region con nombre unico global.
  • Objeto de prueba sample.txt.
  • Grant opcional de roles/storage.objectViewer sobre el bucket para un principal externo.
  • Service account read-bucket-objects.
  • Roles sobre el bucket para el service account de la VM:
    • roles/storage.objectViewer
    • roles/storage.objectCreator
  • Grant opcional de roles/iam.serviceAccountUser sobre el service account.
  • Grant opcional de roles/compute.instanceAdmin.v1 a nivel proyecto.
  • VM demoiam con imagen Debian 12 y scope de Storage read/write.

Uso rapido

  1. Inicializa:
terraform init
  1. Crea terraform.tfvars:
project_id = "tu-project-id"
region     = "us-central1"
zone       = "us-central1-a"

network_name    = "default"
subnetwork_name = "default"

limited_storage_member        = "user:student-02@example.com"
service_account_user_member   = "group:platform-admins@example.com"
compute_instance_admin_member = "group:platform-admins@example.com"
  1. Revisa cambios y aplica:
terraform plan
terraform apply

Notas

  • El lab original concede Storage Object Viewer desde el IAM del proyecto; en este ejemplo se acota ese acceso al bucket para mantener menor privilegio sin perder el comportamiento observable del ejercicio.
  • Si queres reproducir el momento del 403 AccessDeniedException, aplica primero con:
service_account_bucket_roles = [
  "roles/storage.objectViewer",
]

Despues agrega roles/storage.objectCreator y vuelve a aplicar.

  • La VM usa solo el scope https://www.googleapis.com/auth/devstorage.read_write, asi que desde adentro de la instancia deberias seguir viendo que gcloud compute instances list no queda habilitado como en el lab.
  • Se asume que ya existe una red/subred accesible para la VM. Los defaults default/default suelen calzar con el escenario del lab; si tu proyecto no las tiene, ajusta network_name y subnetwork_name.

Link al lab

Recursos identificados

  • APIs/servicios involucrados: IAM, Cloud Storage, Compute Engine, Service Accounts.
  • Principales identidades:
    • Username 1 con permisos de administración del proyecto.
    • Username 2 con acceso inicial de lectura al proyecto y luego acceso acotado a Cloud Storage.
    • principal externo altostrat.com usado para practicar grants de Service Account User y Compute Instance Admin (v1).
  • Almacenamiento:
    • bucket de Cloud Storage multi-region con un objeto de prueba sample.txt.
  • IAM:
    • remoción del acceso de proyecto para Username 2.
    • grant de Storage Object Viewer para validar acceso restringido.
    • service account read-bucket-objects.
    • cambio de permisos del service account desde Storage Object Viewer a Storage Object Creator.
  • Cómputo:
    • VM demoiam en Compute Engine.
    • imagen Debian GNU/Linux 12 (bookworm).
    • machine type e2-micro.
    • service account read-bucket-objects adjunta a la VM con scope de Storage.
  • Validaciones del lab:
    • listado de objetos del bucket desde Cloud Shell con permisos limitados.
    • pruebas de lectura/escritura al bucket desde SSH en la VM.

Comandos ejecutados

Listar el contenido del bucket con el segundo usuario

Verifica que Username 2 tenga acceso restringido a Cloud Storage sin recuperar acceso completo al proyecto.

gcloud storage ls gs://[YOUR_BUCKET_NAME]

Probar acceso a Compute Engine desde la VM

Se ejecuta desde la VM demoiam para comprobar que la identidad adjunta no puede listar instancias.

gcloud compute instances list

Descargar el archivo de prueba desde el bucket

La copia se hace desde la VM usando el service account adjunto.

gcloud storage cp gs://[YOUR_BUCKET_NAME]/sample.txt .

Renombrar el archivo descargado

Prepara un segundo nombre para probar la escritura sobre el bucket.

mv sample.txt sample2.txt

Intentar subir el archivo renombrado sin permisos de escritura

Antes de cambiar el rol del service account, esta operación devuelve 403 AccessDeniedException.

gcloud storage cp sample2.txt gs://[YOUR_BUCKET_NAME]

Reintentar la subida después de otorgar Storage Object Creator

Luego de actualizar el rol del service account, la misma copia pasa a funcionar.

gcloud storage cp sample2.txt gs://[YOUR_BUCKET_NAME]

Link al lab

Recursos identificados

  • APIs/servicios involucrados: IAM, Cloud Storage, Compute Engine, Service Accounts, Cloud Shell.
  • Principales IAM del ejercicio:
    • Username 1 como administrador del proyecto temporal del lab.
    • Username 2, que pasa de tener Viewer a no tener acceso al proyecto y luego recibe acceso acotado a Cloud Storage.
    • un principal de ejemplo sobre altostrat.com para practicar Service Account User y Compute Instance Admin (v1).
  • Cloud Storage:
    • bucket con nombre globalmente único y ubicación multi-región.
    • objeto sample.txt para probar lectura y escritura.
  • Compute e identidad:
    • service account read-bucket-objects.
    • VM demoiam (e2-micro, Debian 12) usando esa service account.
    • scope de Storage Read Write en la VM para probar acceso desde SSH.
  • Roles relevantes:
    • remoción del acceso de proyecto para Username 2.
    • roles/storage.objectViewer para Username 2.
    • roles/storage.objectViewer y luego roles/storage.objectCreator sobre la service account read-bucket-objects.
    • roles/iam.serviceAccountUser sobre la service account.
    • roles/compute.instanceAdmin.v1 a nivel proyecto.

Comandos ejecutados

Listar el bucket desde Cloud Shell como Username 2

Verifica que el usuario sin acceso al proyecto igual pueda inspeccionar objetos si tiene permisos puntuales sobre Cloud Storage.

gcloud storage ls gs://[YOUR_BUCKET_NAME]

Intentar listar instancias desde la VM demoiam

Prueba el alcance efectivo de la service account adjunta a la VM y sus scopes.

gcloud compute instances list

Copiar sample.txt desde el bucket hacia la VM

Descarga el archivo de prueba usando las credenciales de la service account.

gcloud storage cp gs://[YOUR_BUCKET_NAME]/sample.txt .

Renombrar el archivo descargado

Prepara un nuevo nombre local para probar la subida posterior.

mv sample.txt sample2.txt

Intentar subir sample2.txt sin permiso de creación

Este paso falla mientras la service account solo tenga permisos de lectura.

gcloud storage cp sample2.txt gs://[YOUR_BUCKET_NAME]

Reintentar la subida después de otorgar Storage Object Creator

Vuelve a ejecutar la copia una vez ajustado el rol de la service account.

gcloud storage cp sample2.txt gs://[YOUR_BUCKET_NAME]

Terraform

Prácticas enfocadas en flujo de trabajo Terraform, estado e infraestructura como código.

Terraform Example: Build IaC with Terraform

Este ejemplo implementa una práctica Terraform basada en el lab Build IaC with Terraform.

Referencias del lab

Qué crea

  • APIs: compute.googleapis.com, storage.googleapis.com.
  • Cloud Storage bucket para simular backend/state remoto.
  • VPC + subnets mediante módulo terraform-google-modules/network/google.
  • Compute Engine instances tf-instance-1 y tf-instance-2.
  • Tercera instancia opcional (create_third_instance) para practicar taint y reconciliación.
  • Firewall tf-firewall para exponer tcp:80.
  • Service account para VMs con rol roles/logging.logWriter.

Uso rápido

  1. Crear terraform.tfvars:
project_id = "tu-project-id"
region     = "us-central1"
zone       = "us-central1-a"
bucket_name = "tf-bucket-unico-12345"

# Opcional para practicar task de taint/recreate
create_third_instance = true
third_instance_name   = "tf-instance-3"
  1. Inicializar y planificar:
terraform init
terraform plan
  1. Aplicar:
terraform apply

Comandos del flujo del lab

terraform import google_compute_instance.tf_instance_1 <INSTANCE_ID_1>
terraform import google_compute_instance.tf_instance_2 <INSTANCE_ID_2>
terraform taint google_compute_instance.tf_instance_3[0]

La guía original usa estructura de módulos locales (modules/instances y modules/storage); este ejemplo lo simplifica en un layout compacto pero mantiene los mismos conceptos del lab.

Notas

  • disable_on_destroy = false se aplica al habilitar APIs para evitar apagarlas al destruir.
  • No hay secretos hardcodeados en los archivos .tf.
  • Para backend remoto real, después de crear el bucket podés migrar estado agregando un bloque backend "gcs" y re-ejecutar terraform init.

Link al lab

Recursos identificados

  • APIs y providers:
    • Terraform provider: hashicorp/google.
    • API principal utilizada por los recursos: Compute Engine API (compute.googleapis.com).
  • Recursos principales:
    • VPC auto mode: mynetwork (google_compute_network).
    • Firewall rule: mynetwork-allow-http-ssh-rdp-icmp (google_compute_firewall).
    • VM instances: mynet-vm-1 y mynet-vm-2 (google_compute_instance).
  • IAM:
    • Se usa la identidad del proyecto/lab en Cloud Shell para aprovisionar recursos (sin creación explícita de service accounts en el flujo base).
  • Integraciones:
    • Módulo Terraform reutilizable para instancias (source = "./instance" en el lab original).
    • Referencias entre recursos para dependencia implícita (por ejemplo google_compute_network.mynetwork.self_link).

Comandos ejecutados

Verificar Terraform instalado

terraform --version

Crear carpeta de trabajo Terraform

mkdir tfinfra

Inicializar Terraform en la carpeta del lab

cd tfinfra
terraform init

Formatear configuración Terraform

terraform fmt

Inicializar nuevamente luego de crear módulos y archivos

terraform init

Revisar plan de infraestructura

terraform plan

Aplicar cambios de infraestructura

terraform apply

Confirmar aplicación del plan

yes

Verificar conectividad entre VMs por IP interna

ping -c 3 <Enter mynet-vm-2's internal IP here>

Práctica Terraform: Automating Infrastructure Deployment With Terraform

Este ejemplo replica el flujo central del lab de Google Skills para desplegar infraestructura básica con Terraform:

  • VPC auto mode (mynetwork)
  • Firewall para SSH/HTTP/RDP/ICMP
  • Dos VM instances (mynet-vm-1 y mynet-vm-2)

Lab original: Automating the Deployment of Infrastructure Using Terraform

Archivos

  • versions.tf: versión de Terraform, provider y configuración base de google.
  • variables.tf: variables de entrada para proyecto, red, zonas y VMs.
  • main.tf: habilitación de API + recursos principales.
  • outputs.tf: datos útiles post-deploy.

Uso rápido

  1. Crear un archivo terraform.tfvars (o pasar variables por CLI):
project_id = "tu-proyecto"
region     = "us-central1"
zones      = ["us-central1-a", "us-central1-b"]
  1. Ejecutar:
terraform init
terraform fmt
terraform plan
terraform apply

Buenas prácticas aplicadas

  • Variables para valores configurables (project_id, region, zones, nombres).
  • locals para definir estructura de VMs.
  • outputs útiles para inspección y debugging.
  • API de Compute habilitada con disable_on_destroy = false.
  • Sin secretos hardcodeados.

Link al lab

La URL del lab requiere login. Para extraer comandos se usó como fuente pública equivalente este walkthrough: GSP345 | Automating Infrastructure on Google Cloud with Terraform: Challenge Lab (Gist).

Recursos identificados

  • APIs habilitadas en el flujo: compute.googleapis.com y storage.googleapis.com.
  • Recursos principales:
    • Compute Engine instances (tf-instance-1, tf-instance-2 y temporalmente tf-instance-3).
    • Cloud Storage bucket para backend "gcs" de Terraform state.
    • VPC y subnets creadas con módulo del Terraform Registry (terraform-google-modules/network/google).
    • Firewall rule (google_compute_firewall) para tráfico tcp:80.
  • IAM:
    • uso implícito de permisos del usuario/sesión de Cloud Shell para crear/importar y administrar recursos.
    • no se define un service account custom en la guía base.
  • Integraciones:
    • Terraform import para adoptar instancias ya existentes.
    • Terraform backend remoto en GCS (prefix = "terraform/state").
    • Integración con módulo público del Terraform Registry para networking.

Comandos ejecutados

Estructura inicial de archivos

touch main.tf
touch variables.tf
mkdir modules
cd modules
mkdir instances
cd instances
touch instances.tf
touch outputs.tf
touch variables.tf
cd ..
mkdir storage
cd storage
touch storage.tf
touch outputs.tf
touch variables.tf
cd

Inicialización de Terraform

terraform init

Import de infraestructura existente

terraform import module.instances.google_compute_instance.tf-instance-1 <Instance ID - 1>
terraform import module.instances.google_compute_instance.tf-instance-2 <Instance ID - 2>

Revisar y aplicar cambios de estado

terraform plan
terraform apply

Crear bucket para backend remoto

terraform init
terraform apply

Migrar state a backend GCS

terraform init

Actualizar infraestructura de instancias

terraform init
terraform apply

Taint y recreación de recurso

terraform taint module.instances.google_compute_instance.tf-instance-3
terraform init
terraform apply

Eliminar tercer recurso y reconciliar

terraform apply

Crear VPC con módulo del Registry

terraform init
terraform apply

Reconfigurar instancias sobre nuevas subnets

terraform init
terraform apply

Configurar firewall final

terraform init
terraform apply

Observabilidad

Prácticas Terraform para observabilidad en Google Cloud: monitoreo, alertas, logs, métricas, trazas y SLOs.

PrácticaDescripción
Alerting in GCPApp Engine + alert policy de Cloud Monitoring (latencia p99)
Service MonitoringApp Engine + SLO de disponibilidad y alerta por burn rate del error budget
Log AnalyticsGKE + log bucket con Log Analytics, dataset enlazado en BigQuery y log sink
Cloud TraceCluster GKE con scopes para Cloud Trace y app demo con OpenTelemetry
Ops Agent MonitoringVM con Apache + Ops Agent vía startup script, canal de notificación y alerting opcional
Monitoring Applications in GCPMonitoreo de aplicaciones desplegadas en Google Cloud

Uso rápido

cd <practica>
terraform init
terraform plan -var="project_id=<PROJECT_ID>"
terraform apply -var="project_id=<PROJECT_ID>"

Recomendaciones

  • Revisar el README de cada práctica: algunas requieren pasos manuales (desplegar la app demo, habilitar APIs).
  • Usar terraform destroy al terminar para evitar costos innecesarios.

Práctica Terraform: Alerting in GCP

Este ejemplo implementa con Terraform una base reproducible para el lab Alerting in Google Cloud:

  • Habilita APIs necesarias.
  • Crea la App Engine application del proyecto.
  • Crea un Cloud Monitoring alerting policy sobre latencia (99th percentile).
  • (Opcional) Crea un notification channel de tipo email.

Qué NO despliega

  • El código de la aplicación y el deploy de App Engine (eso en el lab se hace con gcloud app deploy).
  • El generador de carga con curl (es un comando del lab para disparar incidentes).

Uso rápido

  1. Inicializá:
terraform init
  1. Creá terraform.tfvars:
project_id             = "tu-project-id"
region                 = "us-central1"
app_engine_location_id = "us-central"

# Opcional: crea el notification channel
notification_email = "tu-email@ejemplo.com"
  1. Plan y apply:
terraform plan
terraform apply

Notas de compatibilidad

  • app_engine_location_id no es lo mismo que region. Ejemplos típicos:
    • Region: us-central1 → App Engine location: us-central
    • Region: southamerica-east1 → App Engine location: southamerica-east1

Salidas útiles

El ejemplo expone por outputs:

  • alert_policy_name
  • notification_channel_name (si aplica)

Link al lab

Este lab se complementa con la práctica Terraform en README.md dentro de esta misma carpeta.

Práctica Terraform: Service Monitoring

Este ejemplo implementa con Terraform una base reproducible para el lab Service Monitoring:

  • Habilita APIs necesarias.
  • Crea la App Engine application del proyecto.
  • Crea un Service Monitoring SLO de disponibilidad (rolling window) para el App Engine service default.
  • Crea un Cloud Monitoring alert policy basado en burn rate del error budget del SLO (via MQL select_slo_burn_rate).
  • (Opcional) Crea un notification channel de tipo email.

Qué NO despliega

  • El código de la app Node.js ni el deploy a App Engine (en el lab se hace con gcloud app deploy).
  • La generación de carga con curl (en el lab se usa para provocar errores).

Prerrequisitos

  • Tener un servicio App Engine default desplegado en el proyecto. Si todavía no existe, el datasource google_monitoring_app_engine_service puede fallar porque Service Monitoring aún no “ve” el servicio.

Uso rápido

  1. Inicializá:
terraform init
  1. Creá terraform.tfvars:
project_id             = "tu-project-id"
region                 = "us-central1"
app_engine_location_id = "us-central"

# Opcional: crea el notification channel
notification_email = "tu-email@ejemplo.com"

# Defaults del lab
slo_goal                  = 0.995
slo_rolling_period_days    = 7
burn_rate_lookback_seconds = 600
burn_rate_threshold        = 1.5
  1. Plan y apply:
terraform plan
terraform apply

Salidas útiles

El ejemplo expone por outputs:

  • slo_name
  • alert_policy_name
  • notification_channel_name (si aplica)

Link al lab

Este lab se complementa con la práctica Terraform en README.md dentro de esta misma carpeta.

Link al lab

Recursos identificados

  • App Engine (standard): creación de la aplicación App Engine y deploy de un servicio Node.js.
  • Service Monitoring (Cloud Monitoring): definición de un SLO de disponibilidad para el servicio App Engine default (rolling window 7 días, objetivo 99.5%).
  • Cloud Monitoring Alerting: creación de un alert atado al SLO (burn rate) con lookback de 10 minutos y threshold 1.5.
  • Notification channels: canal de notificación por email (configurado desde la UI).
  • Métricas/telemetría:
    • Tráfico HTTP a App Engine (/random-error) para inducir errores.
    • Cálculo de burn rate del error budget vía select_slo_burn_rate.
  • IAM / APIs:
    • APIs típicamente requeridas: appengine.googleapis.com, monitoring.googleapis.com.
    • La creación/edición de SLOs y alert policies requiere permisos de Monitoring (por ejemplo roles tipo roles/monitoring.editor en el proyecto).

Comandos ejecutados

git clone https://github.com/haggman/HelloLoggingNodeJS.git
cd HelloLoggingNodeJS
edit index.js
gcloud app create --region={{{project_0.startup_script.app_region|REGION}}}
gcloud app deploy
while true; \
do curl -s https://$DEVSHELL_PROJECT_ID.appspot.com/random-error \
  -w '\n' ;sleep .1s;done
gcloud app deploy

Práctica Terraform: Log Analytics

Este ejemplo implementa con Terraform una base reproducible inspirada en el lab Log Analytics on Google Cloud (GSP1088):

  • Habilita APIs necesarias.
  • Crea un cluster GKE.
  • Crea un log bucket con Log Analytics habilitado.
  • Crea un linked dataset en BigQuery para consultar logs con SQL.
  • Crea un log sink con el filtro resource.type="k8s_container" hacia el log bucket.

Qué NO despliega

  • El deploy de la app microservices-demo (Online Boutique) con Terraform. En el lab se hace con kubectl y acá queda documentado como comandos.

Prerrequisitos

  • Terraform instalado.
  • Permisos en el proyecto para crear GKE, Logging y BigQuery.
  • gcloud y kubectl si vas a desplegar la demo.

Uso rápido

  1. Inicializá:
terraform init
  1. Creá terraform.tfvars:
project_id = "tu-project-id"
region     = "us-west1"
zone       = "us-west1-a"
  1. Plan y apply:
terraform plan
terraform apply

Comandos del lab (deploy de Online Boutique)

Estos comandos están extraídos del lab; sirven para generar carga y logs desde GKE.

git clone https://github.com/GoogleCloudPlatform/microservices-demo.git
cd microservices-demo
kubectl apply -f release/kubernetes-manifests.yaml
kubectl get pods
export EXTERNAL_IP=$(kubectl get service frontend-external -o jsonpath="{.status.loadBalancer.ingress[0].ip}")
echo $EXTERNAL_IP
curl -o /dev/null -s -w "%{http_code}\n" http://${EXTERNAL_IP}

Consultas del lab (Log Analytics / BigQuery)

Filtro usado para el sink:

resource.type="k8s_container"

Ejemplos SQL (ajustá PROJECT_ID si lo pegás tal cual):

SELECT
  hour,
  MIN(took_ms) AS min,
  MAX(took_ms) AS max,
  AVG(took_ms) AS avg
FROM (
  SELECT
    FORMAT_TIMESTAMP("%H", timestamp) AS hour,
    CAST(JSON_VALUE(json_payload, '$."http.resp.took_ms"') AS INT64) AS took_ms
  FROM `PROJECT_ID.global.day2ops-log._AllLogs`
  WHERE timestamp > TIMESTAMP_SUB(CURRENT_TIMESTAMP(), INTERVAL 24 HOUR)
    AND json_payload IS NOT NULL
    AND SEARCH(labels, "frontend")
    AND JSON_VALUE(json_payload.message) = "request complete"
  ORDER BY took_ms DESC, timestamp ASC
)
GROUP BY 1
ORDER BY 1
SELECT
  count(*)
FROM `PROJECT_ID.global.day2ops-log._AllLogs`
WHERE text_payload like "GET %/product/L9ECAV7KIM %"
  AND timestamp > TIMESTAMP_SUB(CURRENT_TIMESTAMP(), INTERVAL 1 HOUR)
SELECT
  JSON_VALUE(json_payload.session),
  COUNT(*)
FROM `PROJECT_ID.global.day2ops-log._AllLogs`
WHERE JSON_VALUE(json_payload['http.req.method']) = "POST"
  AND JSON_VALUE(json_payload['http.req.path']) = "/cart/checkout"
  AND timestamp > TIMESTAMP_SUB(CURRENT_TIMESTAMP(), INTERVAL 1 HOUR)
GROUP BY JSON_VALUE(json_payload.session)

Salidas útiles

El ejemplo expone por outputs:

  • cluster_name, cluster_location
  • log_bucket_name, log_bucket_destination
  • linked_dataset_resource_name
  • sink_name, sink_writer_identity

Link al lab

Recursos identificados

  • GKE: cluster day2-ops (trabajo con workloads k8s_container).
  • Cloud Logging:
    • Log bucket (upgrade del bucket existente _Default o creación de un bucket nuevo).
    • Log Analytics habilitado en el bucket.
    • Log view _AllLogs dentro del bucket.
    • Log sink con filtro resource.type="k8s_container" hacia el bucket.
  • BigQuery:
    • Dataset linkeado al log bucket (para ejecutar consultas SQL sobre el log view).
  • Integraciones:
    • Export/routing de logs vía Logs Router (sink) hacia un log bucket.

Comandos ejecutados

gcloud auth list
gcloud config list project
gcloud config set compute/zone ZONE
gcloud container clusters list
gcloud container clusters get-credentials day2-ops --region REGION
kubectl get nodes
git clone https://github.com/GoogleCloudPlatform/microservices-demo.git
cd microservices-demo
kubectl apply -f release/kubernetes-manifests.yaml
kubectl get pods
export EXTERNAL_IP=$(kubectl get service frontend-external -o jsonpath="{.status.loadBalancer.ingress[0].ip}")
echo $EXTERNAL_IP
curl -o /dev/null -s -w "%{http_code}\n" http://${EXTERNAL_IP}
resource.type="k8s_container"
SELECT
  hour,
  MIN(took_ms) AS min,
  MAX(took_ms) AS max,
  AVG(took_ms) AS avg
FROM (
  SELECT
    FORMAT_TIMESTAMP("%H", timestamp) AS hour,
    CAST(JSON_VALUE(json_payload, '$."http.resp.took_ms"') AS INT64) AS took_ms
  FROM `PROJECT_ID.global.day2ops-log._AllLogs`
  WHERE timestamp > TIMESTAMP_SUB(CURRENT_TIMESTAMP(), INTERVAL 24 HOUR)
    AND json_payload IS NOT NULL
    AND SEARCH(labels, "frontend")
    AND JSON_VALUE(json_payload.message) = "request complete"
  ORDER BY took_ms DESC, timestamp ASC
)
GROUP BY 1
ORDER BY 1
SELECT
  count(*)
FROM `PROJECT_ID.global.day2ops-log._AllLogs`
WHERE text_payload like "GET %/product/L9ECAV7KIM %"
  AND timestamp > TIMESTAMP_SUB(CURRENT_TIMESTAMP(), INTERVAL 1 HOUR)
SELECT
  JSON_VALUE(json_payload.session),
  COUNT(*)
FROM `PROJECT_ID.global.day2ops-log._AllLogs`
WHERE JSON_VALUE(json_payload['http.req.method']) = "POST"
  AND JSON_VALUE(json_payload['http.req.path']) = "/cart/checkout"
  AND timestamp > TIMESTAMP_SUB(CURRENT_TIMESTAMP(), INTERVAL 1 HOUR)
GROUP BY JSON_VALUE(json_payload.session)

Cloud Trace — Análisis de latencia de aplicaciones

Práctica Terraform basada en el lab View application latency with Cloud Trace.

Crea un cluster GKE con los scopes necesarios para exportar traces a Cloud Trace. La app demo (Python + OpenTelemetry) se despliega manualmente con el script del repositorio oficial de Google.

Recursos creados

RecursoNombre
Cluster GKEcloud-trace-demo
Node poolcloud-trace-demo-nodes (e2-medium × 3)

Cloud Trace no requiere recursos Terraform — los spans llegan automáticamente desde la app via OpenTelemetry con el scope cloud-platform.

Uso rápido

terraform init

terraform apply \
  -var="project_id=TU_PROJECT_ID"

Deployar la app demo

Una vez que el cluster esté activo:

# Configurar kubectl
gcloud container clusters get-credentials cloud-trace-demo \
  --zone us-central1-c \
  --project TU_PROJECT_ID

# Verificar nodos
kubectl get nodes

# Clonar y deployar la app
git clone https://github.com/GoogleCloudPlatform/python-docs-samples.git
cd python-docs-samples/trace/cloud-trace-demo-app-opentelemetry && ./setup.sh

Generar tráfico para ver traces

curl $(kubectl get svc \
  -o=jsonpath='{.items[?(@.metadata.name=="cloud-trace-demo-a")].status.loadBalancer.ingress[0].ip}')

Repetir varias veces, luego ir a Cloud Trace → Explorador de traces en la consola para ver los spans distribuidos entre los tres servicios (a→b→c).

Variables requeridas

VariableDescripción
project_idID del proyecto GCP

Notas

  • El cluster usa oauth_scopes = ["cloud-platform"] que incluye cloudtrace.append — necesario para que los pods exporten spans sin service account adicional.
  • No se puede validar runtime real sin un proyecto activo con billing habilitado y la app desplegada.

Link al lab

Recursos identificados

  • APIs habilitadas: container.googleapis.com, cloudtrace.googleapis.com.
  • Cluster GKE: cloud-trace-demo (standard, us-central1-c).
  • Deployments de Kubernetes: cloud-trace-demo-a, cloud-trace-demo-b, cloud-trace-demo-c — app Python con Flask + OpenTelemetry que propaga contexto de tracing entre servicios.
  • Services de Kubernetes: LoadBalancer para cloud-trace-demo-a (punto de entrada), ClusterIP para b y c.
  • Cloud Trace: recibe los spans exportados por la app via OpenTelemetry; no requiere recursos Terraform propios.
  • IAM: las VMs del nodo pool usan la service account por defecto del proyecto con scope trace.append.

Comandos ejecutados

En los comandos siguientes, reemplazá <ZONE> y <PROJECT_ID> por los valores de tu lab.

Verificar autenticación y proyecto activo

gcloud auth list
gcloud config list project

Crear el cluster GKE

gcloud container clusters create cloud-trace-demo \
  --zone us-central1-c

Configurar kubectl para el cluster

gcloud container clusters get-credentials cloud-trace-demo \
  --zone us-central1-c

kubectl get nodes

Clonar el repositorio de la app demo

git clone https://github.com/GoogleCloudPlatform/python-docs-samples.git

Deployar la app con el script de setup

cd python-docs-samples/trace/cloud-trace-demo-app-opentelemetry && ./setup.sh

El script despliega los tres servicios (a, b, c) y espera a que el LoadBalancer de cloud-trace-demo-a obtenga IP externa.

Obtener la IP externa del servicio de entrada

kubectl get svc

Generar tráfico para producir traces

curl $(kubectl get svc -o=jsonpath='{.items[?(@.metadata.name=="cloud-trace-demo-a")].status.loadBalancer.ingress[0].ip}')

Repetir varias veces para generar suficientes spans visibles en Cloud Trace.

Ver los traces (Console)

Cloud Trace → Explorador de traces — los puntos en el scatter plot representan requests individuales. Hacer click en un punto para ver el Gantt chart con los spans de a→b→c y los atributos de cada span.

Limpiar el cluster al terminar

gcloud container clusters delete cloud-trace-demo \
  --zone us-central1-c

Ops Agent Monitoring — Monitoreo de Compute Engine

Práctica Terraform basada en el lab Monitoring a Compute Engine by using Ops Agent.

Crea una VM con Apache y el Ops Agent preconfigurado via startup script. Opcionalmente crea un canal de notificación y un alerting policy para tráfico Apache.

Recursos creados

RecursoNombre
VM Compute Enginequickstart-vm (e2-small, Debian)
Firewallallow-http-ops-agent (tcp:80)
Notification channelemail (opcional)
Alert policyApache traffic > threshold (opcional)

Uso rápido

terraform init

# Sin alertas
terraform apply \
  -var="project_id=TU_PROJECT_ID"

# Con alertas
terraform apply \
  -var="project_id=TU_PROJECT_ID" \
  -var="alert_notification_email=tu@email.com"

Variables requeridas

VariableDescripción
project_idID del proyecto GCP

Generar tráfico para ver métricas

Una vez desplegado, conectate a la VM y generá tráfico:

# SSH a la VM
gcloud compute ssh --zone us-east4-c quickstart-vm --project TU_PROJECT_ID

# Generar requests durante 2 minutos
timeout 120 bash -c -- 'while true; do curl localhost; sleep $((RANDOM % 4)) ; done'

Luego ir a Cloud Monitoring → Dashboards → Apache Overview para ver las métricas exportadas por el Ops Agent.

Notas

  • El startup script instala Apache, PHP y el Ops Agent, y escribe la config de pipelines para Apache automáticamente.
  • El scope cloud-platform en la service account incluye monitoring.write y logging.write, necesarios para que el Ops Agent exporte datos.
  • La alerta y el canal de notificación son opcionales — se crean solo si se pasa alert_notification_email.
  • No se puede validar runtime real sin un proyecto activo con billing habilitado.

Link al lab

Recursos identificados

  • APIs habilitadas: compute.googleapis.com, monitoring.googleapis.com, logging.googleapis.com.
  • VM: quickstart-vm (e2-small, Debian, us-east4-c, tag http-server).
  • Firewall: permite tcp:80 desde 0.0.0.0/0 a VMs con tag http-server.
  • Software en la VM: Apache2 + PHP + Google Cloud Ops Agent.
  • Ops Agent config: pipelines personalizados para métricas y logs de Apache (apache, apache_access, apache_error).
  • Cloud Monitoring: dashboard predefinido "Apache Overview", canal de notificación por email, alerting policy por tráfico Apache (workload.googleapis.com/apache.traffic > 4 KiB/s).

Comandos ejecutados

En los comandos siguientes, reemplazá <ZONE> y <PROJECT_ID> por los valores de tu lab.

Verificar autenticación y proyecto activo

gcloud auth list
gcloud config list project

Conectarse a la VM por SSH

gcloud compute ssh --zone "<ZONE>" "quickstart-vm" --project "<PROJECT_ID>"

Instalar Apache y PHP

sudo apt-get update
sudo apt-get install apache2 php7.0 -y

Instalar el Ops Agent

curl -sSO https://dl.google.com/cloudagents/add-google-cloud-ops-agent-repo.sh
sudo bash add-google-cloud-ops-agent-repo.sh --also-install

Hacer backup del config y configurar pipelines de Apache

sudo cp /etc/google-cloud-ops-agent/config.yaml /etc/google-cloud-ops-agent/config.yaml.bak

sudo tee /etc/google-cloud-ops-agent/config.yaml > /dev/null << EOF
metrics:
  receivers:
    apache:
      type: apache
  service:
    pipelines:
      apache:
        receivers:
          - apache
logging:
  receivers:
    apache_access:
      type: apache_access
    apache_error:
      type: apache_error
  service:
    pipelines:
      apache:
        receivers:
          - apache_access
          - apache_error
EOF

Reiniciar el Ops Agent y verificar estado

sudo systemctl restart google-cloud-ops-agent
sudo systemctl status "google-cloud-ops-agent*"

Generar tráfico al servidor Apache

timeout 120 bash -c -- 'while true; do curl localhost; sleep $((RANDOM % 4)) ; done'

Ver el dashboard de Apache (Console)

Cloud Monitoring → Dashboards → Apache Overview — muestra métricas de tráfico, workers activos y requests por segundo exportadas por el Ops Agent.

Crear canal de notificación y alerting policy (Console)

  1. Monitoring → Alerting → Edit notification channels → agregar canal Email.
  2. Monitoring → Alerting → Create policy → métrica workload.googleapis.com/apache.traffic, threshold > 4 KiB/s, duración 1 minuto, notificar al canal creado.

Monitoring Applications in Google Cloud

Práctica Terraform basada en el lab GSP659.

Provisiona la infraestructura de observabilidad para una app App Engine: uptime checks, alertas de latencia y canal de notificaciones por email.

Nota: el código de la aplicación Flask se despliega con gcloud app deploy, no con Terraform. Este ejemplo cubre exclusivamente la capa de monitoreo.

Recursos creados

RecursoDescripción
google_app_engine_applicationAplicación App Engine en el proyecto
google_monitoring_uptime_check_configUptime check HTTPS cada 60s
google_monitoring_alert_policy (latencia)Alerta cuando p99 > umbral configurado
google_monitoring_alert_policy (uptime)Alerta ante falla del uptime check
google_monitoring_notification_channelCanal de email (opcional)

Uso

terraform init
terraform plan -var="project_id=<PROJECT_ID>" -var="uptime_check_host=<PROJECT_ID>.appspot.com"
terraform apply -var="project_id=<PROJECT_ID>" -var="uptime_check_host=<PROJECT_ID>.appspot.com"

Con notificaciones por email:

terraform apply \
  -var="project_id=<PROJECT_ID>" \
  -var="uptime_check_host=<PROJECT_ID>.appspot.com" \
  -var="notification_email=tu@email.com"

Variables principales

VariableRequeridaDefaultDescripción
project_idGCP project ID
uptime_check_hostHost del uptime check
app_engine_location_idus-centralLocation de App Engine
regionus-central1Region para recursos regionales
notification_emailnullEmail para alertas
latency_threshold_seconds8Umbral p99 latencia (segundos)

Link al lab

Este lab se complementa con la práctica Terraform en README.md dentro de esta misma carpeta.

Recursos identificados

  • App Engine: aplicación Python 3.11 (Flask) desplegada con gcloud app deploy
  • Cloud Profiler: habilitado via SDK en la app (google-cloud-profiler)
  • Cloud Trace: integrado automáticamente en App Engine
  • Cloud Monitoring: dashboards, uptime checks y alert policies
  • Compute Engine: VM usada para generar carga con ab (Apache Bench)
  • APIs: cloudprofiler.googleapis.com, appengine.googleapis.com, monitoring.googleapis.com, compute.googleapis.com

Comandos ejecutados

Configuración inicial

gcloud auth list
gcloud config list project
gcloud config set project [PROJECT_ID]

Clonar el código de ejemplo

mkdir gcp-logging
cd gcp-logging
gcloud storage cp gs://cloud-training/CBL175/design-process.zip .
unzip design-process.zip
cd design-process/deploying-apps-to-gcp

Habilitar Cloud Profiler

gcloud services enable cloudprofiler.googleapis.com

Probar la app localmente con Docker

docker build -t test-python .
docker run --rm -p 8080:8080 test-python

Crear la aplicación en App Engine y desplegar

gcloud app create --region=[REGION]
gcloud app deploy --version=one --quiet

Generar carga desde la VM de Compute Engine

sudo apt update
sudo apt install apache2-utils -y
ab -k -n 1000 -c 10 https://<your-project-id>.appspot.com/

Modificaciones al código de la app

main.py: agregar inicialización del profiler:

import googlecloudprofiler

try:
    googlecloudprofiler.start(verbose=3)
except (ValueError, NotImplementedError) as exc:
    print(exc)

requirements.txt: agregar dependencias:

google-cloud-profiler==4.1.0
protobuf==3.20.1

app.yaml:

runtime: python311

CI/CD

Prácticas Terraform para pipelines de integración y entrega continua en Google Cloud (curso "Reliable Google Cloud Infrastructure: Design and Process").

PrácticaDescripción
DevOps Pipeline con Cloud BuildCloud Build trigger + Artifact Registry conectado a GitHub

Uso rápido

cd <practica>
terraform init
terraform plan -var="project_id=<PROJECT_ID>"
terraform apply -var="project_id=<PROJECT_ID>"

Recomendaciones

  • Revisar el README de cada práctica antes de hacer apply — algunas requieren pasos manuales previos (por ejemplo, conectar GitHub a Cloud Build).
  • Usar terraform destroy al terminar para evitar costos innecesarios.

DevOps Pipeline con Cloud Build y Artifact Registry

Practica basada en el lab "Building a DevOps Pipeline" (curso 41). Crea la infraestructura CI/CD que construye y publica automáticamente una imagen Docker en Artifact Registry cada vez que se hace push a la rama main de un repositorio GitHub.

Arquitectura

git push → GitHub repo (devops-repo)
               │
               ▼ webhook (Cloud Build GitHub App)
         Cloud Build trigger (devops-trigger)
               │ usa cloudbuild.yaml
               ▼
         Artifact Registry (devops-repo)
         $REGION-docker.pkg.dev/$PROJECT_ID/devops-repo/devops-image:$COMMIT_SHA

Pre-requisito: conectar GitHub a Cloud Build

El trigger usa la Cloud Build GitHub App, que requiere una conexión OAuth manual:

  1. Ir a Cloud Build → Triggers → Manage repositories en Cloud Console.
  2. Conectar la cuenta GitHub y autorizar el repositorio devops-repo.
  3. Recién después ejecutar terraform apply.

Sin este paso, el trigger falla con un error de permisos sobre el repositorio GitHub.

Uso

terraform init

terraform apply \
  -var="project_id=<PROJECT_ID>" \
  -var="github_owner=<GITHUB_USERNAME>"

cloudbuild.yaml esperado en el repositorio

El repositorio GitHub debe contener un cloudbuild.yaml en la raíz:

steps:
  - name: 'gcr.io/cloud-builders/docker'
    args: ['build', '-t', 'REGION-docker.pkg.dev/PROJECT_ID/devops-repo/devops-image:$COMMIT_SHA', '.']
images:
  - 'REGION-docker.pkg.dev/PROJECT_ID/devops-repo/devops-image:$COMMIT_SHA'
options:
  logging: CLOUD_LOGGING_ONLY

Probar el pipeline

# En el repositorio GitHub clonado localmente:
git commit -a -m "Testing Build Trigger"
git push origin main

# Verificar que se disparó el build:
gcloud builds list --region=$REGION --limit=5

# Ver la imagen publicada:
gcloud artifacts docker images list \
  $(terraform output -raw artifact_registry_url)

Variables requeridas

VariableDescripción
project_idID del proyecto GCP
github_ownerUsuario u organización dueña del repo GitHub

Link al lab

Recursos identificados

  • APIs: cloudbuild.googleapis.com, artifactregistry.googleapis.com.
  • Artifact Registry: repositorio devops-repo (formato Docker, regional).
  • Cloud Build trigger: devops-trigger — se dispara en cada push a main del repositorio GitHub.
  • Cloud Build config: cloudbuild.yaml que construye y pushea la imagen con tag $COMMIT_SHA.
  • GitHub repository: devops-repo (privado) — fuente del código del pipeline.
  • Imagen Docker: $REGION-docker.pkg.dev/$PROJECT_ID/devops-repo/devops-image:$COMMIT_SHA.
  • Compute Engine VMs: dos instancias de prueba creadas manualmente para validar el deploy.

Comandos ejecutados

Instalar GitHub CLI

curl -sS https://webi.sh/gh | sh

Autenticarse con GitHub

gh auth login

Obtener username de GitHub y configurar git

GITHUB_USERNAME=$(gh api user -q ".login")
echo ${GITHUB_USERNAME}

git config --global user.name "${GITHUB_USERNAME}"
git config --global user.email "<YOUR_EMAIL>"

Crear repositorio privado en GitHub y clonarlo

gh repo create devops-repo --private
gh repo clone devops-repo
cd devops-repo

Crear repositorio Docker en Artifact Registry

gcloud artifacts repositories create devops-repo \
  --repository-format=docker \
  --location=$REGION

Configurar autenticación Docker para Artifact Registry

gcloud auth configure-docker $REGION-docker.pkg.dev

Agregar archivos de la aplicación Python (main.py, requirements.txt, Dockerfile, cloudbuild.yaml)

Se crean manualmente en el directorio clonado. El Dockerfile usa Python 3.13 con gunicorn:

FROM python:3.13
WORKDIR /app
COPY . .
RUN pip install gunicorn
RUN pip install -r requirements.txt
ENV PORT=80
CMD exec gunicorn --bind :$PORT --workers 1 --threads 8 main:app

El cloudbuild.yaml construye y pushea la imagen usando $COMMIT_SHA como tag:

steps:
  - name: 'gcr.io/cloud-builders/docker'
    args: ['build', '-t', '$REGION-docker.pkg.dev/$PROJECT_ID/devops-repo/devops-image:$COMMIT_SHA', '.']
images:
  - '$REGION-docker.pkg.dev/$PROJECT_ID/devops-repo/devops-image:$COMMIT_SHA'
options:
  logging: CLOUD_LOGGING_ONLY

Primer commit y push

git add --all
git commit -a -m "Initial Commit"
git push origin main

Build manual inicial (antes del trigger)

gcloud builds submit \
  --tag $REGION-docker.pkg.dev/$DEVSHELL_PROJECT_ID/devops-repo/devops-image:v0.1 .

Commit con el Dockerfile (agrega soporte Docker)

git add Dockerfile
git commit -m "Added Docker Support"
git push origin main

Crear el build trigger (devops-trigger) desde Cloud Console

El trigger conecta el repositorio GitHub con Cloud Build usando cloudbuild.yaml. Se configura en: Cloud Build → Triggers → Create Trigger → GitHub (App).

Probar que el trigger funciona

git commit -a -m "Testing Build Trigger"
git push origin main

BigQuery

Prácticas Terraform sobre BigQuery: carga de datos, consultas y gestión de datasets.

Prácticas disponibles

PrácticaDescripción
Loading Data into BigQueryCrea dataset, tabla externa desde GCS y vista filtrada

Uso rápido

cd loading-data
terraform init
terraform apply -var="project_id=<TU_PROYECTO>"

Loading Data into BigQuery

Práctica Terraform basada en el lab Loading data into BigQuery.

Crea el dataset nyctaxi, una tabla externa apuntando a datos de NYC Taxi en GCS, y una vista de viajes de enero.

Recursos creados

RecursoTipoDescripción
nyctaxigoogle_bigquery_datasetDataset principal
2018tripsgoogle_bigquery_table (external)Tabla externa sobre CSV en GCS
january_tripsgoogle_bigquery_table (view)Vista filtrada por mes de enero

Uso

terraform init
terraform plan -var="project_id=<TU_PROYECTO>"
terraform apply -var="project_id=<TU_PROYECTO>"

Variables principales

VariableDefaultDescripción
project_idID del proyecto GCP (obligatoria)
regionUSUbicación del dataset
dataset_idnyctaxiID del dataset
gcs_source_uriURI del CSV de NYC Taxi en GCSFuente de datos para la tabla externa

Nota: el lab original carga los datos vía bq load y UI. Esta práctica modela el estado final con tabla externa (sin necesidad de copiar datos al proyecto) y una vista equivalente a january_trips.

Link al lab

Recursos identificados

  • Servicio principal: BigQuery.
  • Dataset: nyctaxi (región por defecto del proyecto).
  • Tablas:
    • 2018trips — cargada desde CSV local y luego desde Cloud Storage.
    • january_trips — creada con DDL (CREATE TABLE ... AS SELECT).
  • Fuentes de datos:
    • CSV local descargado al entorno del lab.
    • GCS: gs://cloud-training/OCBL013/nyc_tlc_yellow_trips_2018_subset_2.csv.
  • APIs habilitadas: BigQuery API.
  • IAM: usa credenciales del proyecto de lab (sin service account explícita).

Comandos ejecutados

Crear dataset desde consola

Se crea el dataset nyctaxi con configuración predeterminada desde BigQuery Studio.

Crear tabla desde CSV local (consola)

Se descarga nyc_tlc_yellow_trips_2018_subset_1.csv y se carga con Auto Detect de esquema.

Consultar los viajes más caros

SELECT * FROM nyctaxi.2018trips ORDER BY fare_amount DESC LIMIT 5

Cargar segunda parte del dataset desde Cloud Storage

bq load \
  --source_format=CSV \
  --autodetect \
  --noreplace \
  nyctaxi.2018trips \
  gs://cloud-training/OCBL013/nyc_tlc_yellow_trips_2018_subset_2.csv

Crear tabla de enero con DDL

CREATE TABLE nyctaxi.january_trips AS
SELECT * FROM nyctaxi.2018trips
WHERE EXTRACT(Month FROM pickup_datetime) = 1;

Consultar el viaje más largo de enero

SELECT * FROM nyctaxi.january_trips
ORDER BY trip_distance DESC LIMIT 1

Vertex AI

Prácticas Terraform sobre Vertex AI: habilitación de APIs, service accounts y configuración de infraestructura base para labs de IA generativa.

Prácticas disponibles

PrácticaDescripción
Get Started with Vertex AI StudioAPIs + SA para labs de prompt design, multimodal y Cloud Run deploy

Uso rápido

cd get-started-with-studio
terraform init
terraform apply -var="project_id=<TU_PROYECTO>"

Get Started with Vertex AI Studio

Práctica Terraform basada en el lab Get Started with Vertex AI Studio (GSP1154).

El lab es UI-driven: se trabaja en la consola de Vertex AI Studio para diseñar prompts, deployar una app con Cloud Run y explorar capacidades multimodales con Gemini. Esta práctica Terraform modela el estado de infraestructura previo al lab: APIs habilitadas y service account listo.

Recursos creados

RecursoTipoDescripción
aiplatform.googleapis.comAPIVertex AI API
cloudbuild.googleapis.comAPICloud Build API
run.googleapis.comAPICloud Run API
texttospeech.googleapis.comAPI (opcional)Cloud Text-to-Speech API
insurance-risk-summary-sagoogle_service_accountSA para el servicio Cloud Run
IAM bindingroles/aiplatform.userPermiso de SA para invocar Vertex AI

Uso

terraform init
terraform plan -var="project_id=<TU_PROYECTO>"
terraform apply -var="project_id=<TU_PROYECTO>"

Para habilitar también la Text-to-Speech API (tarea 5 opcional):

terraform apply -var="project_id=<TU_PROYECTO>" -var="enable_tts_api=true"

Variables principales

VariableDefaultDescripción
project_idID del proyecto GCP (obligatoria)
regionus-central1Región de Cloud Run
cloud_run_service_nameinsurance-risk-summaryNombre del servicio Cloud Run
allow_unauthenticatedtrueAcceso público al servicio (igual que el deploy desde Studio)
enable_tts_apifalseHabilitar Text-to-Speech API (tarea 5 opcional)

Flujo del lab (resumen)

  1. Tarea 1: Crear prompt de chat → deployar como app Cloud Run.
  2. Tarea 2: Zero-shot y few-shot prompting; ajustar temperatura, tokens, Top-P.
  3. Tarea 3: Comparar variaciones de prompts con la feature Compare.
  4. Tarea 4: Analizar imagen (timetable.png) desde Cloud Storage con Gemini multimodal.
  5. Tarea 5: Generar imagen con Imagen 4; síntesis de voz con Chirp 3 (opcional).

Link al lab

Recursos identificados

  • Servicio principal: Vertex AI Studio (parte de Agent Platform).
  • Modelos usados:
    • gemini-2.5-flash (tareas 1, 2, 3, 4)
    • Gemini 2.5 Pro (comparación en tarea 3)
    • Imagen 4 (generación de imágenes, tarea 5)
    • Chirp 3 HD Voices (síntesis de voz, tarea 5 — opcional)
  • APIs habilitadas:
    • Vertex AI API
    • Cloud Build API
    • Cloud Run API
    • Cloud Text-to-Speech API (opcional)
  • Recursos creados:
    • 5 prompts guardados en Vertex AI Studio
    • 1 aplicación Cloud Run deployada desde la consola
  • IAM: roles implícitos del proyecto de lab; Cloud Run con acceso no autenticado.

Este lab es UI-driven: todos los pasos se hacen desde la consola de Google Cloud. No hay comandos gcloud en el flujo principal.


Tarea 1: Crear una aplicación desde un prompt

El objetivo es construir un prototipo de chat para análisis de riesgo de seguros y deployarlo como una app real en Cloud Run, todo desde la UI.

Pasos:

  1. Desde la consola, ir a Agent Platform > Studio (o búscarlo como "Vertex AI Studio").
  2. Hacer clic en New prompt y elegir tipo Chat.
  3. Nombrar el prompt: Insurance Risk Summary - Prototype.
  4. En el campo System instructions, escribir algo como:

    "You are an expert insurance underwriter. Analyze facility risk based on the information provided and produce a concise risk summary."

  5. En el área de chat, pegar el siguiente escenario de cliente:

    "SafeHarbor Warehousing — Facility stores flammable chemicals, located in a flood zone, last inspection 3 years ago."

  6. Seleccionar modelo: gemini-2.5-flash, región: Global.
  7. Hacer clic en Submit y revisar la respuesta del modelo.
  8. Guardar el prompt con Save.
  9. Ir a Code > Deploy > Deploy as app para deployarlo en Cloud Run.
    • Cuando la consola lo pida, habilitar Cloud Build API y Cloud Run API.
    • Esperar a que el deploy finalice (puede tardar 2-3 minutos).
  10. Abrir la URL de la app deployada y probarla con una nueva consulta distinta al escenario original.

Qué se aprende: el ciclo completo prompt → prototipo → aplicación productiva, sin escribir una sola línea de código.


Tarea 2: Diseñar prompts efectivos

El objetivo es entender cómo cambia la respuesta del modelo según la técnica de prompting y los parámetros configurados.

Zero-shot prompting:

  1. Crear un nuevo prompt tipo Chat: Insurance Claim Data Extraction.
  2. En System instructions: definir el rol como extractor de datos estructurados de notificaciones de siniestros.
  3. En el chat, pegar una notificación de siniestro en texto libre (ejemplo: un incidente de daño por agua con fecha, descripción y monto estimado).
  4. Configurar Temperature: 0.1 y Output Token Limit: 1024.
  5. Enviar y observar qué extrae el modelo sin ejemplos.

Few-shot prompting:

  1. Sin cambiar el prompt anterior, agregar un bloque de ejemplo antes del caso real:
    • Input de ejemplo: otra notificación de siniestro.
    • Output de ejemplo: la extracción correctamente formateada.
  2. Volver a enviar la consulta original y comparar la mejora en estructura y precisión.

Experimentos con parámetros:

  1. Ajustar Temperature a 1.5 y reenviar: notar respuestas más creativas/impredecibles.
  2. Cambiar Output Token Limit a 500: la respuesta se corta; con 65535 no se corta.
  3. Modificar Top-P entre 0.8 y 1.0: controla qué tan diverso es el vocabulario usado.
  4. Explorar (sin modificar) los paneles de: Safety Filters, Thinking Budget, Structured Output y Grounding.

Qué se aprende: por qué few-shot supera a zero-shot en tareas estructuradas, y cómo temperatura/Top-P/tokens afectan el output de maneras concretas y distintas.


Tarea 3: Gestión y comparación de prompts

El objetivo es usar la feature Compare de Vertex AI Studio para evaluar variantes de un mismo prompt en paralelo.

Pasos:

  1. Crear nuevo prompt: Insurance Risk Factor Identification.
  2. System instructions: rol de analista de riesgos que identifica factores de riesgo en un negocio.
  3. Ingresar como input la descripción de un restaurante (ejemplo: local en zona comercial densa, cocina a gas, sin rociadores).
  4. Configurar gemini-2.5-flash, temperatura 0.2.
  5. Enviar y guardar.
  6. Hacer clic en Compare para abrir el panel de comparación lado a lado.
  7. Probar estas tres variaciones:
    • Variación A: agregar a las instrucciones que el modelo también debe sugerir estrategias de mitigación por cada riesgo.
    • Variación B: temperatura 0.2 (original) vs temperatura 2.0 (muy alta): observar la diferencia en coherencia.
    • Variación C: gemini-2.5-flash vs Gemini 2.5 Pro: comparar profundidad y razonamiento en el análisis.

Qué se aprende: cómo iterar sobre prompts de forma sistemática en lugar de hacerlo de a uno; la diferencia práctica entre modelos de distinta capacidad.


Tarea 4: Prompts multimodales con Gemini

El objetivo es usar Gemini para analizar una imagen y responder preguntas de razonamiento sobre su contenido.

Pasos:

  1. Crear nuevo prompt: Timetable Image Analysis.
  2. En el área de contenido, hacer clic en Insert > Image from Cloud Storage.
  3. Importar timetable.png (imagen de un horario de vuelos, provista por el lab en un bucket público).
  4. Configurar gemini-2.5-flash, región Global.
  5. Junto a la imagen, escribir el prompt:

    "Provide a title for this image, a short description, and extract all visible text."

  6. Enviar y revisar: el modelo describe la imagen y transcribe el texto del horario.
  7. Enviar un segundo prompt de razonamiento:

    "What percentage of departures listed are international flights?" El modelo razona sobre los datos que acaba de extraer.

  8. Cambiar temperatura a 0.8 y reenviar el segundo prompt: notar variación en el estilo de respuesta.
  9. Volver a temperatura 0.2 para respuestas más determinísticas.

Qué se aprende: Gemini puede interpretar imágenes y razonar sobre ellas en el mismo contexto conversacional, sin preprocesamiento externo.


Tarea 5: Generación de media

Imágenes con Imagen 4

  1. En Vertex AI Studio, hacer clic en New > Image.
  2. Escribir un prompt descriptivo. Ejemplo:

    "A photorealistic macro photograph of a honeybee collecting nectar from lavender flowers, golden hour lighting."

  3. Seleccionar modelo: Imagen 4.
  4. Configurar: aspect ratio 1:1, cantidad de resultados: 4.
  5. Hacer clic en Generate y revisar los cuatro resultados.
  6. Seleccionar una imagen y explorar las opciones Inpaint (modificar una región de la imagen) y Outpaint (expandir el encuadre).
  7. Notar el badge de SynthID: marca de agua digital que identifica imágenes generadas por IA.

Voz con Chirp 3 (opcional)

  1. Si no está habilitada, activar Cloud Text-to-Speech API desde el panel de configuración.
  2. Hacer clic en el ícono de audio para abrir la herramienta de síntesis de voz.
  3. Ingresar el texto:

    "Welcome to the world of generative AI on Google Cloud."

  4. Seleccionar modelo: Chirp 3 HD Voices, idioma: inglés (US).
  5. Elegir una variante de voz y hacer clic en Generate.
  6. Escuchar el audio generado.

Qué se aprende: Vertex AI Studio no es solo texto — agrupa en un mismo lugar generación de imágenes (Imagen 4), voz (Chirp) y texto (Gemini), todos accesibles sin código.