Traffikey
- published
- reading time
- 4 minutes
In the previous post, I’ve mentioned something called Traffikey that would help through my transition out of the Hashicorp products.
Since I’ve been using it for quite a while now and I’ve finally added some much needed features, I think it’s time to talk about it.
The use case
Put simply, etcd can be used by Traefik for it’s configuration of routers, services and middlewares the same way as Consul can be used. But since this would be all manual because there is nothing to “detect” those services, something would need to be automated to put the right keys at the right places in etcd.
Traefik internals
Here is an example for an HTTP service hosted on localhost that would listen on port 8181 and would reached from traefik when the url contains the path /path
. To complicate things futher and show what needs to be done for using middlewares, we’ll also strip the /path
from the forwarded request.
Key | Value |
---|---|
traefik/http/middlewares/prefix/stripprefix/prefixes |
/path |
traefik/http/routers/path/entrypoints |
web |
traefik/http/routers/path/middlewares |
prefix |
traefik/http/routers/path/rule |
Path(`/path/`) |
traefik/http/routers/path/service |
path |
traefik/http/services/path/loadbalancer/servers/0/url |
http://127.0.0.1:8181 |
As you can see, there are quite a lot of keys required to get the service (the target in Traefik’s terms) setup. At minimum, we are talking about three for the router itself and one for the service. In our case we need two more for the middleware, one declaring the middleware itself and one with the router to use said middleware.
Someting else to note too is the first part of the key (traefik
) is something you can change in Traefik’s configuration so you can use multiple instances of Traefik on the same etcd cluster to route traffic differently. I personally use 2 prefixes: internal (traefik
) and public (public
).
And we aren’t even talking about TLS/SSL usage :)
Implementation
Traffikey is a Go based suite (only one so far) of service(s) to help managing the etcd keys for Traefik. Currently the main usage is a tool that will start, analyze it’s configuration, apply the necessary changes and exit out. This can be used as a systemd unit of OneShot
type.
The way to use it is primarily through it’s configuration file which is JSON encoded.
The below example is the same as the keys above but this time as the JSON configuration.
{
"etcd": {
"endpoints": [
"http://127.0.0.1:2379"
]
},
"targets": [
{
"entrypoint": "web",
"middlewares": [
{
"kind": "stripprefix",
"name": "prefix",
"values": {
"prefixes": "/path"
}
}
],
"name": "path",
"prefix": "",
"rule": "Path(`/path/`)",
"tls": false,
"type": "http",
"urls": [
"127.0.0.1:8181"
]
}
],
"traefik": {
"default_entrypoint": "web",
"default_prefix": "traefik"
}
}
The fun part
Since this is a JSON file and pretty much everything under the sun now can manipulate it, we can generate the configuration!
Automating the automation
I’m a big fan and heavy user of NixOS and the nix package manager. The Traffikey repository contains a NixOS module which makes it possible to generate more configuration for targets.
Since we’ve been using the same example, let’s keep going and the above configuration will be generated when using the NixOS module like so:
services.traffikey = {
enable = true;
etcdEndpoints = [ "http://127.0.0.1:2379" ];
defaultEntrypoint = "web";
defaultPrefix = "traefik";
targets = {
"path" = {
rule = "Path(`/path/`)";
serverUrls = [ "127.0.0.1:8181" ];
middlewares = {
prefix = {
kind = "stripprefix";
values.prefixes = "/path";
};
};
};
};
};
The future
I’m very pleased with the way things are working right now but as with everything, things could be improved.
One feature I plan on adding would be to have Traffikey work as a optional server which would detect the targets and check if they are alive. If they are, the keys gets written as before but if they are not, it will write in etcd to point to itself and print an error message. This avoids something like an error 502 or a 404 if something is missing.