Interroger les balises EC2 à partir de l'instance


96

Amazon a récemment ajouté la merveilleuse fonctionnalité de balisage des instances EC2 avec des paires clé-valeur pour faciliter la gestion d'un grand nombre de machines virtuelles.

Existe-t-il un moyen d'interroger ces balises de la même manière que certaines des autres données définies par l'utilisateur? Par exemple:

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

Existe-t-il un moyen similaire d'interroger les balises?

Réponses:


35

Vous pouvez utiliser une combinaison de l' outil de métadonnées AWS (pour récupérer votre ID d'instance) et de la nouvelle API Tag pour récupérer les balises de l'instance actuelle.


OK, j'ai suivi ce lien, et il semble que ce soit la documentation de l'API. N'existe-t-il aucun outil que je puisse utiliser ou dois-je lire la documentation de l'API et écrire mon propre outil?
Edward Falk

3
La commande ec2-describe-tags est-elle facilement disponible? On suppose que c'est dans le paquet ec2-api-tools, mais je n'ai rien d'autre que des 404 quand j'ai essayé de l'installer.
Edward Falk

2
donnez un exemple, obtenez la valeur du rôle de balise: aws ec2 describe-tags --filters Name = resource-id, Values ​​= ec2metadata --instance-id--out = json | jq '.Tags [] | select (.Key == "role") | .Value '
jolestar

11
Ceci est un pointeur vers une réponse mais pas une réponse en soi
Roy Truelove

3
L' ec2metadataoutil est obsolète. Maintenant, vous interrogez l'URL «magique» à 169.254.169.254/latest/meta-data - appuyez dessus avec cURL et cela vous donne des points de terminaison magiques que vous pouvez utiliser pour obtenir divers bits de données. Dans ce cascurl http://169.254.169.254/latest/meta-data/instance-id
obtenez

52

Le script bash suivant renvoie le nom de votre instance ec2 actuelle (la valeur de la balise "Name"). Modifiez TAG_NAME selon votre cas spécifique.

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`"

Pour installer le aws cli

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

Si vous utilisez IAM au lieu d'informations d'identification explicites, utilisez ces autorisations IAM:

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

J'obtenais "Vous n'êtes pas autorisé à effectuer cette opération" avec aws ec2 describe-tags. J'avais besoin d'ajouter cet IAM aux stratégies en ligne de mon rôle IAM. Merci!
Victor D.

Une très légère optimisation POURRAIT être de remplacer le | cut -f5par --query="Tags[0].Value".
Richard A Quadling le

47

Une fois que vous avez ec2-metadataet ec2-describe-tagsinstallé (comme mentionné dans la réponse de Ranieri ci-dessus ), voici un exemple de commande shell pour obtenir le "nom" de l'instance actuelle, en supposant que vous ayez une balise "Name = Foo" dessus.

Suppose que les variables d'environnement EC2_PRIVATE_KEY et EC2_CERT sont définies.

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

Cela revient Foo.


17
Cela aurait été bien si mes processus pouvaient obtenir les balises pour l'instance actuelle sans avoir à avoir l'EC2_PRIVATE_KEY sur l'instance également. :-(
William Payne

1
@ william-payne Ouais, c'est vraiment nul. Peut-être qu'en utilisant l'IAM d'Amazon, vous pourriez au moins utiliser un utilisateur avec un accès très limité à tout. FWIW, je n'utilise plus cette approche et n'utilise que des scripts externes pour configurer la boîte.
Overhink

12
@WilliamPayne Vous pouvez configurer un rôle IAM avec la stratégie "Amazon EC2 Read Only Access" et créer l'instance ayant ce rôle. Il est également possible de créer une stratégie personnalisée ayant uniquement le privilège «DescribeTags» si vous souhaitez être plus granulaire.
roverwolf

@WilliamPayne J'ai aimé la suggestion de roverwolf. Cela a très bien fonctionné. En fait, j'ai répondu à une autre question avec les détails si vous voulez la voir: stackoverflow.com/questions/9950586/...
Tony

2
Notez que la valeur par ec2-describe-tagsdéfaut est us-east-2. Veuillez passer le --regiondrapeau pour utiliser une région différente.
Avance

15

Vous pouvez ajouter ce script à vos données utilisateur cloud-init pour télécharger les balises EC2 dans un fichier 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

Vous avez besoin des outils AWS CLI installés sur votre système: vous pouvez les installer avec une packagessection dans un fichier de configuration cloud avant le script, utiliser une AMI qui les inclut déjà, ou ajouter un aptouyum commande au début du script.

Pour accéder aux balises EC2, vous avez besoin d'une stratégie comme celle-ci dans le rôle IAM de votre instance:

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

Les balises EC2 de l'instance seront disponibles /etc/ec2-tagsdans ce format:

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

Vous pouvez inclure le fichier tel quel dans un script shell en utilisant . /etc/ec2-tags, par exemple:

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

Les balises sont téléchargées lors de l'initialisation de l'instance, elles ne refléteront donc pas les modifications ultérieures.


Le script et la stratégie IAM sont basés sur la réponse d'itaifrenkel.


a + préférez cette méthode
Cmag

dommage que cela casse pour les tags créés par des groupes d' aws:autoscaling:groupName
autoscaling

2
Alors essayez ceci: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 vous n'êtes pas dans la zone de disponibilité par défaut, les résultats de la réflexion excessive reviendraient vides.

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 vous souhaitez ajouter un filtre pour obtenir une balise spécifique (élastiquebeanstalk: nom d'environnement dans mon cas), vous pouvez le faire.

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

Et pour obtenir uniquement la valeur de la balise sur laquelle j'ai filtré, nous faisons un tuyau pour couper et obtenir le cinquième champ.

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

excellent travail, merci, avoir une autre instance-data DNS ne fonctionne pas pour moi, pour le dernier si vous avez besoin de remplacer le tag de nom elasticbeanstalk:environment-nameparName
detzu

5

Pour 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)

Légitime. Les lecteurs notent que pour les informations locales de base, vous n'avez même pas besoin d'informations d'identification, juste leinstance_metadata = utils.get_instance_metadata(timeout=0.5, num_retries=1)
Bartvds

En outre, cela joue bien avec les rôles IAM - si vous définissez un rôle d'instance, boto détectera automatiquement l'ID et la clé.
dbn le

5

Vous pouvez également utiliser l' describe-instancesappel cli plutôt quedescribe-tags :

Cet exemple montre comment obtenir la valeur de la balise 'my-tag-name' pour l'instance:

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

Changez la région en fonction de vos circonstances locales. Cela peut être utile lorsque votre instance dispose du privilège describe-instances mais pas de balises describe-tags dans la stratégie de profil d'instance


3

En utilisant les API AWS 'user data' et 'meta data', il est possible d'écrire un script qui enveloppe la marionnette pour démarrer une exécution de marionnette avec un nom de certificat personnalisé.

Commencez par démarrer une instance aws avec des données utilisateur personnalisées: 'role: webserver'

#!/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 

Cela appelle marionnette avec un nom de certificat comme «webserver.i-hfg453.aws», vous pouvez ensuite créer un manifeste de nœud appelé «serveur Web» et les marionnettes «correspondance de nœud flou» signifieront qu'il est utilisé pour provisionner tous les serveurs Web.

Cet exemple suppose que vous construisez sur une image de base avec la marionnette installée, etc.

Avantages:

1) Vous n'avez pas à passer vos informations d'identification

2) Vous pouvez être aussi précis que vous le souhaitez avec les configurations de rôle.


3

J'ai rassemblé ce qui suit qui, espérons-le, est plus simple et plus propre que certaines des réponses existantes et utilise uniquement l'AWS CLI et aucun outil supplémentaire.

Cet exemple de code montre comment obtenir la valeur de la balise 'myTag' pour l'instance EC2 actuelle:

Utilisation des balises describe :

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

Ou, alternativement, en utilisant des instances de description :

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

2

Une variante de certaines des réponses ci-dessus, mais c'est ainsi que j'ai obtenu la valeur d'une balise spécifique à partir du script de données utilisateur sur une instance

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')

1

Installez l'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

Récupérez les balises de l'instance actuelle:

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

Les sorties:

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

Utilisez un peu de perl pour extraire les balises:

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

Retour:

Webserver

ec2metadatan'est pas dans aws-cli, mais il peut être remplacé par curl --silent http://169.254.169.254/latest/meta-data/instance-id. aussi, jqpeut analyser le json plus facilement, ou un format de sortie différent est encore plus facile.
tedder42

Cela fonctionne, mais je dois ajouter ce qui suit: sudo apt-get -y install pythonetexport AWS_DEFAULT_REGION=us-west-1
Eugene

Cela ne fonctionnera pas ... 1. ec2metadata est une commande incorrecte. 2. ec2-metadata --instance-id reviendrainstance-id: i-07f59f3564618f148
Daniel Hornik le


1

Jq + ec2metadata le rend un peu plus agréable. J'utilise cf et ai accès à la région. Sinon, vous pouvez l'attraper 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'

0

Pour ceux qui sont assez fous pour utiliser Fish shell sur EC2, voici un extrait pratique pour votre /home/ec2-user/.config/fish/config.fish. La commande hostdata listera maintenant toutes vos balises ainsi que l'adresse IP publique et le nom d'hôte.

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
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.