Fragen Sie EC2-Tags innerhalb einer Instanz ab

96

Amazon hat kürzlich die wunderbare Funktion hinzugefügt, EC2-Instanzen mit Schlüssel-Wert-Paaren zu versehen, um die Verwaltung einer großen Anzahl von VMs etwas zu vereinfachen.

Gibt es eine Möglichkeit, diese Tags auf die gleiche Weise wie einige der anderen vom Benutzer festgelegten Daten abzufragen? Beispielsweise:

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

Gibt es eine ähnliche Möglichkeit, die Tags abzufragen?

Josh Lindsey
quelle

Antworten:

36

Sie können eine Kombination aus dem AWS-Metadaten-Tool (zum Abrufen Ihrer Instanz-ID) und der neuen Tag-API verwenden , um die Tags für die aktuelle Instanz abzurufen.

drxzcl
quelle
OK, ich bin diesem Link gefolgt und es sieht so aus, als wäre es die API-Dokumentation. Gibt es kein Tool, das ich verwenden kann, oder muss ich die API-Dokumentation lesen und mein eigenes Tool schreiben?
Edward Falk
3
Ist der Befehl ec2-description-tags leicht verfügbar? Angeblich ist es im Paket ec2-api-tools enthalten, aber ich habe nur 404 bekommen, als ich versucht habe, es zu installieren.
Edward Falk
2
Geben Sie ein Beispiel und holen Sie sich den Wert der Tag-Rolle: aws ec2 description-tags --filters Name = Ressourcen-ID, Werte = ec2metadata --instance-id--out = json | jq '.Tags [] | select (.Key == "role") | .Value '
jolestar
11
Dies ist ein Zeiger auf eine Antwort, aber keine Antwort an sich
Roy Truelove
3
Das ec2metadataTool ist veraltet. Jetzt fragen Sie die 'magische' URL unter 169.254.169.254/latest/meta-data ab - drücken Sie sie mit cURL und Sie erhalten magische Endpunkte, mit denen Sie verschiedene Datenbits abrufen können. In diesem Fall erhalten curl http://169.254.169.254/latest/meta-data/instance-idSie Ihre Instanz-ID
Asfand Qazi
52

Das folgende Bash-Skript gibt den Namen Ihrer aktuellen ec2-Instanz zurück (den Wert des Tags "Name"). Ändern Sie TAG_NAME an Ihren speziellen Fall.

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

So installieren Sie die aws cli

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

Wenn Sie IAM anstelle expliziter Anmeldeinformationen verwenden, verwenden Sie die folgenden IAM-Berechtigungen:

{
  "Version": "2012-10-17",
  "Statement": [
    {    
      "Effect": "Allow",
      "Action": [ "ec2:DescribeTags"],
      "Resource": ["*"]
    }
  ]
}
itaifrenkel
quelle
Ich erhielt die Meldung "Sie sind nicht berechtigt, diesen Vorgang auszuführen" mit aws ec2 describe-tags. Ich musste diesen IAM zu den Inline-Richtlinien meiner IAM-Rolle hinzufügen. Vielen Dank!
Victor D.
Eine sehr leichte Optimierung könnte den Ersatz | cut -f5mit --query="Tags[0].Value".
Richard A Quadling
47

Sobald Sie haben ec2-metadataund ec2-describe-tagsinstalliert (wie in erwähnt Ranieri Antwort oben ), hier ist ein Befehl Beispiel Shell den „Namen“ der aktuellen Instanz zu erhalten, vorausgesetzt , Sie sind ein „Name = Foo“ Tag drauf haben.

Angenommen, die Umgebungsvariablen EC2_PRIVATE_KEY und EC2_CERT sind festgelegt.

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

Dies kehrt zurück Foo.

überdenken
quelle
17
Es wäre schön gewesen, wenn meine Prozesse die Tags für die aktuelle Instanz erhalten könnten, ohne dass auch EC2_PRIVATE_KEY für die Instanz erforderlich wäre. :-(
William Payne
1
@ William-Payne Ja, das ist wirklich lahm. Vielleicht könnten Sie mit Amazon IAM zumindest einen Benutzer mit sehr eingeschränktem Zugriff auf alles verwenden. FWIW, ich verwende diesen Ansatz nicht mehr und verwende nur externe Skripte, um die Box einzurichten.
überdenken
12
@WilliamPayne Sie können eine IAM-Rolle mit der Richtlinie "Amazon EC2 Read Only Access" einrichten und die Instanz mit dieser Rolle erstellen. Es ist auch möglich, eine benutzerdefinierte Richtlinie mit nur der Berechtigung "DescribeTags" zu erstellen, wenn Sie detaillierter arbeiten möchten.
Roverwolf
@ WilliamPayne Ich mochte Roverwolfs Vorschlag. Es hat super funktioniert. Ich habe tatsächlich eine andere Frage mit den Details beantwortet, wenn Sie sie sehen möchten: stackoverflow.com/questions/9950586/…
Tony
2
Beachten Sie, dass der ec2-describe-tagsStandardwert ist us-east-2. Bitte übergeben Sie die --regionFlagge, um eine andere Region zu verwenden.
Advait
15

Sie können dieses Skript zu Ihren Cloud-Init- Benutzerdaten hinzufügen , um EC2-Tags in eine lokale Datei herunterzuladen:

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

Sie benötigen die auf Ihrem System installierten AWS CLI-Tools: Sie können sie entweder mit einem packagesAbschnitt in einer Cloud-Konfigurationsdatei vor dem Skript installieren , eine AMI verwenden, die sie bereits enthält, oder ein aptoder hinzufügenyum -Befehl am Anfang des Skripts .

Um auf EC2-Tags zugreifen zu können, benötigen Sie eine Richtlinie wie diese in der IAM-Rolle Ihrer Instanz:

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

Die EC2-Tags der Instanz sind /etc/ec2-tagsin folgendem Format verfügbar :

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

Sie können die Datei unverändert in ein Shell-Skript aufnehmen, indem Sie . /etc/ec2-tagsbeispielsweise Folgendes verwenden :

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

Die Tags werden während der Instanzinitialisierung heruntergeladen, sodass sie keine nachfolgenden Änderungen widerspiegeln.


Das Skript und die IAM-Richtlinie basieren auf der Antwort von itaifrenkel.

Andrea
quelle
a + bevorzugen diese Methode
Cmag
aws:autoscaling:groupName
Schade,
2
Dann versuchen Sie dies: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

Wenn Sie sich nicht in der Standardverfügbarkeitszone befinden, werden die Ergebnisse des Überdenkens leer zurückgegeben.

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)

Wenn Sie einen Filter hinzufügen möchten, um ein bestimmtes Tag zu erhalten (elastischer Bohnenstiel: Umgebungsname in meinem Fall), können Sie dies tun.

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

Und um nur den Wert für das Tag zu erhalten, nach dem ich gefiltert habe, leiten wir das fünfte Feld aus.

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
quelle
großartige Arbeit, danke, eine andere dns instanz Daten aufweist , ist für mich nicht funktioniert, für die letzte , wenn Sie das Namensschild ersetzen müssen elasticbeanstalk:environment-namemitName
detzu
5

Für 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
quelle
Legitim. Leser beachten für grundlegende lokale Informationen, dass Sie nicht einmal Anmeldeinformationen benötigen, nur dieinstance_metadata = utils.get_instance_metadata(timeout=0.5, num_retries=1)
Bartvds
Dies funktioniert auch gut mit IAM-Rollen. Wenn Sie eine Instanzrolle festlegen, erkennt boto die ID und den Schlüssel automatisch.
dbn
5

Sie können alternativ den describe-instancesCLI-Aufruf verwenden, anstatt describe-tags:

Dieses Beispiel zeigt, wie der Wert des Tags 'my-tag-name' für die Instanz ermittelt wird:

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

Ändern Sie die Region entsprechend Ihren örtlichen Gegebenheiten. Dies kann nützlich sein, wenn Ihre Instanz über die Berechtigung zum Beschreiben von Instanzen verfügt, jedoch nicht über Beschreibungs-Tags in der Instanzprofilrichtlinie

Shonky Linux Benutzer
quelle
3

Mithilfe der AWS-APIs "Benutzerdaten" und "Metadaten" kann ein Skript geschrieben werden, das die Puppe umschließt, um einen Puppenlauf mit einem benutzerdefinierten Zertifikatsnamen zu starten.

Starten Sie zuerst eine aws-Instanz mit benutzerdefinierten Benutzerdaten: '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 

Dadurch wird Puppet mit einem Zertifikatsnamen wie "webserver.i-hfg453.aws" aufgerufen. Anschließend können Sie ein Knotenmanifest mit dem Namen "webserver" erstellen. Puppets "Fuzzy Node Matching" bedeuten, dass alle Webserver bereitgestellt werden.

In diesem Beispiel wird davon ausgegangen, dass Sie auf einem Basis-Image mit installierter Puppe usw. aufbauen.

Leistungen:

1) Sie müssen Ihre Anmeldeinformationen nicht weitergeben

2) Mit den Rollenkonfigurationen können Sie so detailliert sein, wie Sie möchten.

Ben Waine
quelle
3

Ich habe Folgendes zusammengestellt, das hoffentlich einfacher und sauberer ist als einige der vorhandenen Antworten und nur die AWS-CLI und keine zusätzlichen Tools verwendet.

Dieses Codebeispiel zeigt, wie der Wert des Tags 'myTag' für die aktuelle EC2-Instanz abgerufen wird:

Verwenden von Beschreibungs-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

Oder alternativ mit Beschreibungsinstanzen :

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

Eine Variation einiger der obigen Antworten, aber auf diese Weise habe ich den Wert eines bestimmten Tags aus dem Benutzerdatenskript einer Instanz erhalten

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
quelle
1

Installieren Sie 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

Holen Sie sich die Tags für die aktuelle Instanz:

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

Ausgänge:

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

Verwenden Sie ein bisschen Perl, um die Tags zu extrahieren:

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

Kehrt zurück:

Webserver
Patrick Collins
quelle
ec2metadataist nicht in aws-cli, kann aber durch ersetzt werden curl --silent http://169.254.169.254/latest/meta-data/instance-id. Außerdem jqkann das JSON einfacher analysiert werden, oder ein anderes Ausgabeformat ist noch einfacher.
Tedder42
Dies funktioniert, aber ich muss Folgendes hinzufügen: sudo apt-get -y install pythonundexport AWS_DEFAULT_REGION=us-west-1
Eugene
Dies wird nicht funktionieren ... 1. ec2metadata ist ein falscher Befehl. 2. ec2-metadata --instance-id wird zurückkehreninstance-id: i-07f59f3564618f148
Daniel Hornik
1

Laden Sie dazu eine eigenständige ausführbare Datei herunter und führen Sie sie aus.

Manchmal kann man awscli nicht installieren, was von Python abhängt. Docker könnte auch nicht im Bild sein.

Hier ist meine Implementierung in Golang: https://github.com/hmalphettes/go-ec2-describe-tags

Hmalphetten
quelle
1

Jq + ec2metadata macht es ein bisschen schöner. Ich benutze cf und habe Zugang zur Region. Andernfalls können Sie es in Bash greifen.

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

Für diejenigen, die verrückt genug sind, um Fish Shell auf EC2 zu verwenden, ist hier ein praktischer Ausschnitt für Ihren /home/ec2-user/.config/fish/config.fish. Der Befehl hostdata listet jetzt alle Ihre Tags sowie die öffentliche IP und den Hostnamen auf.

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
quelle