In this quick post, I show how you can discover the etcd endpoint from within a container running on CoreOS.
Reading and writing to etcd within a CoreOS is straightforward – you can use the etcdctl
utility or just use regular HTTP to http://127.0.0.1:4001/v2/keys
But what about inside a container?
The CoreOS manual tells you you how to obtain the address of the docker0 interface on the host, but you still have to figure out how to get that into your container.
Here’s two alternatives you can try
Pulling the etcd endpoint from inside the container
Inside the container, you can use the address of the default gateway, as this will correspond with the docker0
interface on the host.
You could use a bash startup script for your service which uses a bit of grep and awk to build the endpoint, for example:
#!/bin/bash ETCD_ENDPOINT=$(route|grep default|awk '{print $2}'):4001
So this is nice, but unsatisying. It’s not really finding where etcd is, it’s just exploiting a side effect of how CoreOS sets things up.
Pushing the etcd endpoint into the container
Here’s my current favourite method – we make the etcd service on the host write an environment file we can incorporate into our fleet units. To do that, we need to create a new file /run/systemd/system/etcd.service.d/30-environment.conf
containing this
[Service] #write an environment file to use in other units ExecStartPost=/bin/bash -c "echo ETCD_ENDPOINT=${ETCD_ADDR} > /etc/etcd.environment"
You can write this file by hand and then have it take effect with
sudo systemctl daemon-reload sudo systemctl restart etcd.service
You should see it created /etc/etcd.environment
and we can include that in any fleet unit with Environment=/etc/etcd.environment
, and from there it’s easy to use the ETCD_ENDPOINT
variable to configure services.
This configuration isn’t permanent, we’ll lose it the next time CoreOS updates itself. You’ll need to have your provisioning system deploy it for you. Alternatively you can include a little extra bit into your cloud-config to create the file on newly minted or updated machines. Something like this would do the trick:
write_files: - path: /run/systemd/system/etcd.service.d/30-environment.conf permissions: 420 content: | [Service] #write an environment file to use in other units ExecStartPost=/bin/bash -c "echo ETCD_ENDPOINT=${ETCD_ADDR} > /etc/etcd.environment"
Summary
I’ve tried to show how a container can discover the etcd endpoint. The first method is fine, but I’d prefer something that wasn’t looking for a side effect, and was unequivocally told where etcd can be found. The second method does this, but is admittedly a bit more involved. I’d like to see CoreOS incorporate something like this themselves.
Hope this helps someone in the meantime!