Mit den ersten Schritten mit Kubernetes weißt Du bereits, wie Du Anwendungen in Deinem Kubernetes Cluster startest. Nun exponieren wir Deine Anwendung online. Wie das Ganze funktioniert und wie Du mit einem Kubernetes Nginx Ingress Controller am besten selbst direkt loslegen kannst, erläutere ich Dir im Folgenden an einem Beispiel. Um in einem Kubernetes Cluster Anwendungen von außen erreichbar zu machen, kann man einen Service vom Typ Loadbalancer verwenden. In der NETWAYS Cloud starten wir hier im Hintergrund ein Openstack Octavia LB mit öffentlicher IP und leiten den eingehenden Traffic an die Pods weiter (Bingo). Somit benötigen wir für jede Anwendung einen eigenen Loadbalancer mit öffentlicher IP. Um in einem Fall wie diesem etwas ressourcen- und somit kosteneffizienter arbeiten zu können, hat man vor Langem named-based virtual hosts und server name indication (sni) erfunden. Der altbekannte NGINX-Webserver unterstützt beides und als Kubernetes Ingress Controller kann dieser, mit nur einer öffentlichen IP-Adresse, all unsere http/s-Anwendungen schnell und einfach erreichbar machen. Die Installation und die Aktualisierung des Ningx Ingress Controllers ist dank eines Helm Charts sehr vereinfacht. Mit K8s Ingress Objekten konfiguriert man die Zuordnung von vHosts, URI-Pfaden und TLS-Zertifikaten zu K8s Services und somit zu unseren Anwendungen. Damit die Buzzwords Dir nicht den Blick aufs Wesentliche verhindern, hier ein kleiner Überblick, wie die HTTP-Anfragen an unsere Anwendungen weitergeleitet werden:
Installation Kubernetes Nginx Ingress Controller
Zur einfachen Installation des Kubernetes Nginx Ingress Controllers solltest Du Helm verwenden. Helm bezeichnet sich selbst als Paketmanager für Kubernetes-Anwendungen. Neben der Installation bietet Helm auch einfache Updates seiner Anwendungen. Wie auch bei kubectl brauchst Du nur die K8s-Config, um direkt loszulegen:
$ helm repo add ingress-nginx https://kubernetes.github.io/ingress-nginx $ helm repo update $ helm install my-ingress ingress-nginx/ingress-nginx
Mit diesen Befehlen startet Helm alle nötigen Komponenten im default Namespace und gibt diesen das Label my-ingress. Für den Nginx Ingress Controller wird ein deployment, ein replicaset und ein pod erstellt. Alle http/s-Anfragen müssen an diesen pod weitergeleitet werden, damit dieser anhand von vHosts und URI-Pfaden die Anfragen sortieren kann. Dafür wurde ein service vom Typ loadbalancer erstellt, welcher auf eine öffentliche IP lauscht und den ankommenden Traffic auf den Ports 443 und 80 an unseren pod weiterleitet. Ein ähnliches Konstrukt wird auch für das default-backend angelegt, auf welche ich hier aber nicht näher eingehe. Damit Du den Überblick nicht verlierst, kannst Du Dir alle beteiligten Komponenten mit kubectl anzeigen lassen:
$ kubectl get all -l app.kubernetes.io/instance=my-ingress
NAME READY STATUS RESTARTS AGE pod/my-ingress-ingress-nginx-controller-7df9f7d78d-qfn2z 1/1 Running 0 11m NAME READY UP-TO-DATE AVAILABLE AGE deployment.apps/my-ingress-ingress-nginx-controller 1/1 1 1 11m NAME DESIRED CURRENT READY AGE replicaset.apps/my-ingress-ingress-nginx-controller-7df9f7d78d 1 1 1 11m NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE service/my-ingress-ingress-nginx-controller LoadBalancer 10.254.129.117 185.233.188.56 80:30782/TCP,443:31750/TCP 11m service/my-ingress-ingress-nginx-controller-admission ClusterIP 10.254.189.222 <none> 443/TCP 11m
Beispielanwendungen: Apache und Nginx
Als nächstes starten wir zwei einfache Beispielanwendungen. Im Beispiel verwende ich Apache und Nginx. Ziel ist es, beide Anwendungen unter eigenen name-based virtual hosts verfügbar zu machen: nginx.nws.netways.de und apache.nws.netways.de. Damit die beiden Deployments innerhalb des K8s Clusters erreichbar sind, müssen wir diese noch jeweils mit einem Service verbinden.
K8s Deployments
Nginx DeploymentApache Deployment--- apiVersion: apps/v1 kind: Deployment metadata: name: nginx-deployment labels: app: nginx spec: replicas: 3 selector: matchLabels: app: nginx template: metadata: labels: app: nginx spec: containers: - name: nginx image: nginx:1.7.9 ports: - containerPort: 80--- apiVersion: apps/v1 kind: Deployment metadata: name: apache-deployment labels: app: apache spec: replicas: 3 selector: matchLabels: app: apache template: metadata: labels: app: apache spec: containers: - name: apache image: httpd:2.4 ports: - containerPort: 80K8s Service
Nginx Service--- apiVersion: v1 kind: Service metadata: name: nginx-svc spec: ports: - port: 80 targetPort: 80 protocol: TCP name: http selector: app: nginxApache Service--- apiVersion: v1 kind: Service metadata: name: apache-svc spec: ports: - port: 80 targetPort: 80 protocol: TCP name: http selector: app: apacheVirtual Hosts ohne TLS
Um nun die Anfragen vom Nginx Controller zu unseren Anwendungen weiterzureichen, müssen wir ein passendes Kubernetes Ingress Objekt ausrollen. Im spec Bereich des Ingress Objekts können wir unterschiedliche Pfade und virtuell Hosts definieren. Im Beispiel sehen wir vHosts für nginx.nws.netways.de und apache.nws.netways.de. Für jeden der beiden vHosts ist im Bereich backend natürlich der entsprechende service eingetragen. Die öffentliche IP findet man im service des Nginx Ingress Controllers und kubectl describe zeigt alle wichtigen Details zum Service (siehe unten). Zum Testen manipulierst Du am besten seine /etc/hosts Datei und trägst dort die IP von LoadBalancer Ingress ein.K8s Ingress--- apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: my-ingress spec: ingressClassName: nginx rules: - host: apache.nws.netways.de http: paths: - path: / pathType: Prefix backend: service: name: apache-svc port: number: 80 - host: nginx.nws.netways.de http: paths: - path: / pathType: Prefix backend: service: name: nginx-svc port: number: 80$ kubectl describe service/my-ingress-ingress-nginx-controller
$ kubectl get service/my-ingress-ingress-nginx-controller -o jsonpath=
'
{.status.loadBalancer.ingress[].ip}'
Virtual Hosts mit TLS
Natürlich bietet man selten Anwendungen ohne Verschlüsselung öffentlich erreichbar an. Speziell für TLS-Zertifikate hat Kubernetes einen eigenen Typ tls innerhalb des secret Objekts. Alles was man benötigt ist ein TLS-Zertifikat und den dazugehörigen Schlüssel. Mit kubectl kannst Du das Pärchen in Kubernetes speichern:$ kubectl create secret tls my-secret
--
key cert.key--
cert cert.crtDas angelegte secret kann dann durch den angegebenen Namen my-secret in spec des Ingress Objekts referenziert werden. Dazu gibst Du im Array hosts innerhalb von tls unser virtual host und das dazugehörige TLS-Zertifikat an. Ein automatischer Redirect von http auf https ist von Anfang an aktiviert.
--- apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: my-ingress spec: ingressClassName: nginx rules: - host: apache.nws.netways.de http: paths: - path: / pathType: Prefix backend: service: name: apache-svc port: number: 80 - host: nginx.nws.netways.de http: paths: - path: / pathType: Prefix backend: service: name: nginx-svc port: number: 80 tls: - hosts: - apache.nws.netways.de - nginx.nws.netways.de secretName: my-secretFazit
Mit dem Nginx Ingress Controller ist es eine Leichtigkeit, Deine webbasierten Anwendungen öffentlich erreichbar zu machen. Die angebotenen Features und Konfigurationsmöglichkeiten sollten die Anforderungen aller Anwendungen abdecken und sind im offiziellen User Guide zu finden. Neben der eigenen Anwendung benötigst Du nur ein Helm Chart und ein K8s Ingress-Objekt. Kubernetes schafft es auch hier, mit nur wenigen abstrakten Objekten wie deployment und ingress viele komplexe Ebenen und Technologien zu verstecken. Mit einer NETWAYS Managed Kubernetes Lösung kannst Du die Vorteile dieser Abstraktion voll ausnutzen und Dich auf die eigene Anwendung konzentrieren. Na also: Leg los!