Getting Familiar with the Rancher Metadata Service

Exploring ways of accessing metadata information about your environment in Rancher through the metadata service.

One of the features I’ve had fun using in Rancher is the metadata service. For containers deployed using the Rancher managed network, you get access to metadata about other containers, services, stacks, and hosts in the environment. It also provides information specific to only that container, like it’s primary IP. Although it may not appear too exciting at first glance, the metadata service can reduce the amount of data you need up front when launching a container, and even help when bootstrapping clustered services.

Starting a Stack to Play With

In order to start playing with the metadata service, we’ll need a stack. Below is what I’m using to creating a simple stack, example-stack, that launches a long-running container for us to later exec into:

# docker-compose.yml
example:
image: appropriate/curl
command: ping localhost
# rancher-compose.yml
example:
scale: 3

With our example-stack created, we can open up a shell to one of our containers:

$ docker exec -it r-example-stack_example_1 /bin/sh

The metadata service listens on TCP port 80 and can be reached by the DNS name rancher-metadata. Querying that name will return a list of metadata versions available:

/ # curl rancher-metadata
2015-07-25
2015-12-19
latest

We’ll use latest for the rest of the post, and querying latest returns the available categories of information available to us:

/ # curl rancher-metadata/latest
containers/
hosts/
self/
services/
stacks/
version

Each category exposes different metadata about the environment, depending on what you want to drill down into. The table below briefly describes each category (for a more detailed explanation, see http://docs.rancher.com/rancher/metadata-service/):

category description hosts Provides metadata on all hosts in the environment stacks Provides metadata on all stacks in the environment services Provides metadata on all services in the environment containers Provides metadata on all containers in the environment self Provides host, stack, service, and container metadata of the container you are on

Scenarios

If you are like me, you want to see all the keys and values available via the metadata service to provide some context. The following script will walk the entire metadata tree and print out each path along with the values associated with each key (for the lazy, here is some example output):

_tree_walk() {
echo $1
for d in `curl -s rancher-metadata/latest${1}`; do
if echo $d | egrep -q "/$"; then
_tree_walk "${1}/$(echo $d | sed 's/\///g')"
elif echo $d | egrep -q '^[0-9]+='; then
_tree_walk "${1}/$(echo $d | cut -d'=' -f1)"
else
_tree_get ${1}/${d}
fi
done
}
_tree_get() {
echo "${1} : $(curl -s rancher-metadata/latest${1})"
}
_tree_walk

Below are some scenarios where I’ve found interacting with the metadata to be useful (although I’m sure plenty more exist).

Retrieve All Container IPs of a Given Service

A common data point I find myself after is a list of all the IPs of a given service to be used in a configuration of some sort. Using the metadata service makes this task easy since it knows of all the services and stacks available. Normally, a service discovery tool is also a good fit for this sort of information, however, this can be useful when no such service exists or you are bootstrapping one. Let’s try it out using the example service running in the example-stack stack.

We can see all the containers running for our service, example:

/ # curl -s rancher-metadata/latest/services/example/containers
0=example-stack_example_1
1=example-stack_example_2
2=example-stack_example_3

To get the primary IP address of a container, we can access the primary_ip key:

/ # curl -s rancher-metadata/latest/services/example/containers/0/primary_ip
10.42.168.101

An ugly, yet effective shell loop to concatenate each container’s primary IP into a single, comma-separated list could look like:

/ # for c in $(curl -s rancher-metadata/latest/services/example/containers); do
> i=$(echo $c | cut -d'=' -f1)
> curl -s rancher-metadata/latest/services/example/containers/$i/primary_ip
> echo -n ","
> done | rev | cut -c 2- | rev
10.42.168.101,10.42.176.75,10.42.92.62

Retrieve the IP of the Docker Host Running a Container

Another data-point I’m often after is the IP address of the host running my container. This can be easily accessed through the self section of the metadata:

curl rancher-metadata/latest/self/host/agent_ip
172.17.0.1

Giddyup

Those shell commands demonstrate some of the accessibility of information in the metadata service, however, a more formal way of interacting with such a service is desired. cloudnautique has authored giddyup, a tool that provides a more consistent way for interacting with the metadata service. It also provides a clean interface for leader elections and leader traffic forwarding, which is detailed on the project page.

Giddyup is written in go and can be downloaded as a binary:

/ # wget -O giddyup https://github.com/cloudnautique/giddyup/releases/download/v0.7.0/giddyup
/ # chmod +x giddyup

We can now, more easily, concatenate a list of our container IPs:

/ # ./giddyup ip stringify
10.42.168.101,10.42.176.75,10.42.92.62

Or more explicitly:

/ # ./giddyup ip stringify example-stack/example
10.42.168.101,10.42.176.75,10.42.92.62

Originally published at thisendout.com on February 22, 2016.