Mejores prácticas al usar Terraform [cerrado]

111

Estoy en el proceso de cambiar nuestra infraestructura a terraform. ¿Cuál es la mejor práctica para administrar realmente los archivos y el estado de terraform? Me doy cuenta de que es una infraestructura como código y enviaré mis archivos .tf a git, pero ¿también confirmo tfstate? ¿Debería residir en algún lugar como S3? Me gustaría eventualmente que CI manejara todo esto, pero eso es muy extenso y requiere que descubra las piezas móviles de los archivos.

Realmente solo estoy buscando ver cómo la gente utiliza este tipo de cosas en la producción.

Marc Young
fuente

Respuestas:

85

También estoy en un estado de migración de la infraestructura de AWS existente a Terraform, por lo que intentaré actualizar la respuesta a medida que la desarrolle.

Me he basado en gran medida en los ejemplos oficiales de Terraform y en múltiples pruebas y errores para desarrollar áreas en las que no estaba seguro.

.tfstate archivos

La configuración de Terraform se puede utilizar para aprovisionar muchas cajas en diferentes infraestructuras, cada una de las cuales podría tener un estado diferente. Como también puede ser ejecutado por varias personas, este estado debe estar en una ubicación centralizada (como S3) pero no en git.

Esto se puede confirmar mirando el Terraform .gitignore.

Control del desarrollador

Nuestro objetivo es proporcionar un mayor control de la infraestructura a los desarrolladores al tiempo que mantenemos una auditoría completa (git log) y la capacidad de verificar los cambios (solicitudes de extracción). Con eso en mente, el nuevo flujo de trabajo de infraestructura al que apunto es:

  1. Base de base de AMI comunes que incluyen módulos reutilizables, por ejemplo, títeres.
  2. Infraestructura central provista por DevOps usando Terraform.
  3. Los desarrolladores cambian la configuración de Terraform en Git según sea necesario (número de instancias; nueva VPC; adición de región / zona de disponibilidad, etc.).
  4. Se envió la configuración de Git y se envió una solicitud de extracción para que un miembro del equipo de DevOps verificara la cordura.
  5. Si se aprueba, llama al webhook a CI para compilar e implementar (no está seguro de cómo particionar múltiples entornos en este momento)

Edición 1: actualización del estado actual

Desde que comencé esta respuesta, he escrito mucho código TF y me siento más cómodo en nuestro estado de cosas. Hemos encontrado errores y restricciones en el camino, pero acepto que esta es una característica del uso de software nuevo que cambia rápidamente.

Diseño

Tenemos una infraestructura de AWS complicada con varias VPC, cada una con varias subredes. La clave para gestionar esto fácilmente fue definir una taxonomía flexible que abarque la región, el medio ambiente, el servicio y el propietario, que podamos utilizar para organizar nuestro código de infraestructura (tanto terraform como títere).

Módulos

El siguiente paso fue crear un único repositorio de git para almacenar nuestros módulos terraform. Nuestra estructura de directorios de nivel superior para los módulos se ve así:

tree -L 1 .

Resultado:

├── README.md
├── aws-asg
├── aws-ec2
├── aws-elb
├── aws-rds
├── aws-sg
├── aws-vpc
└── templates

Cada uno establece algunos valores por defecto sensatos pero los expone como variables que pueden ser sobrescritas por nuestro "pegamento".

pegamento

Tenemos un segundo repositorio con nuestro glueque hace uso de los módulos mencionados anteriormente. Se presenta de acuerdo con nuestro documento de taxonomía:

.
├── README.md
├── clientA
   ├── eu-west-1
      └── dev
   └── us-east-1
       └── dev
├── clientB
   ├── eu-west-1
      ├── dev
      ├── ec2-keys.tf
      ├── prod
      └── terraform.tfstate
   ├── iam.tf
   ├── terraform.tfstate
   └── terraform.tfstate.backup
└── clientC
    ├── eu-west-1
       ├── aws.tf
       ├── dev
       ├── iam-roles.tf
       ├── ec2-keys.tf
       ├── prod
       ├── stg
       └── terraform.tfstate
    └── iam.tf

Dentro del nivel de cliente, tenemos .tfarchivos específicos de la cuenta de AWS que proporcionan recursos globales (como roles de IAM); el siguiente es el nivel de región con claves públicas EC2 SSH; Por último, en nuestro entorno ( dev, stg, prodetc.) son nuestra configuraciones de VPC, la creación de instancias y mirando uniones y conexiones están almacenados.

Nota al margen: Como puede ver, voy en contra de mi propio consejo anterior de mantenerme terraform.tfstateen git. Esta es una medida temporal hasta que me cambie a S3, pero me conviene ya que actualmente soy el único desarrollador.

Próximos pasos

Este sigue siendo un proceso manual y aún no está en Jenkins, pero estamos portando una infraestructura bastante grande y complicada y hasta ahora todo va bien. Como dije, ¡pocos errores pero van bien!

Edición 2 - Cambios

Ha pasado casi un año desde que escribí esta respuesta inicial y el estado de Terraform y yo hemos cambiado significativamente. Ahora estoy en una nueva posición usando Terraform para administrar un clúster de Azure y Terraform ahora v0.10.7.

Estado

La gente me ha dicho repetidamente que el estado no debería entrar en Git, y tienen razón. Usamos esto como una medida provisional con un equipo de dos personas que se basó en la comunicación y la disciplina de los desarrolladores. Con un equipo distribuido más grande, ahora estamos aprovechando por completo el estado remoto en S3 con el bloqueo proporcionado por DynamoDB. Idealmente, esto se migrará a consul ahora es v1.0 para cortar proveedores de nube cruzada.

Módulos

Anteriormente creamos y usamos módulos internos. Este sigue siendo el caso, pero con la llegada y el crecimiento del registro de Terraform , intentamos utilizarlos como al menos una base.

Estructura de archivo

La nueva posición tiene una taxonomía mucho más simple con solo dos entornos infx: devy prod. Cada uno tiene sus propias variables y salidas, reutilizando nuestros módulos creados anteriormente. El remote_stateproveedor también ayuda a compartir los resultados de los recursos creados entre entornos. Nuestro escenario son los subdominios en diferentes grupos de recursos de Azure para un TLD administrado globalmente.

├── main.tf
├── dev
   ├── main.tf
   ├── output.tf
   └── variables.tf
└── prod
    ├── main.tf
    ├── output.tf
    └── variables.tf

Planificación

Nuevamente, con los desafíos adicionales de un equipo distribuido, ahora siempre guardamos nuestra salida del terraform plancomando. Podemos inspeccionar y saber qué se ejecutará sin el riesgo de algunos cambios entre la etapa plany apply(aunque el bloqueo ayuda con esto). Recuerde eliminar este archivo de plan, ya que podría contener variables "secretas" de texto sin formato.

En general, estamos muy contentos con Terraform y seguimos aprendiendo y mejorando con las nuevas funciones agregadas.

Ewan
fuente
¿Ha tenido suerte / problemas desde esta respuesta? El tuyo se parece mucho a lo que pretendo hacer, pero es posible que estés más adelantado que yo.
Marc Young
3
Tengo curiosidad por saber por qué crees que los archivos tfstate no deberían almacenarse en git. ¿Es simplemente porque no vale la pena salvar el estado anterior o hay otros problemas?
agbodike
3
@agbodike: cuando se trabaja como un solo desarrollador o como parte de un equipo muy pequeño, tfstate se puede mantener en git siempre que se comprometa y empuje regularmente para evitar conflictos. Mi siguiente paso es configurar esto según sus documentos de estado remoto en S3 (que también dicen: "hace que trabajar con Terraform en un equipo sea complicado, ya que es una fuente frecuente de conflictos de fusión. El estado remoto ayuda a aliviar estos problemas"). . Como con la mayoría de las cosas, una buena comunicación en equipo puede ayudar a aliviar la mayoría / todos los problemas, independientemente de la táctica para mantener el estado :-)
Ewan
1
@ the0ther: me temo que mi repositorio principal es propietario, sin embargo, actualmente estoy trabajando en uno personal que pondré a disposición del público en un futuro muy cercano.
Ewan
2
¿Tuviste suerte en un repositorio de Git @Ewan? Me encantaría ver lo que estás haciendo.
David
85

Usamos Terraform en gran medida y nuestra configuración recomendada es la siguiente:

Diseño de archivo

Recomendamos encarecidamente almacenar el código de Terraform para cada uno de sus entornos (por ejemplo, stage, prod, qa) en conjuntos separados de plantillas (y por lo tanto, .tfstatearchivos separados ). Esto es importante para que sus entornos separados estén realmente aislados entre sí al realizar cambios. De lo contrario, mientras se juega con algo de código en la puesta en escena, también es muy fácil hacer estallar algo en la producción. Consulte Terraform, VPC y por qué desea un archivo tfstate por env para una explicación detallada de por qué.

Por lo tanto, nuestro diseño de archivo típico se ve así:

stage
   main.tf
   vars.tf
   outputs.tf
prod
   main.tf
   vars.tf
   outputs.tf
global
   main.tf
   vars.tf
   outputs.tf

Todo el código de Terraform para la VPC de etapa va a la stagecarpeta, todo el código de la VPC de producción va a la prodcarpeta y todo el código que vive fuera de una VPC (por ejemplo, usuarios de IAM, temas de SNS, depósitos de S3) va a la globalcarpeta .

Tenga en cuenta que, por convención, normalmente dividimos nuestro código Terraform en 3 archivos:

  • vars.tf: Variables de entrada.
  • outputs.tf: Variables de salida.
  • main.tf: Los recursos reales.

Módulos

Normalmente, definimos nuestra infraestructura en dos carpetas:

  1. infrastructure-modules: Esta carpeta contiene módulos pequeños, reutilizables y con versiones. Piense en cada módulo como un modelo de cómo crear una única pieza de infraestructura, como una VPC o una base de datos.
  2. infrastructure-live: Esta carpeta contiene la infraestructura real en ejecución, que crea combinando los módulos en infrastructure-modules. Piense en el código de esta carpeta como las casas reales que construyó a partir de sus planos.

Un módulo de Terraform es cualquier conjunto de plantillas de Terraform en una carpeta. Por ejemplo, podríamos tener una carpeta llamada vpcen infrastructure-modulesque define todas las tablas de enrutamiento, subredes, puertas de enlace, ACL, etc. para una sola VPC:

infrastructure-modules
   vpc
     main.tf
     vars.tf
     outputs.tf

Luego, podemos usar ese módulo en infrastructure-live/stagey infrastructure-live/prodpara crear las VPC de etapa y producción. Por ejemplo, esto es lo que infrastructure-live/stage/main.tfpodría parecer:

module "stage_vpc" {
  source = "git::[email protected]:gruntwork-io/module-vpc.git//modules/vpc-app?ref=v0.0.4"

  vpc_name         = "stage"
  aws_region       = "us-east-1"
  num_nat_gateways = 3
  cidr_block       = "10.2.0.0/18"
}

Para usar un módulo, use el modulerecurso y apunte su sourcecampo a una ruta local en su disco duro (por ejemplo source = "../infrastructure-modules/vpc") o, como en el ejemplo anterior, una URL de Git (vea las fuentes del módulo ). La ventaja de la URL de Git es que podemos especificar un git sha1 o tag ( ref=v0.0.4) específico . Ahora, no solo definimos nuestra infraestructura como un grupo de pequeños módulos, sino que podemos versionar esos módulos y actualizarlos o deshacerlos cuidadosamente según sea necesario.

Hemos creado una serie de paquetes de infraestructura reutilizables, probados y documentados para crear VPC, clústeres de Docker, bases de datos, etc., y bajo el capó, la mayoría de ellos son solo módulos Terraform versionados.

Estado

Cuando usa Terraform para crear recursos (por ejemplo, instancias EC2, bases de datos, VPC), registra información sobre lo que creó en un .tfstatearchivo. Para realizar cambios en esos recursos, todos los miembros de su equipo necesitan acceso a este mismo .tfstatearchivo, pero NO debe registrarlo en Git (consulte aquí para obtener una explicación del motivo ).

En su lugar, recomendamos almacenar .tfstatearchivos en S3 habilitando Terraform Remote State , que automáticamente empujará / extraerá los archivos más recientes cada vez que ejecute Terraform. Asegúrese de habilitar el control de versiones en su bucket de S3 para que pueda volver a .tfstatearchivos más antiguos en caso de que de alguna manera corrompa la última versión. Sin embargo, una nota importante: Terraform no proporciona bloqueo . Entonces, si dos miembros del equipo se ejecutan terraform applyal mismo tiempo en el mismo .tfstatearchivo, es posible que terminen sobrescribiendo los cambios del otro.

Para resolver este problema, creamos una herramienta de código abierto llamada Terragrunt , que es un contenedor delgado para Terraform que usa Amazon DynamoDB para proporcionar bloqueo (que debería ser completamente gratuito para la mayoría de los equipos). Consulte Agregar configuración y bloqueo de estado remoto automático a Terraform con Terragrunt para obtener más información.

Otras lecturas

Acabamos de comenzar una serie de publicaciones de blog llamadas Una guía completa de Terraform que describe en detalle todas las mejores prácticas que hemos aprendido para usar Terraform en el mundo real.

Actualización: la serie de publicaciones de blog de la Guía completa de Terraform se hizo tan popular que la expandimos a un libro llamado Terraform: Up & Running !

Yevgeniy Brikman
fuente
Creo que esta es la respuesta correcta. Utilice módulos, versionelos y mantenga los entornos separados.
wrangler
¿Es necesario volver a ejecutar el paso de configuración remota cada vez que desee trabajar en un componente / entorno / módulo de terraform diferente / lo que sea si no se usa terragrunt o algún otro contenedor?
jmreicha
@jmreicha: Debe ejecutar remote configsi acaba de verificar sus configuraciones de Terraform o si desea cambiar una configuración remota anterior. Terraform 0.9 introducirá el concepto de backends, que simplificará mucho esto. Vea este PR para más detalles.
Yevgeniy Brikman
Para que lo entienda, estoy trabajando en una 'etapa' de entorno pero luego empiezo a trabajar en 'prod'. Necesitaré volver a ejecutar el remote configcomando para apuntar al estado de prod. Suponiendo un estado diferente por entorno. ¿Está bien? Espero la v0.9.
jmreicha
Si iba a implementar exactamente el mismo conjunto de .tfarchivos en dos entornos diferentes, sí, necesitaría ejecutarlo remote configcada vez que cambiara. Obviamente, esto es muy propenso a errores, por lo que no recomiendo usar esta técnica. En su lugar, consulte el diseño de archivo de Terraform recomendado en esta publicación de blog junto con cómo usar los módulos de Terraform en esta publicación de blog .
Yevgeniy Brikman
9

Anteriormente remote configpermitía esto, pero ahora ha sido reemplazado por " backends ", por lo que terraform remote ya no está disponible.

terraform remote config -backend-config="bucket=<s3_bucket_to_store_tfstate>" -backend-config="key=terraform.tfstate" -backend=s3
terraform remote pull
terraform apply
terraform remote push

Consulte los documentos para obtener más detalles.

Shantanu
fuente
¿Es necesario reconfigurar la fuente remota cada vez que desee trabajar en un componente / entorno / módulo de terraform diferente / lo que sea?
jmreicha
6

Cubierto con más profundidad por @Yevgeny Brikman pero respondiendo específicamente a las preguntas del OP:

¿Cuál es la mejor práctica para administrar realmente los archivos y el estado de terraform?

Utilice git para archivos TF. Pero no registre los archivos de estado (es decir, tfstate). En su lugar, utilice Terragruntpara sincronizar / bloquear archivos de estado en S3.

pero ¿me comprometo también con el estado?

No.

¿Debería residir en algún lugar como S3?

si

Snowcrash
fuente
2

Sé que hay muchas respuestas aquí, pero mi enfoque es bastante diferente.

   Modules
   Environment management 
   Separation of duties

Módulos

  1. Cree módulos para colecciones lógicas de recursos. Ejemplo: si su objetivo es implementar una API, que requiere una base de datos, máquinas virtuales HA, ajuste de escala automático, DNS, PubSub y almacenamiento de objetos, entonces todos estos recursos deben tener una plantilla en un solo módulo.
  2. Evite crear módulos que utilicen un solo recurso. Esto se puede y se ha hecho, y muchos de los módulos del registro lo hacen, pero es una práctica que ayuda con la accesibilidad a los recursos en lugar de la orquestación de la infraestructura. Ejemplo: un módulo para AWS EC2 ayuda al usuario a acceder a EC2 haciendo que las configuraciones complejas sean más fáciles de invocar, pero un módulo como el ejemplo en 1. ayuda al usuario a orquestar la aplicación, el componente o la infraestructura impulsada por el servicio.
    1. Evite las declaraciones de recursos en su espacio de trabajo. Se trata más de mantener su código ordenado y organizado. Como los módulos se pueden versionar fácilmente, tiene más control sobre sus versiones.

Gestión medioambiental

IaC ha hecho que el proceso SDLC sea relevante para la gestión de la infraestructura y no es normal esperar tener una infraestructura de desarrollo y entornos de aplicaciones de desarrollo.

  1. No use carpetas para administrar sus entornos IaC. Esto conduce a la deriva, ya que no existe una plantilla común para su infraestructura.
  2. Utilice un solo espacio de trabajo y variables para controlar las especificaciones del entorno. Ejemplo: escriba sus módulos de modo que cuando cambie la variable de entorno (var.stage es popular) el plan se modifique para adaptarse a sus requisitos. Normalmente, los entornos deben variar lo menos posible, siendo la cantidad, la exposición y la capacidad las configuraciones variables. El desarrollador puede implementar 1 VM con 1 núcleo y 1 GB de RAM en topología privada, pero la producción puede ser de 3 VM con 2 núcleos y 4 GB de RAM con topología pública adicional. Por supuesto, puede tener más variación: dev puede ejecutar el proceso de la base de datos en el mismo servidor que la aplicación para ahorrar costos, pero la producción puede tener una instancia de base de datos dedicada. Todo esto se puede gestionar cambiando una sola variable, declaraciones ternarias e interpolación.

Separación de tareas

Si está en una organización pequeña o está ejecutando una infraestructura personal, esto realmente no se aplica, pero lo ayudará a administrar sus operaciones.

  1. Divida su infraestructura por deberes, responsabilidades o equipos. Ejemplo: control central de TI subyacente a los servicios compartidos (redes virtuales, subredes, direcciones IP públicas, grupos de registros, recursos de gobernanza, bases de datos de múltiples inquilinos, claves compartidas, etc.) mientras que el equipo de API solo controla los recursos necesarios para su servicio (VM, LB , PubSub, etc.) y consumen los servicios de TI central a través de fuentes de datos y búsquedas de estado remotas.
    1. Gobierne el acceso del equipo. Ejemplo: TI central puede tener derechos de administrador, pero el equipo de API solo tiene acceso a un conjunto restringido de API de nube pública.

Esto también ayuda con las preocupaciones de liberación, ya que encontrará que algunos recursos rara vez cambian, mientras que otros cambian todo el tiempo. La separación elimina el riesgo y la complejidad.

Esta estrategia establece un paralelismo con la estrategia de cuentas múltiples de AWS. Lea para obtener más información.

CI / CD

Este es un tema en sí mismo, pero Terraform funciona muy bien dentro de una buena canalización. El error más común aquí es tratar la IC como una solución milagrosa. Técnicamente, Terraform solo debería aprovisionar infraestructura durante las etapas de una tubería de ensamblaje. Esto sería independiente de lo que sucede en las etapas de CI, donde normalmente se validan y prueban las plantillas.

NB Escrito en el móvil, así que disculpe cualquier error.

Henry Dobson
fuente
0

Antes de que las respuestas hayan sido muy sólidas e informativas, intentaré agregar mis 2 centavos aquí.

Recomendaciones comunes para estructurar código

  1. Es más fácil y rápido trabajar con una menor cantidad de recursos:

    • Cmds terraform plany terraformapply hacen llamadas a la API en la nube para verificar el estado de los recursos.
    • Si tiene toda su infraestructura en una sola composición, esto puede llevar muchos minutos (incluso si tiene varios archivos en la misma carpeta).
  2. El radio de explosión es más pequeño con menos recursos:

    • Aislar los recursos no relacionados entre sí colocándolos en composiciones separadas (carpetas) reduce el riesgo si algo sale mal.
  3. Inicie su proyecto usando el estado remoto:

  4. Intente practicar una estructura coherente y una convención de nomenclatura:

    • Al igual que el código de procedimiento, el código de Terraform debe escribirse para que la gente lo lea primero, la coherencia ayudará cuando se produzcan cambios dentro de seis meses.
    • Es posible mover recursos en el archivo de estado de Terraform, pero puede ser más difícil hacerlo si tiene una estructura y un nombre inconsistentes.
  5. Mantenga los módulos de recursos lo más sencillos posible.

  6. No codifique valores que puedan pasarse como variables o descubrirse utilizando fuentes de datos.

  7. Utilice datafuentes y terraform_remote_stateespecíficamente como un pegamento entre los módulos de infraestructura dentro de la composición.

( artículo de referencia: https://www.terraform-best-practices.com/code-structure )


Ejemplo:

Es más fácil y rápido trabajar con una menor cantidad de recursos, por lo que a continuación presentamos un diseño de código recomendado.

NOTA: solo como referencia no se debe seguir estrictamente ya que cada proyecto tiene sus propias características específicas

.
├── 1_tf-backend #remote AWS S3 + Dynamo Lock tfstate 
   ├── main.tf
   ├── ...
├── 2_secrets
   ├── main.tf
   ├── ...
├── 3_identities
   ├── account.tf
   ├── roles.tf
   ├── group.tf
   ├── users.tf
   ├── ...
├── 4_security
   ├── awscloudtrail.tf
   ├── awsconfig.tf
   ├── awsinspector.tf
   ├── awsguarduty.tf
   ├── awswaf.tf
   └── ...
├── 5_network
   ├── account.tf
   ├── dns_remote_zone_auth.tf
   ├── dns.tf
   ├── network.tf
   ├── network_vpc_peering_dev.tf
   ├── ...
├── 6_notifications
   ├── ...
├── 7_containers
   ├── account.tf
   ├── container_registry.tf
   ├── ...
├── config
   ├── backend.config
   └── main.config
└── readme.md
Exequiel Barrirero
fuente
0

Creo que es necesario seguir algunas prácticas recomendadas al utilizar terraform para orquestar la infraestructura.

  1. No vuelva a escribir el mismo código (reutilización)
  2. Mantenga la configuración del entorno separada para mantenerla fácilmente.
  3. Use el backend remoto s3 (cifrado) y la base de datos dynamo para manejar el bloqueo de concurrencia
  4. Cree un módulo y use ese módulo en la infraestructura principal varias veces, es como una función reutilizable que se puede llamar varias veces pasando diferentes parámetros.

Manejar múltiples entornos

La mayoría de las veces, la forma recomendada es usar terraform 'espacio de trabajo' para manejar los múltiples entornos, pero creo que el uso del espacio de trabajo podría variar según la forma de trabajo en una organización. Otro es almacenar el código de Terraform para cada uno de sus entornos (por ejemplo, etapa, prod, QA) para separar los estados del entorno. Sin embargo, en este caso solo estamos copiando el mismo código en muchos lugares.

├── main.tf
├── dev
   ├── main.tf
   ├── output.tf
   └── variables.tf
└── prod
├── main.tf
├── output.tf
└── variables.tf

Seguí un enfoque diferente para manejar y evitar la duplicación del mismo código de terraform manteniéndolo en cada carpeta de entorno, ya que creo que la mayoría de las veces todos los entornos serían 90% iguales.

├── deployment
 ├── 01-network.tf
 ├── 02-ecs_cluster.tf
 ├── 03-ecs_service.tf
 ├── 04-eks_infra.tf
 ├── 05-db_infra.tf
 ├── 06-codebuild-k8s.tf
 ├── 07-aws-secret.tf
 ├── backend.tf
 ├── provider.tf
 └── variables.tf
├── env
 ├── dev
  ├── dev.backend.tfvar
  └── dev.variables.tfvar
 └── prod
 ├── prod.backend.tfvar
 └── prod.variables.tfvar
├── modules
 └── aws
 ├── compute
  ├── alb_loadbalancer
  ├── alb_target_grp
  ├── ecs_cluster
  ├── ecs_service
  └── launch_configuration
 ├── database
  ├── db_main
  ├── db_option_group
  ├── db_parameter_group
  └── db_subnet_group
 ├── developertools
 ├── network
  ├── internet_gateway
  ├── nat_gateway
  ├── route_table
  ├── security_group
  ├── subnet
  ├── vpc
 └── security
 ├── iam_role
 └── secret-manager
└── templates

Configuración relacionada con los entornos

Mantenga la configuración y los parámetros relacionados con el entorno separados en un archivo variable y transfiera ese valor para configurar la infraestructura. por ejemplo, como a continuación

  • dev.backend.tfvar

      region = "ap-southeast-2"
      bucket = "dev-samplebackendterraform"
      key = "dev/state.tfstate"
      dynamo_db_lock = "dev-terraform-state-lock"
  • dev.variable.tfvar

    environment                     =   "dev"
    vpc_name                        =   "demo"
    vpc_cidr_block                  =   "10.20.0.0/19"
    private_subnet_1a_cidr_block    =   "10.20.0.0/21"
    private_subnet_1b_cidr_block    =   "10.20.8.0/21"
    public_subnet_1a_cidr_block     =   "10.20.16.0/21"
    public_subnet_1b_cidr_block     =   "10.20.24.0/21"

Omisión condicional de la parte de infraestructura

Cree una configuración en un archivo de variable específico de env y, en función de esa variable, decida crear u omitir esa parte. De esta manera, según la necesidad, se puede omitir la parte específica de la infraestructura.

variable vpc_create {
   default = "true"
}

module "vpc" {
  source = "../modules/aws/network/vpc"
  enable = "${var.vpc_create}"
  vpc_cidr_block = "${var.vpc_cidr_block}"
  name = "${var.vpc_name}"
 }

 resource "aws_vpc" "vpc" {
    count                = "${var.enable == "true" ? 1 : 0}"
    cidr_block           = "${var.vpc_cidr_block}"
    enable_dns_support   = "true"
   enable_dns_hostnames = "true"
}

Se requiere el siguiente comando para inicializar y ejecutar los cambios de infraestructura para cada entorno, cd a la carpeta de entorno requerida.

  terraform init -var-file=dev.variables.tfvar -backend-config=dev.backend.tfvar ../../deployment/

  terraform apply -var-file=dev.variables.tfvar ../../deployment

Para referencia: https://github.com/mattyait/devops_terraform

Mahattam
fuente
0

No me gusta la idea de subcarpetas porque esto dará como resultado diferentes fuentes por entorno y esto tiende a desviarse.

El mejor enfoque es tener una sola pila para todos los entornos (digamos dev, preprod y prod). Para trabajar en un solo uso ambiental terraform workspace.

terraform workspace new dev

Esto crea un nuevo espacio de trabajo. Esto incluye un archivo de estado dedicado y la variable terraform.workspaceque puede usar en su código.

resource "aws_s3_bucket" "bucket" {
  bucket = "my-tf-test-bucket-${terraform.workspace}"
}

De esta manera obtendrá cubos llamados

  • my-tf-test-bucket-dev
  • my-tf-test-bucket-preprod
  • my-tf-test-bucket-prod

después de aplicar a los espacios de trabajo anteriores (se usa terraform workspace select <WORKSPACE>para cambiar de entorno). Para hacer que el código sea incluso a prueba de múltiples regiones, hágalo así:

data "aws_region" "current" {}

resource "aws_s3_bucket" "bucket" {
  bucket = "my-tf-test-bucket-${data.aws_region.current.name}-${terraform.workspace}"
}

to get (para la región us-east-1)

  • my-tf-test-bucket-us-east-1-dev
  • my-tf-test-bucket-us-east-1-preprod
  • my-tf-test-bucket-us-east-1-prod
Magister Halderian
fuente
0

Algunas mejores prácticas de Terraform a seguir:

  1. Evite la codificación rígida: a veces, los desarrolladores crean recursos manualmente directamente. Debe marcar estos recursos y utilizar terraform import para incluirlos en los códigos. Una muestra:

    account_number = “123456789012" account_alias = "mycompany"

  2. Ejecute Terraform desde un contenedor Docker: Terraform lanza un contenedor Docker oficial que le permite controlar fácilmente qué versión puede ejecutar.

Se recomienda ejecutar el contenedor Terraform Docker cuando configure su trabajo de compilación en la canalización de CI / CD.

TERRAFORM_IMAGE=hashicorp/terraform:0.11.7
TERRAFORM_CMD="docker run -ti --rm -w /app -v ${HOME}/.aws:/root/.aws -v ${HOME}/.ssh:/root/.ssh -v `pwd`:/app $TERRAFORM_IMAGE"

Para obtener más información, consulte mi blog: https://medium.com/tech-darwinbox/how-darwinbox-manages-infrastructure-at-scale-with-terraform-371e2c5f04d3

ND1772
fuente
0

Me gustaría contribuir a este hilo.

  • Lo más probable es que sea AWS S3 + DynamoDB, a menos que esté utilizando Terraform Cloud.
  • Infraestructura separada (red + RBAC) de backends de producción y no productivos.
  • Planifique deshabilitar el acceso a los archivos de estado (acceso a la red y RBAC) desde fuera de una red designada (por ejemplo, grupo de agentes de implementación).
  • No mantenga la infraestructura backend de Terraform con el entorno de tiempo de ejecución. Utilice una cuenta separada.
  • Habilite el control de versiones de objetos en sus backends de Terraform para evitar perder cambios y archivos de estado, y para mantener el historial de estado de Terraform.

En algunos casos especiales, se requerirá acceso manual a los archivos de estado de Terraform. Cosas como refactorizar, romper cambios o arreglar defectos requerirán que el personal de operaciones ejecute las operaciones estatales de Terraform. Para tales ocasiones, planifique un acceso controlado extraordinario al estado de Terraform utilizando un host bastión, VPN, etc.

Consulte un blog de mejores prácticas más extenso que cubre esto en detalle, incluidas las pautas para las canalizaciones de CI / CD.

Piotr Gwiazda
fuente
-1

Si todavía está buscando la mejor solución, eche un vistazo a los espacios de trabajo que pueden reemplazar el mantenimiento de una estructura de carpetas de entorno diferente que puede tener variables específicas del espacio de trabajo.

Como mencionó Yevgeniy Brikman , es mejor tener una estructura de módulos.

Rajendra
fuente
-1

Utilice terraform cloud para administrar y guardar estados, junto con los consejos anteriores.

Den Zalman
fuente