Bastian Voigt
Bastian Voigt

Reputation: 5671

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

I run the following shell command to drain my ECS instance before rebooting it:

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

It gives me the following error:

An error occurred (InvalidParameterException) when calling the UpdateContainerInstancesState operation: instanceId shorter than 36.

Apparently this is because it wants the ECS containerInstanceId which is different from the ec2InstanceId. What is the best way to find out the containerInstanceId of the local machine?

The way I figured out so far is

  1. use aws ecs list-container-instances to get all the container instance IDs in the cluster
  2. use aws ecs describe-container-instances to get the corresponding EC2 instance IDs
  3. use instance metadata (http://169.254.169.254/latest/meta-data/instance-id) to find out the local EC2 instance ID
  4. Use jq combined with grep or some other tool to filter

This seems a little complicated. Is there a simpler way?

Upvotes: 5

Views: 10888

Answers (4)

Rob Geraghty
Rob Geraghty

Reputation: 127

Here's ruby code I used for this:

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

Upvotes: 0

tgoodhart
tgoodhart

Reputation: 3266

Another option is to populate a custom attribute on the instance containing the instance Id. For example, in your /etc/ecs/ecs.config, you may have the following:

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

This can then be used in conjunction with the --filter parameter of list-container-instances to find the associated container instance.

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

If you are using the cfn-init script and CloudFormation, then this can be automated when you create the EC2 instance.

....
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
...

References:

Upvotes: 5

Mike D
Mike D

Reputation: 6195

With jq installed, this is fairly straight forward.

Using the ECS Container Introspection endpoint, you get these values and pass them to the aws ecs update-container-instances-state command.

It can be useful to do this in user data and add the results into /etc/environment so they are always readily available.

#!/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"

Adding them to /etc/environment via user data:

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

Notes:

  • jq -e flag means to set the exit code if the key is not found.
  • jq -r flag means to dump output as raw text instead of json.

Upvotes: 0

Samuel Karp
Samuel Karp

Reputation: 4672

If you're running a script on the instance, you can find the container instance ID from the ECS agent's introspection API.

If you're running a script from within an ECS task, you can use the container metadata file.

Upvotes: 4

Related Questions