Episodio 4 · un equipo con entornos

Cuánto rompe un apply

lectura · 14 mindominio · BCPS Bankinfraestructura · la app en tres entornos

Tres minutos para cambiar la memoria

Han pasado unos meses. La infraestructura de la app ya no es una VPC: es la red, los datos y la propia app, con sus servicios, sus colas, sus permisos y sus alarmas. Y hay tres entornos, desarrollo, preproducción y producción, cada uno con su copia de todo. Unos 2.000 recursos, todos en el mismo estado.

Jon quiere subir la memoria de la app de desarrollo. Una línea. El plan tarda casi tres minutos, porque antes de comparar tiene que leer de la API de la nube los 2.000 recursos, uno por uno. Mientras tanto, el estado está bloqueado y nadie más puede aplicar nada, tampoco en producción. Y en el mismo plan, si alguien ha tocado a mano la red de producción, sale su drift, mezclado con el cambio de Jon.

El lock del episodio anterior pone a la gente en fila; aquí la fila es de todo el equipo, por cualquier cambio. Este episodio va de la tercera pregunta de la serie: cuánto rompe un apply, y de qué pasa cuando se parte el estado para que rompa menos.

La app, la red y tres entornos

Cada panel dibuja los 2.000 recursos agrupados en una rejilla: capas en filas (red, datos, app) y entornos en columnas. Cada cuadradito son cinco recursos. A la izquierda, todo en un estado, con el borde grueso alrededor. A la derecha, nueve estados, uno por celda; la app no ve el estado de la red, así que tiene que leer de ella el id de su subred, y el primer mando elige cómo.

Cambia la app de desarrollo y compara lo que lee cada plan y su radio de impacto. Luego cambia el rango de la subred de la app de producción, que obliga a reemplazarla, y mira qué pasa con la app a cada lado. Los otros dos mandos llevan la partición más lejos (un estado por recurso) o cambian cómo se separan los entornos.

Qué ha pasado

El radio de impacto es el estado

Un apply puede tocar cualquier cosa que esté en el estado sobre el que se ejecuta, y nada más. Por eso el radio de impacto del marcador no depende del cambio, sino del estado: a la izquierda, 2.000 recursos y seis críticos (la red de producción y las tres bases de datos), aunque el cambio sea la memoria de desarrollo. Un error en el código, un módulo actualizado sin querer, un drift que nadie ha visto: todo eso puede acabar en el mismo apply. A la derecha, el estado de la app de desarrollo tiene 460 recursos y ninguno crítico. Si algo sale mal, sale mal ahí.

El tamaño se paga también en tiempo. El plan lee cada recurso del estado antes de comparar, y la API de la nube tiene un límite de peticiones por segundo: a la izquierda, casi tres minutos por plan, con el estado bloqueado durante el plan y el apply. A la derecha, unos cuarenta segundos, y solo se bloquea el estado de la app de desarrollo.

Por capa y por entorno

Partir el estado sigue dos ejes. Por entorno, porque un cambio en desarrollo no debería poder tocar producción. Por capa, porque cada capa cambia a un ritmo distinto y la tocan personas distintas: la red cambia unas pocas veces al año y es de plataforma; la app cambia varias veces al día y es del equipo de la app. Cada estado tiene su lock, así que los cambios en la app ya no esperan a los de la red.

Para los entornos hay dos formas habituales. Con directorios, cada entorno es una carpeta (envs/dev, envs/pro) con su propio estado; el código común va en módulos y cada carpeta los usa con sus valores. Con workspaces, el mismo directorio tiene varios estados y se elige cuál con terraform workspace select. Los workspaces evitan copiar, pero el entorno pasa a ser algo que no se ve en el código. Pon el mando en workspaces, cambia la red de producción y luego la app de desarrollo: el workspace seleccionado sigue siendo pro, y el cambio va a producción. Los directorios tienen el problema contrario: como cada entorno es una copia, divergen sin querer (un arreglo que se hizo en desarrollo y nunca llegó a producción). Separar los entornos en cuentas distintas de la nube, que es la frontera más fuerte, es cosa del episodio 6.

Contratos entre estados

Al partir, lo que antes era una referencia dentro del mismo grafo (module.red_pro.subred_app) pasa a cruzar de un estado a otro. La app necesita el id de su subred, y hay tres formas de conseguirlo:

# 1. Leer el estado de la red
data "terraform_remote_state" "red" { config = { key = "red/pro.tfstate" } }
# 2. Leer un valor que la red publica
data "nube_parametro" "subred_app" { nombre = "/red/pro/subred_app" }
# 3. Preguntar a la nube
data "nube_subred" "app" { etiquetas = { capa = "app", entorno = "pro" } }

Con remote state, la app lee el estado de la red entero y coge las salidas; necesita permiso para leer todo ese estado, secretos incluidos, y queda atada a cómo lo organiza la red. Con valores publicados, la red escribe en un almacén de parámetros lo que ofrece y la app lee solo eso: es un contrato explícito, y la red puede reorganizarse por dentro sin avisar a nadie mientras siga publicando lo mismo. Con un data source, la app pregunta a la nube por la subred con ciertas etiquetas, y le da igual quién o cómo la creó; a cambio, depende de que esas etiquetas sean únicas y no cambien. Es la misma pregunta que en DDD: qué se expone entre dos partes y qué se queda dentro.

Cuándo hace daño: el orden que nadie escribió

Cambia la red de producción. A la izquierda, un solo apply lo hace todo: la subred nueva y, en el mismo grafo, los 38 recursos de la app que la usan, en orden. Es la gran ventaja del estado único: Terraform ve todas las dependencias.

A la derecha, el estado de la red se aplica solo. Su radio es pequeño y el apply termina bien. Pero la app de producción sigue apuntando a la subred vieja, que ya no existe: los contratos se leen al planificar, y el estado de la app no se ha planificado. Hay un orden entre estados, primero la red y luego la app, que no está escrito en ningún sitio. Con nueve estados, se lleva en la cabeza, en un README o en el pipeline, que aplica en ese orden.

Activa ahora un estado por recurso, el extremo contrario, y repite. El radio de cada apply es de un recurso, pero los 38 recursos de la app que usan la subred son 38 estados, y hay que aplicarlos todos después de la red, cada uno con su plan. El grafo que antes calculaba Terraform ya no lo tiene nadie. Partir no quita las dependencias; las saca del grafo y las convierte en trabajo de personas.

Criterio

Un estadoPor capa y entornoUno por recurso
Radio de un applyTodoUna capa de un entornoUn recurso
Tiempo de planCrece con todo lo demásEl de su capaMínimo, pero multiplicado
DependenciasLas resuelve el grafoPocas, entre capas, con contratoTodas fuera del grafo
Quién espera a quiénTodos a todosSolo quien toca la misma capa y entornoNadie, y nadie coordina
Bueno paraAlgo pequeño, que cambia junto, de un equipoCasi todo lo demásCasi nada
  1. ¿Hay partes que cambian a ritmos distintos o que tocan equipos distintos?La red y la app; producción y desarrollo.
    un estado por cada parte, con contratos explícitos entre ellas
  2. ¿El plan tarda tanto que la gente deja de leerlo?O el lock hace esperar a otros a menudo.
    partir por donde menos dependencias crucen
  3. Un estado. Partir tiene un coste: cada corte es un contrato que mantener y un orden que alguien tiene que saber.

En el mundo real

El orden entre estados es el problema que resuelve Terragrunt: cada estado declara de qué otros depende y lee sus salidas, y terragrunt run-all apply los aplica en orden. Las stacks de HCP Terraform y las dependencias entre stacks de Spacelift hacen lo mismo como servicio. Sin ellos, lo habitual es un pipeline que aplica las capas en un orden fijo y lanza la siguiente cuando cambian las salidas de la anterior.

Los workspaces de la CLI de Terraform son los que se ven en este episodio: varios estados para el mismo código. Los de HCP Terraform se llaman igual pero son otra cosa, más cercana a un directorio con su propio estado, sus variables y sus permisos. Para publicar valores entre estados se usan almacenes como AWS SSM Parameter Store, Azure App Configuration o Google Secret Manager y Runtime Configurator, o las salidas de los workspaces de HCP Terraform, que se pueden compartir con permisos explícitos.

No hay un tamaño correcto, pero hay una señal: cuando la gente deja de leer el plan porque es demasiado largo, o empieza a usar -target para aplicar solo una parte, el estado es demasiado grande. -target existe para emergencias; usarlo de costumbre es partir el estado sin decirlo.

Siguiente episodio

La red de la app ya tiene su estado. Entonces el equipo de Notificaciones pide una VPC igual, y Marta, en lugar de copiar, la convierte en un módulo de plataforma. La pregunta es qué enseña el módulo y qué esconde.

Episodio 5 Módulos como contratos Interfaz, versiones y el módulo profundo frente al envoltorio fino.

← Todos los episodios · Episodio 3: Dos personas, un estado · Cuentas en el mapa de BCPS Bank