如何获取本地ec2实例的container-instance-id
Posted
技术标签:
【中文标题】如何获取本地ec2实例的container-instance-id【英文标题】:How to get the container-instance-id of the local ec2 instance 【发布时间】:2018-10-17 06:05:28 【问题描述】:我在重启之前运行以下 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最好的方法是什么?
到目前为止我想出的方法是
-
使用
aws ecs list-container-instances
获取集群中的所有容器实例ID
使用aws ecs describe-container-instances
获取对应的EC2实例ID
使用实例元数据 (http://169.254.169.254/latest/meta-data/instance-id
) 找出本地 EC2 实例 ID
使用jq
结合grep
或其他工具进行过滤
这似乎有点复杂。有没有更简单的方法?
【问题讨论】:
我相信您应该输入容器实例 ID 而不是 EC2 实例 ID。容器实例 ID 如下所示:1c3be8ed-df30-47b4-8f1e-6e68ebd01f34。我从 AWS API 指南中提取了它:docs.aws.amazon.com/AmazonECS/latest/APIReference/… 你说得对。我通过使用 aws ecs list-container-instances,然后使用 aws ecs describe-container-instances 以及一些 grepping 和 awking 解决了这个问题。这么简单的任务似乎有点复杂 【参考方案1】:另一个选项是在包含实例 ID 的实例上填充自定义属性。例如,在您的 /etc/ecs/ecs.config 中,您可能有以下内容:
ECS_INSTANCE_ATTRIBUTES=\"ec2_instance\":\"i-0000000000000000000\"
这可以与 list-container-instances 的 --filter 参数一起使用来查找关联的容器实例。
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
...
参考资料:
https://docs.aws.amazon.com/AmazonECS/latest/developerguide/ecs-agent-config.html https://docs.aws.amazon.com/cli/latest/reference/ecs/list-container-instances.html https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/cfn-init.html【讨论】:
自发布以来,Jose 注意到现在有一个“ec2InstanceId”属性自动填充并可用于列表容器实例。无需对自定义属性大惊小怪。【参考方案2】:如果您在实例上运行脚本,您可以从 ECS 代理的introspection API 中找到容器实例 ID。
如果您在 ECS 任务中运行脚本,则可以使用 container metadata file。
【讨论】:
【参考方案3】:安装了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。
【讨论】:
【参考方案4】:这是我用于此的 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
【讨论】:
以上是关于如何获取本地ec2实例的container-instance-id的主要内容,如果未能解决你的问题,请参考以下文章
如何使用 AWS *** 从 EC2 实例 ping 到本地 Windows Server?
如何在Python AWS boto API中获取EC2实例ID的容器实例列表