如何获取本地ec2实例的container-instance-id

How to get the container-instance-id of the local ec2 instance

我 运行 使用以下 shell 命令在重新启动之前耗尽我的 ECS 实例:

INSTANCE_ID=$(curl http://169.254.169.254/latest/meta-data/instance-id)
aws ecs update-container-instances-state \
  --region eu-central-1 \
  --cluster mycluster \
  --status DRAINING \
  --container-instances $INSTANCE_ID

它给我以下错误:

调用UpdateContainerInstancesState操作时发生错误(InvalidParameterException):instanceId小于36。

显然这是因为它需要与 ec2InstanceId 不同的 ECS containerInstanceId。找出本地机器的 containerInstanceId 的最佳方法是什么?

目前我想到的方法是

  1. 使用aws ecs list-container-instances获取集群中所有容器实例ID
  2. 使用aws ecs describe-container-instances获取对应的EC2实例ID
  3. 使用实例元数据 (http://169.254.169.254/latest/meta-data/instance-id) 找出本地 EC2 实例 ID
  4. 使用 jq 结合 grep 或其他一些工具来过滤

这似乎有点复杂。有没有更简单的方法?

如果您是 运行 实例上的脚本,您可以从 ECS 代理的 introspection API.

中找到容器实例 ID

如果您是 运行 ECS 任务中的脚本,您可以使用 container metadata file.

另一种选择是在包含实例 ID 的实例上填充自定义属性。例如,在您的 /etc/ecs/ecs.config 中,您可能有以下内容:

ECS_INSTANCE_ATTRIBUTES={\"ec2_instance\":\"i-0000000000000000000\"}

这可以与 --filter 参数一起使用 list-container-instances 来查找关联的容器实例.

aws ecs list-container-instances --cluster <MY Cluster> --filter attribute:ec2_instance==i-0000000000000000000

如果您正在使用 cfn-init 脚本和 CloudFormation,那么这可以在您创建 EC2 实例时自动执行。

....
MyLaunchConfiguration:
  Type: AWS::AutoScaling::LaunchConfiguration
  Metadata:
    AWS::CloudFormation::Init:
      config: 
        commands: 
          00_configure_ecs_agent:
            command: |
              #!/bin/bash
                echo ECS_INSTANCE_ATTRIBUTES={\"ec2_instance\":\"$(wget -q -O - http://169.254.169.254/latest/meta-data/instance-id)\"} >> /etc/ecs/ecs.config
...

参考文献:

安装 jq 后,这非常简单。

使用 ECS Container Introspection 端点,您可以获得这些值并将它们传递给 aws ecs update-container-instances-state 命令。

user data 中执行此操作并将结果添加到 /etc/environment 中会很有用,这样它们就随时可用。

#!/usr/bin/env bash
set -euo pipefail

CONTAINER_INSTANCE_ARN="$(curl -s --fail http://localhost:51678/v1/metadata | jq -er '.ContainerInstanceArn')"
CLUSTER="$(curl -s --fail http://localhost:51678/v1/metadata | jq -er '.Cluster')"

aws ecs update-container-instances-state --cluster "$CLUSTER" \
    --container-instances "$CONTAINER_INSTANCE_ARN" --status "DRAINING"

通过用户数据将它们添加到 /etc/environment

cat<<-EOF>>/etc/environment
CONTAINER_INSTANCE_ARN="$(curl -s --fail http://localhost:51678/v1/metadata | jq -er '.ContainerInstanceArn')"
CLUSTER="$(curl -s --fail http://localhost:51678/v1/metadata | jq -er '.Cluster')"
EOF
source /etc/environment

备注:

  • jq -e flag 表示如果找不到密钥,则设置退出代码。
  • jq -r 标志表示将输出转储为原始文本而不是 json。

这是我为此使用的 ruby 代码:

require 'aws-sdk-ecs'

region = JSON.parse(`curl --silent http://169.254.169.254/latest/dynamic/instance-identity/document`)['region']
instance_id = `ec2metadata --instance-id`.strip
cluster_name = `cat /etc/ecs/ecs.config | grep '^ECS_CLUSTER=' | cut -d "=" -f2`.strip

container_instance_arn = lambda do
  ECS_CLIENT.describe_container_instances({
    :cluster => cluster_name,
    :container_instances => ECS_CLIENT.list_container_instances({
      :cluster => cluster_name,
    }).container_instance_arns
  }).container_instances.select do |instance|
    instance.ec2_instance_id == instance_id
  end.first.container_instance_arn
end.call