Proveedor épico de Terraform para tu infraestructura en Amazon

Si planeas gestionar y trabajar con Amazon Web Services (AWS), es imprescindible utilizar el proveedor Terraform de AWS. Esto te permite interactuar con los numerosos recursos admitidos por AWS, como Amazon S3, Elastic Beanstalk, Lambda y muchos más.

En esta guía definitiva, aprenderás, paso a paso, casi todo lo que necesitas saber sobre el proveedor de AWS y cómo utilizarlo con Terraform para gestionar tu infraestructura de Amazon.

¡Vamos a hacerlo!

Prerrequisitos

Si desea seguir este tutorial, asegúrese de tener lo siguiente en su lugar:

  • A code editor – Even though you can use any text editor to work with Terraform configuration files, you should have one that understands the HCL Terraform language. Try out Visual Studio (VS) Code.

¿Qué es el proveedor de AWS de Terraform?

Terraform depende de complementos para interactuar con proveedores de nube como AWS, Google Cloud Platform (GCP) y Oracle. Uno de los proveedores más utilizados es el proveedor de AWS. Este proveedor interactúa con muchos recursos compatibles con AWS, como Amazon S3, Elastic Beanstalk, Lambda, y muchos más.

Terraform utiliza el proveedor de AWS con credenciales adecuadas para conectarse con Amazon y gestionar o implementar/actualizar docenas de servicios de AWS.

El proveedor de AWS se declara dentro del archivo de configuración de Terraform e incluye varios parámetros como la versión, las URL de los puntos de conexión o las regiones en la nube, etc.

Declaración del proveedor de AWS

Cuando necesitas hacer referencia al nombre de un proveedor, debes definir un nombre local. El nombre local es el nombre del proveedor asignado dentro del bloque required_providers. Los nombres locales se asignan al requerir un proveedor y deben ser únicos por módulo.

Al declarar los required_providers, también debes declarar el parámetro source en Terraform 0.13 y versiones posteriores. El parámetro source establece la dirección fuente donde Terraform puede descargar plugins.

Las direcciones de origen constan de tres partes, de la siguiente manera:

  • Hostname – El nombre de host del registro de Terraform que distribuye el proveedor. El nombre de host predeterminado es registry.terraform.io.
  • Namespace – Un namespace organizacional dentro del registro especificado.
  • Type – Un tipo es un nombre corto que proporcionas para la plataforma o sistema que gestiona el proveedor, y debe ser único.

A continuación, puedes ver la sintaxis de declaración del parámetro source, donde las tres partes de una dirección fuente están delimitadas por barras (/).

## <HOSTNAME>/]<NAMESPACE>/<TYPE>

# EJEMPLO DE USO DE LA SINTAXIS DEL PARÁMETRO DE ORIGEN

# Declarando la ubicación/dirección de origen donde Terraform puede descargar complementos
# El proveedor oficial de AWS pertenece al espacio de nombres de hashicorp en el 
# registro.terraform.io. Entonces, la dirección de origen de hashicorp es hashicorp/aws
source  = "hashicorp/aws"

Ahora, la configuración de Terraform a continuación declara el nombre del proveedor requerido (aws), junto con la dirección de origen, la versión del proveedor de AWS y configura la región del proveedor (us-east-2).

# Declarando los requisitos del proveedor cuando Terraform está instalado en la versión 0.13 o posterior
terraform {
  # Un requisito del proveedor consta de un nombre local (aws), 
  # ubicación de origen y una restricción de versión. 
  required_providers {
    aws = {     
      # Declarando la ubicación/dirección de origen donde Terraform puede descargar complementos
      source  = "hashicorp/aws"
      # Declarando la versión del proveedor de aws como superior a 3.0
      version = "~> 3.0"  
    }
  }
}

# Configurando el Proveedor de AWS en la región us-east-2
provider "aws" {
  region = "us-east-2"
}

Autenticar una cuenta de AWS con credenciales codificadas en el código

Ahora que tienes una comprensión básica de cómo declarar el proveedor de AWS, veamos cómo autenticar una cuenta de AWS.

Puede autenticar el proveedor de AWS mediante varios métodos, como declarar variables de entorno y almacenar credenciales en un perfil con nombre. Pero la forma más rápida de autenticarse en una cuenta de AWS es codificar las credenciales directamente dentro de su proveedor de AWS.

Aunque no se recomienda el uso de credenciales codificadas debido a la posibilidad de fugas, aún puede declarar credenciales codificadas en la configuración de Terraform para probar rápidamente cualquier recurso de AWS. Pero siga leyendo y aprenderá más adelante una mejor manera de autenticar una cuenta de AWS mediante la declaración de variables de entorno.

La siguiente configuración declara un nombre local (aws) junto con la región del proveedor (us-east-2), como se muestra a continuación. Puede ver que el bloque del proveedor de AWS también declara una clave de acceso y una clave secreta para autenticar una cuenta de AWS.

# Declarando un proveedor de AWS con el nombre aws
provider "aws" {
  # Declarando la región del proveedor
  region = "us-east-2"
  # Declarando la access_key y secret_key
  access_key = "access-key"
  secret_key = "secret-key"
}

Asegurando las credenciales mediante la declaración de variables de entorno

Acaba de aprender que es posible codificar estáticamente las credenciales para autenticar el servicio en la nube de AWS con Terraform. Sin embargo, la codificación estática no es segura y solo se recomienda al implementar en un entorno de prueba para probar rápidamente el código.

¿Hay otra forma de asegurar credenciales? Sí, declarándolas como variables de entorno, no hay límite en cuántas puedes declarar. Las variables de entorno son variables cuyos valores se establecen fuera del archivo de configuración de Terraform y están compuestas por un par de nombre/valor.

Ejecuta la serie de comandos export a continuación para exportar cada variable de entorno. Exportar variables de entorno las hace disponibles en todo el programa o hasta que Terraform se ejecute.

# Exportando la variable AWS_ACCESS_KEY_ID
export AWS_ACCESS_KEY_ID="access-key"
# Exportando AWS_SECRET_ACCESS_KEY
export AWS_SECRET_ACCESS_KEY="secret-key"
# Exportando AWS_DEFAULT_REGION
export AWS_DEFAULT_REGION="us-east-2"

Almacenar Múltiples Credenciales en un Perfil Nombrado

Tanto codificar en duro como declarar credenciales como variables de entorno te permiten autenticar una cuenta de AWS una a la vez. Pero ¿qué pasa si necesitas almacenar múltiples credenciales y usarlas cuando sea necesario? Almacenar credenciales en un perfil nombrado es la opción ideal.

El código a continuación crea un perfil nombrado (Myprofile) que contiene una clave de acceso y una clave secreta.

La ubicación predeterminada de los perfiles nombrados es en $HOME/.aws/credentials/Myprofile en Linux y macOS, o %USERPROFILE%\.aws\credentials\Myprofile en Windows. Reemplaza Myprofile con el nombre real del perfil nombrado.

# Creando el Perfil Nombrado llamado 'Myprofile'
[Myprofile]
aws_access_key_id = AKIAVWOJMI5836154yRW31
aws_secret_accesss_key = vIaGmx2bJCAK90hQbpNhPV2k5wlW7JsVrP1bm9Ft

Una vez que hayas creado un perfil nombrado en ~/.aws/credentials, luego puedes hacer referencia a ese perfil en tu configuración de Terraform usando el atributo profile. A continuación, estás haciendo referencia al perfil nombrado llamado Myprofile.

# Configurando el Proveedor AWS llamado 'aws' en la región us-east-2
provider "aws" {
  region = "us-east-2"
  # Declarando el perfil nombrado (Myprofile)
  profile = "Myprofile"
}

Declarando el Rol de Suposición en el Proveedor AWS

Acabas de aprender a configurar un Proveedor AWS declarando credenciales codificadas antes de ejecutar Terraform. Pero quizás desees declarar credenciales en tiempo de ejecución. Si es así, la API AssumeRole es lo que necesitas. AssumeRole proporciona credenciales temporales que contienen un ID de clave de acceso, una clave de acceso secreta y un token de seguridad. Estas credenciales te permiten conectarte a AWS.

El código a continuación declara el proveedor llamado aws y un assume_role que contiene un nombre de rol y un nombre de sesión. Para configurar el acceso a AssumeRole, debes definir un rol IAM que especifique los privilegios que otorga y qué entidades pueden asumirlo.

# Declarando el proveedor AWS llamado 'aws'
provider "aws" {
  # Declarando AssumeRole
  assume_role {
		# Declarando un nombre de recurso.
    # El role_arn es el Amazon Resource Name (ARN) del Rol de IAM a asumir.
    # ARN es un número único que está alineado con todos los recursos en la cuenta de AWS.
    role_arn     = "arn:aws:iam::ACCOUNT_ID:role/ROLE_NAME"
    # Declarando un nombre de sesión
    session_name = "SESSION_NAME"
  }
}

Declarando Múltiples Proveedores de AWS

Hasta ahora, has aprendido cómo declarar y configurar el Proveedor de AWS en Terraform que funciona con una sola región. Pero ¿qué pasa si necesitas administrar tu infraestructura o servicios de AWS en múltiples regiones en la nube? En ese caso, necesitarás declarar la palabra clave alias.

El alias permite definir múltiples configuraciones para el mismo proveedor y seleccionar cuál usar en base a un recurso o módulo o para admitir múltiples regiones.

El código a continuación declara el Proveedor de AWS predeterminado llamado aws con la region establecida en us-east-2. Y luego declara un Proveedor de AWS adicional con el mismo nombre, pero con un alias declarado llamado west y una region establecida en us-west-2.

Declarar un alias te permite crear recursos en la región us-east-2 de forma predeterminada, o en la región us-west-2 si eliges el proveedor aws.west según los requisitos.

# Los recursos de configuración predeterminados del proveedor que comienzan con aws.
provider "aws" {
  # Declarando la región us-east-2 para el proveedor AWS llamado 'aws'
  region = "us-east-2" 
}

# Configuración adicional del proveedor para la región oeste.
# Los recursos pueden hacer referencia a esto como aws.west.
provider "aws" {
  alias  = "west"
  # Declarando la región us-west-2 para el proveedor AWS referenciado como 'west'
  region = "us-west-2"
}

# Declarando el recurso usando un proveedor adicional en la región oeste
resource "aws_instance" "west-region" {
  # Declarando el proveedor como aws.west
  # aws.west se referencia desde el proveedor AWS llamado 'aws' y con el alias 'west'
  provider = aws.west
}

# Declarando el recurso usando el proveedor predeterminado
resource "aws_instance" "east-region" 
}

Personalizar la Configuración del Punto de Extremo del Proveedor de AWS

Personalizar la configuración del punto de extremo es útil al conectar con puntos de extremo de servicios de AWS no predeterminados, como AWS Snowball o al realizar pruebas locales.

Configura el proveedor de AWS en Terraform para utilizar puntos finales personalizados. Hazlo declarando el bloque de configuración endpoints dentro del bloque del proveedor, como se muestra a continuación.

La siguiente configuración te permite acceder al servicio AWS S3 en el puerto local 4572, como si estuvieras accediendo al servicio AWS S3 en una cuenta AWS. De manera similar, la configuración te permite acceder a dynamodb localmente en el puerto 4569. DynamoDB es un servicio de base de datos NoSQL que ofrece un rendimiento rápido con escalabilidad sin problemas.

Consulta la lista de puntos finales personalizados que el proveedor Terraform AWS permite.

# Declarando el proveedor AWS llamado 'aws'
provider "aws" {
  # Declarando puntos finales
  endpoints { 
    # Declarando el dynamodb en localhost con el puerto 4569 
    dynamodb = "<http://localhost:4569>"  
    # Declarando el S3 en localhost con el puerto 4572
    s3 = "<http://localhost:4572>"  
  }
}

Añadiendo Etiquetas

Anteriormente, aprendiste cómo se declara un proveedor de AWS con configuraciones como región, ubicación de origen, etc. Pero para gestionar mejor tus recursos, necesitas agregar etiquetas a nivel de proveedor.

Las etiquetas son etiquetas que consisten en claves y valores definidos por el usuario. Las etiquetas son útiles cuando necesitas verificar la facturación, propiedad, automatización, control de acceso y muchos otros casos de uso en la cuenta de AWS.

En lugar de agregar etiquetas a todos los recursos individualmente, aprendamos cómo agregar etiquetas a todos los recursos a nivel de proveedor, lo que ayudará a ahorrar mucho código y tiempo.

El código a continuación configura un proveedor de AWS con etiquetas definidas dentro de default_tags. El beneficio de agregar etiquetas dentro del proveedor es que las etiquetas especificadas se agregarán automáticamente cuando crees cualquier recurso con este proveedor.

# Configurando el proveedor de AWS llamado 'aws'
provider "aws" {
  # Agregando las etiquetas predeterminadas Ambiente y Propietario a nivel de proveedor
  default_tags {
    # Declarando el valor de las etiquetas
    tags = {
      Environment = "Production"
      Owner       = "shanky"
    }
  }
}
# Creando el recurso 'aws_vpc' etiquetado con Nombre=MyVPC
resource "aws_vpc" "myinstance" {
  tags = {
    Name = "MyVPC"
  }
}

Ignorando Etiquetas

Habilitar etiquetas a nivel de proveedor ayuda a aplicar etiquetas en todo el entorno. Pero a veces, necesitas ignorar las etiquetas, como si no deseas agregar una etiqueta predeterminada a una instancia de EC2 y prefieres aplicarla al resto de los recursos en la cuenta de AWS. ¡Veamos!

El código a continuación configura un proveedor de AWS con ignore_tags definido dentro del proveedor. El beneficio de usar la etiqueta de ignorar es cuando no deseas agregar etiquetas predeterminadas a ciertos recursos y prefieres aplicarlas al resto de los recursos.

En el siguiente código, cuando creas cualquier recurso utilizando el proveedor aws, todos los recursos ignorarán las etiquetas LastScanned y kubernetes.io.


# Configurando el proveedor de AWS llamado aws

provider "aws" {
	
# Ignorar key_prefixes y claves de etiqueta en todos los recursos bajo el proveedor de AWS (aws)

  ignore_tags {
    key_prefixes = ["kubernetes.io"]
  }
  ignore_tags {
    keys = ["LastScanned"]
  }
}

Creando un bucket de AWS S3

Hasta ahora, has aprendido todo sobre cómo declarar y configurar los proveedores de AWS en profundidad. Pero simplemente declarar el proveedor de AWS no hace nada hasta que administres recursos de AWS como aprovisionar un bucket de AWS S3 o eliminar una instancia Ec2, etc. Entonces, ¡aprendamos cómo crear un bucket de AWS S3!

1. Crea una carpeta llamada ~/terraform-s3-demo, luego cambia (cd) el directorio de trabajo a esa carpeta. La carpeta ~/terraform-s3-demo contendrá tu archivo de configuración y todos los archivos asociados que Terraform creará.

mkdir ~/terraform-s3-demo
cd ~/terraform-s3-demo

2. Copia y pega la configuración a continuación en tu editor de código favorito, y guárdalo como main.tf en el directorio ~/terraform-s3-demo.

El archivo main.tf crea algunos recursos necesarios:

  • Requisito del proveedor: Un requisito del proveedor consta de un nombre local, una ubicación de origen y una restricción de versión.

  • Clave de cifrado: La clave de cifrado de Amazon S3 ayuda al bucket S3 para que todos los objetos nuevos estén cifrados cuando se almacenan en el bucket. Las claves de cifrado se crean usando aws_kms_key en Terraform.
  • Configuración del proveedor de AWS: Declarando el nombre del proveedor (aws) junto con la región us-east-2.
  • Bucket: Este módulo de Terraform crea un bucket llamado terraformdemobucket. Terraform no puede destruir este bucket ya que contiene una bandera force_destroy.

Versionado: El versionado en Amazon S3 significa mantener múltiples versiones de un objeto en el mismo bucket

# Configurando el proveedor de AWS llamado aws
provider "aws" {
# Ignorar etiquetas key_prefixes y keys en todos los recursos bajo un proveedor aws. 
  ignore_tags {
    key_prefixes = ["kubernetes.io/"]
  }
  ignore_tags {
    keys = ["LastScanned"]
  }
}

# Declarando los requisitos del proveedor
terraform {
  required_providers {
    aws = {
      source = "hashicorp/aws"
      version = "~> 3.0"
    }
  }
}

# Configurando el proveedor de AWS (aws) con la región establecida en 'us-east-2'
provider "aws" {
  region = "us-east-2"
}

# Concediendo acceso al bucket
resource "aws_s3_bucket_public_access_block" "publicaccess" {
  bucket = aws_s3_bucket.demobucket.id
  block_public_acls = false
  block_public_policy = false
}

# Creando la clave de cifrado que cifrará los objetos del bucket
resource "aws_kms_key" "mykey" {
  deletion_window_in_days = "20"
}

# Creando el bucket llamado terraformdemobucket
resource "aws_s3_bucket" "demobucket" {
  bucket = terraformdemobucket
  force_destroy = false
  server_side_encryption_configuration {
    rule {
        apply_server_side_encryption_by_default {
        kms_master_key_id = aws_kms_key.mykey.arn
        sse_algorithm = "aws:kms"
      }
    }
  }
  # Manteniendo múltiples versiones de un objeto en el mismo bucket
  versioning {
    enabled = true
  }
}

3. Ahora, ejecuta los comandos a continuación para navegar al directorio ~\\terraform-s3-demo e iniciar Terraform. Terraform inicializa los complementos y proveedores que son necesarios para trabajar con recursos.

Típicamente, Terraform utiliza un enfoque de tres comandos en orden secuencial terraform init, terraform plan, y terraform apply.

cd ~\terraform-s3-demo       # Cambiar al directorio ~\terraform-s3-demo
terraform init               # Iniciar Terraform
terraform plan               # Asegurar que la sintaxis de tu configuración sea correcta
terraform apply -auto-approve # Provisionar el cubo de AWS S3

Creando Instancias EC2 de AWS y Usuarios IAM

En la sección anterior, aprendiste cómo crear un único objeto (cubo AWS S3) usando Terraform con el Proveedor AWS. Pero de hecho, puedes crear múltiples objetos del mismo tipo usando Terraform con el Proveedor AWS.

1. Crea una carpeta llamada ~/terraform-ec2-iam-demo, luego navega hacia ella.

2. Abre tu editor de código favorito, copia/pega la configuración a continuación y guarda el archivo como main.tf en el directorio ~/terraform-ec2-iam-demo.

El código a continuación crea dos instancias de EC2, ec21a y ec21a, con los tipos de instancia t2.micro y t2.medium respectivamente, luego crea usuarios IAM con cuatro nombres diferentes. La ami declarada en el código es una Amazon Machine Image (AMI), que proporciona la información necesaria para lanzar una instancia, como el tipo de sistema operativo, qué software instalar, etc.

Puedes encontrar AMIs de Linux usando la consola de Amazon EC2.

# Creando la instancia con el tipo de instancia t2.micro y t2.medium
resource "aws_instance" "my-machine" {
# Declarando el AMI
  ami = "ami-0a91cd140a1fc148a"
  for_each  = {
      key1 = "t2.micro"
	    key2 = "t2.medium"
   }
  instance_type  = each.value
	key_name       = each.key
    tags =  {
	   Name  = each.value
	}
}
# Creando usuarios IAM con cuatro nombres diferentes
resource "aws_iam_user" "accounts" {
  for_each = toset( ["Account1", "Account2", "Account3", "Account4"] )
  name     = each.key
}

3. A continuación, crea otro archivo, copia/pega el código a continuación y guarda el archivo como vars.tf en el directorio ~/terraform-ec2-iam-demo.

El código a continuación declara todas las variables que se hacen referencia en el archivo main.tf. Después de ejecutar el código de Terraform, la variable tag_ec2 con los valores ec21a y ec21b se asigna a las dos instancias EC2 definidas en el archivo main.tf.

variable "tag_ec2" {
  type = list(string)
  default = ["ec21a","ec21b"]
}

4. Crea otro archivo de configuración de Terraform llamado output.tf en el directorio ~/terraform-ec2-iam-demo, luego copia/pega el código a continuación en el archivo output.tf.

Después de la ejecución exitosa del comando terraform apply, deberías ver los valores de ${aws_instance.my-machine.*.id} y ${aws_iam_user.accounts.*.name} al final de la salida del comando.

El código a continuación le dice a Terraform que haga referencia a los recursos aws_instance y aws_iam_user definidos en el archivo de configuración main.tf.

output "aws_instance" {
   value = "${aws_instance.my-machine.*.id}"
}
output "aws_iam_user" {
   value = "${aws_iam_user.accounts.*.name}"
}

5. Crea un archivo de configuración más en el directorio ~/terraform-ec2-iam-demo llamado provider.tf, y pega el código a continuación en el archivo provider.tf. El archivo provider.tf siguiente define el proveedor de AWS de Terraform para que Terraform sepa cómo interactuar con todos los recursos de AWS que has definido en los pasos anteriores.

provider "aws" {
   region = "us-east-2"
 }

6. Ahora, verifica que todos los archivos requeridos a continuación estén contenidos en la carpeta ~/terraform-ec2-iam-demo ejecutando el comando tree.

Showing all the Terraform configuration files required

7. Ejecuta los comandos a continuación en orden secuencial para inicializar Terraform y crear Instancias EC2 de AWS y Usuarios IAM.

terraform init
terraform plan
terraform apply
Terraform apply command executed successfully.

Finalmente, ve a la Consola de Administración de AWS, y luego dirígete al servicio EC2 de AWS y la consola IAM.

En las siguientes capturas de pantalla, puedes verificar que las instancias EC2 y los usuarios IAM existen.

Verifying the two EC2 instances that got created using Terraform
Verifying the four IAM users that got created using Terraform

Conclusión

Con esta guía definitiva, ahora tienes el conocimiento que necesitas para trabajar con el Proveedor AWS, desde declarar hasta ejecutar el Proveedor AWS dentro de Terraform. También aprendiste cómo el Proveedor AWS te permite declarar credenciales de muchas maneras de forma segura.

Ahora, ¿qué servicio de AWS tienes en mente para gestionar con el Proveedor AWS y Terraform?

Source:
https://adamtheautomator.com/terraform-aws/