¿Qué son los agentes de Terraform Cloud?
Terraform permite que las empresas aprovisionen y gestionen su infraestructura cloud aplicando buenas prácticas mediante la definición de infraestructura como código.
Los agentes de Terraform Cloud son pequeños binarios, que pueden ser instalados en un cloud privado o en un centro de datos propio, que ejecutan tareas de Terraform (plan, apply y destroy) en nombre de Terraform Cloud.
Terraform Cloud es una aplicación SaaS para aprovisionar y gestionar infraestructura utilizando Terraform por medio de una solución Cloud certificada SOC 2 Type I Compliant y con capacidades empresariales para equipos y empresas.
Terraform Cloud gestiona el estado de la infraestructura (state file) y monitoriza los VCS ( Sistemas de control de versiones) como GitHub para desencadenar cambios en la infraestructura.

Hasta ahora, las empresas que querían usar Terraform Cloud debían publicar su infraestructura en Internet, ya que cada ejecución de Terraform (plan, apply o destroy) se ejecutaba desde los servidores de HashiCorp en el cloud público o tenían que instalar la edición on-premises llamada Terraform Enterprise.
Los agentes de Terraform forman parte de las nuevas funcionalidades anunciadas por HashiCorp el 12 de agosto para su nueva edición de Terraform Cloud para empresas. Esta edición incluye además otras funcionalidades empresariales como mejoras en la seguridad y auditoría
Por qué una empresa necesita Agentes de Terraform?
Con los agentes de Terraform, una empresa puede gestionar su infraestructura privada como código y beneficiarse de toda la funcionalidad de Terraform en un escenario SaaS.
Los agentes son pequeños binarios (o una imagen Docker o un POD de Kubernetes) que se ejecutan dentro del centro de datos de una empresa (en infraestructura on-premises, cloud privado o ambos, facilitando el cloud híbrido)
La edición Business de Terraform Cloud permite:
- Gestión de infraestructura on-premises con Terraform.
- Gestión de cloud privada dentro y cloud pública en AWS, Azure, o Google.
- Mantener toda la infraestructura privada aislada de Internet.
- Aplicación de procesos de gestión de la configuración estrictos.
- Aplicación de buenas prácticas.
Los agentes de Terraform Cloud son responsables de contactar con los servidores de Terraform Cloud para solicitar instrucciones y ejecutar trabajos de Terraform. La empresa tan sólo debe permitir el tráfico de salida a Internet dirigido a los servidores de Terraform Cloud y puede mantener el tráfico entrante limitado o denegarlo.
Gestión de infraestructura Interna con Terraform Cloud y sus agentes
En este tutorial, usaremos la edición Business de Terraform Cloud para gestionar toda la infraestructura como código mediante un agente instalado en un clúster privado de Kubernetes que será el que ejecute los planes y cambios en la infraestructura.
El clúster de Kubernetes solo tiene acceso saliente a Internet. El agente instalado en el clúster contactará con Terraform Cloud para obtener instrucciones.
Aunque tradicionalmente Terraform se utiliza exclusivamente para desplegar infraestructura y el despliegue de aplicaciones se realiza con Ansible, el uso de Kubernetes y contenedores hace posible que se utilice Terraform para desplegar tanto la infraestructura que requiere una aplicación como la propia aplicación.
Proceso de despliegue usando Terraform Cloud y sus agentes.
En la demo, desplegaremos la aplicación «Color App» en nuestro clúster interno de Kubernetes. La «Color App» es una pequeña aplicación escrita en Golang que cambia el color de fondo en base al valor de las cookies o las variables de entorno, ha sido creada por IT Wonder Lab para probar patrones con Istio.
Actualizaciones:
- 18 Agosto 2020: Mover los certificados PEM a Variables de Terraform Cloud
Este tutorial despliega agentes de Terraform en Kubernetes usando un plan de Terraform (por supuesto!), No hay instrucciones oficiales en la documentación de Terraform y IT Wonder Lab aún no ha realizado pruebas exhaustivas. Para otros tutoriales vea Terraform Cloud Agents de Jon Schulman, Senior Product Manager en HashiCorp.
Prerrequisitos:
- Una Cuenta Business en Terraform Cloud.
- Un Clúster de Kubernetes. Nosotros usaremos las instrucciones del tutorial Creación de un Clúster de Kubernetes usando Vagrant y Ansible en 3 minutos para desplegar nuestro clúster interno.
Ciclo de vía de un agente de Terraform Cloud
Nuestros agente de Terraform Cloud tendrá un ciclo de vida desencadenado por la los cambios en el código fuente que define la infraestructura, en este caso los ficheros de configuración escritos en Terraform de nuestra aplicación de prueba.

- Un usuario edita un fichero de Terraform
- El cambio en la infraestructura se envía mediante commit a GitHub
- GitHub ejecuta una llamada a Terraform Cloud indicando que se ha realizado un cambio en el repositorio, Terraform Cloud descarga los cambios y planifica una ejecución de Terraform.
- El agente de Terraform que se ejecuta dentro del clúster on-premises de Kubernetes está constantemente preguntando a Terraform Cloud si tiene un trabajo para que ejecute, ahora que ha descargado los cambios de GitHub tiene un trabajo para ejecutar en el Workspace asignado. El agente descarga el trabajo junto con el código fuente.
- El agente de Terraform Cloud descarga el binario de Terraform y los proveedores requeridos, en este ejemplo nuestra configuración de Terraform requiere el proveedor de Kubernetes para ejecutar el plan. Enviará el resultado a Terraform Cloud y si es aceptado (de forma manual o automática), Terraform Cloud solicitará al agente que aplique el cambio.
- El agente de Terraform aplica el cambio. En nuestro código estamos creando un POD con al aplicación Color App que descarga una imagen de Docker del registro público de Docker y creará además un ServicePort para acceder a la aplicación. El resultado de al ejecución será enviado a Terraform Cloud.
Creación de un Token para el Agente de Terraform Cloud
Abra https://app.terraform.io/ y vaya a Settings -> Agent para registrar un nuevo token de agente.
Pulse en manage tokens

Pulse en new token

Fije un nombre (descripción)
Escribimos ditwl-agent-k8s-01 y pulsamos Create token:

Se muestra el nuevo token

No publique o comparta el token. Este se utiliza para registrar de forma segura el agente en el servidor de Terraform Cloud.
Almacene el valor del nuevo token. Usaremos el token y el nombre como variables de entorno en el despliegue del agente en el clúster de Kubernetes.
Desplegando el Agente de Terraform Cloud en Kubernetes
Usaremos una configuración local de Terraform para desplegar el agente de Terraform Cloud en nuestro clúster de Kubernetes.
Cree el fichero de configuración de Terraform
Fije los valores (nombre y token) del agente de Terraform Cloud como variables de entorno en el fichero de configuración de Terraform:
- TFC_AGENT_NAME
- TFC_AGENT_TOKEN
ditwl-agent-k8s.tf
terraform { required_version = "~> 0.12" } #----------------------------------------- # Default provider: Kubernetes #----------------------------------------- provider "kubernetes" { #Context to choose from the config file. config_context = "[email protected]" version = "~> 1.12" } #----------------------------------------- # KUBERNETES DEPLOYMENT COLOR APP #----------------------------------------- resource "kubernetes_deployment" "tfc-agent" { metadata { name = "tfc-agent" labels = { app = "tfc-agent" } //labels } //metadata spec { selector { match_labels = { app = "tfc-agent" } //match_labels } //selector #Number of replicas replicas = 1 #Template for the creation of the pod template { metadata { labels = { app = "tfc-agent" } //labels annotations = { "sidecar.istio.io/inject" = "false" } } //metadata spec { container { image = "hashicorp/tfc-agent:latest" #Docker image name name = "tfc-agent" #Name of the container specified as a DNS_LABEL. #Each container in a pod must have a unique name (DNS_LABEL). #Block of string name and value pairs to set in the container's environment env { name = "TFC_AGENT_TOKEN" value = "GMzAzKlaeajdvQ.atlasv1.YggshHnEiEL5ypyGsXzcS2PMpF6hMd1P7mB0Dgq6fGhF28lMw5byDn6BGdm5DRHjaCU" } //env env { name = "TFC_AGENT_NAME" value = "ditwl-agent-k8s-01" } //env resources { limits { cpu = "1" memory = "512Mi" } //limits requests { cpu = "250m" memory = "50Mi" } //requests } //resources } //container } //spec } //template } //spec } //resource
Terraform init, plan y apply
Ejecute
$terraform init $terraform plan $terraform apply
Vea la ejecución de terraform apply
en el clúster de Kubernetes:
Comprobación del despliegue del agente de Terraform Cloud en el clúster de Kubernetes
Acceda al Kubernetes dashboard o utilice el comando kubectl
para comprobar el estado del despliegue.
Kubernetes dashboard

Compruebe usando kubectl
$ kubectl get all NAME READY STATUS RESTARTS AGE pod/tfc-agent-7ddc594f56-72ljm 1/1 Running 1 72m NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE service/kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 11d NAME READY UP-TO-DATE AVAILABLE AGE deployment.apps/tfc-agent 1/1 1 1 72m NAME DESIRED CURRENT READY AGE replicaset.apps/tfc-agent-7ddc594f56 1 1 1 72m
Comprobar el estado del agente en Terraform Cloud
Una vez desplegado en Kubernetes, el agente de Terraform Cloud contactará y se registrará para recibir trabajos.
Ver el estado del agente
Abra https://app.terraform.io/ vaya a Settings -> Agent para ver el estado.

Nuestro Agente de Terraform Cloud instalado en Kubernetes se ha registrado y está a la espera de recibir trabajos.
Depurando Agente de Terraform
Para depurar problemas con el Agente o con Terraform, se debe incrementar el nivel de registro del agente y comprobar los logs mediante el dashboard de Kubernetes o la línea de comando.
Para subir el nivel de log del agente y de Terraform se fija una nueva variable de entorno en el recurso de despliegue de Terraform Kubernetes y se aplica el cambio al clúster mediante terraform apply
.
- Nombre: TFC_AGENT_LOG_LEVEL
- Valores permitidos: «trace», «debug», «info», «warn», and «error».
Edite ditwl-agent-k8s.tf añadiendo la variable de entorno TFC_AGENT_LOG_LEVEL ENV y su valor
env { name = "TFC_AGENT_NAME" value = "ditwl-agent-k8s-01" } //env env { name = "TFC_AGENT_LOG_LEVEL" value = "DEBUG" } //env
No fije el valor de TF_LOG
TF_LOG se utiliza par depurar planes de ejecución de Terraform mediante línea de comando, pero al utilizar agentes de Terraform no se debe usar pues el agente no está preparado para gestionar los mensajes de esta forma. En su lugar el agente, al configurar TFC_AGENT_LOG_LEVEL también aumenta el nivel de Terraform.
Aplique el cambio al clúster de Kubernetes
$terraform apply kubernetes_deployment.tfc-agent: Refreshing state... [id=default/tfc-agent] An execution plan has been generated and is shown below. Resource actions are indicated with the following symbols: ~ update in-place ... kubernetes_deployment.tfc-agent: Modifying... [id=default/tfc-agent] kubernetes_deployment.tfc-agent: Modifications complete after 1s [id=default/tfc-agent] Apply complete! Resources: 0 added, 1 changed, 0 destroyed.
Usando el comando kubectl
obtendrá el nombre del POD que está ejecutando el agente
$ kubectl get pods NAME READY STATUS RESTARTS AGE color-blue-dep-bcb4d8b9c-5qlrw 1/1 Running 0 15m color-blue-dep-bcb4d8b9c-j5gk4 1/1 Running 0 15m color-blue-dep-bcb4d8b9c-k4p76 1/1 Running 0 15m tfc-agent-7cd5545984-szfwx 1/1 Running 0 20m
Consulte los logs del POD
$kubectl logs -f tfc-agent-7cd5545984-szfwx 2020-08-15T12:57:36.442Z [INFO] agent: Starting: name=ditwl-agent-k8s-01 version=0.1.2 2020-08-15T12:57:36.442Z [DEBUG] plugin: starting plugin: path=/usr/bin/tfc-agent-core args=[/usr/bin/tfc-agent-core] 2020-08-15T12:57:36.442Z [DEBUG] plugin: plugin started: path=/usr/bin/tfc-agent-core pid=9 2020-08-15T12:57:36.442Z [DEBUG] plugin: waiting for RPC address: path=/usr/bin/tfc-agent-core 2020-08-15T12:57:36.501Z [DEBUG] plugin.tfc-agent-core: plugin address: network=unix address=/tmp/plugin751737478 timestamp=2020-08-15T12:57:36.501Z 2020-08-15T12:57:36.501Z [DEBUG] plugin: using plugin: version=1 2020-08-15T12:57:36.506Z [INFO] core: Starting: version=0.1.2 2020-08-15T12:57:36.506Z [DEBUG] core: Registering agent... 2020-08-15T12:57:37.053Z [INFO] core: Agent registered successfully with Terraform Cloud: id=agent-47ao7XsLiLF39btP pool-id=apool-HEdmePLwpjdMwyo7 2020-08-15T12:57:37.069Z [DEBUG] agent: Starting periodic core updates: interval=1h0m0s 2020-08-15T12:57:37.069Z [INFO] core: Waiting for next job ... 2020-08-15T13:01:42.174Z [DEBUG] terraform.cli: Plan: 2 to add, 0 to change, 0 to destroy. 2020-08-15T13:01:48.582Z [INFO] terraform: Generating and uploading provider schemas JSON 2020-08-15T13:01:48.582Z [DEBUG] terraform: Running command: cmd="/root/.tfc-agent/component/terraform/runs/run-kxyUydYxPCVA9sBe.plan/bin/terraform providers schema -json" 2020-08-15T13:01:49.371Z [DEBUG] core: Updating status: agent=busy job=running 2020-08-15T13:02:01.676Z [INFO] terraform: Persisting filesystem to remote storage 2020-08-15T13:02:03.372Z [DEBUG] terraform: Output stream has stopped 2020-08-15T13:02:03.435Z [INFO] terraform: Finished handling run 2020-08-15T13:02:03.436Z [DEBUG] core: Updating status: agent=idle job=finished 2020-08-15T13:02:03.978Z [INFO] core: Waiting for next job 2020-08-15T13:02:04.647Z [INFO] core: Job received: type=apply id=run-kxyUydYxPCVA9sBe 2020-08-15T13:02:04.647Z [INFO] terraform: Handling run: id=run-kxyUydYxPCVA9sBe type=apply org=ITWonderLab workspace=terraform-cloud-agent-k8s-deploy-app
Configuración de la App Color en Terraform
El siguiente fichero define la configuración que Terraform Cloud descargará del repositorio privado de IT Wonder Lab en GitHub https://github.com/itwonderlab/terraform-cloud-agent-k8s-deploy-app.
Las mejores prácticas de IT Wonder Lab incluyen modularizar la configuración de Terraform y no almacenar contraseñas en los ficheros de Terraform. En este ejemplo todo se define en único fichero. Vea otros tutoriales de IT Wonder Lab donde se aplican buenas prácticas.
ditwl-k8s-color.tf
# Copyright (C) 2018 - 2020 IT Wonder Lab (https://www.itwonderlab.com) # # This software may be modified and distributed under the terms # of the MIT license. See the LICENSE file for details. # -------------------------------- WARNING -------------------------------- # IT Wonder Lab's best practices for infrastructure include modularizing # Terraform configuration. # In this example, we define everything in a single file. # See other tutorials for Terraform best practices for Kubernetes deployments. # -------------------------------- WARNING -------------------------------- terraform { required_version = "~> 0.12" } variable "cluster_ca_certificate" { description = "CA Certificate PEM Encoded" } variable "client_certificate" { description = "Client Certificate PEM Encoded" } variable "client_key" { description = "Client Key PEM Encoded" } #----------------------------------------- # Default provider: Kubernetes #----------------------------------------- provider "kubernetes" { version = "~> 1.12" load_config_file = "false" host = "kubernetes.default.svc" #host = "https://192.168.50.11:6443" cluster_ca_certificate = var.cluster_ca_certificate client_certificate = var.client_certificate client_key = var.client_key } #----------------------------------------- # KUBERNETES DEPLOYMENT COLOR APP #----------------------------------------- resource "kubernetes_deployment" "color" { metadata { name = "color-blue-dep" labels = { app = "color" color = "blue" } //labels } //metadata spec { selector { match_labels = { app = "color" color = "blue" } //match_labels } //selector #Number of replicas replicas = 1 #Template for the creation of the pod template { metadata { labels = { app = "color" color = "blue" } //labels annotations = { "sidecar.istio.io/inject" = "false" } } //metadata spec { container { image = "itwonderlab/color:latest" #Docker image name name = "color-blue" #Name of the container specified as a DNS_LABEL. Each container in a pod must have a unique name (DNS_LABEL). #Block of string name and value pairs to set in the container's environment env { name = "COLOR" value = "blue" } //env #List of ports to expose from the container. port { container_port = 8080 } //port resources { limits { cpu = "0.5" memory = "512Mi" } //limits requests { cpu = "250m" memory = "50Mi" } //requests } //resources } //container } //spec } //template } //spec } //resource #------------------------------------------------- # KUBERNETES DEPLOYMENT COLOR SERVICE NODE PORT #------------------------------------------------- resource "kubernetes_service" "color-service-np" { metadata { name = "color-service-np" } //metadata spec { selector = { app = "color" } //selector session_affinity = "ClientIP" port { port = 8080 node_port = 30085 } //port type = "NodePort" } //spec } //resource
Despliegue de la aplicación Color App en el clúster interno de Kubernetes usando Terraform Cloud
Ahora podemos crear un workspace o espacio de trabajo en Terraform Cloud Business.
Configurar el workspace
Abrir https://app.terraform.io/ e ir a Workspaces.

Pulse sobre el botón New workspace

Bajo «Connect to a version control provider» pulse GitHub.
Selecciones el repositorio de GitHub
El repositorio de GitHub tiene la configuración de Terraform que queremos gestionar con Terraform Cloud, en nuestro ejemplo es un repositorio privado:
https://github.com/itwonderlab/terraform-cloud-agent-k8s-deploy-app.

Finalice la creación del workspace
Pulse en Create workspace

Espere unos minutos hasta que Terraform Cloud haya descargado el repositorio y configure el workspace.
Configure el modo de ejecución
Vaya a settings del workspace y seleccione que este workspace utiliza una agente, pulse Save Setting.

Añada las vaiables al workspace
Usaremos variables de Terraform Cloud, es una una funcionalidad que permite fijar el valor de algunas variables en el workspace. Es una gran forma de evitar almacenar valores sensibles (contraseñas) en ficheros de Terraform y su correspondiente VCS (GitHUb).
Vaya a Variables y añada los certificados codificados en formato PEM
En la página Variables del Workspace de Terraform Cloud añada las siguientes variables los sus valores extraidos y codificados en formato PEM del fichero kube/config:
- cluster_ca_certificate: certificado en formato PEM de certificate-authority-data
- client_certificate: certificado en formato PEM de client-certificate-data
- client_key: certificado en formato PEM de client-key-data
Obtenga los valores ejecutando el siguiente código en su máquina, que extrae (grep & awk
) y codifica (base64 -d -i
) los certificados desde $HOME/.kube/config:
$grep 'certificate-authority-data' $HOME/.kube/config | awk '{print $2}' | base64 -d -i $grep 'client-certificate-data' $HOME/.kube/config | awk '{print $2}' | base64 -d -i $grep 'client-key-data' $HOME/.kube/config | awk '{print $2}' | base64 -d -i
Los valores son de tipo multi línea por lo que requieren un tratamiento especial en Terraform, se usará la sintaxis de tipo shell “here doc”.
Coloque cada certificado PEM entre <<EOF y EOF, asegurándose de que hay un espacio en blanco antes de <<EOF, y que las líneas no están indentadas.
Ejemplo:
[ESPACIO]<<EOF
—–BEGIN CERTIFICATE—–
MIICyDCCAbCgAwIB … [OCULTO]
PBI5s7EgYqgwoijVwOZnU=
—–END CERTIFICATE—–
EOF
Puede marcar Sensitive para que no se vuelvan a mostrar nunca los valores de las variables

Guarde y continúe.
Ejecute el plan de Terraform
Regrese a Runs o pulse Queue plan para desplegar la aplicación en nuestros clúster privado de Kubernetes.

Confirmar y aplicar el plan

Compruebe los resultados
El plan ha sido aplicado y la aplicación publicada en el clúster de Kubernetes:

Acceda a la URL de la aplicación Color App
La configuración de Terraform para el despliegue crea un servicio de Kubernetes de tipo NodePort, se requiere para acceder a la aplicación cuando no se dispone de una balanceador. Vea una explicación en Uso de NodePort en un clúster Kubernetes sobre VirtualBox.
La aplicación Color App has sido publicada en http://192.168.50.11:30085/ (y en todas las IPs del clúster).
Abra http://192.168.50.11:30085/

Desencadenando una ejecución de Terraform Cloud publicando una cambio en GitHub
Una gran ventaja de utilizar Terraform Cloud (incluso en su versión gratuita) es que fuerza a los usuarios a aplicar un proceso de gestión de la configuración estricto que implica versionar cada cambio en la infraestructura antes de aplicarlo. Esta gestión de la configuración es crítica para realizar roll back y para auditar cambios.
Si editamos la configuración del plan de Terraform para nuestro despliegue, por ejemplo cambiando el número de réplicas y enviamos los cambios al repositorio de GitHub. Terraform Cloud comenzará una nueva ejecución del plan para incrementar las réplicas de la aplicación.
#Number of replicas replicas = 3
$ git add . $ git commit -m "Increase replicas to 3" [master 5cc2b09] Increase replicas to 3 1 file changed, 1 insertion(+), 1 deletion(-) $ git push Enumerating objects: 5, done. ... remote: Resolving deltas: 100% (2/2), completed with 2 local objects. To github.com:ITWonderLab/terraform-cloud-agent-k8s-deploy-app.git 1b659b1..5cc2b09 master -> master
El plan de Terraform se está ejecutando
Terraform Cloud muestra que se está ejecutando un plan desencadenado por un cambio en el VCS (GitHub). Pulse Confirm Plan para continuar.

El Dashboard de Kubernetes muestra 3 réplicas
Una vez que el plan ha sido confirmado, el agente aplica el cambio que incrementa el número de réplicas a 3, somo se muestra en el Dashboard de Kubernetes.

Conclusión
Recomiendo Terraform Cloud Business con sus agentes remotos y las funcionalidades avanzadas de seguridad y auditoría a aquellas empresas que han usado la versión gratuita de Terraform y ahora quieren extender el uso de Terraform a toda la organización aplicando buenas prácticas y cumpliendo todos los requisitos que una versión empresarial proporciona.
Los agentes son una nueva funcionalidad y la plataforma cloud de Terraform aún no permite crear asociaciones entre agentes y workspaces, esto debe ser tenido en cuenta en empresas que requieran múltiples agentes por su distribución de entornos y data centers. Así mismo HashiCorp está realizando una transición a productos y servicios dirigidos a la empresa que aún requiere ajustes y rodaje.