【问题标题】:Finding all Amazon AWS Instances That Do Not Have a Certain Tag查找所有没有特定标签的 Amazon AWS 实例
【发布时间】:2022-01-23 15:48:46
【问题描述】:

我正在尝试使用 Amazon AWS 命令​​行工具来查找所有没有指定标签的实例。

使用标签查找所有实例很简单,例如

ec2-describe-instances --filter "tag-key=Name"

但是我将如何反转该过滤器以仅返回没有标签“名称”的实例?

【问题讨论】:

  • // ,对于那些在查找如何通过 ==tag 删除而不是通过 !=tag 删除时以某种方式到达这里的人,(咳咳),你可以试试这个:stackoverflow.com/questions/42076274/…跨度>

标签: command-line amazon-web-services filter


【解决方案1】:

AFAIK 直接通过 CLI 是无法做到的。

根据您使用的语法,我猜您使用的是旧的 cli。我建议你下载新的 CLI http://aws.amazon.com/cli/ 并调用

aws ec2 describe-instances --output json

来自 python、ruby 或任何脚本语言,您可能希望根据需要使用适当的正则表达式解析 json 输出过滤

【讨论】:

    【解决方案2】:

    你总是可以这样做: ec2-describe-instances | grep -v "Name" :p

    【讨论】:

    • 此评论没有回答问题。此外,像这样的简单命令是行不通的
    【解决方案3】:

    这将满足您的要求 - 查找每个不包含名为“YOUR_KEY_NAME_HERE”标签的实例(第二行过滤器用于没有名为“名称”标签的实例):

    aws ec2 describe-instances | jq '.Reservations[].Instances[] | select(contains({Tags: [{Key: "YOUR_KEY_NAME_HERE"} ]}) | not)' 
    aws ec2 describe-instances | jq '.Reservations[].Instances[] | select(contains({Tags: [{Key: "Name"} ]}) | not)' 
    

    如果您想过滤标签的值,而不是标签的名称,此查询会列出不包含名为 YOUR_KEY_NAME_HERE 且值为 EXCLUDE_ME 的标签的所有实例。 (第二行列出了未命名为“testbox1”的实例。)

    aws ec2 describe-instances | jq '.Reservations[].Instances[] | select(contains({Tags: [{Key: "YOUR_KEY_NAME_HERE"}, {Value: "EXCLUDE_ME"}]}) | not)'
    aws ec2 describe-instances | jq '.Reservations[].Instances[] | select(contains({Tags: [{Key: "Name"}, {Value: "testbox1"}]}) | not)'
    

    费利佩是正确的。解析输出是唯一的方法,因为 AWS API 不提供此功能,任何官方 AWS CLI 也不提供。 JSON 输出非常易于解析,尤其是与旧 CLI 默认打印的多行文本记录相比。

    http://docs.aws.amazon.com/AWSEC2/latest/APIReference/ApiReference-query-DescribeInstances.html

    API 本身返回 JSON,新的 awscli 将该 JSON 打印为其默认输出格式。 "jq" 程序对解析它非常有用,甚至在发送到终端时会着色,或者您可以 --output text 将其还原为字符串。

    【讨论】:

    • 这有一个非常有用的 JQ tidibt 在这里我一直在寻找解决一段时间。谢谢!
    【解决方案4】:

    我遇到了同样的问题,我想出了如何查询标签值 您很可能会为所有实例定义相同的标签键;我在所有实例上定义了一个标签键“MachineName”,我想按标签键名称的值进行过滤

    下面是过滤 Name=Machine1 的示例

    使用选项

    --filters "Name=tag-key,Values=MachineName" "Name=tag-values,Values=Machine1"
    

    这对我来说很好用

    【讨论】:

    • 我不明白这是如何回答这个问题的。
    【解决方案5】:

    不幸的是,底层 api 调用 DescribeInstances 不支持反向标签过滤,因此 CLI 也不支持。但是,您可以使用执行JMESPath 搜索的--query 参数进行客户端过滤。这将使您不必像 user2616321 的回答那样使用管道。

    例如:

    aws ec2 describe-instances --query "Reservations[].Instances[?Tags[?Key == 'Name']][]"
    

    在末尾添加 .InstanceId 以获取实例 ID。

    【讨论】:

    • 愿意提供一个您将用于此的 JMESPath 示例吗?
    • 没问题,我马上就搞定
    • 嗯...当我运行那个版本时,我似乎只得到包含一个“名称”标签的实例——相当于--filter "tag-key=Name"。问题正好相反。
    【解决方案6】:

    我也对通过 CLI 执行此操作的难度感到震惊。我喜欢 user2616321 的回答,但我在让它输出每个实例所需的确切字段时遇到了一些麻烦。在花了一段时间在查询语法中弄乱并使用 JMESPath 失败后,我最终只制作了一个小 ruby​​ 脚本来执行此操作。如果有人想节省几分钟写自己的,这里是:

    #!/usr/bin/env ruby
    require 'json'
    
    # We'll output any instance that doesn't contain all of these tags
    desired_tags = if ARGV.empty?
                     %w(Name)
                   else
                     ARGV
                   end
    
    # Put the keys we want to output per instance/reservation here
    reservation_keys = %w(OwnerId RequesterId)
    instance_keys = %w(Tags InstanceId InstanceType PublicDnsName LaunchTime PrivateIpAddress KeyName) 
    instances_without_tags = []
    
    # Just use CLI here to avoid AWS dependencies
    reservations = JSON.parse(
      `aws ec2 describe-instances`
    )["Reservations"]
    
    # A reservation is a single call to spin up instances. You could potentially
    # have more than one instance in a reservation, but often only one is
    # spun up at a time, meaning there is a single instance per reservation.
    reservations.each do |reservation|
      reservation["Instances"].each do |instance|
        # Filter instances without the desired tags
        tag_keys = instance["Tags"].map { |t| t["Key"] }
        unless (tag_keys & desired_tags).length == desired_tags.length
          instances_without_tags << 
            reservation.select { |k| reservation_keys.include?(k) }.
              merge(instance.select { |k| instance_keys.include?(k) })
        end
      end
    end
    
    puts JSON.pretty_generate(instances_without_tags)
    

    【讨论】:

      【解决方案7】:

      您可以使用 jmespath(驱动 --query 参数的引擎)来做到这一点,不管别人怎么说:

      aws ec2 describe-instances \
        --query 'Reservations[].Instances[?!not_null(Tags[?Key == `Name`].Value)] | []'
      

      来源:Using Amazon Web Services Command Line Interface (AWS CLI) to Find Instances without a 'Name' Tag.

      【讨论】:

      • 您确定过滤器是 server-side 而不是 client-side?为此发送的实际请求是什么?
      • @CraigRinger 这绝对是客户端。 DescribeInstances api 允许服务器端过滤器(aws cli:--filters),但缺少“不”功能。所以全部拉到本地,用jmespath过滤。您可以在 aws cli 上使用 --debug 来查看其对 API 的实际调用。
      • 感谢您的确认。啊。我很沮丧,过滤器 API 缺少任何形式的否定。
      【解决方案8】:

      由于--filters参数似乎不支持反向过滤,下面是我使用--query参数解决这个问题的方法:

      aws ec2 describe-instances \
      --query 'Reservations[].Instances[?!contains(Tags[].Key, `Name`)][].InstanceId'
      

      它查看每个实例的标签键数组并过滤那些在数组中没有标签“名称”的实例。然后将输出展平为实例 ID 数组。

      • 相对于以前的一些答案的优势:不需要jq 或其他命令来过滤输出。
      • 相对于真正的逆滤波器的缺点:在大量实例中可能会慢得多。

      【讨论】:

        【解决方案9】:

        我使用这个 python3/boto 脚本进行非常大的反标签过滤操作:

        import boto3
        from botocore.config import Config
        
        # Attempts
        config = Config(
          retries = dict(
            max_attempts = 3
          )
        )
        
        # Tag(s)
        my_tags = [
          {
            "Key": "backup",
            "Value": "true"
          }
        ]
        
        # Owner ID Filter
        owner_id = 'SOME_OWNER_ID'
        
        # Connection
        ec2 = boto3.client("ec2", config=config)
        
        # Instances
        def tag_instances():
          # All Reservations [instances] (tagged or untagged)
          all_reservations = ec2.describe_instances(Filters = [{'Name': 'owner-id', 'Values':[owner_id]}])
        
          # Append each InstanceId in all_reservations to all_instances
          all_instances = []
          for all_reservation in all_reservations['Reservations']:
            for all_instance in all_reservation['Instances']:
              all_instances.append(all_instance['InstanceId'])
        
          # Append each InstanceId with backup:true or backup:false to tagged_instances
          tagged_reservations = ec2.describe_instances(Filters = [{'Name': 'owner-id', 'Values':[owner_id]},{'Name': 'tag:backup', 'Values':['true','false']}])
          tagged_instances = []
          for tagged_reservation in tagged_reservations['Reservations']:
            for tagged_instance in tagged_reservation['Instances']:
              tagged_instances.append(tagged_instance['InstanceId'])
        
          # Append each InstanceId in all_instances and not in tagged_instances to untagged_instances
          untagged_instances = [all_instance for all_instance in all_instances if all_instance not in tagged_instances]
        
          # Print untagged InstanceId
          print("untagged_instanceids:",untagged_instances)
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2019-10-03
          • 2019-07-11
          • 1970-01-01
          • 2011-04-16
          • 1970-01-01
          • 1970-01-01
          • 2017-02-23
          相关资源
          最近更新 更多