Zapytanie o tagi EC2 z poziomu instancji

99

Amazon dodał ostatnio wspaniałą funkcję oznaczania instancji EC2 parami klucz-wartość, aby nieco ułatwić zarządzanie dużą liczbą maszyn wirtualnych.

Czy istnieje sposób na zapytanie o te tagi w taki sam sposób, jak w przypadku niektórych innych danych ustawionych przez użytkownika? Na przykład:

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

Czy istnieje podobny sposób odpytywania tagów?

Josh Lindsey
źródło

Odpowiedzi:

36

Możesz użyć kombinacji narzędzia AWS do obsługi metadanych (w celu pobrania identyfikatora instancji) i nowego interfejsu API tagów, aby pobrać tagi dla bieżącej instancji.

drxzcl
źródło
OK, skorzystałem z tego linku i wygląda na to, że jest to dokumentacja API. Czy nie ma narzędzia, którego mógłbym użyć, czy też muszę przeczytać dokumentację API i napisać własne narzędzie?
Edward Falk
3
Czy polecenie ec2-opis-tags jest łatwo dostępne? Podobno znajduje się w pakiecie ec2-api-tools, ale kiedy próbowałem go zainstalować, otrzymałem tylko 404.
Edward Falk
2
podaj przykład, pobierz wartość roli tagu: aws ec2 opis-tags --filters Nazwa = identyfikator-zasobu, Wartości = ec2metadata --instance-id--out = json | jq '.Tags [] | select (.Key == "role") | .Value '
jolestar
12
To jest wskazówka do odpowiedzi, ale nie odpowiedź sama w sobie
Roy Truelove
3
ec2metadataNarzędzie jest przestarzałe. Teraz odpytujesz „magiczny” adres URL pod adresem 169.254.169.254/latest/meta-data - kliknij go za pomocą cURL, a otrzymasz magiczne punkty końcowe, których możesz użyć do uzyskania różnych bitów danych. W tym przypadku curl http://169.254.169.254/latest/meta-data/instance-idTwój identyfikator instancji zostanie
pobrany
57

Poniższy skrypt bash zwraca nazwę bieżącej instancji ec2 (wartość tagu „Name”). Dostosuj TAG_NAME do swojego przypadku.

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

Aby zainstalować plik aws cli

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

Jeśli używasz uprawnień zamiast jawnych danych logowania, użyj tych uprawnień:

{
  "Version": "2012-10-17",
  "Statement": [
    {    
      "Effect": "Allow",
      "Action": [ "ec2:DescribeTags"],
      "Resource": ["*"]
    }
  ]
}
itaifrenkel
źródło
Otrzymałem komunikat „Nie masz uprawnień do wykonania tej operacji” z aws ec2 describe-tags. Musiałem dodać to uprawnienia do wewnętrznych zasad mojej roli uprawnień. Dzięki!
Victor D.
1
Bardzo niewielki optymalizacja mogłoby być zastąpienie | cut -f5z --query="Tags[0].Value".
Richard A Quadling
47

Po zainstalowaniu ec2-metadatai ec2-describe-tagszainstalowaniu (jak wspomniano w odpowiedzi Ranieri powyżej ), oto przykładowe polecenie powłoki, aby uzyskać „nazwę” bieżącej instancji, zakładając, że masz na niej tag „Name = Foo”.

Zakłada się, że ustawione są zmienne środowiskowe EC2_PRIVATE_KEY i EC2_CERT.

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

To wraca Foo.

przemyślenie
źródło
17
Byłoby miło, gdyby moje procesy mogły pobierać tagi dla bieżącej instancji bez konieczności posiadania EC2_PRIVATE_KEY również w instancji. :-(
William Payne
1
@ william-payne Tak, to jest naprawdę kiepskie. Być może korzystając z IAM Amazona, możesz przynajmniej użyć użytkownika z bardzo ograniczonym dostępem do czegokolwiek. FWIW, nie używam już tego podejścia i po prostu używam zewnętrznych skryptów do konfiguracji skrzynki.
overthink
12
@WilliamPayne Możesz ustawić rolę IAM z zasadą „Dostęp tylko do odczytu Amazon EC2” i utworzyć instancję mającą tę rolę. Możliwe jest również utworzenie niestandardowej polityki mającej tylko uprawnienie „DescribeTags”, jeśli chcesz być bardziej szczegółowy.
roverwolf
@WilliamPayne Podobała mi się sugestia roverwolfa. Działało świetnie. Właściwie odpowiedziałem na inne pytanie ze szczegółami, jeśli chcesz je zobaczyć: stackoverflow.com/questions/9950586/ ...
Tony
2
Zauważ, że ec2-describe-tagsdomyślnie us-east-2. Przekaż --regionflagę, aby użyć innego regionu.
Advait
15

Możesz dodać ten skrypt do danych użytkownika Cloud-init, aby pobrać tagi EC2 do pliku lokalnego:

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

Potrzebujesz narzędzi AWS CLI zainstalowanych w systemie: możesz zainstalować je z packagessekcją w pliku cloud-config przed skryptem, użyć AMI, który już je zawiera, lub dodać polecenie aptlub yumna początku skryptu.

Aby uzyskać dostęp do tagów EC2, potrzebujesz zasady takiej jak ta w roli IAM Twojej instancji:

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

Tagi EC2 instancji będą dostępne /etc/ec2-tagsw następującym formacie:

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

Możesz dołączyć plik w takiej postaci, w jakiej jest, do skryptu powłoki, używając . /etc/ec2-tagsna przykład:

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

Tagi są pobierane podczas inicjowania instancji, więc nie będą odzwierciedlać późniejszych zmian.


Skrypt i zasady IAM są oparte na odpowiedzi itaifrenkel.

Andrea
źródło
a + wolę tę metodę
Cmag
szkoda, że ​​to psuje się dla tagów utworzonych przez grupy autoskalowania:aws:autoscaling:groupName
Cmag
2
Spróbuj tego: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

Jeśli nie jesteś w domyślnej strefie dostępności, wyniki overerthink zwróciłyby się jako puste.

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)

Jeśli chcesz dodać filtr, aby uzyskać określony tag (elastyczna łodyga: nazwa-środowiska w moim przypadku), możesz to zrobić.

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

Aby uzyskać tylko wartość tagu, według którego przefiltrowałem, potokujemy, aby wyciąć i uzyskać piąte pole.

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
źródło
wielkie dzieło, dziękuję, mający inny dns instancji dane nie pracuje dla mnie, dla tej ostatniej, jeśli trzeba zastąpić tag Nazwa elasticbeanstalk:environment-namezName
detzu
5

W przypadku Pythona:

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)
Siergiej
źródło
Legit. Uwaga czytelników, aby uzyskać podstawowe informacje lokalne, nie potrzebujesz nawet poświadczeń, tylkoinstance_metadata = utils.get_instance_metadata(timeout=0.5, num_retries=1)
Bartvds
Również dobrze współgra to z rolami IAM - jeśli ustawisz rolę instancji, boto automatycznie wykryje identyfikator i klucz.
dbn
5

Alternatywnie możesz użyć describe-instanceswywołania CLI zamiast describe-tags:

Ten przykład pokazuje, jak uzyskać wartość tagu „my-tag-name” dla instancji:

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

Zmień region, aby dopasować go do lokalnych warunków. Może to być przydatne, gdy instancja ma uprawnienie opisywać-instancje, ale nie ma tagów opisywać w zasadach profilu instancji

shonky użytkownik linuxa
źródło
4

Złożyłem razem następujące, miejmy nadzieję, prostsze i czystsze niż niektóre z istniejących odpowiedzi i używa tylko interfejsu wiersza polecenia AWS bez dodatkowych narzędzi.

Ten przykład kodu pokazuje, jak uzyskać wartość tagu „myTag” dla bieżącej instancji EC2:

Korzystanie z tagów opisujących :

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

Lub, alternatywnie, używając opisu-instancji :

aws ec2 describe-instances --instance-id $instance_id \
  --query 'Reservations[].Instances[].Tags[?Key==`myTag`].Value' --output text
Alex Harvey
źródło
3

Korzystając z API AWS „dane użytkownika” i „metadane”, można napisać skrypt, który opakuje marionetkę, aby uruchomić marionetkę z niestandardową nazwą certyfikatu.

Najpierw uruchom instancję aws z niestandardowymi danymi użytkownika: „role: serwer sieciowy”

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

To wywołuje marionetkę z nazwą certyfikatu, taką jak „webserver.i-hfg453.aws”. Następnie możesz utworzyć manifest węzła o nazwie „serwer sieciowy”, a „rozmyte dopasowanie węzła” marionetek będzie oznaczać, że jest używany do obsługi wszystkich serwerów WWW.

W tym przykładzie założono, że tworzysz obraz podstawowy z zainstalowaną marionetką itp.

Korzyści:

1) Nie musisz przekazywać swoich danych uwierzytelniających

2) Konfiguracje ról mogą być tak szczegółowe, jak chcesz.

Ben Waine
źródło
2

Jq + ec2metadata sprawia, że ​​jest trochę ładniej. Używam cf i mam dostęp do regionu. W przeciwnym razie możesz go złapać w 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
źródło
2

Odmiana niektórych z powyższych odpowiedzi, ale w ten sposób uzyskałem wartość określonego tagu ze skryptu danych użytkownika w instancji

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')
RzeczywistyAl
źródło
1

Zainstaluj 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

Pobierz tagi dla bieżącej instancji:

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

Wyjścia:

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

Użyj trochę perla, aby wyodrębnić tagi:

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

Zwroty:

Webserver
Patrick Collins
źródło
ec2metadatanie znajduje się w aws-cli, ale można go zastąpić curl --silent http://169.254.169.254/latest/meta-data/instance-id. Ponadto, jqmożna analizować JSON łatwiej, lub inny format wyjściowy jest jeszcze łatwiejsze.
przetrząsacz42
To działa, jednak muszę dodać, co następuje: sudo apt-get -y install pythoniexport AWS_DEFAULT_REGION=us-west-1
Eugene
To nie zadziała ... 1. ec2metadata to niepoprawne polecenie. 2. ec2-metadata --instance-id wróciinstance-id: i-07f59f3564618f148
Daniel Hornik
0

Dla tych, którzy są wystarczająco szaleni, aby używać Fish shell na EC2, oto przydatny fragment dla twojego /home/ec2-user/.config/fish/config.fish. Polecenie hostdata wyświetli teraz wszystkie tagi, a także publiczny adres IP i nazwę hosta.

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
źródło