Am 11.11. begann nicht nur der Karneval, auch die Kubernetes Community gab etwas Lustiges bekannt: Das Ende vom Nginx Ingress Controller. Freude dürfte auch bei denen aufgekommen sein, die erst unlängst von Bitnami auf die CNCF Version vom Nginx Ingress Controller gewechselt sind, nachdem der neue Eigentümer von Bitnami die ganzen Lurker nicht mehr wollte. Aber wie geht’s jetzt weiter?
Angepriesen als das nächste Pferd, was ins Rennen gehen soll, ist Gateway API. Das Ding ist auch schnell installiert und es gibt auch einen Migrations Guide: Migrating from Ingress. Da versucht man dem Nutzer das ganze noch etwas schmachkaft zu machen, erklärt die vielen neuen Objekte und der Kenner merkt sofort: Jede Menge Arbeit.
Denn mit einem
kubectl apply --server-side -f https://github.com/kubernetes-sigs/gateway-api/releases/download/v1.4.0/standard-install.yaml
ist es leider nicht getan. Denn das installiert nur die CRDs. Für das Projekt ist der Fall erledigt und er denkt sich, es wird schon genug Leute geben, die das benutzen wollen.
Die Nginx Gateway Fabric ist das neue Herzstück der Anlage und ersetzt den Nginx Ingress Controller. Den haben wir beispielsweise installiert mit
helm -n ingress-nginx upgrade -i ingress-nginx --set controller.hostPort.enabled=true --set controller.service.annotations."kube-vip\.io\/loadbalancerIPs"=${public_ip} . --create-namespace
Achso, das ganze läuft in unserem OTC Tofu Setup, ein Kubernetes Cluster mit Kubeadm, Kube-Vip, Cert-Manager auf Ubuntu VM auf der Open Telekom Cloud. Der Ingress Controller kann aus einem Software Shell script dort zusätzlich installiert werden.
Cert Manager ist allseits beliebt beim Ausstellen von Server Zertifikaten in Zusammenhang mit Let’s Encrypt. Bisher reichte eine Standard-Installation. Jetzt brauchen wir die Erweiterung, damit Cert Manager auf die neuen Objekte reagieren kann. Deswegen muss man den installieren oder upgraden mit:
helm -n cert-manager upgrade -i cert-manager jetstack/cert-manager --set crds.enabled=true --create-namespace --set config.apiVersion="controller.config.cert-manager.io/v1alpha1" --set config.kind="ControllerConfiguration" --set config.enableGatewayAPI=true
Die Nginx Gateway Fabric können wir wieder mit Helm installieren. Dazu müssen wir in den Service Pods Hostnetwork aktivieren und die Loadbalancer IP mitgeben. Die wird bei der OTC ausgewürfelt beim Ausführen des Tofu Deployments:
helm upgrade -i ngf oci://ghcr.io/nginx/charts/nginx-gateway-fabric --create-namespace -n nginx-gateway --set nginx.service.externalTrafficPolicy=Cluster --set gwAPIExperimentalFeatures=true --set gwAPIInferenceExtension=true --set nginx.container.hostPorts[0].port=80 --set nginx.container.hostPorts[0].containerPort=80 --set nginx.container.hostPorts[1].port=443 --set nginx.container.hostPorts[1].containerPort=443 --set nginx.service.loadBalancerIP=164.30.3.60
Der hostPort bezieht sich auf den Container des Service. Also es läuft im Cluster der Nginx Gateway Fabric Controller mit einem Pod und einem Service. Dann wird pro Gateway ein weiterer Pod und Service gestartet. Der Service ist vom Typ Loadbalancer im Namespace der Applikation.
Das deployen wir unten extra, das Helm Chart vom Nginx Gateway Fabric würde das aber auch mit hergeben für eine zentrale Instanz.
Und die loadBalancerIP können wir direkt angeben, bislang haben wir das mit einer Annotation im Loadbalancer Service gemacht:
annotations:
kube-vip.io/loadbalancerIPs: 164.30.3.60
Kommen wir nun zu dem, was früher mal ein Ingress war. Wenn man die Gateway Spec so ansieht, ist es dem Ingress gar nicht mal so unähnlich:
---
apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
name: kubeadm-gateway
namespace: drachenboot
annotations:
cert-manager.io/cluster-issuer: letsencrypt
#kube-vip.io/loadbalancerIPs: 164.30.3.60
spec:
gatewayClassName: nginx
listeners:
- name: https
hostname: drachenboot.otc.mcsps.de
port: 443
protocol: HTTPS
allowedRoutes:
namespaces:
from: All
tls:
mode: Terminate
certificateRefs:
- name: drachenboot-otc-mcsps-de-tls
- name: http
port: 80
protocol: HTTP
hostname: drachenboot.otc.mcsps.de
Wir haben das Gateway für unsere Webseite drachenboot.otc.mcsps.de. Die hat oben erstmal die cert-manager annotation, damit mit dem ClusterIssuer namens letsencrypt ein Zertifikat ausgestellt werden kann. Im Helm Chart vom Nginx Gateway Fabric wird ein Job mit installiert, der das dazugehörige Secret anlegt, was wir weiter unten bei den Listenern konfiguriert haben.
Die Listener selber sind relativ selbsterklärend. Sie matchen auf einen Hostnamen und dem Protokoll/Port, wobei die HTTPS Traffic auf dem Gateway terminiert wird. Das ganze gehört zur GatewayClass nginx, was vergleichbar zur IngressClass ist, womit man mehrere Controller parallel installieren kann. Standardmässig heisst das Ding nginx.
Jetzt routen wir Traffic:
---
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: drachenboot
namespace: drachenboot
spec:
parentRefs:
- name: kubeadm-gateway
sectionName: https
hostnames:
- drachenboot.otc.mcsps.de
rules:
- matches:
- path:
type: PathPrefix
value: /
backendRefs:
- name: drachenboot-webapp
namespace: drachenboot
port: 8080
---
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: tls-redirect
spec:
parentRefs:
- name: kubeadm-gateway
sectionName: http
hostnames:
- drachenboot.otc.mcsps.de
rules:
- filters:
- type: RequestRedirect
requestRedirect:
scheme: https
port: 443
Wir referenzieren auf unser Gateway und möchten alles unter / auf unseren Service drachenboot-webapp:8080 weiterleiten. Sollte es jemand mit http als Protokoll versuchen, was das Gateway auch konfiguriert hat, soll auf https umgeleotet werden. Dazu brauchen wir die zweite Route.
Fertig! So sieht das dann aus:
$ kubectl -n drachenboot get pod,gateway,httproutes,services
NAME READY STATUS RESTARTS AGE
pod/drachenboot-webapp-65d44f4ff7-pphk6 1/1 Running 1 26h
pod/kubeadm-gateway-nginx-58d49cf5bf-lkhzd 1/1 Running 1 4h29m
NAME CLASS ADDRESS PROGRAMMED AGE
gateway.gateway.networking.k8s.io/kubeadm-gateway nginx 164.30.3.60 True 4h29m
NAME HOSTNAMES AGE
httproute.gateway.networking.k8s.io/drachenboot ["drachenboot.otc.mcsps.de"] 4h29m
httproute.gateway.networking.k8s.io/tls-redirect ["drachenboot.otc.mcsps.de"] 4h29m
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/drachenboot-webapp ClusterIP 10.109.189.86 <none> 8080/TCP 26h
service/kubeadm-gateway-nginx LoadBalancer 10.111.174.94 164.30.3.60 80:31369/TCP,443:31439/TCP 4h29m
Den Ingress Controller und Kube-VIP können wir jetzt löschen:
rm /etc/kubernetes/manifests/kube-vip.yaml
helm -n ingress-nginx delete ingress-nginx
War jetzt doch nicht so viel Raketenwissenschaft und für unsere kleine Webseite kriegt man die Umstellung auch hin. Bloss auch da gibt es Handlungsbedarf, denn so wie wir es bisher installiert haben, geht es nicht mehr:
$ helm -n drachenboot upgrade -i drachenboot --set image.repository=ghcr.io/eumelnet/eumelnet/drachenboot --set image.tag=0.0.7 --set ingress.enabled=true --set ingress.className=nginx --set ingress.annotations."kubernetes\.io/ingress\.class"=nginx --set ingress.annotations."cert-manager\.io/cluster-issuer"=letsencrypt --set ingress.hosts[0].host=drachenboot.otc.mcsps.de --set ingress.hosts[0].paths[0].path=/ --set ingress.hosts[0].paths[0].pathType=ImplementationSpecific --set ingress.tls[0].hosts[0]=drachenboot.otc.mcsps.de --set ingress.tls[0].secretName=drachenboot-otc-mcsps-de-tls-secret oci://ghcr.io/eumelnet/webapp:0.1.1 --create-namespace
Jedes Helm Chart, was eine Ingress Konfiguration anbietet, muss angefasst werden. Die neue Funktion mit dem Gateway muss sich etablieren, wobei da verschiedene Betriebsmodelle vorgesehen sind. Die Kollegen vom Cert-Manager stellen sich in ihrer Architektur Beschreibung etwa vor, dass der Cluster-Administrator das Gateway installiert und der User/Developer die HttpRoutes, was wiederum bedeutet, dass ein Helmchart HttpRoutes enthalten kann, aber kein Gateway (obwohl es dessen Namen referenzieren muss).
Die Nginx Gateway Fabric ist nur eine von vielen Implementierungen, wenn man in die Liste schaut. Und jeder wird natürlich seine eigenen Vorzüge haben, da auch schon einige den GA Status erreicht haben. Bleibt abzuwarten, wie es da weitergeht. Anzumerken zum Schluss ist auch noch, dass Nginx mittlerweile zur Firma F5 gehört und die Nginx Gateway Fabric natürlich von F5-Leuten verwaltet wird. Es gibt auch Optionen, dass mit Nginx Plus zu betreiben, ein kommerzielles Produkt, welches aus der Fusion hervorgegangen ist.
Aber wer weiss, vielleicht lebt Ingress Nginx als Fork weiter und wir brauchen nichts umzustellen. Wäre ja auch mal etwas.
Bis dahin