从实例中查询EC2标签


96

亚马逊最近增加了用键-值对标记EC2实例的奇妙功能,使管理大量VM更加容易。

有什么方法可以和其他用户设置的数据一样查询这些标签?例如:

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

是否有一些类似的方式来查询标签?

Answers:


35

您可以结合使用AWS元数据工具(检索您的实例ID)和新的Tag API来检索当前实例的标签。


好的,我点击了该链接,看起来就像是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 [] | 选择(。重点== “角色”)| .value的”
jolestar

11
这是指向答案的指针,而不是本身的答案
Roy Truelove

3
ec2metadata工具已弃用。现在,您在169.254.169.254/latest/meta-data上查询“魔术” URL- 用cURL对其进行匹配,它为您提供了魔术端点,可用于获取各种数据。在这种情况下curl http://169.254.169.254/latest/meta-data/instance-id,您将获得您的实例ID
Asfand Qazi

52

以下bash脚本返回当前ec2实例的名称(“名称”标签的值)。根据您的具体情况修改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": ["*"]
    }
  ]
}

我得到了“您无权执行此操作” aws ec2 describe-tags。我需要将此IAM添加到我的IAM角色的内联策略中。谢谢!
维克多D.16年

一个非常轻微的优化,可以更换| cut -f5--query="Tags[0].Value"
理查德·阿瓜

47

一旦你得到了ec2-metadataec2-describe-tags安装(如提及拉涅利的回答以上),这里是一个例子shell命令来获取当前实例的“名”,假设你有上有一个“名称=富”的标签。

假设设置了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是的,那真是la子。也许使用Amazon的IAM,您至少可以使用对任何内容都具有非常有限的访问权限的用户。FWIW,我不再使用这种方法,而只是使用外部脚本来设置该框。
仔细考虑了2012年

12
@WilliamPayne您可以使用“ Amazon EC2只读访问权限”策略设置IAM角色,并创建具有该角色的实例。如果您希望更精细,也可以创建仅具有“ DescribeTags”特权的自定义策略。
roverwolf 2012年

@WilliamPayne我喜欢roverwolf的建议。效果很好。如果您要查看它,我实际上回答了另一个问题,其详细信息是:stackoverflow.com/questions/9950586/…–
Tony

2
请注意,ec2-describe-tags默认值为us-east-2。请通过该--region标志以使用其他区域。
2015年

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在脚本之前在cloud-config文件中的一节中安装它们,或者使用已经包含它们的AMI,或者在脚本的开头添加aptor 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,将文件原样包含在shell脚本中,例如:

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

标签是在实例初始化期间下载的,因此它们不会反映后续更改。


该脚本和IAM策略基于itaifrenkel的答案。


a +更喜欢这种方法
Cmag 2015年

太糟糕了,这破坏了由自动缩放组创建的标签: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
Ryan Gooler

10

如果您不在默认的可用区域中,那么考虑过度的结果将返回空。

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:environment-name),则可以执行此操作。

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-nameName
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 2015年

此外,这与IAM角色配合得很好-如果您设置实例角色,则boto将自动检测ID和密钥。
dbn

5

您也可以使用describe-instancescli调用,而不是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

更改区域以适合您的当地情况。当您的实例具有describe-instances特权但在实例配置文件策略中没有describe-tags时,这可能会很有用


3

使用AWS的“用户数据”和“元数据” API,可以编写一个脚本,该脚本将木偶包装起来,以使用自定义证书名称启动木偶运行。

首先使用自定义用户数据启动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'的puppet,然后您可以创建一个名为“ webserver”的节点清单,而puppets的“ fuzzy node matching”将意味着它将用于配置所有Web服务器。

本示例假定您在安装了木偶等的基础映像上构建。

好处:

1)您不必传递身份证明

2)您可以根据自己的喜好使用角色配置。


3

我整理了以下内容,希望这些内容比某些现有答案更简单,更简洁,并且仅使用AWS CLI,而不使用其他工具。

此代码示例演示如何获取当前EC2实例的标记“ myTag”的值:

使用describe-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

或者,或者使用describe-instances

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

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

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 pythonexport AWS_DEFAULT_REGION=us-west-1
Eugene

这将不起作用... 1. ec2metadata命令错误。2. ec2-metadata --instance-id将返回instance-id: i-07f59f3564618f148
Daniel Hornik


1

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'

0

对于那些疯狂到可以在EC2上使用Fish shell的人来说,这是/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
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.