Interroga i tag EC2 dall'interno dell'istanza


96

Amazon ha recentemente aggiunto la meravigliosa funzionalità di tagging delle istanze EC2 con coppie chiave-valore per rendere un po 'più semplice la gestione di un gran numero di VM.

C'è un modo per interrogare questi tag allo stesso modo di alcuni degli altri dati impostati dall'utente? Per esempio:

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

Esiste un modo simile per interrogare i tag?

Risposte:


35

Puoi utilizzare una combinazione dello strumento per i metadati AWS (per recuperare l'ID istanza) e la nuova API Tag per recuperare i tag per l'istanza corrente.


OK, ho seguito quel collegamento e sembra che sia la documentazione dell'API. Non esiste uno strumento che posso utilizzare o ho bisogno di leggere la documentazione API e scrivere il mio strumento?
Edward Falk

3
Il comando ec2-description-tags è facilmente disponibile? Presumibilmente è nel pacchetto ec2-api-tools, ma non ho ricevuto altro che 404 quando ho provato ad installarlo.
Edward Falk

2
fai un esempio, ottieni il valore del ruolo del tag: aws ec2 Descrivi-tags --filters Name = resource-id, Values ​​= ec2metadata --instance-id--out = json | jq '.Tags [] | select (.Key == "role") | .Value '
jolestar

11
Questo è un puntatore a una risposta ma non a una risposta in sé e per sé
Roy Truelove

3
Lo ec2metadatastrumento è deprecato. Ora interroghi l'URL "magico" in 169.254.169.254/latest/meta-data - colpiscilo con cURL e ti dà endpoint magici che puoi usare per ottenere vari bit di dati. In questo caso, curl http://169.254.169.254/latest/meta-data/instance-idottieni il tuo ID istanza
Asfand Qazi

52

Il seguente script bash restituisce il nome dell'istanza ec2 corrente (il valore del tag "Name"). Modifica TAG_NAME in base al tuo caso specifico.

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

Per installare aws cli

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

Se utilizzi IAM invece delle credenziali esplicite, utilizza queste autorizzazioni IAM:

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

Ricevo "Non sei autorizzato a eseguire questa operazione" con aws ec2 describe-tags. Avevo bisogno di aggiungere questo IAM alle policy inline del mio ruolo IAM. Grazie!
Victor D.

Una leggerissima ottimizzazione POTREBBE essere quella di sostituire | cut -f5con --query="Tags[0].Value".
Richard A Quadling

47

Una volta che hai ec2-metadatae ec2-describe-tagsinstallato (come menzionato nella risposta di Ranieri sopra ), ecco un comando di shell di esempio per ottenere il "nome" dell'istanza corrente, supponendo che tu abbia un tag "Name = Foo" su di esso.

Presuppone che le variabili di ambiente EC2_PRIVATE_KEY e EC2_CERT siano impostate.

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

Questo ritorna Foo.


17
Sarebbe stato bello se i miei processi potessero ottenere i tag per l'istanza corrente senza dover avere anche EC2_PRIVATE_KEY sull'istanza. :-(
William Payne

1
@ william-payne Sì, è davvero noioso. Forse usando IAM di Amazon potresti almeno usare un utente con accesso molto limitato a qualsiasi cosa. FWIW, non utilizzo più questo approccio e utilizzo solo script esterni per configurare la scatola.
pensare troppo al

12
@WilliamPayne Puoi configurare un ruolo IAM con la policy "Accesso in sola lettura Amazon EC2" e creare l'istanza con quel ruolo. È anche possibile creare un criterio personalizzato con solo il privilegio "DescribeTags" se si desidera essere più granulari.
roverwolf

@ WilliamPayne Mi è piaciuto il suggerimento di roverwolf. Ha funzionato benissimo. In realtà ho risposto a un'altra domanda con i dettagli se vuoi vederlo: stackoverflow.com/questions/9950586/…
Tony

2
Nota che il ec2-describe-tagsvalore predefinito è us-east-2. Passa la --regionbandiera per utilizzare una regione diversa.
advait

15

Puoi aggiungere questo script ai tuoi dati utente cloud-init per scaricare i tag EC2 in un file locale:

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

Hai bisogno degli strumenti AWS CLI installati sul tuo sistema: puoi installarli con una packagessezione in un file di configurazione cloud prima dello script, utilizzare un'AMI che li include già o aggiungere un aptoyum comando all'inizio dello script.

Per accedere ai tag EC2 è necessaria una policy come questa nel ruolo IAM della tua istanza:

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

I tag EC2 dell'istanza saranno disponibili /etc/ec2-tagsin questo formato:

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

È possibile includere il file così com'è in uno script di shell utilizzando . /etc/ec2-tags, ad esempio:

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

I tag vengono scaricati durante l'inizializzazione dell'istanza, quindi non rifletteranno le modifiche successive.


Lo script e la policy IAM si basano sulla risposta di itaifrenkel.


a + preferisco questo metodo
Cmag

aws:autoscaling:groupName
peccato che

2
Quindi prova questo: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

Se non ti trovi nella zona di disponibilità predefinita, i risultati di overthink torneranno vuoti.

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)

Se vuoi aggiungere un filtro per ottenere un tag specifico (elasticbeanstalk: nome-ambiente nel mio caso), puoi farlo.

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

E per ottenere solo il valore per il tag su cui ho filtrato, eseguiamo il pipe per tagliare e ottenere il 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

ottimo lavoro, grazie, avere un diverso dato di istanza dns non funziona per me, per l'ultimo se hai bisogno del tag Nome sostituiscilo elasticbeanstalk:environment-nameconName
detzu

5

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

Legittimo. Nota dei lettori per le informazioni locali di base che non servono nemmeno le credenziali, solo ilinstance_metadata = utils.get_instance_metadata(timeout=0.5, num_retries=1)
Bartvds

Inoltre, funziona bene con i ruoli IAM: se imposti un ruolo di istanza, boto rileverà automaticamente l'ID e la chiave.
dbn

5

In alternativa è possibile utilizzare la describe-instanceschiamata cli anzichédescribe-tags :

Questo esempio mostra come ottenere il valore del tag "my-tag-name" per l'istanza:

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

Cambia la regione in base alle circostanze locali. Ciò può essere utile quando l'istanza dispone del privilegio di descrizione delle istanze ma non dei tag di descrizione nella politica del profilo dell'istanza


3

Utilizzando le API AWS "dati utente" e "metadati" è possibile scrivere uno script che avvolge il pupazzo per avviare un'esecuzione del pupazzo con un nome certificato personalizzato.

Per prima cosa avvia un'istanza aws con i dati utente personalizzati: "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 

Questo chiama puppet con un nome certificato come "webserver.i-hfg453.aws", puoi quindi creare un manifesto del nodo chiamato "webserver" e "fuzzy node matching" dei pupazzi significa che viene utilizzato per fornire tutti i server web.

Questo esempio presuppone che tu costruisca su un'immagine di base con il pupazzo installato ecc.

Benefici:

1) Non devi passare le tue credenziali

2) Puoi essere granulare quanto vuoi con le configurazioni dei ruoli.


3

Ho messo insieme quanto segue che si spera sia più semplice e pulito di alcune delle risposte esistenti e utilizza solo l'AWS CLI e nessuno strumento aggiuntivo.

Questo esempio di codice mostra come ottenere il valore del tag "myTag" per l'istanza EC2 corrente:

Utilizzo dei tag di descrizione :

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

Oppure, in alternativa, utilizzando la descrizione delle istanze :

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

2

Una variazione su alcune delle risposte precedenti, ma è così che ho ottenuto il valore di un tag specifico dallo script dei dati utente su un'istanza

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

Installa 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

Ottieni i tag per l'istanza corrente:

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

Uscite:

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

Usa un po 'di perl per estrarre i tag:

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

Ritorna:

Webserver

ec2metadatanon è in aws-cli, ma può essere sostituito con curl --silent http://169.254.169.254/latest/meta-data/instance-id. inoltre, jqpuò analizzare più facilmente il json o un formato di output diverso è ancora più semplice.
tedder42

Funziona, tuttavia devo aggiungere quanto segue: sudo apt-get -y install pythoneexport AWS_DEFAULT_REGION=us-west-1
Eugene

Questo non funzionerà ... 1. ec2metadata è un comando errato. 2. ec2-metadata --instance-id torneràinstance-id: i-07f59f3564618f148
Daniel Hornik il


1

Jq + ec2metadata lo rende un po 'più carino. Sto usando cf e ho accesso alla regione. Altrimenti puoi prenderlo in 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

Per quelli abbastanza pazzi da usare Fish shell su EC2, ecco un utile frammento per il tuo /home/ec2-user/.config/fish/config.fish. Il comando hostdata ora elencherà tutti i tuoi tag così come l'IP pubblico e il nome 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
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.