从实例内查询 EC2标记

Amazon 最近增加了一个奇妙的特性: 用键值对标记 EC2实例,从而使管理大量虚拟机变得更加容易。

是否有某种方法可以像查询其他用户集数据一样查询这些标记?例如:

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

是否有类似的方法来查询标记?

125460 次浏览

可以使用 AWS 元数据工具(检索实例 ID)和 新的标签应用程式介面的组合来检索当前实例的标记。

Once you've got ec2-metadata and ec2-describe-tags installed (as mentioned in 以上是拉涅利的回答), here's an example shell command to get the "name" of the current instance, assuming you have a "Name=Foo" tag on it.

假设设置了 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

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

First start an aws instance with custom user data: '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”的木偶。然后,你可以创建一个名为“ webserver”的节点清单,木偶“模糊节点匹配”将意味着它被用于提供所有的 webserver。

这个示例假设您在安装了傀儡等的基础映像上构建。

好处:

1)你不必传阅你的证书

2) You can be as granular as you like with the role configs.

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

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)

If you want to add a filter to get a specific tag (elasticbeanstalk:environment-name in my case) then you can do this.

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

The following bash script returns the Name of your current ec2 instance (the value of the "Name" tag). Modify TAG_NAME to your specific case.

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": ["*"]
}
]
}

对于 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)

您可以将此脚本添加到 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,或者在脚本的开头添加 aptyum命令。

In order to access EC2 tags you need a policy like this one in your instance's IAM role:

{
"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 的答案。

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

Outputs:

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

下载并运行一个独立的可执行文件。

有时候不能安装依赖 python.docker 的 awscli。

以下是我在 Golang 中的实现: Https://github.com/hmalphettes/go-ec2-describe-tags

你可以选择使用 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

Change the region to suit your local circumstances. This may be useful where your instance has the describe-instances privilege but not describe-tags in the instance profile policy

我将下面的内容拼凑起来,希望它比现有的一些答案更简单、更清晰,并且只使用 AWS CLI 而不使用其他工具。

这个代码示例演示如何为当前 EC2实例获取标记‘ myTag’的值:

使用 描述标签:

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

或者,也可以使用 描述实例:

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

Jq + ec2元数据使它更好一些。我正在使用 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'

没有 JQ。

aws ec2 describe-tags --region us-west-2 \
--filters "Name=resource-id,Values=`ec2-metadata --instance-id | cut -d " " -f 2`" \
--query 'Tags[?Key==`Name`].Value' \
--output text

上面的一些答案的一个变体,但这是我如何从实例的用户数据脚本中获得特定标记的值的

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

对于那些疯狂到在 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

元数据工具似乎不再可用,但无论如何这是一个不必要的依赖。

Follow the AWS documentation to have the instance's profile grant it the "ec2:DescribeTags" action in a policy, restricting the target resources as much as you wish. (If you need a profile for another reason then you'll need to merge policies into a new profile-linked role).

然后:

aws --region $(curl -s http://169.254.169.254/latest/meta-data/placement/availability-zone  | sed -e 's/.$//') ec2 describe-tags --filters Name=resource-type,Values=instance Name=resource-id,Values=$(curl http://169.254.169.254/latest/meta-data/instance-id) Name=key,Values=Name |
perl -nwe 'print "$1\n" if /"Value": "([^"]+)/;'

这里有很多很好的答案,但是没有一个对我来说是完全开箱即用的,我认为 CLI 已经被更新了,因为其中的一些,我确实喜欢使用 CLI。在2021年,以下单个命令可以灵活运行(只要实例的 IAM 角色允许描述标记)。

aws ec2 describe-tags \
--region "$(ec2-metadata -z | cut -d' ' -f2 | sed 's/.$//')" \
--filters "Name=resource-id,Values=$(ec2-metadata --instance-id | cut -d " " -f 2)" \
--query 'Tags[?Key==`Name`].Value' \
--output text

从2022年1月开始,这也应该可以通过 ec2元数据 api 直接获得(如果启用的话)。

curl http://169.254.169.254/latest/meta-data/tags/instance

Https://aws.amazon.com/about-aws/whats-new/2022/01/instance-tags-amazon-ec2-instance-metadata-service/

AWS has recently announced support for instance tags in Instance Metadata Service: https://aws.amazon.com/about-aws/whats-new/2022/01/instance-tags-amazon-ec2-instance-metadata-service/

如果你有一个实例的 启用标记元数据选项,你可以简单地做

$ TOKEN=`curl -X PUT "http://169.254.169.254/latest/api/token" -H "X-aws-ec2-metadata-token-ttl-seconds: 900"`
$ curl -H "X-aws-ec2-metadata-token: $TOKEN" -v http://169.254.169.254/latest/meta-data/tags/instance

可以通过元数据从实例中获取 Instance 标记。

首先,按照解释的 给你,允许访问实例元数据中的标记

然后,对 IMDSv1、 参考运行此命令

curl http://169.254.169.254/latest/meta-data/tags/instance/Name

or this command for IMDSv2

TOKEN=`curl -X PUT "http://169.254.169.254/latest/api/token" -H "X-aws-ec2-metadata-token-ttl-seconds: 21600"` \
&& curl -H "X-aws-ec2-metadata-token: $TOKEN" -v http://169.254.169.254/latest/meta-data/tags/instance