El autor seleccionó el Fondo de Software Libre y Abierto para recibir una donación como parte del programa Write for DOnations.
Introducción
Los módulos de Terraform te permiten agrupar recursos distintos de tu infraestructura en un único recurso unificado. Puedes reutilizarlos más tarde con posibles personalizaciones, sin repetir las definiciones de recursos cada vez que los necesites, lo cual es beneficioso para proyectos grandes y estructurados de manera compleja. Puedes personalizar las instancias de módulos utilizando variables de entrada que defines, así como extraer información de ellos mediante salidas. Además de crear tus propios módulos personalizados, también puedes utilizar los módulos predefinidos publicados públicamente en el Registro de Terraform. Los desarrolladores pueden utilizarlos y personalizarlos utilizando entradas como los módulos que creas, pero su código fuente está almacenado y se extrae desde la nube.
En este tutorial, crearás un módulo de Terraform que configurará múltiples Droplets detrás de un Balanceador de Carga para redundancia. También utilizarás las funciones de bucle for_each
y count
del Lenguaje de Configuración de Hashicorp (HCL) para implementar múltiples instancias personalizadas del módulo al mismo tiempo.
Prerrequisitos
- A DigitalOcean Personal Access Token, which you can create via the DigitalOcean control panel. You can find instructions in the DigitalOcean product document, How to Create a Personal Access Token.
- Tener Terraform instalado en tu máquina local y un proyecto configurado con el proveedor DO. Completa el Paso 1 y el Paso 2 del tutorial Cómo usar Terraform con DigitalOcean, y asegúrate de nombrar la carpeta del proyecto como
terraform-modules
, en lugar deloadbalance
. Durante el Paso 2, no incluyas la variablepvt_key
y el recurso de clave SSH. - Familiaridad con los tipos de datos y los bucles de HCL. Para obtener más información, consulta el tutorial Cómo mejorar la flexibilidad usando variables, dependencias y condicionales en Terraform.
- Familiaridad con las salidas de Terraform y su uso. Puedes seguir el tutorial Cómo gestionar datos de infraestructura con las salidas de Terraform para aprender más sobre ellas.
Nota: Este tutorial ha sido probado específicamente con Terraform 1.1.3
.
Estructura y Beneficios del Módulo
En esta sección, aprenderás qué beneficios aportan los módulos, dónde se suelen colocar en el proyecto y cómo deberían estar estructurados.
Los módulos personalizados de Terraform se crean para encapsular componentes conectados que se utilizan y despliegan juntos con frecuencia en proyectos más grandes. Son autocontenidos, agrupando solo los recursos, variables y proveedores que necesitan.
Los módulos suelen almacenarse en una carpeta central en la raíz del proyecto, cada uno en su subcarpeta respectiva debajo. Para mantener una separación limpia entre los módulos, siempre arquitectónicamente deben tener un único propósito y asegurarse de que nunca contengan submódulos.
Es útil crear módulos a partir de tus esquemas de recursos cuando te encuentras repitiéndolos con personalizaciones poco frecuentes. Empaquetar un único recurso como un módulo puede ser superfluo y gradualmente elimina la simplicidad de la arquitectura general.
Para proyectos de desarrollo y pruebas pequeños, incorporar módulos no es necesario porque no aportan muchas mejoras en esos casos. Con su capacidad de personalización, los módulos son el elemento de construcción de proyectos estructurados de manera compleja. Los desarrolladores utilizan módulos para proyectos más grandes debido a las importantes ventajas que ofrecen para evitar la duplicación de código. Los módulos también ofrecen el beneficio de que las definiciones solo necesitan modificarse en un solo lugar, lo que luego se propagará al resto de la infraestructura.
A continuación definirás, usarás y personalizarás módulos en tus proyectos de Terraform.
Creando un Módulo
En esta sección, definirás varios Droplets y un Balanceador de Carga como recursos de Terraform y los empaquetarás en un módulo. También harás que el módulo resultante sea personalizable mediante entradas de módulo.
Almacenarás el módulo en un directorio llamado droplet-lb
, dentro de un directorio llamado modules
. Suponiendo que te encuentras en el directorio terraform-modules
que creaste como parte de los requisitos previos, crea ambos a la vez ejecutando:
El argumento -p
instruye a mkdir
para que cree todos los directorios en la ruta proporcionada.
Dirígete a él:
Como se señaló en la sección anterior, los módulos contienen los recursos y variables que utilizan. A partir de Terraform 0.13
, también deben incluir definiciones de los proveedores que utilizan. Los módulos no requieren ninguna configuración especial para indicar que el código representa un módulo, ya que Terraform considera que cada directorio que contiene código HCL es un módulo, incluso el directorio raíz del proyecto.
Las variables definidas en un módulo se exponen como sus entradas y pueden usarse en las definiciones de recursos para personalizarlos. El módulo que crearás tendrá dos entradas: el número de Droplets a crear y el nombre de su grupo. Crea y abre para editar un archivo llamado variables.tf
donde almacenarás las variables:
Agregar las siguientes líneas:
Guarda y cierra el archivo.
Almacenarás la definición de Droplet en un archivo llamado droplets.tf
. Créalo y ábrelo para editarlo:
Agrega las siguientes líneas:
Para el parámetro count
, que especifica cuántas instancias de un recurso crear, pasas la variable droplet_count
. Su valor se especificará cuando se llame al módulo desde el código principal del proyecto. El nombre de cada uno de los Droplets implementados será diferente, lo que logras agregando el índice del Droplet actual al nombre del grupo proporcionado. La implementación de los Droplets será en la región fra1
y ejecutarán Ubuntu 20.04.
Cuando hayas terminado, guarda y cierra el archivo.
Con los Droplets ahora definidos, puedes pasar a crear el Balanceador de Carga. Almacenarás su definición de recurso en un archivo llamado lb.tf
. Créalo y ábrelo para editarlo ejecutando:
Agrega su definición de recurso:
Defines el Balanceador de Carga con el nombre de grupo en su nombre para hacerlo distinguible. Lo implementas en la región fra1
junto con los Droplets. Las siguientes dos secciones especifican los puertos y protocolos de destino y monitoreo.
El bloque destacado droplet_ids
recibe los IDs de los Droplets que deben ser gestionados por el Balanceador de Carga. Dado que hay múltiples Droplets y su cantidad no se conoce de antemano, se utiliza un bucle for
para recorrer la colección de Droplets (digitalocean_droplet.droplets
) y obtener sus IDs. Se rodea el bucle for
con corchetes ([]
) para que la colección resultante sea una lista.
Guarda y cierra el archivo.
Ahora has definido el Droplet, el Balanceador de Carga y las variables para tu módulo. Debes definir los requisitos del proveedor, especificando qué proveedores utiliza el módulo, incluyendo su versión y dónde se encuentran. Desde Terraform 0.13
, los módulos deben definir explícitamente las fuentes de los proveedores no mantenidos por Hashicorp que utilizan; esto se debe a que no los heredan del proyecto padre.
Almacenarás los requisitos del proveedor en un archivo llamado provider.tf
. Créalo para editarlo ejecutando:
Agrega las siguientes líneas para requerir el proveedor digitalocean
:
Guarda y cierra el archivo cuando hayas terminado. El módulo droplet-lb
ahora requiere el proveedor digitalocean
.
Los módulos también admiten salidas, que puedes utilizar para extraer información interna sobre el estado de sus recursos. Definirás una salida que exponga la dirección IP del Balanceador de Carga y la almacenarás en un archivo llamado outputs.tf
. Créalo para editarlo:
Agrega la siguiente definición:
Esta salida recupera la dirección IP del Balanceador de Carga. Guarda y cierra el archivo.
El módulo droplet-lb
está ahora completo y listo para implementarse. Lo llamarás desde el código principal, que almacenarás en la raíz del proyecto. Primero, navega hacia él subiendo dos veces en el directorio de archivos:
Luego, crea y abre para editar un archivo llamado main.tf
, en el cual utilizarás el módulo:
Agrega las siguientes líneas:
En esta declaración invocas al módulo droplet-lb
ubicado en el directorio especificado como source
. Configuras la entrada que proporciona, droplet_count
y group_name
, que se establece en group1
para que puedas distinguir entre las instancias más adelante.
Dado que la salida de la IP del balanceador de carga está definida en un módulo, no se mostrará automáticamente al aplicar el proyecto. La solución a esto es crear otra salida que recupere su valor (loadbalancer_ip
).
Guarda y cierra el archivo cuando hayas terminado.
Inicializa el módulo ejecutando:
La salida será similar a esto:
OutputInitializing modules...
- groups in modules/droplet-lb
Initializing the backend...
Initializing provider plugins...
- Finding digitalocean/digitalocean versions matching "~> 2.0"...
- Installing digitalocean/digitalocean v2.19.0...
- Installed digitalocean/digitalocean v2.19.0 (signed by a HashiCorp partner, key ID F82037E524B9C0E8)
...
Terraform has been successfully initialized!
You may now begin working with Terraform. Try running "terraform plan" to see
any changes that are required for your infrastructure. All Terraform commands
should now work.
If you ever set or change modules or backend configuration for Terraform,
rerun this command to reinitialize your working directory. If you forget, other
commands will detect it and remind you to do so if necessary.
Puedes intentar planificar el proyecto para ver qué acciones tomaría Terraform ejecutando:
La salida será similar a esto:
Este resultado detalla que Terraform crearía tres Droplets, llamados group1-0
, group1-1
y group1-2
, y también crearía un Balanceador de Carga llamado group1-lb
, que gestionará el tráfico hacia y desde los tres Droplets.
Puedes intentar aplicar el proyecto en la nube ejecutando:
Ingresa yes
cuando se te solicite. La salida mostrará todas las acciones y también se mostrará la dirección IP del Balanceador de Carga:
Has creado un módulo que contiene un número personalizable de Droplets y un Balanceador de Carga que se configurará automáticamente para gestionar su tráfico entrante y saliente.
Renombrando Recursos Implementados
En la sección anterior, desplegaste el módulo que definiste y lo llamaste grupos
. Si alguna vez deseas cambiar su nombre, simplemente cambiar el nombre de la llamada al módulo no dará los resultados esperados. Cambiar el nombre de la llamada provocará que Terraform destruya y vuelva a crear recursos, causando un tiempo de inactividad excesivo.
Por ejemplo, abre main.tf
para editarlo ejecutando:
Renombra el módulo grupos
a grupos_renombrados
, como se muestra:
Guarda y cierra el archivo. Luego, inicializa el proyecto nuevamente:
Ahora puedes planificar el proyecto:
La salida será larga, pero se verá similar a esto:
Output...
Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the following symbols:
+ create
- destroy
Terraform will perform the following actions:
# module.groups.digitalocean_droplet.droplets[0] será destruido
...
# module.groups_renamed.digitalocean_droplet.droplets[0] será creado
...
Terraform te pedirá que destruyas las instancias existentes y crees nuevas. Esto es destructivo e innecesario, y puede causar un tiempo de inactividad no deseado.
En su lugar, utilizando el bloque moved
, puedes instruir a Terraform que mueva los recursos antiguos bajo el nuevo nombre. Abre main.tf
para editarlo y agrega las siguientes líneas al final del archivo:
Cuando hayas terminado, guarda y cierra el archivo.
Ahora puedes planificar el proyecto:
Cuando planeas con el bloque moved
presente en main.tf
, Terraform quiere mover los recursos en lugar de recrearlos:
OutputTerraform will perform the following actions:
# module.groups.digitalocean_droplet.droplets[0] se ha trasladado a module.groups_renamed.digitalocean_droplet.droplets[0]
...
# module.groups.digitalocean_droplet.droplets[1] se ha trasladado a module.groups_renamed.digitalocean_droplet.droplets[1]
...
Al mover los recursos, cambia su ubicación en el estado de Terraform, lo que significa que los recursos en la nube actual no se modificarán, destruirán o recrearán.
Como modificarás significativamente la configuración en el próximo paso, destruye los recursos implementados ejecutando:
Ingresa yes
cuando se te solicite. La salida finalizará en:
Output...
Destroy complete! Resources: 4 destroyed.
En esta sección, has renombrado recursos en tu proyecto de Terraform sin destruirlos en el proceso. Ahora desplegarás múltiples instancias de un módulo desde el mismo código utilizando for_each
y count
.
Despliegue de Múltiples Instancias de Módulo
En esta sección, utilizarás count
y for_each
para desplegar el módulo droplet-lb
varias veces con personalizaciones.
Utilizando count
Una forma de implementar múltiples instancias del mismo módulo a la vez es pasar cuántas al parámetro count
, que está disponible automáticamente para cada módulo. Abre main.tf
para editarlo:
Modifícalo para que se vea así, eliminando la definición de salida existente y el bloque moved
:
Al establecer count
en 3
, indicas a Terraform que implemente el módulo tres veces, cada una con un nombre de grupo diferente. Cuando hayas terminado, guarda y cierra el archivo.
Planifica la implementación ejecutando:
La salida será larga y se verá así:
Detalles de Terraform en la salida que cada una de las tres instancias del módulo tendría tres Droplets y un Balanceador de Carga asociado con ellas.
Utilizando for_each
Puedes usar for_each
para módulos cuando necesitas una personalización de instancia más compleja, o cuando el número de instancias depende de datos de terceros (a menudo presentados como mapas) que no se conocen al escribir el código.
Ahora definirás un mapa que empareje nombres de grupos con recuentos de Droplets e implementarás instancias de droplet-lb
de acuerdo con él. Abre main.tf
para editar ejecutando:
Modifica el archivo para que se vea así:
Primero defines un mapa llamado group_counts
que contiene cuántos Droplets debería tener un grupo dado. Luego, invocas el módulo droplet-lb
, pero especificas que el bucle for_each
debe operar en var.group_counts
, el mapa que acabas de definir. droplet_count
toma each.value
, el valor del par actual, que es el recuento de Droplets para el grupo actual. group_name
recibe el nombre del grupo.
Guarda y cierra el archivo cuando hayas terminado.
Intenta aplicar la configuración ejecutando:
La salida detallará las acciones que Terraform tomaría para crear los dos grupos con sus Droplets y Balanceadores de Carga:
En este paso, has utilizado count
y for_each
para implementar múltiples instancias personalizadas del mismo módulo desde el mismo código.
Conclusión
En este tutorial, creaste e implementaste módulos de Terraform. Utilizaste módulos para agrupar recursos lógicamente vinculados y personalizarlos para implementar múltiples instancias diferentes a partir de una definición de código central. También utilizaste salidas para mostrar atributos de los recursos contenidos en el módulo.
Si quieres aprender más sobre Terraform, echa un vistazo a nuestra serie Cómo Administrar Infraestructura con Terraform.
Source:
https://www.digitalocean.com/community/tutorials/how-to-build-a-custom-terraform-module