home ec2 east aws bash amazon-web-services packer terraform

bash - east - ec2 dashboard



¿Cómo puedo encadenar automáticamente la salida ami id del empaquetador a las variables terraformadas? (3)

Debe considerar el uso de la Fuente de datos de Terraform para aws_ami . Con esto, puede confiar en las etiquetas personalizadas que configura en la AMI cuando se crea (por ejemplo, un número de versión o marca de tiempo). Luego, en la configuración de Terraform, simplemente puede filtrar las AMI disponibles para esta cuenta y región para obtener la ID de AMI que necesita.

https://www.terraform.io/docs/providers/aws/d/ami.html

data "aws_ami" "nat_ami" { most_recent = true executable_users = ["self"] filter { name = "owner-alias" values = ["amazon"] } filter { name = "name" values = ["amzn-ami-vpc-nat*"] } name_regex = "^myami-//d{3}" owners = ["self"] }

NOTA: en el ejemplo anterior (de los documentos), la combinación de filtros es probablemente excesiva. Probablemente puedas arreglártelas con algo como:

data "aws_ami" "image" { most_recent = true owners = ["self"] filter { name = "tag:Application" values = ["my-app-name"] } } output "ami_id" { value = "${data.aws_ami.image.id}" }

¡Un beneficio adicional de esto es que puede implementarse en múltiples regiones con la misma configuración y sin mapa de variables!

Estoy utilizando Packer con Ansible Provisioner para crear un ami y terraform para configurar la infraestructura con ese ami como fuente, algo similar a este artículo: http://www.paulstack.co.uk/blog/2016/01/02/building-an-elasticsearch-cluster-in-aws-with-packer-and-terraform

Cuando Command packer build pack.json completa correctamente, obtengo el ID de ami de salida en este formato:

eu-central-1: ami-12345678

En mis variables de terraformas variables.tf necesito especificar la fuente ami id, la región, etc. El problema aquí es que no quiero especificarlas manualmente o varias veces. Para la región (que sé de antemano) es fácil ya que puedo usar variables de entorno en ambas situaciones, pero ¿qué pasa con la salida ami? ¿Existe una forma integrada de encadenar estos productos o algún enfoque no tan intrincado para hacerlo?

EDIT: Hacky enfoque para cualquier persona que pueda estar interesado. En esta solución, voy a grep la región aws & ami de la salida del empaquetador y uso una expresión regular en perl para escribir el resultado en un archivo terraform.tfvars :

vars=$(pwd)"/terraform.tfvars" packer build pack.json | / tee /dev/tty | / grep -E -o ''/w{2}-/w+-/w{1}: ami-/w+'' | / perl -ne ''@parts = split /[:,/s]+/, $_; print "aws_amis." . $parts[0] ." = /"" . $parts[1] . "/"/n"'' > ${vars}


Este es el enfoque que utilicé:

  1. Envuelva la llamada del empaquetador y obtenga la AMI analizando la salida
  2. Use la AMI analizada para crear archivos Terraform que proporcionen el valor como una variable

Es similar a la versión en la respuesta editada. En más detalle, puede verse así:

Primero, crea un archivo llamado ami.tf.template :

# "ami.tf" was automatically generated from the template "ami.tf.template". variable "ami" { default = "${AMI_GENERATED_BY_PACKER}" description = "The latest AMI." }

Esta plantilla se utilizará para crear el archivo ami.tf , que hace que la AMI del empaquetador esté disponible para su configuración de Terraform existente.

En segundo lugar, cree un script de envoltorio de shell para ejecutar el empaquetador. Puedes usar las siguientes ideas:

# run packer (prints to stdout, but stores the output in a variable) packer_out=$(packer build packer.json | tee /dev/tty) # packer prints the id of the generated AMI in its last line ami=$(echo "$packer_out" | tail -c 30 | perl -n -e''/: (ami-.+)$/ && print $1'') # create the ''ami.tf'' file from the template: export AMI_GENERATED_BY_PACKER="$ami" && envsubst < ami.tf.template > ami.tf

Una vez que se realiza el script, se ha creado un archivo ami.tf , que puede tener este aspecto:

# "ami.tf" was automatically generated from the template "ami.tf.template". variable "ami" { default = "ami-aa92a441" description = "The latest AMI." }

Finalmente, ponga ese archivo junto a su configuración existente de Terraform. A continuación, puede acceder a la AMI de esta manera:

resource "aws_launch_configuration" "foo" { image_id = "${var.ami}" ... }


La manera "oficial" recomendada por Hashicorp es usar su producto Atlas como un "intermediario" entre los dos. Usaría el post-procesador Atlas en Packer para registrar los artefactos (ID de AMI, en su caso) y luego usaría el recurso atlas_artifact en Terraform para volver a leer los ID de nuevo para usarlos en Terraform.

En este caso, obtendría los identificadores del recurso en lugar de pasarlos usando variables.

Aparte de Atlas, las otras opciones son bastante limitadas y, en algunos casos, intrépidas.

Si desea hacerlo sin ningún servicio externo, puede experimentar con el postprocesador de shell local como una forma de ejecutar un comando local en su artefacto, o puede usar la salida legible por la máquina para extraer las ID de AMI y Escríbalos en un archivo de variables para Terraform.

Otra opción es escribir su propio complemento de post-procesador que interactúe con algún software que ya esté utilizando, como alternativa a Atlas. Por ejemplo, con algunos de mis colegas escribí un postprocesador para registrar artefactos como metadatos en Buildkite , que luego recuperamos utilizando la API de Buildkite . Esto requiere escribir código personalizado en Go.

En el momento de escribir, la versión 0.7 de Terraform aún está en desarrollo, pero está previsto que incluya una nueva función que permita consultar directamente las API de EC2 para las AMI, lo que permitirá (si realmente llega a 0.7) permitir una opción adicional de etiquetar la AMI. con Packer y luego encontrarlo directamente desde EC2 usando esas etiquetas. Esto utiliza EC2 en sí mismo como el "intermediario", lo que tal vez sea menos incómodo ya que de todos modos ya estaba involucrado como almacenamiento para el AMI.