Neuigkeiten von trion.
Immer gut informiert.

Kubernetes Ingress mit traefik

Kubernetes

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.

ClusterRole für traefik Zugriff auf die Kubernetes API
---
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.

Aktivierung der traefik ClusterRole
$ 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.

traefik als DaemonSet mit Auswahl der Master-Nodes
---
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:

Aktivierung des traefikDaemonSet
$ 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:

Ingress für Kubernetes-Dashboard
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:

  1. Name des Ingress

  2. Regel für traefik, woran erkannt wird, dass Anfragen an diesen Ingress gerichtet sind

  3. 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.

traefik Dashboard mit kubernetes Rule
Abbildung 1. traefik-Dashboard mit den Routen auf das traefik- und das Kubernetes-Dashboard

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.

Feedback oder Fragen zu einem Artikel - per Twitter @triondevelop oder E-Mail freuen wir uns auf eine Kontaktaufnahme!

Los geht's!

Bitte teilen Sie uns mit, wie wir Sie am besten erreichen können.