Ein kurzer Blick auf die Kubernetes Gateway API
September 7, 2022
In einem meiner letzten Blogbeiträge habe ich mehrere Möglichkeiten beschrieben, auf Kubernetes-Pods zuzugreifen. Man kann über die IP eines Pods darauf zugreifen, aber Pods sind von Natur aus flüchtig. Die übliche Methode ist die Konfiguration eines Service
: Seine IP ist stabil, und es ist die Aufgabe von Kubernetes, die Zuordnung zwischen einem Service
und den darunterliegenden Pods auf dem neuesten Stand zu halten. Es stehen verschiedene Arten von Services zur Verfügung: nur intern, NodePort
, um schließlich den Zugriff von außerhalb des Clusters zu ermöglichen, und LoadBalancer
, der sich auf eine Drittanbieterkomponente stützt – in der Regel eine eines Cloud-Anbieters. Schließlich habe ich das Ingress
-Objekt erwähnt, das ebenfalls Routing ermöglicht.
Ich habe absichtlich den neuen Mitstreiter, die Gateway API, ausgelassen. Sie ist das Thema dieses Beitrags.
Von Ingress zur Gateway API
Der externe Zugriff auf Kubernetes-Pods durchlief mehrere evolutionäre Schritte, z.B. ist Ingress
die Antwort auf das Problem des fehlenden Routings in LoadBalancer
. Das größte Problem von Ingress
ist seine Abhängigkeit von "proprietären" Objekten. Zur Erinnerung, hier ist der Ausschnitt zur Erstellung von Routing mit Apache APISIX:
apiVersion: apisix.apache.org/v2beta3 #1
kind: ApisixRoute #1
metadata:
name: apisix-route
spec:
http:
- name: left
match:
paths:
- "/left"
backends:
- serviceName: left
servicePort: 80
- name: right
match:
paths:
- "/right"
backends:
- serviceName: right
servicePort: 80
- Proprietäre Objekte
Proprietäre Objekte sind ein Problem bei der Migration. Während die Migration von einem Anbieter zu einem anderen wahrscheinlich ungewöhnlich ist, sollte sie so nahtlos wie möglich sein. Bei der Verwendung proprietärer Objekte müssen Sie zunächst die alten Objekte den neuen zuordnen. Es ist wahrscheinlich, dass dies keine Eins-zu-eins-Zuordnung ist. Dann müssen Sie die Spezifikation in das neue Modell übersetzen: Es wird wahrscheinlich ein umfangreiches Projekt sein.
Die Idee hinter der Gateway API ist es, eine klare Trennung zwischen Standardobjekten und der proprietären Implementierung zu haben.
Die Gateway API
Die Gateway API ist ein Open-Source-Projekt, das von der SIG-NETWORK-Community verwaltet wird. Es ist eine Sammlung von Ressourcen, die das Service-Networking in Kubernetes modellieren. Diese Ressourcen –
GatewayClass
,Gateway
,HTTPRoute
,TCPRoute
,Service
usw. – zielen darauf ab, das Kubernetes-Service-Networking durch ausdrucksstarke, erweiterbare und rollenorientierte Schnittstellen zu entwickeln, die von vielen Anbietern implementiert werden und breite industrielle Unterstützung haben.
Die obige Definition erwähnt auch ein organisatorisches Anliegen: Unterschiedliche Rollen sollten unterschiedliche Objekte verwalten.
Bild von gateway-api.sigs.k8s.io
Tatsächlich sind die Anliegen eines Cluster-Operators und eines Entwicklers ziemlich unterschiedlich. Es ist ziemlich ähnlich wie bei den alten Java-EE-Anwendungsservern, die eine Spezifikation boten, die um Rollen organisiert war: Entwickler, Bereitsteller und Operatoren. Meiner Meinung nach ist der größte Unterschied, dass die Spezifikation hauptsächlich auf die Entwicklererfahrung ausgerichtet war; der Rest lag in der Verantwortung der Implementierer. Die Gateway API scheint sich um alle Personas zu kümmern.
Konfiguration des Pod-Zugriffs über die Gateway API
Ersetzen wir das zuvor konfigurierte Ingress
durch die Gateway API. Dazu sind mehrere Schritte notwendig.
Installation der neuen Gateway CRDs
k apply -f https://github.com/kubernetes-sigs/gateway-api/releases/download/v0.5.0/standard-install.yaml
Installation einer Implementierung
Ich werde Apache APISIX verwenden. Alternativ führt die SIG-Website eine Liste von Implementierungen.
helm install apisix apisix/apisix \
--namespace ingress-apisix \
--create-namespace \
--devel \ #1
--set gateway.type=NodePort \ #2
--set gateway.http.nodePort=30800 \ #2
--set ingress-controller.enabled=true \ #2
--set ingress-controller.config.kubernetes.enableApiGateway=true \ #3
--set ingressPublishService="ingress-apisix/apisix-gateway" #4
- Ohne die
--devel
-Option installiert Helm die neueste Version, die nicht mit der Gateway API funktioniert - Das Gateway muss sowieso von außerhalb des Clusters zugänglich sein
- Hier passiert die Magie!
- Darauf komme ich später zurück
Überprüfen wir, ob alles funktioniert:
k get all -n ingress-apisix
NAME READY STATUS RESTARTS AGE
pod/apisix-5fc9b45c69-cf42m 1/1 Running 0 14m #1
pod/apisix-etcd-0 1/1 Running 0 14m #2
pod/apisix-etcd-1 1/1 Running 0 14m #2
pod/apisix-etcd-2 1/1 Running 0 14m #2
pod/apisix-ingress-controller-6f8bd94d9d-wkzfn 1/1 Running 0 14m #3
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S)
service/apisix-admin ClusterIP 10.96.69.19 <none> 9180/TCP
service/apisix-etcd ClusterIP 10.96.226.79 <none> 2379/TCP,2380/TCP
service/apisix-etcd-headless ClusterIP None <none> 2379/TCP,2380/TCP
service/apisix-gateway NodePort 10.96.101.224 <none> 80:30800/TCP #4
service/apisix-ingress-controller ClusterIP 10.96.141.230 <none> 80/TCP
- Apache APISIX selbst
- Apache APISIX speichert seine Konfiguration in
etcd
. Das Chart plant standardmäßig drei Pods ein, eine gute Praxis zur Handhabung von Ausfällen in verteilten Systemen - Apache APISIX Controller: Ein Kubernetes-Controller ist eine Kontrollschleife, die den bestehenden Zustand in Richtung des gewünschten Zustands bewegt
- Apache APISIX Gateway-Service: Es ist der
NodePort
-Service
, den wir über das Helm-Chart installiert haben. Es ist auch der Name, auf den wir während der Helm-Chart-Installation verwiesen haben –ingressPublishService
An diesem Punkt ist die Infrastruktur bereit.
Deklaration der Gateway-Implementierung
Wie ich oben erwähnt habe, trennt die API sauber zwischen Spezifikation und Implementierung. Allerdings müssen wir sie irgendwie binden. Dies ist die Aufgabe des GatewayClass
-Objekts:
apiVersion: gateway.networking.k8s.io/v1alpha2 #1
kind: GatewayClass #2
metadata:
name: apisix-gateway-class #3
spec:
controllerName: apisix.apache.org/gateway-controller #4
- Wir verwenden nicht die neueste Version absichtlich, da Apache APISIX diese Version verwendet. Seien Sie sich bewusst, dass sie sich in der (nahen) Zukunft weiterentwickeln wird
GatewayClass
-Objekt- Nennen Sie es, wie Sie wollen; wir werden es später verwenden, um auf die Gateway-Klasse zu verweisen
- Der Name des Controllers hängt von der Implementierung ab. Hier verwenden wir den von Apache APISIX.
Beachten Sie, dass die GatewayClass
einen clusterweiten Gültigkeitsbereich hat. Dieses Modell ermöglicht es uns, verschiedene Gateway-API-Implementierungen zu deklarieren und sie parallel innerhalb desselben Clusters zu verwenden.
Erstellung des Gateways
Mit Apache APISIX ist es ziemlich einfach:
apiVersion: gateway.networking.k8s.io/v1alpha2 #1
kind: Gateway #2
metadata:
name: apisix-gateway
spec:
gatewayClassName: apisix-gateway-class #3
listeners: #4
- name: http
protocol: HTTP
port: 80
- Derselbe Namespace wie oben
Gateway
-Objekt- Verweis auf die zuvor deklarierte Gateway-Klasse
- Ermöglicht einige Einschränkungen auf dieser Ebene, damit der Cluster-Operator unerwünschte Nutzung vermeiden kann
Warnung: Die Gateway API spezifiziert die Option, den Port auf der Operator-Seite dynamisch zu ändern. Zum Zeitpunkt dieses Schreibens ist die Port-Zuweisung von Apache APISIX statisch. Es ist geplant, sie in Zukunft dynamisch zu machen. Bitte abonnieren Sie dieses GitHub-Issue, um den Fortschritt zu verfolgen.
Routen, Routen, überall Routen
Bisher war alles Infrastruktur; wir können endlich das Routing konfigurieren.
Ich möchte das gleiche Routing wie im vorherigen Beitrag; einen /left
-Zweig und einen right
-Zweig. Ich werde den letzteren der Kürze halber überspringen.
apiVersion: gateway.networking.k8s.io/v1alpha2 #1
kind: HTTPRoute #2
metadata:
name: left
spec:
parentRefs:
- name: apisix-gateway #3
rules:
- matches: #4
- path: #4
type: PathPrefix #4
value: /left
backendRefs: #5
- name: left #5
port: 80 #5
- Derselbe Namespace wie oben
HTTPRoute
-Objekt- Verweis auf das oben erstellte
Gateway
- Regelübereinstimmungen. In unserem Fall stimmen wir bezüglich eines Pfadpräfixes überein, aber es stehen viele Regeln zur Verfügung. Sie können basierend auf einem Abfrageparameter, einem Header usw. übereinstimmen.
- Das "Upstream", an das weitergeleitet werden soll. Wir haben den
left
-Service
im vorherigen Blogbeitrag definiert.
Überprüfung der Funktionsweise
Nachdem wir unsere Routen konfiguriert haben, können wir überprüfen, ob es funktioniert.
curl localhost:30800/left
Als wir das Helm-Chart installiert haben, haben wir Apache APISIX angewiesen, einen NodePort
-Service auf Port 30800
zu erstellen. Daher können wir den Port verwenden, um von außerhalb des Clusters auf den Service zuzugreifen.
left
Fazit
Es stehen viele Alternativen zur Verfügung, um von außerhalb des Clusters auf einen Pod zuzugreifen. Die CNCF hat die meisten davon hinzugefügt, um die vorherigen zu verbessern.
Die Gateway API ist der neueste Vorschlag in dieser Hinsicht. Die Spezifikation ist ein Work in Progress, und Produkte befinden sich in verschiedenen Implementierungsstadien. Aus diesem Grund ist es zu früh, Ihre Produktion auf die API zu stützen. Sie sollten jedoch wahrscheinlich den Fortschritt verfolgen, da sie eine erhebliche Verbesserung gegenüber den vorherigen Ansätzen darstellen wird.
Der vollständige Quellcode für diesen Beitrag kann auf GitHub gefunden werden.
Um weiterzugehen: