Blog

The Journey to Traefik Enterprise Edition: HTTPS for Everyone

Welcome to the fourth step of our journey towards Traefik Enterprise Edition.

Before jumping in, you should check the previous posts:

Today, we’ll focus on how to use TraefikEE with Let’s Encrypt to get HTTPS by default, for your application.

Create a Kubernetes Cluster with kops

Following the same steps as the previous blog post (“Create a cluster with kops”), start a kops cluster with one Kubernetes manager and three Kubernetes nodes:

$ export NAME=traefikee-demo.containous.cloud
$ export KOPS_STATE_STORE=s3://<YOUR BUCKET>
$ export ROUTE53_ZONE_ID=<ROUTE53_ZONE_ID>
$ export NB_MASTER_NODE=1
$ export NB_WORKER_NODE=3

$ kops create cluster \
    --zones us-east-1a \
    --dns-zone="${ROUTE53_ZONE_ID}" \
    --node-size="t2.large" \
    --master-count="${NB_MASTER_NODE}" \
    --node-count="${NB_WORKER_NODE}" \
    --yes \
    "${NAME}"

After a few minutes, your cluster is started with four Kubernetes nodes:

$ kubectl get nodes
NAME                            STATUS   ROLES    AGE   VERSION
ip-172-20-34-251.ec2.internal   Ready    node     2m    v1.11.6
ip-172-20-49-209.ec2.internal   Ready    node     2m    v1.11.6
ip-172-20-53-165.ec2.internal   Ready    node     2m    v1.11.6
ip-172-20-56-217.ec2.internal   Ready    master   3m    v1.11.6

Pick a Public Domain Name

In the previous blog post, we used a domain name generated by Amazon Web Services as the main entry point to reach our platform.

You cannot use this “generated” public hostname, because Let’s Encrypt has a “forbidden domains list.” Some domains are considered too risky, and any request for issuing certificates under these domains is automatically refused. It’s the case with domains in *.amazonaws.com.

To solve this challenge, let’s pick a custom public domain name. Any domain or sub-domain (like test.company.org ) can be used. You have to be able to create DNS records of type CNAME on this domain.

(A voice in the background): I don’t want to pay for a domain used for evaluating a product. Maybe later if it goes further, but not now.
Containous: You can get free DNS using Dot-T-K, or even cheap ones using NameCheap.

For the next steps, we’ll pick the domain demo.containo.us .

Install TraefikEE

Then, install a simple TraefikEE cluster, without dashboard, as we did on the previous blog post:

$ traefikeectl install \
  --licensekey="$(cat /keybase/…/traefikee-license)" \
  --kubernetes
...

✔ Installation successful

Once the installation succeeded, verify that the TraefikEE cluster is composed of six nodes, three control nodes and three data nodes, as expected:

$ traefikeectl list-nodes
...
Name                                 Role
----                                 ----
traefikee-control-node-0             CONTROL NODE
data-node-traefikee-data-node-9ndbp  DATA NODE
data-node-traefikee-data-node-vqgzr  DATA NODE
traefikee-control-node-1             CONTROL NODE
traefikee-control-node-2             CONTROL NODE (Current Leader)
data-node-traefikee-data-node-5w66x  DATA NODE

Configure the Domain DNS Records

The next step is to create a CNAME DNS record, on the public domain name, pointing to the Load Balancer’s hostname, created during TraefikEE’s installation.

Get the load balancer’s public hostname with the following command (field EXTERNAL-IP):

$ kubectl get svc -n traefikee traefikee-lb
NAME          TYPE         EXTERNAL-IP
traefikee-lb  LoadBalancer a16ff-456.us-east-1.elb.amazonaws.com

Then, create the DNS CNAME record to this hostname (choose a short TTL):

IN  CNAME  demo.containo.us a16ff-456.us-east-1.elb.amazonaws.com

The DNS propagation takes some time, due to the “TTL”. Verify that your computer can resolve the DNS name with tools asdig , drillor nslookup :

$ dig CNAME demo.containo.us
...
;; QUESTION SECTION:
;demo.containo.us.       IN      CNAME

;; ANSWER SECTION:
demo.containo.us. 60     IN      CNAME   a16ff-456.us-east-1.elb.amazonaws.com.

;; Query time: 38 msec
;; SERVER: 212.224.255.252#53(212.224.255.252)
;; WHEN: Wed Feb 06 11:21:25 CET 2019
;; MSG SIZE  rcvd: 136

Configure TraefikEE for HTTPS

Then, we configure TraefikEE to enable HTTPS and Let’s Encrypt for certificate on HTTPS. The configuration is the same as Traefik’s (check Traefik's documentation for more details):

### Configure 2 entrypoints for https and https
  --entryPoints='Name:http Address::80 Redirect.EntryPoint:https' \
  --entryPoints='Name:https Address::443 TLS' \
  --defaultentrypoints=https,http \
  
### Enable ACME protocol for the HTTPS entry point
  --acme.entryPoint=https \
  
### Set up ACME protocol for Let's Encrypt TLS-APLN-01 Challenge
  [email protected] \
  --acme.tlsChallenge \
  
### Tell Traefik to get certificate's hostname from backend's rules
  --acme.onHostRule=true
(A voice in the background): When using Traefik with Let’s Encrypt, I often get certificates requests failures because of the rate limit on Let’s Encrypt side.
Containous: Traefik allows to test your HTTPS configuration with the “staging” environment, without rate limiting, but with untrusted certificates . It’s useful to validate configuration before switching to “production” certificates. Add the flag --acme.caServer='https://acme-staging-v02.api.letsencrypt.org/directory' to the configuration.
Be careful! You cannot change the caServer unless you reinstall TraefikEE.

The main difference from using Traefik here, is that TraefikEE is a distributed system, so you need to specify the configuration after TraefikEE’s installation.

The traefikeectl tool provides a command named deploy to send any routing configuration to the TraefikEE cluster. You can read more on this topic on the reference documentation for routing configurations.

Now, let’s deploy the following configuration to the TraefikEE cluster and that’s all!

traefikeectl deploy --kubernetes \
  --entryPoints='Name:http Address::80 Redirect.EntryPoint:https' \
  --entryPoints='Name:https Address::443 TLS' \
  --defaultentrypoints=https,http \
  --acme.entryPoint=https \
  [email protected] \
  --acme.tlsChallenge \
  --acme.onHostRule=true
(A voice in the background): Why is there a —-kubernetes flag in this configuration?
Containous: This flag tells TraefikEE to watch for any Kubernetes Ingress. It’s the same directive as the one in Traefik.

Deploy an Application

As we previously did on the post, “A Tour of TraefikEE”, we deploy a test application based on https://github.com/containous/whoami.

You can reuse the same YAML file, but you have to change the directive host in the ingress, and map it to your public domain name. I’m using the following one-line shell command for this:

$ curl --location --silent --show-error https://bit.ly/2WE5XFk \
  | sed 's/localhost/demo.damienduportal.org/g' \
  | kubectl apply -f -

deployment.extensions/whoami created
ingress.extensions/whoami created
service/whoami created

You can check that Kubernetes is using the right domain name by checking the ingress “whoami”:

$ kubectl get ingress whoami --namespace=traefikee
NAME     HOSTS                     ADDRESS   PORTS   AGE
whoami   demo.damienduportal.org             80      9m

The page https://demo.damienduportal.org/whoami is now, (after a few seconds, required for issuing certificates), securely served over HTTPS, with a valid certificate, issued by Let’s Encrypt:

Green Lock for Everyone
If you try to access http://demo.damienduportal.org/whoami, then you are redirected to https://demo.damienduportal.org/whoami as expected.

That’s all for today, you are ready to use HTTPS on your applications!
You can now clean your kops cluster with:

kops delete cluster --name="${NAME}"

On the next post, “The Journey to Traefik Enterprise Edition: Smooth Operations,” we’ll focus on how to configure and operate TraefikEE remotely with the traefikeectl command line.