Traefik as Ingress Controller for K8S
- Transfer
It's no secret that K8S has a great community and generally good documentation. In it you can easily find the answer to many questions. But like any other documentation, it cannot cover absolutely everything. In this article I will try to provide detailed instructions on how to deploy and configure Traefik for use as an Ingress controller.
What is Ingress?
Ingress is an API object that controls external access to services in a cluster, mainly via HTTP / HTTPS. In order for the Ingress resource to work, you need an Ingress controller. If you are using GCE, then the Ingress controller is already deployed to the wizard. However, if you have loaded the cluster yourself, for example from kops
AWS, you need to deploy the Ingress controller yourself. On minikube, this is solved by including the Ingress add-in.
Ingress controllers
The role of the Ingress Controller can be performed by NGINX Ingress Controller, Kong, Octavia Ingress Controller, etc. In this article we will look at a tool like Traefik and see how you can use it as an Ingress Controller for services in a cluster.
What for?
Why use the Ingress controller if you can provide access to each service through NodePort
or LoadBalancer
? In short, it allows you to get one central point for proxying all traffic. That is, using the Ingress controller, you only need one LoadBalancer for Traefik and nothing else. This bunch will settle all traffic.
Traefik components
Traefik announced support for Kubernetes Ingress in version 1.4. However, the recently released Traefik 1.7 has an option publishedService,
that can update the field status
in Ingress, which was not the case in previous versions. Below is a list of components that will be required for work.
Create:
- namespace
- service account
- TLS secret
- cluster role
- cluster role binding
- configmap
- deployment
- service for http and https
- service for Traefik dashboard
- Ingress
Namespace
Create a namespace:
kubectl create namespacetraefik
Tls secret
(note. Trans. - in the example below, the author for some reason duplicates the same config, the actual config is found in the README file provided by the link below)
First create a certificate:
openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout ./tls.key -out ./tls.crt -subj "/CN=*.example.com"
Create a TLS certificate:
openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout ./tls.key -out ./tls.crt -subj "/CN=*.example.com"
Create Secret:
kubectl create secret tls traefik-ui-tls-cert --key ./tls.key --cert ./tls.crt
For convenience, I made a README file with these commands and uploaded it to my GitHub .
ConfigMap
---
apiVersion: v1
kind: ConfigMap
metadata:
name: traefik-configmap
namespace: traefik
data:
traefik.toml: |
defaultEntryPoints = ["http","https"]
[entryPoints]
[entryPoints.http]
address = ":80"
[entryPoints.https]
address = ":443"
[entryPoints.https.tls]
[[entryPoints.https.tls.certificates]]
CertFile = "/ssl/tls.crt"
KeyFile = "/ssl/tls.key"
[entryPoints.traefik]
address = ":8080"
[entryPoints.traefik.auth.basic]
users = ["admin:$apr1$zjjGWKW4$W2JIcu4m26WzOzzESDF0W/"]
[kubernetes]
[kubernetes.ingressEndpoint]
publishedService = "traefik/traefik"
[ping]
entryPoint = "http"
[api]
entryPoint = "traefik"
By default, the EntryPoints are ports 80
and 443
.
EntryPoint is http
listening :80
and has no additional rules.
EntryPoint https
listens :443
and contains a rule for connecting TLS certificates.
EntryPoint traefik
listens :8080
and uses basic-authentication. Username - admin
, password - admin
.
Determining the corresponding endpoint Ingress in Kubernetes is done by setting publishService
and must consist of a value namespace
and a name service
for Traefik. In this case it is traefik / traefik
.
ping
or a health check will use entryPoint http
.
api
or dashboard / ui will use entryPoint traefik
.
Please note that you can define additional entryPoints with indication of the port. This port can proxy traffic to any port, instead of dynamic ports and NodePort
.
Clusterraole
Service account for Traefik must have permission to update the field Ingress status
. This is an important parameter, and it is not yet presented in the official documentation of Traefik :
---
kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1beta1
metadata:
name: traefik-ingress-controller
rules:
- apiGroups:
- ""
resources:
- services
- endpoints
- secrets
verbs:
- get
- list
- watch
- apiGroups:
- extensions
resources:
- ingresses
verbs:
- get
- list
- watch
- apiGroups:
- extensions
resources:
- ingresses/status
verbs:
- update
The last 6 lines are very important for correct operation.
Deployment
Deployment is pretty simple and straightforward. Let's take a quick look at the main blocks:
volumes:
- name: traefik-ui-tls-cert
secret:
secretName: traefik-ui-tls-cert
- name: traefik-configmap
configMap:
name: traefik-configmap
Define volumes
for ConfigMap and Secret, which can then be used in volumeMounts
.
volumeMounts:
- mountPath: "/ssl"
name: "traefik-ui-tls-cert"
- mountPath: "/config"
name: "traefik-configmap"
A health check is performed on port 80, as defined in the ConfigMap.
Open the ports for all entryPoints specified in the configuration file:
ports:
- name: http
containerPort: 80
- name: https
containerPort: 443
- name: dashboard
containerPort: 8080
I remind you that some examples and documentation on the Internet are outdated, so do not miss the section args
necessary for the work of Traefik:
args:
- --logLevel=INFO
- --configfile=/config/traefik.toml
Do not pass additional flags and arguments, such as -api, -ping or -kubernetes, because this will override the settings specified in the config file.
Service
The first of these services defines Loadbalancer for entryPoints http
and https
. If you look at the Security Group (Ingress) for LoadBalancer, you will see ports 80 and 443 are open there. K8s will create LoadBalancer and connect to the nodes that Traefik is running on. If you want to create an internal ELB, like me, you need to define annotations:
---
kind: Service
apiVersion: v1
metadata:
name: traefik
namespace: traefik
annotations: {}
# service.beta.kubernetes.io/aws-load-balancer-internal: 0.0.0.0/0
spec:
selector:
k8s-app: traefik-ingress
ports:
- protocol: TCP
port: 80
name: http
- protocol: TCP
port: 443
name: https
type: LoadBalancer
Service (for Dashboard)
Now the fun part! Since Dashboard uses basic authentication, I needed it https
. To use SSL, we need to redirect traffic to the port :8080
on which the Dashboard is running. As you can see, it is very simple. All the magic happens in Ingress.
---
kind: Service
apiVersion: v1
metadata:
name: traefik-dashboard
namespace: traefik
spec:
selector:
k8s-app: traefik-ingress
ports:
- port: 8080
name: dashboard
Ingress (for Dashboard)
The magic lies in the fact that proxying protected traffic to Dashboard is done through Traefik itself. Traefik in Ingress is managed using Traefik annotations :
---
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: traefik-dashboard-ingress
namespace: traefik
annotations:
kubernetes.io/ingress.class: traefik
traefik.ingress.kubernetes.io/frontend-entry-points: http,https
traefik.ingress.kubernetes.io/redirect-entry-point: https
traefik.ingress.kubernetes.io/redirect-permanent: "true"
spec:
rules:
- host: traefik-ui.example.com
http:
paths:
- path: /
backend:
serviceName: traefik-dashboard
servicePort: 8080
It took only 4 simple and understandable annotations.
Of course, to ensure full functionality, you need to create a DNS record traefik-ui.example.com
that will point to your ELB.
Would it be great if this (automatic translation is meant to create DNS records)? Not a problem, I will write about the automatic creation of DNS-records in the next article.
Links
Ready deployment.yaml file can be downloaded in my Github repository . If during the setup process you have any difficulties, do not hesitate to ask.
Translation from the translator
Read other articles on our blog:
Stateful backups in Kubernetes
Backup a large number of heterogeneous web-projects
Telegram-bot for Redmine. How to simplify the life of yourself and people