Kubernetes Ingress mit traefik
Um auf Kubernetes-Dienste zuzugreifen gibt es mehrere Möglichkeiten, eine davon ist der Ingress. Ingress eignet sich für HTTP basierte Dienste und kann Funktionalitäten wie TLS-Terminierung und Load-Balancing übernehmen. Im Prinzip handelt es sich bei Ingress also um so etwas wie einen Reverse-Proxy.
Kubernetes bringt dabei keine Ingress-Implementierung mit, sondern es gibt diverse Optionen von nginx über HA-Proxy und Apache Trafficserver bis zu traefik. Wie traefik als Kubernetes-Ingress-Implementierung eingesetzt werden kann, wird in diesem Beitrag vorgestellt.
Bei traefik handelt es sich um ein OpenSource-Projekt in der Programmiersprache Go: https://traefik.io/. Die Installation kann auch außerhalb von Kubernetes mit und ohne Docker vorgenommen werden. Besonders ist jedoch, dass traefik Unterstützung für dynamische Umgebungen, wie Docker oder Kubernetes bietet. Damit kann traefik eine automatisch (Um-)Konfiguration vornehmen, wenn sich an der Umgebung etwas ändert, z.B. weil ein neuer Container gestartet wird.
traefik in kubernetes
Es gibt zwei grundsätzliche Varianten, traefik in Kubernetes zu betreiben:
-
Kubernetes DaemonSet
-
Kubernetes Deployment
Beide Varianten haben spezifische Vor- und Nachteile. Im Beispiel wird ein DaemonSet verwendet, damit wird traefik prinzipiell auf sämtlichen Nodes des Kubernetes-Cluster als Pod gestartet. Damit traefik auf die Kubernetes-API zugreifen kann und darüber eine dynamische Konfiguration vornehmen kann, wird eine entsprechende ClusterRole für traefik angelegt und ein ClusterRoleBinding erzeugt.
---
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
---
kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1beta1
metadata:
name: traefik-ingress-controller
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: traefik-ingress-controller
subjects:
- kind: ServiceAccount
name: traefik-ingress-controller
namespace: kube-system
In Kubernetes wird die Konfiguration dann mit kubectl
aktiviert.
$ kubectl apply -f traefik-clusterrole.yml
clusterrole.rbac.authorization.k8s.io/traefik-ingress-controller created
clusterrolebinding.rbac.authorization.k8s.io/traefik-ingress-controller created
Da die Resourcen im Demo-Cluster recht knapp sind, soll traefik lediglich auf Master-Nodes gestartet werden. Dazu werden ein NodeSelector und eine Taint-Toleration konfiguriert. Ersteres sorgt dafür, dass nur Master-Nodes ausgewählt werden, letzteres ermöglicht, dass auf dem Master die Pods auch erzeugt werden. Normalerweise werden Master-Nodes nämlich ignoriert, denn dort soll lediglich die Kubernetes Control-Plane ausgeführt werden.
Für traefik wird auch ein Kubernetes-Service angelegt. Mit diesen Service kann das traefik-Dashboard durch den traefik-Ingress selbst ebenfalls bereitgestellt werden.
---
apiVersion: v1
kind: ServiceAccount
metadata:
name: traefik-ingress-controller
namespace: kube-system
---
kind: DaemonSet
apiVersion: extensions/v1beta1
metadata:
name: traefik-ingress-controller
namespace: kube-system
labels:
k8s-app: traefik-ingress-lb
spec:
template:
metadata:
labels:
k8s-app: traefik-ingress-lb
name: traefik-ingress-lb
spec:
serviceAccountName: traefik-ingress-controller
terminationGracePeriodSeconds: 60
nodeSelector:
node-role.kubernetes.io/master: ""
tolerations:
- key: node-role.kubernetes.io/master
effect: NoSchedule
containers:
- image: traefik
name: traefik-ingress-lb
ports:
- name: http
containerPort: 80
hostPort: 80
- name: admin
containerPort: 8080
hostPort: 8080
securityContext:
capabilities:
drop:
- ALL
add:
- NET_BIND_SERVICE
args:
- --api
- --kubernetes
- --logLevel=INFO
- --insecureSkipVerify
---
kind: Service
apiVersion: v1
metadata:
name: traefik-ingress-service
namespace: kube-system
spec:
selector:
k8s-app: traefik-ingress-lb
ports:
- protocol: TCP
port: 80
name: web
- protocol: TCP
port: 8080
name: admin
Auch diese Konfiguration wird durch kubectl
angewendet:
$ kubectl apply -f traefik-daemonset.yml
serviceaccount/traefik-ingress-controller unchanged
daemonset.extensions/traefik-ingress-controller created
service/traefik-ingress-service created
In der Konfiguration ist zu sehen, dass traefik mit den Optionen "--api" und "--kubernetes" gestartet wird. Ersteres aktiviert das Dashboard und die API von traefik, über die der aktuelle Zustand abgerufen werden kann. Letzteres sorgt für die Integration in Kubernetes, damit traefik sich automatisch für die Umgebung konfiguriert.
Kubernetes wird nun traefik auf den entsprechenden Nodes bereitstellen. Sobald das geschehen ist, sind auf Port 80 der traefik Reverse-Proxy bzw. Ingress-Dienst und auf Port 8080 das traefik-Dashboard verfügbar. Im Browser kann das Dashboard auch bereits aufgerufen werden, wenn die IP eines Kubernetes-Master verwendet wird: http://10.1.1.1:8080/dashboard/
Ein Zugriff auf Resourcen im Cluster, wie z.B. das Kubernetes-Dashboard, ist jedoch noch nicht möglich, da die notwendige Konfiguration in traefik noch nicht angelegt wurde.
Kubernetes-Dashboard mit traefik
Damit traefik Anwendungen aus dem Cluster bereitstellt, müssen Ingress-Konfigurationsobjekte erzeugt werden. Mit diesen wird traefik signalisiert, dass ein entsprechendes Routing angelegt werden soll. Wichtig ist dazu noch, dass viele Anwendungen selbst innerhalb eines Clusters als TLS-gesichertes HTTPS aufgerufen werden. Um unvollständige Zertifikatketten zu erlauben, wird traefik mit "--insecureSkipVerify" gestartet, wie im Manifest im obigen Beispiel gezeigt.
Für das Kubernetes-Dashboard sieht ein Ingress-Objekt wie folgt aus:
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: kubernetes-dashboard #(1)
namespace: kube-system
annotations:
kubernetes.io/ingress.class: traefik
spec:
rules: #(2)
- host: k8s.c2
http:
paths:
- backend:
serviceName: kubernetes-dashboard #(3)
servicePort: 443
Mit:
-
Name des Ingress
-
Regel für traefik, woran erkannt wird, dass Anfragen an diesen Ingress gerichtet sind
-
Zielname und Port
Nachdem der Ingress angelegt wurde, kann im traefik-Dashboard beobachtet werden, dass ein entsprechendes Frontend und Backend konfiguriert wurden. Für den Zugriff auf das Kubernetes-Dashboard wurde als traefik-Rule "Host: k8s.demo" angegeben. Der Zugriff kann nun - einen entsprechenden DNS-Eintrag vorausgesetzt - durch http://k8s.c2 erfolgen.
Im folgenden Screenshot sind beide Ingress, für traefik und für das Kubernetes-Dashboard zu sehen. Für beide sind jeweils ein Frontend und zugehörige Backends in traefik konfiguriert.
Die Backends verweisen auf die Kubernetes-ClusterIP, die durch die zugehörige Service-Definition in Kubernetes bereitgestellt wird.
Zu den Themen Kubernetes, Docker und Cloud Architektur bieten wir sowohl Beratung, Entwicklungsunterstützung als auch passende Schulungen an:
Auch für Ihren individuellen Bedarf können wir Workshops und Schulungen anbieten. Sprechen Sie uns gerne an.