Espacios de trabajo Terraform
Terraform espacios de trabajo permiten almacenar el estado de forma independiente por entorno para una única configuración IaC. En su página de espacios de trabajo, Hashicorp afirma: "Los espacios de trabajo no son apropiados para la descomposición de sistemas o despliegues que requieran credenciales y controles de acceso independientes. ConsulteCasos de usoen la documentación de Terraform CLI para más detalles y alternativas recomendadas". La página de Casos de Uso deja claro que hay muchas limitaciones y no se recomienda para aislar entornos.
HCP Terraform espacios de trabajo abordar algunas de las cuestiones, pero requieren el uso de su plataforma en la nube y, esencialmente, separa estos espacios de trabajo en su propia configuración independiente, causando un montón de espacio para la deriva y la duplicación de código.
Módulos Terraform
Una de las mejores prácticas de la industria para lograr configuraciones DRY es utilizar módulos Terraform. Mediante la utilización de estos módulos utilizando diferentes variables, el código IaC puede llamar al módulo repetidamente para varios entornos. Esto mantiene las configuraciones que no cambian, globales, dentro del módulo. Los ajustes dinámicos se mantienen fuera del módulo en el código de llamada.
Este enfoque, sin embargo, todavía tiene varios problemas. A saber, la configuración del backend del estado debe repetirse, así como tener configuraciones de entorno desarticuladas que deben actualizarse de forma independiente y podrían causar desviaciones en las configuraciones almacenadas que se utilizan.
Terragrunt
Terragrunt, fue construido para hacer frente a muchos de los problemas necesarios para obtener configuraciones DRY Terraform IaC. El uso de Terragrunt tiene cierta controversia entre algunos ingenieros de la industria, pero creo que muchos de esos argumentos son erróneos y en algunos casos donde es un punto válido, los beneficios DRY de usar Terragrunt a menudo superan esos puntos. Esto es especialmente cierto cuando el tamaño y la capacidad de mantenimiento de las configuraciones de IaC se vuelven difíciles de manejar, pero también puede proporcionar beneficios para los casos de uso más pequeños.
El uso de Terragrunt aborda los problemas de DRY Terraform IaC de varias maneras. Las configuraciones dinámicas pueden ser centralizadas para entradas, módulos, proveedores y backends de estado. Además, el código IaC puede incluir otro código IaC sin tener que crear un módulo completamente separado.
Incluso mientras utilizamos código o configuraciones compartidas (lo llamaré global), podemos diseñar nuestra solución de tal manera que podamos añadir a ese código o anularlo completamente. Además de anular variables, también podemos incluir módulos con diferentes versiones si lo deseamos. Esto puede ser especialmente importante si tienes un entorno sandbox donde quieres probar una nueva versión de un módulo o configuración sin afectar a ningún otro entorno usando tu configuración global. Amplíe este tipo de personalizaciones en su sistema CICD y el código entonces se vuelve manejable en lugar de una telaraña de código duplicado que mantener.
Solución DRY Terragrunt
Vamos a construir la estructura de un proyecto de ejemplo que pasa ACLs y un nombre de dominio a un módulo.
Estructura del Proyecto
Terminaremos con la siguiente estructura de proyecto:
multiple-environments-project
├── dev
│ ├── acls.tf
│ ├── environment.auto.tfvars
│ ├── terragrunt.hcl
│ └── variables.tf
├── global
│ ├─ ─ global-acls.tf
│ ├── global-main.tf
├── prod
│ ├── acls.tf
│ ├── environment.auto.tfvars
│ ├── terragrunt.hcl
│ └── variables.tf
└── terragrunt-root.hcl
terragrunt-root.hcl
Este archivo se utiliza para la configuración compartida del proyecto raíz. Típicamente, esto incluiría ajustes de estado remoto o configuraciones de proveedores. Para esta demostración, el estado no es necesario, por lo que podría ser un archivo vacío.
locals {
environment_remote_backend = get_env("REMOTE_STATE_CREDENTIALS", "") != "" ? "remote_state_tbd" : "local"
}
generate "backend" {
path = "backend.tf"
if_exists = "overwrite_terragrunt"
contents = <<EOF
terraform {
%{if local.environment_remote_backend == "local"}
backend "local" {
path = "terraform.tfstate"
}
%{else}
backend "remote_state_tbd" {
bucket = "myproject-tfstate-${basename(get_terragrunt_dir())}"
}
%{endif}
}
EOF
}
terragrunt.hcl
Este archivo se utiliza en cada directorio de entorno para heredar la configuración raíz de terragrunt. También lo usamos para incluir código global.
terraform {
source = "${get_terragrunt_dir()}/../global"
}
include "root" {
path = find_in_parent_folders("terragrunt-root.hcl")
}
variables.tf
Este archivo se utiliza en cada directorio de entorno para establecer variables de entorno que podrían ser dinámicas por entorno, o credenciales que se pasarán al módulo.
variable "environment_name" {
description = "Environment Name"
type = string
}
environment.auto.tfvars
Este archivo se utiliza en cada directorio de entorno para establecer tfvars ambientales. Comúnmente podría ser el nombre de un entorno.
environment_name = "dev|prod"
global-main.tf
Este archivo se utiliza para llamar globalmente al módulo principal para todos los entornos. Esta misma funcionalidad podría colocarse en cada entorno, pero al mantenerlo en el directorio global, será utilizado automáticamente por los entornos. El módulo utiliza una entrada para ACLs de las ACLs locales definidas para cada entorno.
module "my_reusable_module" {
source = "path-to-my-module"
domain = var.environment_name
acls = local.acls
}
global-acls.tf
Este archivo se utiliza para definir globalmente las ACL que se utilizarán en cualquier entorno que lo desee.
locals {
global_myobjects = [
{
name = "Home"
entries = [
{ ip = "192.168.1.1" },
{ ip = "192.168.1.2" },
]
},
{
name = "Office"
entries = [
{ ip = "192.168.2.1" },
{ ip = "192.168.2.2" },
]
},
]
}
acls.tf
Este archivo se utiliza en cada directorio de entorno para establecer una variable ACL local. En el ejemplo prod, simplemente usamos lo que está en las ACL globales. Para dev, añadimos una tercera ACL que deseamos probar, además de las ACL globales.
Prod:
locals {
acls = concat(
local.global_acls,
)
}
Dev:
locals {
acls = concat(
local.global_acls,
{
name = "Dev Datacenter"
entries = [
{ ip = "192.168.3.1" },
{ ip = "192.168.3.2" },
]
},
)
}
Ejecutando
Ejecutar el código Terraform con Terragrunt se convierte en una simple cuestión:
terragrunt init --all
terragrunt plan --all
terragrunt apply --all --queue-include-dir dev
terragrunt apply --all --queue-include-dir production
terragrunt destroy –all
Reflexiones finales
Aunque existen muchas soluciones para gestionar múltiples entornos con Terraform, con el ejemplo proporcionado, terminamos con una solución flexible Terraform IaC que abstrae la funcionalidad global para la reutilización y facilidad de mantenimiento al tiempo que permite la capacidad de anular la configuración o funcionalidad por entorno.
La implementación de múltiples entornos para utilizar la configuración DRY IaC Terraform con Terragrunt proporciona un código manejable, ya sea utilizando sólo unos pocos entornos, muchos o incluso entornos efímeros. Integre esto para simplificar los flujos de trabajo de CICD y deje que acelere su negocio.
Este tipo de soluciones y personalizaciones permiten una gran flexibilidad y eficacia para las necesidades de su empresa. Para obtener más información sobre cómo nuestras soluciones personalizadas pueden impulsar el éxito de su empresa, póngase en contacto con nosotros¡!