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:
- Clases: conceptos base y decisiones de arquitectura.
- Labs: ejercicios guiados para practicar en Google Cloud.
- 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.

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
- Puedo tener el depto. de contabilidad, de ingeniería, cada uno con sus carpetas o folders
- 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

- 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

- 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
- Familia de las N: relación precio-performance bastante alta
Preguntas
- Diferencias entre N2 y N4, y para qué elegimos c/u
- 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
- Cambia la arquitectura del procesador
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)
- Ejemplos de attachables:
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.

- 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 repairsbasados 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
rolloutsde 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
- 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
- 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: unmain.pyy unrequirements.txten ) - 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

- Region no te cobra el
outbound data transferporque 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
- Justamente por esto es que tanto acá como en dual-region te cobran por
- 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 FROMerró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.
- 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
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.
- Por default tiene configuraciones muy laxas:
- 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 deorigen/destinosegún la dirección, y la combinación deprotocolo: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) yLeast 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
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

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)

La parte del who en IAM es el member.
- Un
memberpuede 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

- 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?

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
- por ejemplo
- Un rol es un paquete de permisos
- El rol responde qué puedo hacer
- El recurso responde dónde lo puedo hacer
- Ejemplo:
roles/compute.instanceAdminagrupa 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

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

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
bindingdice algo como:- a estos
members - dales este
role
- a estos
- 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

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
allowque 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 Accounty 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.

- 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
Links útiles
- Jerarquía de recursos en Google Cloud
- Visión general de IAM
- Service Accounts
- Roles de IAM
- IAM Policies
- Organization Policy
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
-outpara 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
providerconfigura 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í:

- 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()
- si no existe en el state ⇒
- 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_typede 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.
- Ej: si tengo 2 VMs creadas y declaradas en mi
La desviación entre el estado de Terraform con el estado real se conoce como
drift
State local vs remoto
- Local:
terraform.tfstateen 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
applycorriendo al mismo tiempo.
Buenas prácticas
- Nunca apliquen un plan sin revisarlo antes.
- El
planes la herramienta de seguridad principal de Terraform. - Mirar especialmente los
-(destroy) y los-/+(replace).
- El
- Versionar los
.tfen 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.
Links útiles
- Terraform: introducción oficial
- Google Cloud Provider para Terraform
- Comandos de Terraform CLI
- State de Terraform
- Backends remotos
- AWS CloudFormation
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:
- 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.
- Metric Storage: todo se guarda en Cloud Monitoring Storage y se accede vía API.
- 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:
- Ingesta: servicios de GCP y agentes envían logs.
- Router de Logs: filtra, enruta y excluye registros. Acá podés decidir qué logs guardás, adónde van y cuáles descartás.
- Buckets: almacenamiento en
_Defaulto_Required(o buckets propios). - 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
/metricscon 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
/metricscon 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.
| Disponibilidad | Downtime / Año | Downtime / Mes | Downtime / Semana | Downtime / Día |
|---|---|---|---|---|
| 99.999% | 5.256 min | 0.438 min | 0.101 min | 0.014 min |
| 99.990% | 52.56 min | 4.38 min | 1.011 min | 0.144 min |
| 99.900% | 8.76 hs | 43.8 min | 10.108 min | 1.44 min |
| 99.500% | 43.8 hs | 3.65 hs | 50.538 min | 7.2 min |
| 99.000% | 87.6 hs | 7.3 hs | 101.077 min | 14.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étodo | Automatizable | Cuándo usarlo |
|---|---|---|
| Console (CSV upload) | No | Exploración rápida, datasets chicos |
CLI bq load desde GCS | Sí | Pipelines batch repetibles |
DDL CREATE TABLE AS SELECT | Sí | Derivar 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:
| Flash | Pro | |
|---|---|---|
| Latencia | ~0.5s | ~2–5s |
| Costo | ~1.25 / 1M tokens (25x más caro) | |
| Razonamiento | Bueno | Significativamente 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
gcelab2y es de tipoe2-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-shopcon 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): funcionesupload_blob/download_blob. No es Terraform.
- Ejemplo del SDK de Cloud Storage en Python (
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
defaulty 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
- Entrá a la carpeta del ejemplo que quieras.
- Inicializá Terraform con
terraform init. - Definí variables (por ejemplo en
terraform.tfvars). - Revisá cambios con
terraform plan. - Aplicá con
terraform apply.
Recomendaciones
- No hardcodear
project_id, región o nombres sensibles: usá variables. - Usar
terraform fmty, si podés,terraform validateantes 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áctica | Descripción |
|---|---|
| Cloud Run Functions Qwik Start | Función HTTP serverless básica con Cloud Run Functions |
| Cloud Pub/Sub with Cloud Run | Integración event-driven entre Pub/Sub y dos servicios Cloud Run |
| PDF Converter con Cloud Run | Pipeline 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-functionnodejs-storage-functiongce-vm-labelerhello-world-coloredslow-functionslow-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
- Inicializá:
terraform init
- 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"
}
- Plan y apply:
terraform plan
terraform apply
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.publisherpara la Cloud Storage service account.roles/eventarc.eventReceiverpara 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
- Inicializá:
terraform init
- Creá
terraform.tfvars:
project_id = "tu-project-id"
region = "us-central1"
- 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
Recursos identificados
- APIs:
run.googleapis.com(y uso depubsub.googleapis.comen operaciones de Pub/Sub). - Cloud Run services:
store-service(público),order-service(privado). - Pub/Sub: topic
ORDER_PLACED, subscription pushorder-service-sub. - IAM service account:
pubsub-cloud-run-invoker. - IAM bindings:
roles/run.invokersobreorder-servicepara la service account invocadora.roles/iam.serviceAccountTokenCreatorpara 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
| Variable | Descripción |
|---|---|
project_id | ID del proyecto GCP |
lab_report_service_image | URI de imagen del productor |
email_service_image | URI de imagen del consumidor email |
sms_service_image | URI de imagen del consumidor SMS |
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 aemail-service.sms-service-sub→ push autenticado asms-service.
- IAM service account:
pubsub-cloud-run-invoker. - IAM bindings:
roles/run.invokersobreemail-serviceparapubsub-cloud-run-invoker.roles/run.invokersobresms-serviceparapubsub-cloud-run-invoker.roles/iam.serviceAccountTokenCreatorpara 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
| Variable | Descripción |
|---|---|
project_id | ID del proyecto GCP |
rest_api_image | URI de la imagen construida con Cloud Build |
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, subdirectoriolab08. - 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 esDeleplace/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
| Variable | Descripción |
|---|---|
project_id | ID del proyecto GCP |
pdf_converter_image | URI 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.
Recursos identificados
- APIs:
run.googleapis.com,cloudbuild.googleapis.com,storage-component.googleapis.com. - Cloud Run service:
pdf-converter(privado, 2Gi RAM, variable de entornoPDF_BUCKET). - Cloud Storage:
- bucket
$PROJECT_ID-upload— recibe archivos subidos, dispara notificaciones Pub/Sub. - bucket
$PROJECT_ID-processed— destino de los PDFs convertidos.
- bucket
- Pub/Sub topic:
new-doc(creado via notificación de GCS). - Pub/Sub subscription push:
pdf-conv-sub→pdf-converter. - IAM service account:
pubsub-cloud-run-invoker. - IAM bindings:
roles/run.invokersobrepdf-converterparapubsub-cloud-run-invoker.roles/iam.serviceAccountTokenCreatorpara el service agent de Pub/Sub del proyecto.
- Código fuente: repositorio
Deleplace/pet-theory, subdirectoriolab03. 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 enOBJECT_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, variablePDF_BUCKET). - Service account
pubsub-cloud-run-invoker+ bindings IAM. - Suscripcion push
pdf-conv-subcon 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
- Inicializá:
terraform init
- Creá
terraform.tfvars:
project_id = "tu-project-id"
region = "us-central1"
pdf_converter_image = "gcr.io/tu-project-id/pdf-converter"
- 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
Recursos identificados
- APIs:
run.googleapis.com,pubsub.googleapis.com,cloudbuild.googleapis.com,storage.googleapis.com. - Cloud Run service:
pdf-converter(privado, con variable de entornoPDF_BUCKET). - Artifact Registry: imagen
gcr.io/$GOOGLE_CLOUD_PROJECT/pdf-converterconstruida 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 pushpdf-conv-sub. - IAM service account:
pubsub-cloud-run-invoker. - IAM bindings:
roles/run.invokersobrepdf-converterpara la service account invocadora.roles/iam.serviceAccountTokenCreatorpara la Pub/Sub service agent del proyecto.
- Notificacion de Cloud Storage sobre evento
OBJECT_FINALIZE→ Pub/Sub topicnew-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áctica | Descripción |
|---|---|
| Crear una VM | Instancia 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
defaultconaccess_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 destroyal 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-1mynet-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
- SSH desde una IP/CIDR puntual hacia instancias taggeadas con
Uso rápido
- Inicializá:
terraform init
- 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"
- Plan y apply:
terraform plan
terraform apply
Notas
- Para replicar el comportamiento del lab, usá en
ssh_source_cidrla 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
defaulty su eliminación quedan fuera de Terraform a propósito.
Recursos identificados
- APIs habilitadas:
compute.googleapis.com. - Red principal: VPC auto mode
mynetwork, con subnetworks automáticas por región dentro del rango10.128.0.0/9. - Instancias usadas en el lab:
default-vm-1,mynet-vm-1ymynet-vm-2. - Firewall rules observadas o creadas: reglas
default-allow-*de la reddefault,mynetwork-ingress-allow-ssh-from-cs,mynetwork-ingress-allow-icmp-internal,mynetwork-ingress-deny-icmp-allymynetwork-egress-deny-icmp-all. - Etiquetas relevantes:
lab-sshpara 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,
curlaapi.ipify.orgpara 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:bluecon tagweb-servergreensin tag
- Instalación automática de
nginx-lighty página diferenciada en cada servidor. - Firewall rule
allow-http-web-serverpara exponertcp:80eicmpsolo a instancias con el tagweb-server. - VM
test-vmpara validar conectividad. - Service account
network-adminadjunta atest-vm, con:roles/compute.networkAdminroles/compute.securityAdminopcional según variable
Uso rápido
- Inicializá:
terraform init
- 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
- Plan y apply:
terraform plan
terraform apply
Notas
- Este ejemplo asume que existe la red
defaulty que conserva la regladefault-allow-internal, igual que en el lab original. - Para reproducir la progresión del lab, podés aplicar primero con
grant_security_admin = falsey verificar que desdetest-vmse pueden listar firewall rules pero no borrarlas; después cambiás atruey 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.
Recursos identificados
- APIs habilitadas o implícitas:
compute.googleapis.com,iam.googleapis.com. - Red usada por el lab: VPC
default. - Instancias principales:
blue,greenytest-vm. - Firewall rules relevantes:
default-allow-internal,allow-http-web-server. - Tags relevantes:
web-serveraplicado ablue. - IAM relevante: service account
Network-admin, rolCompute Network Admin, luegoCompute Security Admin. - Integraciones: acceso por SSH a VMs,
curlpara validar HTTP interno/externo y activación de credenciales de service account con archivocredentials.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:
managementnetcomo custom modeprivatenetcomo custom modemynetworkcomo auto mode
- Subredes:
managementsubnet-1privatesubnet-1privatesubnet-2- subredes automáticas de
mynetworkenregion_1yregion_2
- Firewall rules para permitir
icmp,tcp:22ytcp:3389en las tres redes necesarias. - VMs simples:
managementnet-vm-1privatenet-vm-1mynet-vm-1mynet-vm-2
- VM
vm-appliancecon 3 interfaces:privatesubnet-1managementsubnet-1- subred automática de
mynetworkenregion_1
Uso rápido
- Inicializá:
terraform init
- 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"
- Plan y apply:
terraform plan
terraform apply
Notas
- El lab original asume que
mynetwork,mynet-vm-1ymynet-vm-2ya existen. En este ejemplo se crean también para que la práctica sea autocontenida. - La
vm-applianceinstalanet-toolspara que puedas correrifconfigcomo en el lab. - La conectividad esperada replica la idea central del ejercicio:
vm-appliancellega a subredes directamente conectadas, pero no necesariamente a otras subredes remotas demynetworksin policy routing adicional.
Recursos identificados
- APIs habilitadas o implícitas:
compute.googleapis.com. - Redes principales:
managementnetyprivatenetcomo custom mode;mynetworkya preexistente en el lab. - Subredes creadas o usadas:
managementsubnet-1enmanagementnetcon10.130.0.0/20privatesubnet-1enprivatenetcon172.16.0.0/24privatesubnet-2enprivatenetcon172.20.0.0/20- subredes automáticas de
mynetworken las regiones del lab
- Firewall rules relevantes:
managementnet-allow-icmp-ssh-rdpprivatenet-allow-icmp-ssh-rdp- reglas preexistentes en
mynetwork
- Instancias creadas o usadas:
managementnet-vm-1privatenet-vm-1mynet-vm-1mynet-vm-2vm-appliancecon 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
| Recurso | Nombre |
|---|---|
| VPC custom | vpc-net |
| Subred con Flow Logs | vpc-subnet (10.1.3.0/24) |
| Firewall | allow-http-ssh (tcp:22,80) |
| VM | web-server (e2-micro, Apache) |
| BigQuery dataset | bq_vpcflows |
| Log sink | vpc-flows → BigQuery |
Uso rápido
terraform init
terraform apply \
-var="project_id=TU_PROJECT_ID"
Variables requeridas
| Variable | Descripción |
|---|---|
project_id | ID 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 recursogoogle_bigquery_dataset_iam_memberle otorga automáticamenteroles/bigquery.dataEditor. - No se puede validar runtime real sin un proyecto activo con billing habilitado.
Recursos identificados
- APIs habilitadas:
compute.googleapis.com,logging.googleapis.com,bigquery.googleapis.com. - Red: VPC custom mode
vpc-net, subredvpc-subnet(10.1.3.0/24) con VPC Flow Logs habilitados (intervalo 5 s, sampling 50%, metadata completa). - Instancia:
web-server(e2-micro, Debian, taghttp-server) envpc-subnet. - Firewall:
allow-http-ssh— permite tcp:22 y tcp:80 desde0.0.0.0/0a VMs con taghttp-server. - Log sink:
vpc-flowsexporta logscompute.googleapis.com/vpc_flowsa BigQuery. - BigQuery dataset:
bq_vpcflows— recibe los registros de flujo para análisis SQL. - IAM: la service account writer del sink recibe
roles/bigquery.dataEditorsobre 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.comiap.googleapis.com
- Red:
- VPC
acme-vpc(custom mode). - Subred
acme-mgmt-subnetpara administración. - Subred
acme-web-subnetparajuice-shop.
- VPC
- Firewall:
allow-ssh-iap-ingress: permite SSH solo desde rango IAP (35.235.240.0/20) haciabastion.allow-http-ingress: permite HTTP (tcp:80) desde Internet ajuice-shop.allow-ssh-internal-ingress: permite SSH interno desde la subnet de management haciajuice-shop.
- Compute Engine:
- VM
bastionsin public IP (acceso por IAP). - VM
juice-shopcon public IP ynginxcomo placeholder de workload HTTP.
- VM
Uso rápido
- Inicializá:
terraform init
- Definí variables en
terraform.tfvars:
project_id = "tu-project-id"
region = "us-central1"
zone = "us-central1-b"
- 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.
- Red
- IAM:
- Uso de permisos para administrar firewall/tagging en Compute Engine.
- Acceso operativo vía IAP (normalmente con rol como
roles/iap.tunnelResourceAccessorpara usuarios operadores).
- Integraciones:
- IAP TCP forwarding -> SSH a
bastion. bastion-> SSH interno ajuice-shop.- Exposición HTTP de
juice-shopmediante regla ingress acotada atcp:80.
- IAP TCP forwarding -> SSH a
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áctica | Descripción |
|---|---|
| Network Load Balancer | Balanceador de capa 4 (TCP) con target pool, health check y forwarding rule |
| Application Load Balancer con Autoscaling | Balanceador 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 confor_eacha partir deinstance_names. - Regla de firewall que permite el puerto HTTP sobre el tag de red de las instancias.
google_compute_http_health_checkpara chequear la salud de las VMs.google_compute_target_poolque agrupa las instancias y usa el health check.google_compute_addressregional (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 destroyal terminar para evitar costos.
Set Up a NLB (Network Load Balancer)
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-central1y otro eneurope-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
- Inicializá:
terraform init
- Definí variables en
terraform.tfvars:
project_id = "tu-project-id"
default_region = "us-central1"
network_name = "default"
- 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_imagepor tu imagen custom.
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.
- regla de firewall para health checks (
- 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.
- VM base
- Health checks y balanceo:
- health check
http-health-check. - Application Load Balancer HTTP global (IPv4/IPv6) con backend services sobre MIG.
- health check
- Testing:
- verificación de disponibilidad con
curl. - stress test con
ab(ApacheBench) desde VMstress-test.
- verificación de disponibilidad con
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áctica | Descripción |
|---|---|
| Cloud Storage | Buckets con versioning, lifecycle y objetos de muestra |
| Cloud SQL | Instancia Cloud SQL con peering privado y VMs de demo |
| SDK Cloud Storage en Python | Ejemplo 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
- Inicializá:
terraform init
- 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
- 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.
Recursos identificados
- Servicio principal:
Cloud Storage. - Recursos de storage:
- bucket principal (
BUCKET_NAME_1). - objetos (
setup.html,setup2.html,setup3.htmly versiones).
- bucket principal (
- Seguridad y acceso:
- ACLs de objeto (
private,AllUsers:R). - CSEK (Customer-supplied encryption keys) vía
.boto. - rotación de claves CSEK.
- ACLs de objeto (
- Gobierno del dato:
- lifecycle policy (delete por edad).
- versioning de bucket.
- Operaciones de datos:
- sincronización recursiva con
gsutil rsync.
- sincronización recursiva con
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-proxywordpress-private-ip
- Firewall para exponer HTTP en las VMs de demo.
Uso rápido
- Inicializá:
terraform init
- 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"
- 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.
Recursos identificados
- Servicio principal:
Cloud SQL(instancia MySQLwordpress-db). - Red y conectividad:
- conexión por proxy (
cloud_sql_proxy) sobre127.0.0.1:3306. - conexión por
Private IP(internal IP de Cloud SQL).
- conexión por proxy (
- Compute Engine:
- VM
wordpress-proxy. - VM
wordpress-private-ip.
- VM
- Base de datos:
- DB
wordpress.
- DB
- 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— funcionesupload_blobydownload_blobque suben y descargan objetos de un bucket usandostorage.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_blobusaif_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
devopscon los permisos de Compute Engine usados en el lab. - Bindings IAM para
user2:roles/viewerroles/iam.serviceAccountUserprojects/<project>/roles/devops
- Service account
devops. - Bindings IAM para la service account:
roles/iam.serviceAccountUserroles/compute.instanceAdmin
- VM
lab-3con la service account adjunta.
Uso rapido
- Inicializa Terraform:
terraform init
- 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"
- 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 initni el cambio entre configuraciones locales (defaultyuser2), porque Terraform trabaja contra una identidad ya autenticada. - La VM usa el scope
cloud-platformpor 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.
Recursos identificados
- Contexto del lab:
- 2 proyectos temporales (
PROJECTID1,PROJECTID2). - 2 identidades humanas (
Username1,Username2). - 2 configuraciones locales de
gcloud:defaultyuser2.
- 2 proyectos temporales (
- APIs/servicios principales:
Compute EngineIdentity 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
- VM existente
- Recursos IAM en el segundo proyecto:
- binding
roles/viewerparaUsername2 - rol custom
projects/$PROJECTID2/roles/devops - binding
roles/iam.serviceAccountUserparaUsername2
- binding
- Recursos de service account:
- service account
devops - binding
roles/iam.serviceAccountUserpara la service account - binding
roles/compute.instanceAdminpara la service account - VM
lab-3con la service account adjunta
- service account
- Archivos/config local usados durante la práctica:
~/.config/gcloud/configurations/config_default~/.bashrcpara exportarPROJECTID2,USERID2ySA
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.objectViewersobre el bucket para un principal externo. - Service account
read-bucket-objects. - Roles sobre el bucket para el service account de la VM:
roles/storage.objectViewerroles/storage.objectCreator
- Grant opcional de
roles/iam.serviceAccountUsersobre el service account. - Grant opcional de
roles/compute.instanceAdmin.v1a nivel proyecto. - VM
demoiamcon imagen Debian 12 y scope de Storage read/write.
Uso rapido
- Inicializa:
terraform init
- 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"
- Revisa cambios y aplica:
terraform plan
terraform apply
Notas
- El lab original concede
Storage Object Viewerdesde 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 quegcloud compute instances listno queda habilitado como en el lab. - Se asume que ya existe una red/subred accesible para la VM. Los defaults
default/defaultsuelen calzar con el escenario del lab; si tu proyecto no las tiene, ajustanetwork_nameysubnetwork_name.
Recursos identificados
- APIs/servicios involucrados:
IAM,Cloud Storage,Compute Engine,Service Accounts. - Principales identidades:
Username 1con permisos de administración del proyecto.Username 2con acceso inicial de lectura al proyecto y luego acceso acotado a Cloud Storage.- principal externo
altostrat.comusado para practicar grants deService Account UseryCompute Instance Admin (v1).
- Almacenamiento:
- bucket de Cloud Storage multi-region con un objeto de prueba
sample.txt.
- bucket de Cloud Storage multi-region con un objeto de prueba
- IAM:
- remoción del acceso de proyecto para
Username 2. - grant de
Storage Object Viewerpara validar acceso restringido. - service account
read-bucket-objects. - cambio de permisos del service account desde
Storage Object VieweraStorage Object Creator.
- remoción del acceso de proyecto para
- Cómputo:
- VM
demoiamen Compute Engine. - imagen
Debian GNU/Linux 12 (bookworm). - machine type
e2-micro. - service account
read-bucket-objectsadjunta a la VM con scope de Storage.
- VM
- 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]
Recursos identificados
- APIs/servicios involucrados:
IAM,Cloud Storage,Compute Engine,Service Accounts,Cloud Shell. - Principales IAM del ejercicio:
Username 1como administrador del proyecto temporal del lab.Username 2, que pasa de tenerViewera no tener acceso al proyecto y luego recibe acceso acotado a Cloud Storage.- un principal de ejemplo sobre
altostrat.compara practicarService Account UseryCompute Instance Admin (v1).
- Cloud Storage:
- bucket con nombre globalmente único y ubicación multi-región.
- objeto
sample.txtpara 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 Writeen la VM para probar acceso desde SSH.
- service account
- Roles relevantes:
- remoción del acceso de proyecto para
Username 2. roles/storage.objectViewerparaUsername 2.roles/storage.objectViewery luegoroles/storage.objectCreatorsobre la service accountread-bucket-objects.roles/iam.serviceAccountUsersobre la service account.roles/compute.instanceAdmin.v1a nivel proyecto.
- remoción del acceso de proyecto para
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
- Lab original (requiere login): Build IaC with Terraform
- Fuente pública usada para trazabilidad de comandos: GSP345 Walkthrough (Gist)
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-1ytf-instance-2. - Tercera instancia opcional (
create_third_instance) para practicartainty reconciliación. - Firewall
tf-firewallpara exponertcp:80. - Service account para VMs con rol
roles/logging.logWriter.
Uso rápido
- 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"
- Inicializar y planificar:
terraform init
terraform plan
- 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 = falsese 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-ejecutarterraform init.
Recursos identificados
- APIs y providers:
- Terraform provider:
hashicorp/google. - API principal utilizada por los recursos:
Compute Engine API(compute.googleapis.com).
- Terraform provider:
- Recursos principales:
- VPC auto mode:
mynetwork(google_compute_network). - Firewall rule:
mynetwork-allow-http-ssh-rdp-icmp(google_compute_firewall). - VM instances:
mynet-vm-1ymynet-vm-2(google_compute_instance).
- VPC auto mode:
- 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).
- Módulo Terraform reutilizable para instancias (
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-1ymynet-vm-2)
Lab original: Automating the Deployment of Infrastructure Using Terraform
Archivos
versions.tf: versión de Terraform, provider y configuración base degoogle.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
- Crear un archivo
terraform.tfvars(o pasar variables por CLI):
project_id = "tu-proyecto"
region = "us-central1"
zones = ["us-central1-a", "us-central1-b"]
- Ejecutar:
terraform init
terraform fmt
terraform plan
terraform apply
Buenas prácticas aplicadas
- Variables para valores configurables (
project_id,region,zones, nombres). localspara definir estructura de VMs.outputsútiles para inspección y debugging.- API de Compute habilitada con
disable_on_destroy = false. - Sin secretos hardcodeados.
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.comystorage.googleapis.com. - Recursos principales:
- Compute Engine instances (
tf-instance-1,tf-instance-2y temporalmentetf-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áficotcp:80.
- Compute Engine instances (
- IAM:
- uso implícito de permisos del usuario/sesión de Cloud Shell para crear/importar y administrar recursos.
- no se define un
service accountcustom 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áctica | Descripción |
|---|---|
| Alerting in GCP | App Engine + alert policy de Cloud Monitoring (latencia p99) |
| Service Monitoring | App Engine + SLO de disponibilidad y alerta por burn rate del error budget |
| Log Analytics | GKE + log bucket con Log Analytics, dataset enlazado en BigQuery y log sink |
| Cloud Trace | Cluster GKE con scopes para Cloud Trace y app demo con OpenTelemetry |
| Ops Agent Monitoring | VM con Apache + Ops Agent vía startup script, canal de notificación y alerting opcional |
| Monitoring Applications in GCP | Monitoreo 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 destroyal 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
- Inicializá:
terraform init
- 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"
- Plan y apply:
terraform plan
terraform apply
Notas de compatibilidad
app_engine_location_idno es lo mismo queregion. Ejemplos típicos:- Region:
us-central1→ App Engine location:us-central - Region:
southamerica-east1→ App Engine location:southamerica-east1
- Region:
Salidas útiles
El ejemplo expone por outputs:
alert_policy_namenotification_channel_name(si aplica)
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
defaultdesplegado en el proyecto. Si todavía no existe, el datasourcegoogle_monitoring_app_engine_servicepuede fallar porque Service Monitoring aún no “ve” el servicio.
Uso rápido
- Inicializá:
terraform init
- 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
- Plan y apply:
terraform plan
terraform apply
Salidas útiles
El ejemplo expone por outputs:
slo_namealert_policy_namenotification_channel_name(si aplica)
Este lab se complementa con la práctica Terraform en README.md dentro de esta misma carpeta.
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.
- Tráfico HTTP a App Engine (
- 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.editoren el proyecto).
- APIs típicamente requeridas:
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
kubectly acá queda documentado como comandos.
Prerrequisitos
- Terraform instalado.
- Permisos en el proyecto para crear GKE, Logging y BigQuery.
gcloudykubectlsi vas a desplegar la demo.
Uso rápido
- Inicializá:
terraform init
- Creá
terraform.tfvars:
project_id = "tu-project-id"
region = "us-west1"
zone = "us-west1-a"
- 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_locationlog_bucket_name,log_bucket_destinationlinked_dataset_resource_namesink_name,sink_writer_identity
Recursos identificados
- GKE: cluster
day2-ops(trabajo con workloadsk8s_container). - Cloud Logging:
- Log bucket (upgrade del bucket existente
_Defaulto creación de un bucket nuevo). - Log Analytics habilitado en el bucket.
- Log view
_AllLogsdentro del bucket. - Log sink con filtro
resource.type="k8s_container"hacia el bucket.
- Log bucket (upgrade del bucket existente
- 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
| Recurso | Nombre |
|---|---|
| Cluster GKE | cloud-trace-demo |
| Node pool | cloud-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
| Variable | Descripción |
|---|---|
project_id | ID del proyecto GCP |
Notas
- El cluster usa
oauth_scopes = ["cloud-platform"]que incluyecloudtrace.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.
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-aobtenga 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
| Recurso | Nombre |
|---|---|
| VM Compute Engine | quickstart-vm (e2-small, Debian) |
| Firewall | allow-http-ops-agent (tcp:80) |
| Notification channel | email (opcional) |
| Alert policy | Apache 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
| Variable | Descripción |
|---|---|
project_id | ID 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-platformen la service account incluyemonitoring.writeylogging.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.
Recursos identificados
- APIs habilitadas:
compute.googleapis.com,monitoring.googleapis.com,logging.googleapis.com. - VM:
quickstart-vm(e2-small, Debian, us-east4-c, taghttp-server). - Firewall: permite tcp:80 desde
0.0.0.0/0a VMs con taghttp-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)
- Monitoring → Alerting → Edit notification channels → agregar canal Email.
- 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
| Recurso | Descripción |
|---|---|
google_app_engine_application | Aplicación App Engine en el proyecto |
google_monitoring_uptime_check_config | Uptime 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_channel | Canal 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
| Variable | Requerida | Default | Descripción |
|---|---|---|---|
project_id | ✅ | — | GCP project ID |
uptime_check_host | ✅ | — | Host del uptime check |
app_engine_location_id | — | us-central | Location de App Engine |
region | — | us-central1 | Region para recursos regionales |
notification_email | — | null | Email para alertas |
latency_threshold_seconds | — | 8 | Umbral p99 latencia (segundos) |
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áctica | Descripción |
|---|---|
| DevOps Pipeline con Cloud Build | Cloud 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 destroyal 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:
- Ir a Cloud Build → Triggers → Manage repositories en Cloud Console.
- Conectar la cuenta GitHub y autorizar el repositorio
devops-repo. - 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
| Variable | Descripción |
|---|---|
project_id | ID del proyecto GCP |
github_owner | Usuario u organización dueña del repo GitHub |
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 amaindel repositorio GitHub. - Cloud Build config:
cloudbuild.yamlque 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áctica | Descripción |
|---|---|
| Loading Data into BigQuery | Crea 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
| Recurso | Tipo | Descripción |
|---|---|---|
nyctaxi | google_bigquery_dataset | Dataset principal |
2018trips | google_bigquery_table (external) | Tabla externa sobre CSV en GCS |
january_trips | google_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
| Variable | Default | Descripción |
|---|---|---|
project_id | — | ID del proyecto GCP (obligatoria) |
region | US | Ubicación del dataset |
dataset_id | nyctaxi | ID del dataset |
gcs_source_uri | URI del CSV de NYC Taxi en GCS | Fuente de datos para la tabla externa |
Nota: el lab original carga los datos vía
bq loady UI. Esta práctica modela el estado final con tabla externa (sin necesidad de copiar datos al proyecto) y una vista equivalente ajanuary_trips.
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áctica | Descripción |
|---|---|
| Get Started with Vertex AI Studio | APIs + 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
| Recurso | Tipo | Descripción |
|---|---|---|
aiplatform.googleapis.com | API | Vertex AI API |
cloudbuild.googleapis.com | API | Cloud Build API |
run.googleapis.com | API | Cloud Run API |
texttospeech.googleapis.com | API (opcional) | Cloud Text-to-Speech API |
insurance-risk-summary-sa | google_service_account | SA para el servicio Cloud Run |
| IAM binding | roles/aiplatform.user | Permiso 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
| Variable | Default | Descripción |
|---|---|---|
project_id | — | ID del proyecto GCP (obligatoria) |
region | us-central1 | Región de Cloud Run |
cloud_run_service_name | insurance-risk-summary | Nombre del servicio Cloud Run |
allow_unauthenticated | true | Acceso público al servicio (igual que el deploy desde Studio) |
enable_tts_api | false | Habilitar Text-to-Speech API (tarea 5 opcional) |
Flujo del lab (resumen)
- Tarea 1: Crear prompt de chat → deployar como app Cloud Run.
- Tarea 2: Zero-shot y few-shot prompting; ajustar temperatura, tokens, Top-P.
- Tarea 3: Comparar variaciones de prompts con la feature Compare.
- Tarea 4: Analizar imagen (
timetable.png) desde Cloud Storage con Gemini multimodal. - Tarea 5: Generar imagen con Imagen 4; síntesis de voz con Chirp 3 (opcional).
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
gclouden 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:
- Desde la consola, ir a Agent Platform > Studio (o búscarlo como "Vertex AI Studio").
- Hacer clic en New prompt y elegir tipo Chat.
- Nombrar el prompt:
Insurance Risk Summary - Prototype. - 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."
- 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."
- Seleccionar modelo:
gemini-2.5-flash, región:Global. - Hacer clic en Submit y revisar la respuesta del modelo.
- Guardar el prompt con Save.
- 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).
- 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:
- Crear un nuevo prompt tipo Chat:
Insurance Claim Data Extraction. - En System instructions: definir el rol como extractor de datos estructurados de notificaciones de siniestros.
- 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).
- Configurar Temperature:
0.1y Output Token Limit:1024. - Enviar y observar qué extrae el modelo sin ejemplos.
Few-shot prompting:
- 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.
- Volver a enviar la consulta original y comparar la mejora en estructura y precisión.
Experimentos con parámetros:
- Ajustar Temperature a
1.5y reenviar: notar respuestas más creativas/impredecibles. - Cambiar Output Token Limit a
500: la respuesta se corta; con65535no se corta. - Modificar Top-P entre
0.8y1.0: controla qué tan diverso es el vocabulario usado. - 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:
- Crear nuevo prompt:
Insurance Risk Factor Identification. - System instructions: rol de analista de riesgos que identifica factores de riesgo en un negocio.
- Ingresar como input la descripción de un restaurante (ejemplo: local en zona comercial densa, cocina a gas, sin rociadores).
- Configurar
gemini-2.5-flash, temperatura0.2. - Enviar y guardar.
- Hacer clic en Compare para abrir el panel de comparación lado a lado.
- 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 temperatura2.0(muy alta): observar la diferencia en coherencia. - Variación C:
gemini-2.5-flashvsGemini 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:
- Crear nuevo prompt:
Timetable Image Analysis. - En el área de contenido, hacer clic en Insert > Image from Cloud Storage.
- Importar
timetable.png(imagen de un horario de vuelos, provista por el lab en un bucket público). - Configurar
gemini-2.5-flash, región Global. - Junto a la imagen, escribir el prompt:
"Provide a title for this image, a short description, and extract all visible text."
- Enviar y revisar: el modelo describe la imagen y transcribe el texto del horario.
- Enviar un segundo prompt de razonamiento:
"What percentage of departures listed are international flights?" El modelo razona sobre los datos que acaba de extraer.
- Cambiar temperatura a
0.8y reenviar el segundo prompt: notar variación en el estilo de respuesta. - Volver a temperatura
0.2para 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
- En Vertex AI Studio, hacer clic en New > Image.
- Escribir un prompt descriptivo. Ejemplo:
"A photorealistic macro photograph of a honeybee collecting nectar from lavender flowers, golden hour lighting."
- Seleccionar modelo:
Imagen 4. - Configurar: aspect ratio
1:1, cantidad de resultados:4. - Hacer clic en Generate y revisar los cuatro resultados.
- Seleccionar una imagen y explorar las opciones Inpaint (modificar una región de la imagen) y Outpaint (expandir el encuadre).
- Notar el badge de SynthID: marca de agua digital que identifica imágenes generadas por IA.
Voz con Chirp 3 (opcional)
- Si no está habilitada, activar Cloud Text-to-Speech API desde el panel de configuración.
- Hacer clic en el ícono de audio para abrir la herramienta de síntesis de voz.
- Ingresar el texto:
"Welcome to the world of generative AI on Google Cloud."
- Seleccionar modelo:
Chirp 3 HD Voices, idioma: inglés (US). - Elegir una variante de voz y hacer clic en Generate.
- 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.