Blog

Kubernetes-Services mit Traefik proxyen

MAR 30, 2017

Ein Blick in die neue Welt der Service Discovery

Henrik Hoegh

Henrik is a DevOps Consultant based in Aarhus. He specializes in Docker, Kubernetes and everything Atlassian. Away from the office Henrik designs loudspeakers and takes a keen interest in quantum physics and astrophotography.

So leitet ihr einen in Kubernetes laufenden Service über Traefik als Load Balancer und Proxy weiter.

Kubernetes-Services über einen Proxy weiterleiten

In unserem letzten Traefik-Blogbeitrag haben wir gezeigt, wie einfach sich auf einem Host laufende Docker-Container über einen Proxy weiterleiten lassen. Dieses Mal zeigen wir, wie einfach sich Container aus einem Kubernetes-Cluster über Traefik weiterleiten lassen.

Traefik ist ein Reverse Proxy für die neue Welt der Service Discovery und besonders hilfreich, wenn Services in Kubernetes laufen.

In diesem Blogbeitrag zeigen wir, wie wir einen in Kubernetes laufenden Service über Traefik als Load Balancer und Proxy weiterleiten können.

Wir stellen einen Service in Kubernetes bereit und greifen über Traefik mithilfe eines DNS-Namens darauf zu. Innerhalb von Kubernetes erstellen wir eine Ingress-Regel, um unser Routing zu definieren. Traefik erkennt diese Regel und konfiguriert sich automatisch.

Voraussetzungen

Ihr benötigt einen laufenden Kubernetes-Cluster und eine Maschine, auf der der Load Balancer läuft. Auf der Maschine, auf der Traefik läuft, müssen Routen eingerichtet sein, damit sie über ihre ClusterIPs auf Pods zugreifen kann. Das würde den Rahmen dieses Artikels sprengen, aber hier ein Hinweis:

K8S_NODES=$(kubectl get nodes | grep "Ready" | cut -d" " -f1 | tr '\n' '\t')for node in $K8S_NODES; do  NODE_IP=$(kubectl describe node $node \            | egrep -w "Addresses"      \            | tr '\n' '\t'              \            | cut -d"," -f1             \            | rev                       \            | cut -d$'\t' -f1           \            | rev)  kubectl describe node ${node}  \            | egrep -w "Name:|PodCIDR"  \            | tr '\n' '\t'              \            | awk -v IP=$NODE_IP '{ print "sudo route add -net " , $4 , " gw " , IP }'done

Wenn ihr weitere Worker-Nodes hinzufügt, müsst ihr auch für diese neue Routen hinzufügen.

Das obige Beispiel setzt voraus, dass ihr CNI-Netzwerk nutzt. Mit Overlay-Netzwerken funktioniert es nicht. In diesem Fall muss die Maschine, auf der der Load Balancer läuft, Teil desselben Overlay-Netzwerks sein.

Deployment, Service und Ingress in Kubernetes bereitstellen

Ein NGINX-Deployment in Kubernetes bereitstellen

Zuerst erstellen wir ein Deployment für NGINX, damit wir es später aktualisieren, skalieren und dauerhaft ausführen können.

Erstellt eine Datei mit dem Namen nginx-deployment.yaml und folgendem Inhalt

apiVersion: extensions/v1beta1kind: Deploymentmetadata:  name: nginx-deploymentspec:  replicas: 3  template:    metadata:      labels:        app: nginx    spec:      containers:      - name: nginx        image: nginx:1.7.9        ports:        - containerPort: 8

Die obige YAML-Datei erstellt ein Deployment, ein ReplicaSet und drei Pods mit NGINX 1.7.9, wenn wir Folgendes ausführen

> kubectl create -f nginx-deployment.yaml deployment "nginx-deployment" created

Prüfen wir das Deployment

> kubectl get deployments NAME              DESIRED  CURRENT  UP-TO-DATE  AVAILABLE  AGE nginx-deployment  3        3        3           0          4s

Nach einer Weile sollte sich „AVAILABLE=0“ in 3 ändern. Dann könnt ihr fortfahren.

Prüfen wir jetzt, ob die Pods laufen.

> kubectl get podsNAME                                READY     STATUS    RESTARTS   AGEnginx-deployment-4087004473-clz6x   1/1       Running   0          3mnginx-deployment-4087004473-jwz0k   1/1       Running   0          3mnginx-deployment-4087004473-zfkzn   1/1       Running   0          3m

Einen NGINX-Service in Kubernetes bereitstellen

Jetzt müssen wir einen Service erstellen – ein Kubernetes-Objekt, das für unser Deployment eine feste IP-Adresse und Cluster-DNS bereitstellt.

Erstellt eine Datei mit dem Namen nginx-service.yaml und folgendem Inhalt

apiVersion: v1kind: Servicemetadata:  labels:    name: nginxservice  name: nginxservicespec:  ports:    # The port that this service should serve on.    - port: 80  # Label keys and values that must match in order to receive traffic for this service.  selector:    app: nginx  type: ClusterIP

Dadurch wird in Kubernetes ein Service-Objekt erstellt, das eine ClusterIP und Endpoint-IP-Adressen für unsere Pods enthält. Wenn ein Pod beendet wird, startet ein neuer Pod und der Service-Endpoint wird aktualisiert.

Erstellt den Service mit

> kubectl create -f nginx-service.yaml service "nginxservice" created

Prüft den Service, indem ihr Folgendes ausführt

> kubectl get servicesNAME            CLUSTER-IP    EXTERNAL-IP   PORT(S)          AGEkubernetes      10.32.0.1     <none>        443/TCP          3dnginxservice    10.32.0.102   <none>        80/TCP           1m

Hier sehen wir, dass die ClusterIP unseres neuen Service 10.32.0.102 lautet.

Ingress in Kubernetes bereitstellen

Bisher haben wir Kubernetes so verwendet, wie wir es vor der Einführung des Ingress-Objekts getan hätten.

Nun definieren wir unsere Routing-Regel von außerhalb zu unserem NGINX-Service, indem wir eine Datei namens nginx-ingress.yaml mit folgendem YAML erstellen:

apiVersion: extensions/v1beta1kind: Ingressmetadata:  name: nginxingressspec:  rules:  - host: nginx.example.com    http:      paths:      - path: /        backend:          serviceName: nginxservice          servicePort: 80

Erstellt den Ingress mit folgendem Befehl:

> kubectl create -f nginx-ingress.yaml ingress "nginxingress" created

Traefik installieren

Unser Cluster ist nun bereit. Wir müssen nur noch Traefik installieren und einrichten sowie einen Eintrag in unserer Hosts-Datei hinzufügen.

Binary herunterladen

Geht zu GitHub, ladet die neueste stabile Version von Traefik für eure Architektur herunter und macht sie ausführbar. Derzeit ist das Version 1.1.2.

https://github.com/containous/traefik/releases/latest

wget https://github.com/containous/traefik/releases/download/v1.1.2/traefik_linux-amd64 mv traefik_linux-amd64 traefik chmod u+x traefik </code>

Konfigurationsdatei erstellen

Erstellt im selben Ordner wie traefik eine Datei namens traefik.toml mit folgendem Inhalt:

[web] address = ":8080" ReadOnly = true [kubernetes] # Kubernetes server endpoint endpoint = "http://controller.example.com:8080" namespaces = ["default","kube-system"]

Die obige Konfiguration weist Traefik an, Inhalte nur aus den beiden Namespaces „default“ und „kube-system“ bereitzustellen. Wenn Traefik Inhalte aus allen Namespaces bereitstellen soll, entfernt einfach diese Zeile.

Der Abschnitt [web] weist Traefik an, ein Dashboard auf Port 8080 bereitzustellen. Das ist praktisch, denn es zeigt alle Services an, die Traefik aktuell bereitstellt.

Der Abschnitt [kubernetes] beschreibt, wie sich Traefik mit eurem Kubernetes kube-apiserver verbinden soll. In diesem Beispiel lauscht der kube-apiserver auf Port 8080 unter controller.example.com. Wenn ihr SSL verwendet und auf Port 8443 lauscht, könnt ihr Zertifikat und Token in diesen beiden Dateien definieren:

/var/run/secrets/kubernetes.io/serviceaccount/ca.crt/var/run/secrets/kubernetes.io/serviceaccount/token

Auch wenn ihr kein Token oder Zertifikat verwendet, benötigt ihr diese beiden Dateien. Erstellt sie in diesem Fall einfach ohne Inhalt.

Traefik starten

Startet Traefik nun entweder manuell

./traefik -c traefik.toml

oder verwendet diese Vorlage, wenn Traefik als Service ausgeführt werden soll:

\
[Unit] Description=Traefik proxy server Documentation=https://github.com/containous/traefik [Service] ExecStart=/root/traefik/traefik \  -c /root/traefik/traefik.toml Restart=on-failure RestartSec=5 [Install] WantedBy=multi-user.target </code>

DNS zur Hosts-Datei hinzufügen

In unserem Ingress-Objekt haben wir definiert, dass unser NGINX-Service über den DNS-Namen nginx.example.com erreichbar sein soll. Da ich keinen DNS-Server habe, erstelle ich einfach einen Eintrag in meiner Hosts-Datei:

Ersetzt [load-balancer-ip] durch die IP-Adresse der Maschine, auf der Traefik ausgeführt wird.

su -c 'echo "[load-balancer-ip] nginx.example.com" &gt;&gt; /etc/hosts'

Unseren Service testen

Ruft zunächst das Traefik-Web-Dashboard unter http://[localbalancer-ip]:8080 auf und stellt sicher, dass der NGINX-Service aufgeführt ist. Dort solltet ihr das Dashboard sowie das NGINX-Frontend und -Backend sehen. Das Frontend beschreibt die Regel, das Backend unsere Pods.

Traefik Nginx

Öffnet nun einen Browser-Tab, ruft http://nginx.example.com auf und ihr solltet die NGINX-Startseite sehen, die über HTTP bereitgestellt wird.

nginx

Eure Anfragen werden auf die drei NGINX-Pods in unserem Kubernetes-Cluster verteilt. Versucht, einen davon zu beenden, und stellt fest, dass ihr weiterhin so oft ihr möchtet F5 drücken könnt. Traefik erkennt das und konfiguriert sich neu. Wenn ein neuer Pod startet und den beendeten ersetzt, wird auch er automatisch von Traefik bereitgestellt. Service Discovery in seiner ganzen Pracht.

SSL und http -> https-Weiterleitung hinzufügen

Das obige Beispiel ist in Ordnung, aber für den Produktivbetrieb nicht geeignet, da es nur http-Anfragen verarbeitet. Wir möchten SSL über https verwenden. Sehen wir uns also an, wie einfach das geht.

Bearbeitet unsere traefik.toml, um die http-Weiterleitung zu https und unsere Zertifikate wie folgt einzubinden:

defaultEntryPoints = ["http", "https"][entryPoints][entryPoints.http]  address = ":80"[entryPoints.http.redirect]  entryPoint = "https"[entryPoints.https]  address = ":443"[entryPoints.https.tls][[entryPoints.https.tls.certificates]]CertFile = "/certs/kubernetes.pem"KeyFile = "/certs/kubernetes-key.pem"[web]address = ":8080"ReadOnly = true[kubernetes]# Kubernetes server endpointendpoint = "http://controller.example.com:8080"namespaces = ["default","kube-system"]

Wir haben zwei Standard-Entry-Points (http und https) hinzugefügt. Im Abschnitt für die Entry-Points richten wir eine Weiterleitung von http zu https ein, von Port 80 zu 433.

Anschließend folgt ein Zertifikatsabschnitt, in dem wir unser Zertifikat und unsere Schlüsseldatei definieren. Das war's.

Startet Traefik jetzt neu, entweder mit Strg + C und anschließendem erneuten Ausführen oder indem ihr den Service stoppt und neu startet.

Wenn Traefik nicht als Service läuft

ctrl + c ./traefik -c traefik.toml

Wenn Traefik als Service läuft, dann

sudo service traefik stop sudo service traefik start

Ruft jetzt http://nginx.example.com in einem Browser auf. Ihr seht, dass ihr zu https weitergeleitet werdet.

Wenn ihr selbstsignierte Zertifikate verwendet, wird euer Browser euch warnen. Fügt einfach eine Ausnahme hinzu und fahrt fort.

Und voilà: nginx wird mit https aus einem Kubernetes-Cluster bereitgestellt – mit nur 20 Zeilen statischer Konfiguration und Service Discovery.

Nginx not safe
  • Cloud

Subscribe to our newsletter