Consultar tags EC2 de dentro da instância

96

A Amazon adicionou recentemente o recurso maravilhoso de marcar instâncias EC2 com pares de valor-chave para tornar o gerenciamento de um grande número de VMs um pouco mais fácil.

Existe alguma maneira de consultar essas tags da mesma maneira que alguns dos outros dados definidos pelo usuário? Por exemplo:

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

Existe alguma maneira semelhante de consultar as tags?

Josh Lindsey
fonte

Respostas:

35

Você pode usar uma combinação da ferramenta de metadados AWS (para recuperar seu ID de instância) e a nova API de tag para recuperar as tags da instância atual.

drxzcl
fonte
OK, eu segui esse link e parece que é a documentação da API. Não existe uma ferramenta que eu possa usar ou preciso ler a documentação da API e escrever minha própria ferramenta?
Edward Falk,
3
O comando ec2-describe-tags está facilmente disponível? Supostamente, está no pacote ec2-api-tools, mas não recebi nada além do 404 quando tentei instalá-lo.
Edward Falk,
2
dê um exemplo, obtenha o valor da função da tag: aws ec2 describe-tags --filters Name = resource-id, Values ​​= ec2metadata --instance-id--out = json | jq '.Tags [] | select (.Key == "role") | .Value '
jolestar
11
Esta é uma indicação para uma resposta, mas não uma resposta em si
Roy Truelove
3
A ec2metadataferramenta está obsoleta. Agora você consulta o URL 'mágico' em 169.254.169.254/latest/meta-data - acesse -o com cURL e ele fornece pontos de extremidade mágicos que você pode usar para obter vários bits de dados. Neste caso, curl http://169.254.169.254/latest/meta-data/instance-idobtém o seu ID de instância
Asfand Qazi
52

O script bash a seguir retorna o Nome da sua instância ec2 atual (o valor da tag "Nome"). Modifique TAG_NAME para seu caso específico.

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

Para instalar o aws cli

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

Caso você use IAM em vez de credenciais explícitas, use estas permissões de IAM:

{
  "Version": "2012-10-17",
  "Statement": [
    {    
      "Effect": "Allow",
      "Action": [ "ec2:DescribeTags"],
      "Resource": ["*"]
    }
  ]
}
itaifrenkel
fonte
Estava recebendo "Você não está autorizado a realizar esta operação" com aws ec2 describe-tags. Eu precisava adicionar este IAM às políticas embutidas da minha função IAM. Obrigado!
Victor D.
PODE ser uma pequena otimização substituir o | cut -f5por --query="Tags[0].Value".
Richard A Quadling
47

Depois de ter ec2-metadatae ec2-describe-tagsinstalado (como mencionado na resposta de Ranieri acima ), aqui está um exemplo de comando shell para obter o "nome" da instância atual, supondo que você tenha uma tag "Nome = Foo" nela.

Presume que as variáveis ​​de ambiente EC2_PRIVATE_KEY e EC2_CERT estão definidas.

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

Isso retorna Foo.

pensar demais
fonte
17
Teria sido bom se meus processos pudessem obter as tags para a instância atual sem precisar ter o EC2_PRIVATE_KEY na instância também. :-(
William Payne,
1
@ william-payne Sim, isso é muito chato. Talvez usando o IAM da Amazon você pudesse pelo menos usar um usuário com acesso muito limitado a qualquer coisa. FWIW, não uso mais essa abordagem e apenas uso scripts externos para configurar a caixa.
pense em
12
@WilliamPayne Você pode configurar uma função IAM com a política "Amazon EC2 Read Only Access" e criar a instância com essa função. Também é possível criar uma política personalizada tendo apenas o privilégio "DescribeTags" se quiser ser mais granular.
roverwolf
@WilliamPayne Gostei da sugestão do roverwolf. Funcionou muito bem. Na verdade, respondi a outra pergunta com os detalhes, se você quiser ver: stackoverflow.com/questions/9950586/…
Tony
2
Observe que o ec2-describe-tagspadrão é us-east-2. Passe a --regionbandeira para usar uma região diferente.
advait
15

Você pode adicionar este script aos seus dados de usuário de inicialização em nuvem para baixar tags EC2 para um arquivo 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

Você precisa das ferramentas AWS CLI instaladas em seu sistema: você pode instalá-las com uma packagesseção em um arquivo de configuração em nuvem antes do script, usar uma AMI que já as inclui ou adicionar um comando aptou yumno início do script.

Para acessar tags EC2, você precisa de uma política como esta na função IAM da sua instância:

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

As tags EC2 da instância estarão disponíveis /etc/ec2-tagsneste formato:

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

Você pode incluir o arquivo como está em um script de shell usando . /etc/ec2-tags, por exemplo:

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

As tags são baixadas durante a inicialização da instância, portanto, não refletirão as alterações subsequentes.


O script e a política do IAM são baseados na resposta de itaifrenkel.

Andrea
fonte
a + prefira este método
Cmag
pena que isso quebra para tags criadas por grupos de escalonamento automático:aws:autoscaling:groupName
Cmag
2
Então tente isto: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 você não estiver na zona de disponibilidade padrão, os resultados do overthink retornarão vazios.

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 você quiser adicionar um filtro para obter uma tag específica (elasticbeanstalk: nome-do-ambiente no meu caso), você pode fazer isso.

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 para obter apenas o valor da tag que filtrou, canalizamos para cortar e obter o 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
Michael Connor
fonte
ótimo trabalho, obrigado, ter uma instância de dados de dns diferente não está funcionando para mim, para o último, se você precisar substituir a tag de nome elasticbeanstalk:environment-nameporName
detzu
5

Para 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
fonte
Legit. Os leitores observam que, para informações locais básicas, você nem precisa de credenciais, apenas oinstance_metadata = utils.get_instance_metadata(timeout=0.5, num_retries=1)
Bartvds
Além disso, isso funciona bem com papéis IAM - se você definir um papel de instância, o boto detectará automaticamente o ID e a chave.
dbn
5

Você também pode usar a describe-instanceschamada cli em vez de describe-tags:

Este exemplo mostra como obter o valor da tag 'my-tag-name' para a instância:

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

Mude a região para se adequar às suas circunstâncias locais. Isso pode ser útil quando sua instância tem o privilégio describe-instances, mas não descreva-as tags na política de perfil da instância

usuário de linux shonky
fonte
3

Usando as APIs de 'dados do usuário' e 'metadados' da AWS, é possível escrever um script que envolve o fantoche para iniciar a execução de um fantoche com um nome de certificado personalizado.

Primeiro inicie uma instância aws com dados de usuário personalizados: '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 

Isso chama puppet com um certname como 'webserver.i-hfg453.aws', você pode então criar um manifesto de nó chamado 'webserver' e puppets 'fuzzy node matching' significará que é usado para provisionar todos os servidores web.

Este exemplo pressupõe que você construiu uma imagem de base com fantoche instalado, etc.

Benefícios:

1) Você não precisa passar suas credenciais

2) Você pode ser tão granular quanto quiser com as configurações de função.

Ben Waine
fonte
3

Eu reuni o seguinte que é esperançosamente mais simples e mais limpo do que algumas das respostas existentes e usa apenas o AWS CLI e nenhuma ferramenta adicional.

Este exemplo de código mostra como obter o valor da tag 'myTag' para a instância EC2 atual:

Usando tags de descrição :

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, alternativamente, usando describe-instances :

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

Uma variação de algumas das respostas acima, mas foi assim que obtive o valor de uma tag específica do script de dados do usuário em uma instância

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')
RealAl
fonte
1

Instale o 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

Obtenha as tags para a instância atual:

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

Saídas:

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

Use um pouco de perl para extrair as tags:

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

Retorna:

Webserver
Patrick Collins
fonte
ec2metadatanão está no aws-cli, mas pode ser substituído por curl --silent http://169.254.169.254/latest/meta-data/instance-id. também, jqpode analisar o json mais facilmente, ou um formato de saída diferente é ainda mais fácil.
tedder42
Isso funciona, no entanto, preciso adicionar o seguinte: sudo apt-get -y install pythoneexport AWS_DEFAULT_REGION=us-west-1
Eugene
Isso não vai funcionar ... 1. ec2metadata é um comando incorreto. 2. ec2-metadata --instance-id retornaráinstance-id: i-07f59f3564618f148
Daniel Hornik
1

Baixe e execute um executável autônomo para fazer isso.

Às vezes, não é possível instalar o awscli que depende do python. o docker também pode estar fora de cogitação.

Aqui está minha implementação em golang: https://github.com/hmalphettes/go-ec2-describe-tags

Hmalphettes
fonte
1

Jq + ec2metadata torna-o um pouco mais agradável. Estou usando cf e tenho acesso à região. Caso contrário, você pode pegá-lo no 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
fonte
0

Para aqueles loucos o suficiente para usar Fish shell no EC2, aqui está um trecho útil para seu /home/ec2-user/.config/fish/config.fish. O comando hostdata agora irá listar todas as suas tags, bem como o IP público e o nome do 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
BooTooMany
fonte