Search code examples
dockeramazon-ecs

Getting introspection metadata from inside a container


I'm wondering how to access introspection metadata from inside a container running in an ECS cluster.

The documentation recommends to call:

curl http://localhost:51678/v1/metadata

Which works on the EC2 instance itself, but not from the container, which is not on the same network (in bridge network mode).

However, the command to access EC2 introspection metadata works well because the call has to be done to an IP address, which is reachable from the container:

curl http://169.254.169.254/latest/meta-data/  

I guess one way to do would be to change the network mode to share the host interface, but in the current setup that's something I'd prefer to avoid.

In context, I'm trying to move my code that sends custom Cloudwatch metrics out from a local script to a utility container. I would like to avoid specifying stuff such as the ECS cluster name, when it could be retrieved from an API call.


Solution

  • Ok, I found a way.

    The container running on the EC2 instance from the ECS cluster can access the host IP, either from its private IP (which is not reliable), or from the Docker Bridge IP, and the introspection calls can be run on them.

    The Docker Bridge IP option, which defines on which network the containers will run, defaults to 172.17.0.0/16, and can be modified in the file /etc/sysconfig/docker (on the official ECS community AMIs), in the definition of OPTIONS:

    OPTIONS="--ip-forward=true --iptables=true --bip="172.32.0.1/24" --storage-opt dm.basesize=100G"
    

    So even if the host's docker0 network interface is likely to have an IP address of 172.17.0.1, it's better to retrieve it from the container by extracting the IP address of the gateway of the docker0 network interface, this way:

    ip route|head -n 1|sed -r 's/default via ([0-9.]+).*$/\1/'


    So in my container, running these commands will return what I expect:

    HOST_IP=$(ip route|head -n 1|sed -r 's/default via ([0-9.]+).*$/\1/')
    clusterName=$(curl -s "http://$HOST_IP:51678/v1/metadata" | jq -r ".Cluster")
    instanceArn=$(curl -s "http://$HOST_IP:51678/v1/metadata" | jq -r ".ContainerInstanceArn")