Cómo configurar tus servicios de Fastly con Terraform

This post was written with version 0.30.0 of the Fastly Terraform provider. This is no longer the latest release so please refer to the documentation.

Los servicios de Fastly se pueden configurar de manera ocasional en la interfaz web, la interfaz de línea de comandos o la API, pero es importante asegurarse de que se conserva y se realiza un seguimiento de la configuración a medida que evoluciona el código de tus aplicaciones. Cuando empiezas a crear más en el edge, crece la importancia de desplegar lógica en el edge del mismo modo que despliegas cambios en tus propias aplicaciones e infraestructura. Con los servicios en la nube ya apenas hay distinción entre software e infraestructura, por lo que cada vez es más necesario desplegar los cambios de código y configuración en los servicios de varios proveedores mediante un único despliegue versionado. El uso de este principio para describir los servicios de Fastly se denomina infraestructura como código (IaC).

Ya hemos explicado cómo se puede diseñar una canalización de despliegue continuo usando la popular herramienta Terraform. Asimismo, hemos seguido mejorando de forma iterativa las funcionalidades disponibles, añadiendo compatibilidad con nuestros recursos sin versiones, WAF, puntos de conexión de registro de terceros, TLS y Compute@Edge. Ahora, tomemos algo de distancia y repasemos de manera integral cómo configurar, gestionar y desplegar los servicios de Fastly mediante Terraform. Explicaré cómo hacerlo basándome en las prácticas recomendadas.

Empieza creando un servicio VCL sencillo con Terraform. En un principio, el servicio será un proxy transparente colocado frente al popular sitio web de pruebas de petición/respuesta https://httpbin.org, de tal forma que, de momento, el servicio no modifique el objeto de la petición antes de que este sea redirigido mediante proxy a httpbin. Luego ya harás cambios para mostrar cómo ejecutar lógica programática en el edge.

Así pues, estos son los pasos que seguiremos:

  • Registro: crear una cuenta de Fastly y generar una clave de API.

  • Escritura: definir tus requisitos con el código de Terraform.

  • Ejecución: «planificar» y «aplicar» tus requisitos usando la CLI de Terraform.

  • Validación: abrir un navegador web y confirmar que el servicio se ejecuta correctamente.

  • Modificación: realizar cambios en los recursos definidos, generar un nuevo plan y volver a aplicarlo.

El siguiente esquema te puede ayudar a conceptualizar estos pasos y crear un modelo mental de la configuración general:

Configuring Fastly services with Terraform es

Creación de una cuenta de Fastly

El primer paso es registrarse y crear una cuenta de Fastly. No conlleva compromiso alguno y te permite probar gratis hasta 50 USD de tráfico. Una vez que te hayas registrado e iniciado sesión, crea un token de la API de Fastly. Se trata de una credencial de autenticación única asociada a ti como usuario individual. Nuestro proveedor de Terraform requiere que facilites este token para poder interactuar con la API de Fastly en tu nombre. 

Escritura de la configuración de Terraform

A continuación, genera un nuevo archivo de Terraform en tu editor de código preferido creando un archivo llamado main.tf y añadiendo el siguiente código:

terraform {
  required_providers {
    fastly = {
      source  = "fastly/fastly"
      version = "~> 0.30"
    }
  }
}
resource "fastly_service_v1" "test_service" { 
 name = "An Example Service"
  domain {
    name = "<name>.global.ssl.fastly.net"
  }
  backend {
    address = "httpbin.org"
    name    = "My Test Backend"
  }
  force_destroy = true
}
output "active" {
  value = fastly_service_v1.test_service.active_version
}

Para ponerte rápidamente manos a la obra, empezarás con un solo archivo, pero a medida que crezca el proyecto, seguramente será mejor que dividas el código en archivos diferentes para facilitar su mantenimiento.

El código anterior es HCL, lenguaje de configuración de HashiCorp, que te permite definir varios bloques y contenedores, indicados por name{ ... }, para organizar el contenido. En el ejemplo anterior, puedes ver tres bloques de nivel superior:

1. terraform
2. resource
3. output

El bloque terraform define una lista de proveedores de Terraform que se pueden utilizar. En este caso, el que necesitamos es el proveedor de Terraform de Fastly

CONSEJO: consulta la documentación de Terraform para obtener más información sobre el uso de restricciones de versión.

Los bloques de recursos describen uno o varios objetos de infraestructura. La configuración anterior define un recurso fastly_service_v1 (etiquetado como «test_service»), que es un tipo específico de recurso proporcionado por nuestro proveedor de Terraform y necesario para poder crear un nuevo servicio VCL. En este recurso encontraremos dos bloques anidados, domain y backend, que sirven para determinar el nombre de dominio para el que el servicio VCL debe administrar las peticiones, así como el servicio de backend que debe procesar dichas peticiones en última instancia. Estas son las dos configuraciones mínimas que necesita todo servicio de Fastly, usemos Terraform o no.

Para este ejemplo, cambia el apartado <name> del valor de dominio a algo que solo tú utilices. De lo contrario, es posible que te encuentres con un error causado por que el dominio ya lo haya tomado otro servicio.

El bloque de salida establece lo que quieres que Terraform te diga una vez que haya terminado de desplegar como quieres la infraestructura. Es algo que suele cambiar debido al despliegue, como un número de versión.

El recurso fastly_service_v1 generará un atributo active_version y el valor solo se conocerá una vez que el servicio se haya creado y activado correctamente. En el código de Terraform, hay un bloque de salida etiquetado como active cuyo valor asignado es una expresión programática de HCL que nos permite acceder a la versión activa.

La sintaxis para hacer referencia a valores de atributos dentro de un recurso es la siguiente:  

<resource_type>.<resource_label>.<resource_attribute>

Puedes encontrar todos los atributos de un recurso concreto de Fastly en la documentación del proveedor de Terraform de Fastly específico del recurso.

Ejecución de Terraform para generar un plan

Ahora que tienes una configuración de Terraform, instala la CLI de Terraform. Una vez instalada, puedes ver todos los comandos disponibles ejecutando lo siguiente en tu terminal:

$ terraform -help

Uno de esos comandos disponibles es init, que inicializa un proyecto de Terraform en el directorio de trabajo actual. Así pues, en el mismo directorio en el que creaste el archivo main.tf, ejecuta:

$ terraform init

El paso de inicialización le pedirá a Terraform que descargue todos los proveedores especificados en el bloque required_providers. Si necesitas agregar un nuevo proveedor más tarde, actualiza tu main.tf para que haga referencia al nuevo proveedor y vuelve a ejecutar terraform init.

Terraform utiliza tu configuración de main.tf para generar un «plan de ejecución» que indica las distintas operaciones necesarias para alcanzar el estado deseado. Acto seguido, Terraform ejecuta el plan para crear la infraestructura descrita. Para este paso también deberás compartir con Terraform el token de la API de Fastly que creaste antes, de tal forma que Terraform pueda interactuar con la API de Fastly en tu nombre. Exporta el token de la API en tu shell como una variable de entorno, y luego genera un plan de ejecución para ver lo que Terraform piensa hacer por ti:

$ export FASTLY_API_KEY="====PUT YOUR TOKEN HERE===="
$ terraform plan

Terraform sabe que aún no ha desplegado esta configuración en un servicio de Fastly, por lo que la salida debe reflejarlo indicando la necesidad de crear los distintos recursos:

An execution plan has been generated and is shown below.
Resource actions are indicated with the following symbols:
  + create
Terraform will perform the following actions:
 # fastly_service_v1.test_service will be created
  + resource "fastly_service_v1" "test_service" {
      + activate       = true
      + active_version = (known after apply)
      + cloned_version = (known after apply)
      + comment        = "Managed by Terraform"
      + default_host   = (known after apply)
      + default_ttl    = 3600
      + force_destroy  = true
      + id           = (known after apply)
      + name           = "An Example Service"
     + backend { 
          + address   = "httpbin.org"
          + auto_loadbalance       = true
          + between_bytes_timeout = 10000
          + connect_timeout     = 1000
          + error_threshold     = 0
          + first_byte_timeout  = 15000
          + max_conn            = 200
          + name                  = "My Test Backend"
          + port            = 80
          + ssl_check_cert        = true
          + use_ssl               = false
          + weight              = 100
        }
      + domain {
          + name = "<name>.global.ssl.fastly.net"
        }
    }
Plan: 1 to add, 0 to change, 0 to destroy.
Changes to Outputs:
  + active = (known after apply)

Como puedes ver en las últimas líneas de la salida, queda un recurso por añadir y no hay nada que cambiar ni borrar.

El proveedor creará un servicio, un dominio y un backend, que corresponden con los bloques anidados de tu configuración. Aunque hayas definido varios bloques dentro del recurso fastly_service_v1, desde el punto de vista de Terraform, solo hay un recurso que crear.

Una vez que hayas revisado el plan y te parezca bien, aplícalo:

$ terraform apply
An execution plan has been generated and is shown below.
Resource actions are indicated with the following symbols:
  + create
Terraform will perform the following actions:
...<snip>...
Do you want to perform these actions?
  Terraform will perform the actions described above.
  Only 'yes' will be accepted to approve.
  Enter a value:

Deberías ver la misma salida que antes, pero esta vez seguida de un aviso interactivo que te pedirá tu visto bueno para aplicar el plan. Escribe «yes» y pulsa Entrar. Las salidas restantes proporcionarán actualizaciones de estado:

Enter a value: yes
fastly_service_v1.test_service: Creating...
fastly_service_v1.test_service: Still creating... [10s elapsed]
fastly_service_v1.test_service: Still creating... [20s elapsed]
fastly_service_v1.test_service: Creation complete after 29s
[id=2Z2KJsHtnsNGkGpafGVdbx]
Apply complete! Resources: 1 added, 0 changed, 0 destroyed.
Outputs:
active = 1

Observa el apartado «Outputs:» en la parte inferior, que muestra la variable de salida active que definiste en main.tf. El valor es el número 1, que indica que el servicio que se acaba de crear está en la versión 1.

CONSEJO: para no tener que introducir «yes» manualmente cuando se te solicite (por ejemplo, al usar Terraform en un entorno automatizado, como un sistema de integración continua), pasa la marca de

<u>-auto-approve</u>
undefinedal subcomando apply.

Validación de la configuración

Al experimentar con configuraciones del servicio, puedes validar los cambios que realices utilizando una URL especial de prueba que Fastly genera en función del dominio que hayas definido para el servicio:

https://<name>.global.ssl.fastly.net

Por ejemplo, si se aplicase correctamente el código original de Terraform (con example como <name> del dominio), la URL sería la siguiente:

https://example.global.ssl.fastly.net

Los nuevos ajustes de configuración pueden tardar hasta 60 segundos en hacerse efectivos. Una vez listos, al visitar la URL de prueba se ve el mismo contenido que en https://httpbin.org/ porque ese dominio se ha configurado como backend y, aunque el recurso de servicio del código de Terraform no tenga definido ningún código VCL personalizado, se utiliza el VCL predeterminado de Fastly. El VCL predeterminado presenta comportamientos seguros y lógicos por defecto, lo cual implica que redirigirá mediante proxy toda petición entrante al backend especificado, y gestionará de forma automática el almacenamiento en caché de las respuestas.

Modificación de la configuración

Ahora modificarás el código de Terraform para agregar un nuevo bloque. Este nuevo bloque se añadirá dentro del recurso fastly_service_v1 y representará un archivo con VCL personalizado. En esta fase puedes dar rienda suelta a tu creatividad y escribir un archivo con VCL personalizado para cualquier lógica que quieras ejecutar en el edge. Sin embargo, para esta demostración, usaremos un archivo con lo básico.  

Empieza creando un directorio vcl en el mismo directorio que tu archivo main.tf, y dentro de ese nuevo directorio añade un archivo main.vcl:

$ mkdir vcl && touch vcl/main.vcl

A continuación, agrega el siguiente código VCL al archivo main.vcl:

sub vcl_recv {
  #FASTLY recv
  if (req.url.path == "/anything/here") {
    set req.http.X-CustomHeader = "example";
  }
  if (req.url.path == "/anything/not/found") {
    error 600;
  }
  return(lookup);
}
sub vcl_error {
  #FASTLY error
  if (obj.status == 600) {
    set obj.status = 404;
    set obj.http.Content-Type = "text/html";
    synthetic {"<h1>Not Found</h1>"};
    return(deliver);
  }
}

Este VCL personalizado es muy sencillo, pero demuestra que las actualizaciones de VCL también se pueden gestionar mediante Terraform. Hay dos partes de lógica diferenciadas en este código VCL:

  1. Si se solicita /anything/here, añade un encabezado HTTP personalizado a la petición (httpbin.org devolverá 200 OK por rutas que empiecen por /anything/, junto con una respuesta JSON que incluirá los detalles de la petición realizada).

  2. Si lo que se solicita es /anything/not/found, devuelve una respuesta sintética 404 Not Found en lugar de la respuesta habitual, 200 OK, que daría httpbin.

CONSEJO: para ayudarte a escribir y probar VCL personalizado, prueba a utilizar Fastly Fiddle o aprende más sobre cómo utilizar VCL en nuestro Developer Hub.

Ahora actualizarás el código de Terraform para que el recurso fastly_service_v1 incluya un bloque

<u>vcl</u>
:

resource "fastly_service_v1" "test_service" {
  ...<snip>...
  vcl {
    content = file("vcl/main.vcl")
    main    = true
    name    = "custom_vcl"
  }
  ...<snip>...
}

Con estas modificaciones, puedes volver a ejecutar los comandos plan y apply:

$ terraform plan

La salida refleja la adición del bloque vcl:

fastly_service_v1.test_service: Refreshing state...[id=2Z2KJsHtnsNGkGpafGVdbx]
An execution plan has been generated and is shown below.
Resource actions are indicated with the following symbols:
  ~ update in-place
Terraform will perform the following actions:
  # fastly_service_v1.test_service will be updated in-place
  ~ resource "fastly_service_v1" "test_service" {
        id             = "2Z2KJsHtnsNGkGpafGVdbx"
        name           = "An Example Service"
        # (5 unchanged attributes hidden)
     + vcl {
          + content = <<-EOT
                sub vcl_recv {
                  #FASTLY recv
                  if (req.url.path == "/anything/here")
                    set req.http.X-CustomHeader = "example";
                  }
                  if (req.url.path == "/anything/not/found")
                    error 600;
                  }
                  return(lookup);
                }
                sub vcl_error {
                  #FASTLY error
                  if (obj.status == 600) {
                    set obj.status = 404;
                    set obj.http.Content-Type = "text/html";
                    synthetic {"<h1>Not Found</h1>"};
                    return(deliver);
                  }
                }
            EOT
          + main    = true
          + name    = "custom_vcl"
        }
        # (2 unchanged blocks hidden)
    }
Plan: 0 to add, 1 to change, 0 to destroy.

Lo primero que hay que observar es «Refreshing state...». El estado de Terraform es una caché de tu infraestructura y configuración. Este estado se utiliza para comparar los requisitos definidos en tu configuración de Terraform con el entorno del mundo real. Al actualizar el estado, Terraform es capaz de calcular un plan de ejecución que utiliza la vista más actualizada de los recursos.

Asimismo, observa que la última línea indica que se debe realizar un cambio. Terraform te informa de que el recurso fastly_service_v1 se actualizará in-place (utilizando una virgulilla ~ para representar visualmente este cambio de estado). 

La salida de diferencias también muestra que algunos de los bloques anidados existentes no se han modificado, y utiliza un carácter + para indicar qué líneas se acaban de añadir. La configuración de Terraform ha utilizado la función file para acceder al archivo VCL del directorio del proyecto, pero al calcular el plan, Terraform ha insertado el contenido del archivo y eso es lo que se muestra en la salida de diferencias.

Si estás conforme con el plan de ejecución que ha presentado Terraform, aplica los cambios (esta vez prueba a usar la marca --auto-approve para evitar tener que escribir «yes»):

$ terraform apply --auto-approve

Una vez aplicados los cambios, espera unos 20 segundos a que la configuración actualizada se despliegue en toda nuestra red y que los puntos de conexión definidos en VCL empiecen a reaccionar siguiendo las nuevas reglas.

Para la primera ruta (/anything/here), el encabezado personalizado "X-Customheader": "example" será visible en la respuesta JSON enviada desde httpbin.org, mientras que la segunda ruta (/anything/not/found) pasará a devolver un 404 Not Found sintético generado por el código VCL. Esto demuestra que la configuración del servicio y el código VCL funcionan como es debido.

¡Y listo! Recapitulemos: has definido requisitos personalizados para un servicio de Fastly utilizando la configuración de Terraform, has diseñado un plan de ejecución y has aplicado el plan para desencadenar la creación de recursos reales de Fastly. Después, has gestionado un ciclo de vida de actualización típico con control y visibilidad totales de los cambios realizados en los recursos del servicio. 

Siguientes pasos

La gestión de VCL es una de las muchas formas en las que se puede sacar partido de la suma de Terraform y Fastly. También permite gestionar servicios de Compute@Edge, que aprovechan las posibilidades de WebAssembly para ejecutar archivos binarios personalizados seguros, compilados a partir de lenguajes como Rust y AssemblyScript. Para ver cómo puedes llevar Fastly más allá con Compute@Edge y Terraform, consulta «Orchestration using Terraform and the Fastly Terraform Provider» y la documentación de Terraform acerca de Fastly.

Mark McDonnell
Staff Software Engineer, Developer Relations
Fecha de publicación:

9 min de lectura

Comparte esta entrada
Mark McDonnell
Staff Software Engineer, Developer Relations

Mark (él/lo) sabe escuchar y desborda compasión. Además, es un programador políglota y ha escrito varios libros técnicos. Antes de entrar en Fastly, trabajó como Staff Software Engineer en BuzzFeed y fue Principal Engineer en BBC News. En los últimos veintitantos años ha desempeñado muchas funciones, entre las que él mismo destaca sus facetas como marido, padre y amante de la música.

¿List@ para empezar?

Ponte en contacto o crea una cuenta.