Consultar etiquetas EC2 desde dentro de la instancia

96

Amazon agregó recientemente la maravillosa característica de etiquetar instancias EC2 con pares clave-valor para facilitar un poco la administración de un gran número de VM.

¿Hay alguna forma de consultar estas etiquetas de la misma manera que algunos de los otros datos establecidos por el usuario? Por ejemplo:

$ curl http://169.254.169.254/latest/meta-data/placement/availability-zone
us-east-1d

¿Existe alguna forma similar de consultar las etiquetas?

Josh Lindsey
fuente

Respuestas:

36

Puede utilizar una combinación de la herramienta de metadatos de AWS (para recuperar su ID de instancia) y la nueva API de etiquetas para recuperar las etiquetas de la instancia actual.

drxzcl
fuente
OK, seguí ese enlace y parece que es la documentación de la API. ¿No hay ninguna herramienta que pueda usar o necesito leer la documentación de la API y escribir mi propia herramienta?
Edward Falk
3
¿Está fácilmente disponible el comando ec2-describe-tags? Supuestamente está en el paquete ec2-api-tools, pero no obtuve nada más que 404 cuando intenté instalarlo.
Edward Falk
2
dé un ejemplo, obtenga el valor del rol de la etiqueta: aws ec2 describe-tags --filters Nombre = resource-id, Values ​​= ec2metadata --instance-id--out = json | jq '.Tags [] | select (.Key == "role") | .Value '
jolestar
11
Este es un indicador de una respuesta, pero no una respuesta en sí misma
Roy Truelove
3
La ec2metadataherramienta está obsoleta. Ahora consulta la URL 'mágica' en 169.254.169.254/latest/meta-data ; presione con cURL y le brinda puntos finales mágicos que puede usar para obtener varios bits de datos. En este caso, curl http://169.254.169.254/latest/meta-data/instance-idobtenga su ID de instancia
Asfa y Qazi
52

El siguiente script bash devuelve el nombre de su instancia ec2 actual (el valor de la etiqueta "Nombre"). Modifique TAG_NAME a su caso específico.

TAG_NAME="Name"
INSTANCE_ID="`wget -qO- http://instance-data/latest/meta-data/instance-id`"
REGION="`wget -qO- http://instance-data/latest/meta-data/placement/availability-zone | sed -e 's:\([0-9][0-9]*\)[a-z]*\$:\\1:'`"
TAG_VALUE="`aws ec2 describe-tags --filters "Name=resource-id,Values=$INSTANCE_ID" "Name=key,Values=$TAG_NAME" --region $REGION --output=text | cut -f5`"

Para instalar aws cli

sudo apt-get install python-pip -y
sudo pip install awscli

En caso de que use IAM en lugar de credenciales explícitas, use estos permisos de IAM:

{
  "Version": "2012-10-17",
  "Statement": [
    {    
      "Effect": "Allow",
      "Action": [ "ec2:DescribeTags"],
      "Resource": ["*"]
    }
  ]
}
itaifrenkel
fuente
Estaba obteniendo "No está autorizado para realizar esta operación" con aws ec2 describe-tags. Necesitaba agregar este IAM a las políticas en línea de mi función de IAM. ¡Gracias!
Victor D.
Una muy leve optimización podría consistir en sustituir el | cut -f5con --query="Tags[0].Value".
Richard A Quadling
47

Una vez que tenga ec2-metadatay ec2-describe-tagsha instalado (como se menciona en la respuesta de Ranieri anterior ), esto es un ejemplo del comando shell para obtener el "nombre" de la instancia actual, suponiendo que tiene una etiqueta "Name = Foo" en él.

Supone que las variables de entorno EC2_PRIVATE_KEY y EC2_CERT están configuradas.

ec2-describe-tags \
  --filter "resource-type=instance" \
  --filter "resource-id=$(ec2-metadata -i | cut -d ' ' -f2)" \
  --filter "key=Name" | cut -f5

Esto vuelve Foo.

pensar demasiado
fuente
17
Hubiera sido bueno si mis procesos pudieran obtener las etiquetas para la instancia actual sin tener que tener EC2_PRIVATE_KEY en la instancia también. :-(
William Payne
1
@ william-payne Sí, eso es realmente patético. Quizás usando IAM de Amazon, al menos podría usar un usuario con acceso muy limitado a cualquier cosa. FWIW, ya no uso este enfoque y solo uso scripts externos para configurar la caja.
pensar demasiado el
12
@WilliamPayne Puede configurar un rol de IAM con la política "Acceso de solo lectura de Amazon EC2" y crear la instancia que tenga ese rol. También es posible crear una política personalizada que tenga solo el privilegio "DescribeTags" si desea ser más granular.
roverwolf
@WilliamPayne Me gustó la sugerencia de Roverwolf. Funcionó muy bien. De hecho, respondí otra pregunta con los detalles si quieres verla: stackoverflow.com/questions/9950586/…
Tony
2
Tenga en cuenta que el valor ec2-describe-tagspredeterminado es us-east-2. Pasa la --regionbandera para usar una región diferente.
Advait
15

Puede agregar esta secuencia de comandos a sus datos de usuario de inicio en la nube para descargar etiquetas EC2 en un archivo local:

#!/bin/sh
INSTANCE_ID=`wget -qO- http://instance-data/latest/meta-data/instance-id`
REGION=`wget -qO- http://instance-data/latest/meta-data/placement/availability-zone | sed 's/.$//'`
aws ec2 describe-tags --region $REGION --filter "Name=resource-id,Values=$INSTANCE_ID" --output=text | sed -r 's/TAGS\t(.*)\t.*\t.*\t(.*)/\1="\2"/' > /etc/ec2-tags

Necesita las herramientas de la AWS CLI instaladas en su sistema: puede instalarlas con una packagessección en un archivo de configuración de la nube antes del script, usar una AMI que ya las incluya o agregar un comando apto yumal principio del script.

Para acceder a las etiquetas EC2, necesita una política como esta en el rol de IAM de su instancia:

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "Stmt1409309287000",
      "Effect": "Allow",
      "Action": [
        "ec2:DescribeTags"
      ],
      "Resource": [
        "*"
      ]
    }
  ]
}

Las etiquetas EC2 de la instancia estarán disponibles /etc/ec2-tagsen este formato:

FOO="Bar"
Name="EC2 tags with cloud-init"

Puede incluir el archivo tal cual en un script de shell usando . /etc/ec2-tags, por ejemplo:

#!/bin/sh
. /etc/ec2-tags
echo $Name

Las etiquetas se descargan durante la inicialización de la instancia, por lo que no reflejarán los cambios posteriores.


El script y la política de IAM se basan en la respuesta de itaifrenkel.

Andrea
fuente
a + prefiero este método
Cmag
Lástima que esto se rompa para las etiquetas creadas por grupos de autoescalado:aws:autoscaling:groupName
Cmag
2
Entonces prueba esto:aws ec2 describe-tags --region $REGION --filter "Name=resource-id,Values=$INSTANCE_ID" --output=text | sed -r 's/TAGS\t(.*)\t.*\t.*\t(.*)/EC2_TAG_\1="\2"/' |sed -r 's/aws:autoscaling:/aws_autoscaling_/' > /etc/ec2-tags
Ryan Gooler
10

Si no se encuentra en la zona de disponibilidad predeterminada, los resultados de pensar demasiado volverán vacíos.

ec2-describe-tags \
   --region \
     $(curl -s http://169.254.169.254/latest/meta-data/placement/availability-zone  | sed -e "s/.$//") \
   --filter \
     resource-id=$(curl --silent http://169.254.169.254/latest/meta-data/instance-id)

Si desea agregar un filtro para obtener una etiqueta específica (elasticbeanstalk: environment-name en mi caso), puede hacerlo.

ec2-describe-tags \
   --region \
     $(curl -s http://169.254.169.254/latest/meta-data/placement/availability-zone  | sed -e "s/.$//") \
   --filter \
     resource-id=$(curl --silent http://169.254.169.254/latest/meta-data/instance-id) \
   --filter \
     key=elasticbeanstalk:environment-name | cut -f5

Y para obtener solo el valor de la etiqueta en la que filtré, canalizamos para cortar y obtenemos el quinto campo.

ec2-describe-tags \
  --region \
    $(curl -s http://169.254.169.254/latest/meta-data/placement/availability-zone  | sed -e "s/.$//") \
  --filter \
    resource-id=$(curl --silent http://169.254.169.254/latest/meta-data/instance-id) \
  --filter \
    key=elasticbeanstalk:environment-name | cut -f5
Michael Connor
fuente
gran trabajo, gracias, tener una instancia de dns diferente: los datos no me funcionan, para el último si necesita reemplazar la etiqueta de nombre elasticbeanstalk:environment-nameconName
detzu
5

Para Python:

from boto import utils, ec2
from os import environ

# import keys from os.env or use default (not secure)
aws_access_key_id = environ.get('AWS_ACCESS_KEY_ID', failobj='XXXXXXXXXXX')
aws_secret_access_key = environ.get('AWS_SECRET_ACCESS_KEY', failobj='XXXXXXXXXXXXXXXXXXXXX')

#load metadata , if  = {} we are on localhost
# http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/AESDG-chapter-instancedata.html
instance_metadata = utils.get_instance_metadata(timeout=0.5, num_retries=1)
region = instance_metadata['placement']['availability-zone'][:-1]
instance_id = instance_metadata['instance-id']

conn = ec2.connect_to_region(region, aws_access_key_id=aws_access_key_id, aws_secret_access_key=aws_secret_access_key)
# get tag status for our  instance_id using filters
# http://docs.aws.amazon.com/AWSEC2/latest/CommandLineReference/ApiReference-cmd-DescribeTags.html
tags = conn.get_all_tags(filters={'resource-id': instance_id, 'key': 'status'})
if tags:
    instance_status = tags[0].value
else:
    instance_status = None
    logging.error('no status tag for '+region+' '+instance_id)
Sergei
fuente
De fiar. Los lectores notan que para obtener información local básica, ni siquiera necesita credenciales, solo elinstance_metadata = utils.get_instance_metadata(timeout=0.5, num_retries=1)
Bartvds
Además, esto funciona muy bien con los roles de IAM: si establece un rol de instancia, boto detectará automáticamente el ID y la clave.
dbn
5

Alternativamente, puede usar la describe-instancesllamada cli en lugar de describe-tags:

Este ejemplo muestra cómo obtener el valor de la etiqueta 'my-tag-name' para la instancia:

aws ec2 describe-instances \
  --instance-id $(curl -s http://169.254.169.254/latest/meta-data/instance-id) \
  --query "Reservations[*].Instances[*].Tags[?Key=='my-tag-name'].Value" \
  --region ap-southeast-2 --output text

Cambie la región para adaptarse a sus circunstancias locales. Esto puede ser útil cuando su instancia tiene el privilegio describe-instance pero no describe-tags en la política de perfil de instancia

usuario de linux shonky
fuente
3

Con las API de 'datos de usuario' y 'metadatos' de AWS, es posible escribir un script que envuelva a puppet para iniciar una ejecución de puppet con un nombre de certificado personalizado.

Primero inicie una instancia de aws con datos de usuario personalizados: 'rol: servidor web'

#!/bin/bash

# Find the name from the user data passed in on instance creation
USER=$(curl -s "http://169.254.169.254/latest/user-data")
IFS=':' read -ra UDATA <<< "$USER"

# Find the instance ID from the meta data api
ID=$(curl -s "http://169.254.169.254/latest/meta-data/instance-id")
CERTNAME=${UDATA[1]}.$ID.aws

echo "Running Puppet for certname: " $CERTNAME
puppet agent -t --certname=$CERTNAME 

Esto llama a puppet con un nombre de certificado como 'webserver.i-hfg453.aws', luego puede crear un manifiesto de nodo llamado 'webserver' y puppets 'fuzzy node matching' significará que se usa para aprovisionar todos los servidores web.

Este ejemplo asume que se basa en una imagen base con la marioneta instalada, etc.

Beneficios:

1) No tiene que pasar sus credenciales

2) Puede ser tan granular como desee con las configuraciones de roles.

Ben Waine
fuente
3

He reunido lo siguiente que, con suerte, es más simple y más limpio que algunas de las respuestas existentes y usa solo la AWS CLI y no herramientas adicionales.

Este ejemplo de código muestra cómo obtener el valor de la etiqueta 'myTag' para la instancia EC2 actual:

Usando etiquetas de descripción :

export AWS_DEFAULT_REGION=us-east-1
instance_id=$(curl -s http://169.254.169.254/latest/meta-data/instance-id)
aws ec2 describe-tags \
  --filters "Name=resource-id,Values=$instance_id" 'Name=key,Values=myTag' \
  --query 'Tags[].Value' --output text

O, alternativamente, usando describe-instances :

aws ec2 describe-instances --instance-id $instance_id \
  --query 'Reservations[].Instances[].Tags[?Key==`myTag`].Value' --output text
Alex Harvey
fuente
2

Una variación de algunas de las respuestas anteriores, pero así es como obtuve el valor de una etiqueta específica del script de datos de usuario en una instancia

REGION=$(curl http://instance-data/latest/meta-data/placement/availability-zone | sed 's/.$//')

INSTANCE_ID=$(curl -s http://instance-data/latest/meta-data/instance-id)

TAG_VALUE=$(aws ec2 describe-tags --region $REGION --filters "Name=resource-id,Values=$INSTANCE_ID" "Name=key,Values='<TAG_NAME_HERE>'" | jq -r '.Tags[].Value')
ActualAl
fuente
1

Instale AWS CLI:

curl "https://s3.amazonaws.com/aws-cli/awscli-bundle.zip" -o "awscli-bundle.zip"
sudo apt-get install unzip
unzip awscli-bundle.zip
sudo ./awscli-bundle/install -i /usr/local/aws -b /usr/local/bin/aws

Obtén las etiquetas de la instancia actual:

aws ec2 describe-tags --filters "Name=resource-id,Values=`ec2metadata --instance-id`"

Salidas:

{
    "Tags": [
        {
            "ResourceType": "instance", 
            "ResourceId": "i-6a7e559d", 
            "Value": "Webserver", 
            "Key": "Name"
        }
    ]
}

Use un poco de perl para extraer las etiquetas:

aws ec2 describe-tags --filters \
"Name=resource-id,Values=`ec2metadata --instance-id`" | \
perl -ne 'print "$1\n" if /\"Value\": \"(.*?)\"/'

Devoluciones:

Webserver
Patrick Collins
fuente
ec2metadatano está en aws-cli, pero se puede reemplazar por curl --silent http://169.254.169.254/latest/meta-data/instance-id. Además, jqpuede analizar el json más fácilmente, o un formato de salida diferente es aún más fácil.
tedder42
Esto funciona, sin embargo, necesito agregar lo siguiente: sudo apt-get -y install pythonyexport AWS_DEFAULT_REGION=us-west-1
Eugene
Esto no funcionará ... 1. ec2metadata es un comando incorrecto. 2. ec2-metadata --instance-id will returninstance-id: i-07f59f3564618f148
Daniel Hornik
1

Descargue y ejecute un ejecutable independiente para hacer eso.

A veces, no se puede instalar awscli que depende de Python. Docker también podría estar fuera de escena.

Aquí está mi implementación en golang: https://github.com/hmalphettes/go-ec2-describe-tags

hmalfetas
fuente
1

Jq + ec2metadata lo hace un poco más agradable. Estoy usando cf y tengo acceso a la región. De lo contrario, puedes agarrarlo en bash.

aws ec2 describe-tags --region $REGION \
--filters "Name=resource-id,Values=`ec2metadata --instance-id`" | jq --raw-output \
'.Tags[] | select(.Key=="TAG_NAME") | .Value'
pbsladek
fuente
0

Para aquellos lo suficientemente locos como para usar Fish Shell en EC2, aquí hay un fragmento útil para su /home/ec2-user/.config/fish/config.fish. El comando hostdata ahora enumerará todas sus etiquetas, así como la IP pública y el nombre de host.

set -x INSTANCE_ID (wget -qO- http://instance-data/latest/meta-data/instance-id)
set -x REGION (wget -qO- http://instance-data/latest/meta-data/placement/availability-zone | sed 's/.$//')

function hostdata
    aws ec2 describe-tags --region $REGION --filter "Name=resource-id,Values=$INSTANCE_ID" --output=text | sed -r 's/TAGS\t(.*)\t.*\t.*\t(.*)/\1="\2"/'
    ec2-metadata | grep public-hostname
    ec2-metadata | grep public-ipv4
end
BooTooMany
fuente