Amazon a récemment ajouté la fonctionnalité merveilleuse consistant à marquer les 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 tags?
Vous pouvez utiliser une combinaison de outil de métadonnées AWS (pour extraire votre ID d'instance) et de nouvelle API de balise pour extraire les balises de l'instance actuelle.
Une fois que vous avez ec2-metadata
et ec2-describe-tags
installed (comme mentionné dans réponse de Ranieri ci-dessus ), voici un exemple de commande Shell permettant d'obtenir le "nom" de l'instance actuelle, en supposant que vous ayez une balise "Name = Foo".
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
Ceci retourne Foo
.
Le script bash suivant renvoie le nom de votre instance actuelle ec2 (la valeur de la balise "Name"). Modifiez TAG_NAME en fonction de votre cas particulier.
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 les autorisations IAM suivantes:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [ "ec2:DescribeTags"],
"Resource": ["*"]
}
]
}
Vous pouvez ajouter ce script à vos tilisateur cloud données utilisateur 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 section packages
dans un fichier cloud-config avant le script, utiliser une AMI qui les inclut déjà ou ajouter un apt
ou yum
commande au début du script.
Afin d'accéder aux balises EC2, vous avez besoin d'une politique 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 dans /etc/ec2-tags
dans ce format:
FOO="Bar"
Name="EC2 tags with cloud-init"
Vous pouvez inclure le fichier tel quel dans un script Shell à l'aide de . /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 de itaifrenkel.
Si vous ne vous trouvez pas dans la zone de disponibilité par défaut, les résultats de overthink seront renvoyés 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 (elasticbeanstalk: nom-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 canalisons 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
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)
En utilisant les API AWS 'user data' et 'meta data', il est possible d'écrire un script qui enveloppe puppet 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 puppet avec un nom de certification tel que 'webserver.i-hfg453.aws'. Vous pouvez ensuite créer un manifeste de noeuds appelé 'webserver' et la correspondance des noeuds fuzzy de puppets signifie qu'elle sera utilisée pour approvisionner tous les serveurs Web.
Cet exemple suppose que vous construisiez sur une image de base avec marionnette installée, etc.
Avantages:
1) Vous n'êtes pas obligé de passer vos informations d'identification
2) Vous pouvez être aussi précis que vous le souhaitez avec les rôles configs.
Vous pouvez aussi utiliser le describe-instances
appel de cli plutôt que describe-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
Modifiez la région en fonction de votre situation locale. Cela peut être utile lorsque votre instance dispose du privilège describe-instances mais pas des balises-describe dans la stratégie de profil d'instance.
Installez 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
Obtenez les balises pour 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\": \"(.*?)\"/'
Résultats:
Webserver
Téléchargez et exécutez un exécutable autonome pour le faire.
Parfois, il est impossible d'installer awscli dépendant de python. docker pourrait être hors de l'image aussi.
Voici mon implémentation dans golang: https://github.com/hmalphettes/go-ec2-describe-tags
J'ai rassemblé les éléments suivants qui, espérons-le, sont plus simples et plus propres que certaines des réponses existantes et n'utilisent que 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:
Utiliser describe-tags :
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 describe-instances :
aws ec2 describe-instances --instance-id $instance_id \
--query 'Reservations[].Instances[].Tags[?Key==`myTag`].Value' --output text
Jq + ec2metadata le rend un peu plus agréable. J'utilise cf et j'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'