从实例内查询 EC2 标签

Posted

技术标签:

【中文标题】从实例内查询 EC2 标签【英文标题】:Query EC2 tags from within instance 【发布时间】:2011-04-22 10:48:34 【问题描述】:

Amazon 最近添加了使用键值对标记 EC2 实例的精彩功能,使管理大量 VM 变得更加容易。

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

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

有类似的查询标签的方法吗?

【问题讨论】:

【参考方案1】:

从 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/

【讨论】:

【参考方案2】:

这里有很多很好的答案,但没有一个完全适合我开箱即用,我认为 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

【讨论】:

【参考方案3】:

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

按照 AWS 文档,让实例的配置文件在策略中授予它“ec2:DescribeTags”操作,尽可能地限制目标资源。 (如果您出于其他原因需要配置文件,则需要将策略合并到新的配置文件相关角色中)。

然后:

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": "([^"]+)/;'

【讨论】:

【参考方案4】:

您可以结合使用AWS metadata tool(检索您的实例ID)和new Tag API 检索当前实例的标签。

【讨论】:

好的,我点击了那个链接,它看起来像是 API 文档。是没有我可以使用的工具,还是我需要阅读 API 文档并编写自己的工具? ec2-describe-tags 命令是否易于使用?据说它在 ec2-api-tools 包中,但是当我尝试安装它时,除了 404 之外什么都没有。 举个例子,获取标签角色的值:aws ec2 describe-tags --filters Name=resource-id,Values=ec2metadata --instance-id --out=json|jq '.Tags[] | select(.Key == "角色")|.Value' 这是一个指向答案的指针,但不是一个答案本身 ec2metadata 工具已弃用。现在您在169.254.169.254/latest/meta-data 查询“魔术” URL - 使用 cURL 访问它,它会为您提供可用于获取各种数据位的魔术端点。在这种情况下,curl http://169.254.169.254/latest/meta-data/instance-id 获取您的实例 ID【参考方案5】:

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'

没有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

【讨论】:

这应该在 2019 年及以后有更多的支持,因为许多其他答案不再有效。 CLI 版本 2 也许?无论如何,这对我来说是开箱即用的,但您确实需要将 describe-tags 权限授予实例的 IAM 角色。哦,使用 ec2-metadata -z | 获得正确的区域sed 's/.$//' 根据其他答案。【参考方案6】:

对于那些疯狂到在 EC2 上使用 Fish shell 的人,这里有一个方便的 sn-p 用于您的 /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

【讨论】:

【参考方案7】:

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

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

【讨论】:

【参考方案8】:

您也可以使用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

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

【讨论】:

【参考方案9】:

我拼凑了以下内容,希望比现有的一些答案更简单、更清晰,并且仅使用 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

【讨论】:

【参考方案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 实例数据对我不起作用,如果您需要名称标签,请使用最后一个将 elasticbeanstalk:environment-name 替换为 Name【参考方案11】:

下载并运行一个独立的可执行文件来做到这一点。

有时无法安装依赖于 python 的 awscli。码头工人也可能不在照片中。

这是我在 golang 中的实现: https://github.com/hmalphettes/go-ec2-describe-tags

【讨论】:

【参考方案12】:

安装 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,或者更轻松地使用不同的输出格式。 这行得通,但是我需要添加以下内容:sudo apt-get -y install pythonexport AWS_DEFAULT_REGION=us-west-1 这行不通... 1. ec2metadata 命令不正确。 2. ec2-metadata --instance-id 将返回instance-id: i-07f59f3564618f148【参考方案13】:

您可以将此脚本添加到您的 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 工具:您可以在脚本之前的 cloud-config 文件中使用 packages 部分安装它们,使用已经包含它们的 AMI,或者添加 aptyum 脚本开头的命令。

为了访问 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+ 更喜欢这种方法 太糟糕了,这打破了自动缩放组创建的标签:aws:autoscaling:groupName 然后试试这个: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_/' &gt; /etc/ec2-tags【参考方案14】:

对于 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) 另外,这与 IAM 角色配合得很好 - 如果您设置实例角色,boto 将自动检测 ID 和密钥。【参考方案15】:

以下 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 角色的内联策略中。谢谢! 一个非常轻微的优化可能是用--query="Tags[0].Value"替换| cut -f5 我只想说这是我一段时间以来看到的一个问题的最佳答案。简洁、完整、以任务为导向。它包括未经要求但完全合理的附加信息。我想建议世界各地的每个人都以这种风格编写文档。【参考方案16】:

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

首先使用自定义用户数据启动一个 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 

这会调用带有证书名称的 puppet,例如“webserver.i-hfg453.aws”,然后您可以创建一个名为“webserver”的节点清单,而 puppet 的“模糊节点匹配”将意味着它用于配置所有网络服务器。

此示例假设您在安装了 puppet 等的基础映像上构建。

好处:

1) 您不必传递您的凭据

2) 您可以根据需要对角色配置进行细化。

【讨论】:

【参考方案17】:

一旦您安装了ec2-metadataec2-describe-tags(如Ranieri's answer above 中所述),下面是一个示例shell 命令,用于获取当前实例的“名称”,假设您有一个“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

【讨论】:

如果我的进程可以获取当前实例的标签而不必在实例上也有 EC2_PRIVATE_KEY,那就太好了。 :-( @william-payne 是的,这真的很蹩脚。也许使用 Amazon 的 IAM,您至少可以使用对任何东西的访问权限非常有限的用户。 FWIW,我不再使用这种方法,只是使用外部脚本来设置盒子。 @WilliamPayne 您可以使用“Amazon EC2 只读访问”策略设置 IAM 角色并创建具有该角色的实例。如果您想更细化,也可以创建仅具有“DescribeTags”权限的自定义策略。 @WilliamPayne 我喜欢 roverwolf 的建议。效果很好。如果你想看的话,我实际上已经用细节回答了另一个问题:***.com/questions/9950586/… 请注意ec2-describe-tags 默认为us-east-2。请传递--region 标志以使用不同的区域。

以上是关于从实例内查询 EC2 标签的主要内容,如果未能解决你的问题,请参考以下文章

如何通过 CloudFormation 设置 EC2 实例根卷的标签

在 Boto3 中获取具有特定标签和值的 EC2 实例列表

BOTO3:如何过滤标签“不相等”的实例?

如何创建 IAM 策略以根据子网名称标签控制对 Amazon EC2 资源的访问?

从 EC2 实例查询 DynamoDB 时遇到高延迟

查找所有没有特定标签的 Amazon AWS 实例