Запросить теги EC2 из экземпляра

99

Amazon недавно добавила замечательную функцию пометки инстансов EC2 парами ключ-значение, чтобы упростить управление большим количеством виртуальных машин.

Есть ли способ запросить эти теги так же, как и некоторые другие данные, заданные пользователем? Например:

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

Есть ли аналогичный способ запроса тегов?

Джош Линдси
источник

Ответы:

36

Вы можете использовать комбинацию инструмента метаданных AWS (для получения идентификатора вашего экземпляра) и нового API тегов для получения тегов для текущего экземпляра.

drxzcl
источник
Хорошо, я перешел по этой ссылке, и похоже, что это документация по API. Нет ли инструмента, который я мог бы использовать, или мне нужно прочитать документацию по API и написать свой собственный инструмент?
Эдвард Фальк
3
Легко ли доступна команда ec2-describe-tags? Предположительно он находится в пакете ec2-api-tools, но я не получил ничего, кроме 404, когда пытался его установить.
Эдвард Фальк
2
приведите пример, получите значение роли тега: aws ec2 describe-tags --filters Name = resource-id, Values ​​= ec2metadata --instance-id--out = json | jq '.Tags [] | select (.Key == "role") | .Value '
jolestar
12
Это указатель на ответ, но не ответ сам по себе
Рой Трулав
3
ec2metadataИнструмент является устаревшим. Теперь вы запрашиваете «волшебный» URL-адрес по адресу 169.254.169.254/latest/meta-data - нажимаете его cURL, и он дает вам волшебные конечные точки, которые вы можете использовать для получения различных битов данных. В этом случае curl http://169.254.169.254/latest/meta-data/instance-idполучает ваш идентификатор экземпляра
Asfand Qazi
58

Следующий сценарий bash возвращает имя вашего текущего экземпляра ec2 (значение тега «Name»). Измените TAG_NAME для вашего конкретного случая.

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

Чтобы установить aws cli

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

Если вы используете IAM вместо явных учетных данных, используйте эти разрешения IAM:

{
  "Version": "2012-10-17",
  "Statement": [
    {    
      "Effect": "Allow",
      "Action": [ "ec2:DescribeTags"],
      "Resource": ["*"]
    }
  ]
}
Itaifrenkel
источник
Я получал «У вас нет прав на выполнение этой операции» с помощью aws ec2 describe-tags. Мне нужно было добавить этот IAM во встроенные политики моей роли IAM. Благодарность!
Виктор Д.
1
Очень небольшая оптимизация МОГ быть , чтобы заменить | cut -f5с --query="Tags[0].Value".
Ричард Квадлинг,
47

После того, как вы получили ec2-metadataи ec2-describe-tagsустановили (как упоминалось в ответе Раньери выше ), вот пример команды оболочки для получения «имени» текущего экземпляра, если у вас есть тег «Name = Foo».

Предполагается, что установлены переменные среды EC2_PRIVATE_KEY и EC2_CERT.

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

Это возвращается Foo.

слишком много думать
источник
17
Было бы неплохо, если бы мои процессы могли получать теги для текущего экземпляра без необходимости иметь EC2_PRIVATE_KEY в экземпляре. :-(
Уильям Пейн
1
@ william-payne Да, это действительно отстой. Возможно, используя Amazon IAM, вы могли бы, по крайней мере, использовать пользователя с очень ограниченным доступом ко всему. FWIW, я больше не использую этот подход и просто использую внешние скрипты для настройки коробки.
overthink
12
@WilliamPayne. Вы можете настроить роль IAM с помощью политики «Доступ только для чтения» Amazon EC2 и создать экземпляр с этой ролью. Также возможно создать настраиваемую политику, имеющую только привилегию «DescribeTags», если вы хотите быть более детализированной.
roverwolf
@WilliamPayne Мне понравилось предложение roverwolf. Это сработало отлично. Я на самом деле ответил на другой вопрос с подробностями, если вы хотите это увидеть: stackoverflow.com/questions/9950586/…
Тони
2
Обратите внимание, что по ec2-describe-tagsумолчанию us-east-2. Пожалуйста, передайте --regionфлаг, чтобы использовать другой регион.
адвайт
15

Вы можете добавить этот скрипт в свои пользовательские данные cloud-init, чтобы загрузить теги EC2 в локальный файл:

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

В вашей системе должны быть установлены инструменты AWS CLI: вы можете установить их с packagesразделом в файле облачной конфигурации перед сценарием, использовать AMI, который уже включает их, или добавить команду aptили yumв начале сценария.

Для доступа к тегам EC2 вам понадобится политика, подобная этой, в роли IAM вашего экземпляра:

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

Теги EC2 экземпляра будут доступны /etc/ec2-tagsв следующем формате:

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

Вы можете включить файл как есть в сценарий оболочки . /etc/ec2-tags, например, используя:

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

Теги загружаются во время инициализации экземпляра, поэтому они не будут отражать последующие изменения.


Сценарий и политика IAM основаны на ответе itaifrenkel.

Андреа
источник
а + предпочитаю этот метод
Cmag
Жаль, что это перерыв для тегов, созданных группами автомасштабирования:aws:autoscaling:groupName
Cmag
2
Тогда попробуйте это: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
Райан Гулер
11

Если вы не находитесь в зоне доступности по умолчанию, результаты чрезмерного обдумывания будут пустыми.

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)

Если вы хотите добавить фильтр для получения определенного тега (в моем случае elasticbeanstalk: имя-среды), вы можете это сделать.

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

И чтобы получить только значение тега, по которому я отфильтровал, мы разрезаем по конвейеру и получаем пятое поле.

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
Майкл Коннор
источник
отличная работа, спасибо, у меня не работают другие данные экземпляра DNS, последний, если вам нужно заменить тег Name elasticbeanstalk:environment-nameнаName
detzu
5

Для 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)
Сергей
источник
Законно. Читатели отмечают, что для базовой местной информации вам даже не нужны учетные данные, простоinstance_metadata = utils.get_instance_metadata(timeout=0.5, num_retries=1)
Bartvds
Кроме того, это хорошо работает с ролями IAM - если вы установите роль экземпляра, boto автоматически определит идентификатор и ключ.
dbn
5

В качестве альтернативы вы можете использовать describe-instancesвызов cli, а не describe-tags:

В этом примере показано, как получить значение тега my-tag-name для экземпляра:

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

Измените регион в соответствии с вашими местными обстоятельствами. Это может быть полезно, если у вашего экземпляра есть привилегия описания-экземпляров, но нет тегов описания в политике профиля экземпляра.

shonky пользователь Linux
источник
4

Я собрал воедино следующее, которое, надеюсь, проще и чище, чем некоторые из существующих ответов, и использует только AWS CLI и никаких дополнительных инструментов.

В этом примере кода показано, как получить значение тега myTag для текущего экземпляра EC2:

Использование тегов описания :

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

Или, в качестве альтернативы, используя description-instance :

aws ec2 describe-instances --instance-id $instance_id \
  --query 'Reservations[].Instances[].Tags[?Key==`myTag`].Value' --output text
Алекс Харви
источник
3

Используя API «пользовательских данных» и «метаданных» AWS, можно написать сценарий, который обертывает марионетку для запуска запуска марионетки с настраиваемым именем сертификата.

Сначала запустите экземпляр aws с пользовательскими данными: '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 

Это вызывает марионетку с именем сертификата, например «webserver.i-hfg453.aws», затем вы можете создать манифест узла с именем «веб-сервер», а «нечеткое сопоставление узлов» марионетки будет означать, что он используется для подготовки всех веб-серверов.

В этом примере предполагается, что вы создаете базовый образ с установленной марионеткой и т. Д.

Льготы:

1) Вам не нужно передавать свои учетные данные

2) Вы можете быть настолько детализированы, насколько хотите, с конфигурациями ролей.

Бен Уэйн
источник
2

Jq + ec2metadata делает его немного лучше. Я использую cf и имею доступ к региону. В противном случае вы можете получить его в 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
источник
2

Вариант некоторых из приведенных выше ответов, но именно так я получил значение определенного тега из сценария пользовательских данных на экземпляре

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
источник
1

Установите 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

Получить теги для текущего экземпляра:

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

Выходы:

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

Используйте немного perl для извлечения тегов:

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

Возврат:

Webserver
Патрик Коллинз
источник
ec2metadataотсутствует в aws-cli, но его можно заменить на curl --silent http://169.254.169.254/latest/meta-data/instance-id. Кроме того, jqможно проще анализировать json, или еще проще использовать другой формат вывода.
tedder42
Это работает, однако мне нужно добавить следующее: sudo apt-get -y install pythonиexport AWS_DEFAULT_REGION=us-west-1
Евгений
Это не сработает ... 1. ec2metadata - неверная команда. 2. ec2-metadata --instance-id вернетсяinstance-id: i-07f59f3564618f148
Даниэль Хорник
1

Для этого загрузите и запустите автономный исполняемый файл.

Иногда нельзя установить awscli, зависящую от python. Докер тоже может быть вне поля зрения.

Вот моя реализация в голанге: https://github.com/hmalphettes/go-ec2-describe-tags

хмальфеты
источник
0

Для тех, кто достаточно сумасшедший, чтобы использовать Fish shell на EC2, вот удобный фрагмент для вашего /home/ec2-user/.config/fish/config.fish. Команда hostdata теперь перечислит все ваши теги, а также общедоступный IP-адрес и имя хоста.

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
источник