Using Traefik with Consul

Consul Key/Value Store and Service Catalog

  • Consul has two functions built in to it: a Key/Value store and a Service Catalog
  • The Key/Value store is useful for defining variables to be shared in the cluster.
  • The Service Catalog is useful for integration with tools like Traefik as a service discovery tool to dynamically define hosts.

Service Catalog

  • The Consul Service Catalog is used as a service discovery tool.
  • The Service Catalog works byt defining a service by name, port, and healthcheck.
curl \
  -v \
  -XPUT \
  -d '{"service": {
        "name": "http-service",
        "tags": ["http-service"],
        "port": 80
      }
    }' \
  http://consul:8500/v1/agent/service/register
  • Once the service has been registered, consul will search the host where the consul agent is running for the port and healthcheck.
  • The service will be listed in the service catalog: consul catalog services
consul
http-service
nomad
nomad-client
  • Curl can be used to list the services
curl http://localhost:8500/v1/catalog/service/http-service
curl 'http://localhost:8500/v1/health/service/http-service?passing'
  • The power of the Service Catalog is that it includes a built-in DNS server for all the registered services
dig @127.0.0.1 -p 8600 web.service.consul
dig @127.0.0.1 -p 8600 web.service.consul SRV

Key/Value Store

curl http://0.0.0.0/v1/kv


consul kv put hello "world"
curl http://0.0.0.0:8500/v1/kv/hello
[
  {
    "LockIndex": 0,
    "Key": "hello",
    "Flags": 0,
    "Value": "ZGFwcA==",
    "CreateIndex": 75,
    "ModifyIndex": 75
  }
]


VALUE=$(curl http://0.0.0.0:8500/v1/kv/hello 2>/dev/null | jq '.[0].Value' | sed 's/"//g' | base64 -D)

echo "[$VALUE]"

world

Bootstrapping the Contents of a new Consul cluster

echo '{
  "web-service": {
    "name": "web",
    "tags": ["apache2"],
    "port": 80
  },
  "tomcat-service": {
    "name": "tomcat",
    "tags": ["tomcat"],
    "port": 8080
  },
  "webapp-service": {
    "name":  "webapp",
    "port":  5000,
    "tags":  ["flask", "backend"],
    "check": {
      "script":   "curl http://localhost:5000/healthcheck > /dev/null 2>&1",
      "interval": "10s"
    }
  }

}' | tee /etc/consul.d/web.json | jq '.'
consul agent -dev -config-dir=/etc/consul.d

Storing Traefik configuration in Consul

  • Traefik defines an entrypoint, a frontend, and a backend.
  • The entrypoint is a listener, think about it as an http or https point where traffic enters Traefik.
  • The entrypoint connects to a frontend. A frontend is a rule for connecting the incoming pipe to the backend outgoing pipe.
  • Consul can be used to store the configuration for Traefik so that a static on-disk config file is not needed.

Define Entrypoints

consul kv put traefik/entryPoints/http/address  ":80"
consul kv put traefik/entryPoints/http/compress true

Define Frontends

  • The frontend is a series of rules which determine how incoming traffic will flow from an entrypoint to the backend.
  • The rules used by Traefik are called matchers
  • Naturally a hostname request is the most common matching rule Host:dapp.hubner.org
  • Rules can be based on the HTTP request method: Method:GET
  • Regular expressions are supported in the rule so long as a named variable is used and the regex is contained in curly brackets: Method:{m:.*}
  • Multiple rules can be combined by separating them with a semicolon (;) : Method:GET;Method:POST
consul kv put traefik/frontends/dapp/backend dapp
consul kv put traefik/frontends/dapp/entrypoints http
consul kv put traefik/frontends/dapp/routes/dapp0/rule "Host:dapp.hubner.org"

Define Backends

consul kv put traefik/backends/dapp/servers/server0/url    "http://0.0.0.0:80"
consul kv put traefik/backends/dapp/servers/server0/weight 1

Configure docker container to register itself with the Consul Service Catalog on startup

IP=`ip addr | grep -E 'eth0.*state UP' -A2 | tail -n 1 | awk '{print $2}' | cut -f1 -d '/'`
SERVICENAME="dapp-service"
SERVICEPORT="5000"

read -r -d '' MSG << EOM
{
  "Name":    "$SERVICENAME",
  "address": "$IP",
  "port":    $SERVICEPORT,
  "Check": {
     "http": "http://$IP:$SERVICEPORT",
     "interval": "5s"
  }
}
EOM
 
curl -v -XPUT -d "$MSG" http://consul:8500/v1/agent/service/register && /app/main "$@"
categories: traefik | traefik-v1 | consul | reverse-proxy | docker | devops | servicemesh |