Luego de de nuestra prolongada selección de información hemos podido solucionar esta dificultad que presentan ciertos de nuestros usuarios. Te ofrecemos la solución y nuestro deseo es servirte de gran apoyo.
Solución:
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 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 mientras 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:
- Base de base de AMI comunes que incluyen módulos reutilizables, por ejemplo, títeres.
- Infraestructura central provista por DevOps usando Terraform.
- 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.).
- 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.
- 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 entorno, 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 cuerdos, pero los expone como variables que pueden ser sobrescritas por nuestro “pegamento”.
Pegamento
Tenemos un segundo repositorio con nuestro glue
que 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 cuentas de AWS específicas .tf
archivos que proporcionan recursos globales (como roles de IAM); el siguiente es el nivel de región con EC2 SSH público keys; Finalmente en nuestro entorno (dev
, stg
, prod
etc.) se almacenan nuestras configuraciones de VPC, creación de instancias y conexiones de intercambio de tráfico, etc.
Nota al margen: Como puede ver, voy en contra de mi propio consejo antes de mantener terraform.tfstate
en 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 debería no vaya en Git – y son correctos. 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 completamente 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: dev
y prod
. Cada uno tiene sus propias variables y salidas, reutilizando nuestros módulos creados anteriormente. los remote_state
El proveedor también ayuda a compartir los resultados de los recursos creados entre los 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 plan
mando. Podemos inspeccionar y saber qué se ejecutará sin el riesgo de algunos cambios entre los plan
y apply
etapa (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.
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, etapa, prod, qa) en conjuntos separados de plantillas (y por lo tanto, por separado .tfstate
archivos). Esto es importante para que sus entornos separados estén realmente aislados entre sí al realizar cambios. De lo contrario, mientras se juega con algún 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 etapa de VPC entra en el stage
carpeta, todo el código de la VPC de prod va a la prod
carpeta, y todo el código que vive fuera de una VPC (p. ej., usuarios de IAM, temas de SNS, depósitos de S3) entra en la carpeta global
carpeta.
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:
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.infrastructure-live
: Esta carpeta contiene la infraestructura real en ejecución, que crea combinando los módulos eninfrastructure-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 vpc
en infrastructure-modules
que 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/stage
y infrastructure-live/prod
para crear las VPC de etapa y producción. Por ejemplo, esto es lo que infrastructure-live/stage/main.tf
podría verse así:
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, usa el module
recurso y apuntar su source
campo a una ruta local en su disco duro (p. ej. source = "../infrastructure-modules/vpc"
) o, como en el ejemplo anterior, una URL de Git (consulte las fuentes del módulo). La ventaja de la URL de Git es que podemos especificar una etiqueta o git sha1 específica (ref=v0.0.4
). Ahora, no solo definimos nuestra infraestructura como un grupo de pequeños módulos, sino que podemos versionar esos módulos y actualizarlos o revertirlos 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 .tfstate
expediente. Para realizar cambios en esos recursos, todos los miembros de su equipo deben tener acceso a este mismo .tfstate
archivo, pero NO debe registrarlo en Git (consulte aquí para obtener una explicación de por qué).
En su lugar, recomendamos almacenar .tfstate
archivos 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 versiones anteriores .tfstate
archivos 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 corren terraform apply
al mismo tiempo en el mismo .tfstate
archivo, pueden terminar sobrescribiendo los cambios del otro.
Editar 2020: Terraform ahora admite el bloqueo: https://www.terraform.io/docs/state/locking.html
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 llamada 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!
Previamente remote config
permitido esto, pero ahora ha sido reemplazado por “backends”, por lo que terraform remote ya no está disponible.
terraform remote config -backend-config="bucket=" -backend-config="key=terraform.tfstate" -backend=s3
terraform remote pull
terraform apply
terraform remote push
Consulte los documentos para obtener más detalles.
Si guardas alguna indecisión o capacidad de refinar nuestro noticia eres capaz de dejar un informe y con placer lo ojearemos.