How can I retrieve private IP from a container on AWS ECS?

Question:

I am trying to retrieve the private IP from my containers on AWS ECS, I am using python and boto3 for that work.

That is my code:

import json
import boto3

def lambda_handler(event, context):
  client = boto3.client("ecs", region_name="sa-east-1")

  clusterArn='ANY ARN'

  tasks = client.list_tasks(cluster=clusterArn)

  containers = []
  for each in tasks['taskArns']:
      containers.append(each)
     
    
  resp = client.describe_tasks(cluster=clusterArn,tasks=containers)
  print(json.dumps(resp, indent=4, default=str, sort_keys=True))

The describe tasks return for me the following IP from container:

{
"bindIP": "0.0.0.0",
"containerPort": 8080,
"hostPort": 8080,
"protocol": "tcp"
}

I alredy tried to use ecs describe task on aws cli, but its the same response. Is there another way to retrieve the private ip using boto3?

Thanks,

Asked By: felipe cesar

||

Answers:

With ECS on EC2, your task will have the IP of your EC2 instance and will then bind with an available port.

You can get the port with the ECS API, but you’ll need the EC2 API to get the IP if there’s no networkInterfaces attached yo your containers.

Here’s an example with the cli to get both IP and ports for a task:

CLUSTER=your-cluster-name                                                                        
TASK_NAME=your-task-name

TASK_ARN=$(aws ecs list-tasks --service-name ${TASK_NAME} --query 'taskArns[0]' --output text --cluster ${CLUSTER})
CONTAINERS_DATA=$(aws ecs describe-tasks --task ${TASK_ARN} --cluster ${CLUSTER})

CONTAINER_ARN=$(echo $CONTAINERS_DATA | jq -r '.tasks[0].containerInstanceArn')
CONTAINER_PORTS=$(echo $CONTAINERS_DATA | jq '.tasks[0].containers[].networkBindings[].hostPort')

EC2_IID=$(aws ecs describe-container-instances --cluster ${CLUSTER} --container-instances ${CONTAINER_ARN} --output text --query 'containerInstances[0].ec2InstanceId')
TASK_IP=$(aws ec2 describe-instances --instance-id ${EC2_IID} --output text --query 'Reservations[0].Instances[0].PrivateIpAddress')

echo "Task IP: ${TASK_IP} | Task Ports: ${CONTAINER_PORTS}"
# Task IP: 10.24.35.188 | Task Ports: 49165
Answered By: RobinFrcd

In AWS IP addresses are provided for Network Interfaces, which will be attached to the running containers. So you would want to fetch the network interface section of a container.

For example:

import boto3


def lambda_handler(event, context):
    client = boto3.client("ecs", region_name="sa-east-1")

    cluster_arn = '...'

    tasks = client.list_tasks(cluster=cluster_arn)
    task_arns = [arn for arn in tasks['taskArns']]
    
    resp = client.describe_tasks(cluster=cluster_arn, tasks=task_arns)
    for task in resp['tasks']:
        for container in task['containers']:
            private_ips = [interface['privateIpv4Address'] for interface in container['networkInterfaces']]
            print(f'{container["name"]}: {private_ips}')

It should output something like this:

nginx: ['10.0.0.49']
node: ['10.0.0.55']
Answered By: Ervin Szilagyi