Einführung
Services stellen stabile Endpunkte für Anwendungen innerhalb eines Clusters bereit. Ingress ergänzt Services um HTTP-Routing-Regeln und ermöglicht es dadurch, mehrere Anwendungen über einen gemeinsamen Einstiegspunkt anhand des Hostnamens oder URL-Pfads zu erreichen.
Sie untersuchen den vorbereiteten ingress-nginx-Controller, stellen zwei Backends bereit, richten Host- und Pfad-Routing ein und verfolgen eine Anfrage durch Ingress, Service und Pod.
Behalten Sie während des gesamten Labs den Weg der Anfrage im Blick: Client → ingress-nginx-Einstiegspunkt → Ingress-Regel → Service → bereiter Pod. Wenn eine Anfrage fehlschlägt, lassen sich diese Verbindungen der Reihe nach deutlich leichter prüfen, als Ingress als eine einzige Blackbox zu betrachten.
Ingress-Controller untersuchen
In diesem Schritt untersuchen Sie den Controller, der bereits von der CKA-Umgebung bereitgestellt wurde, anstatt eine zweite Kopie zu installieren.
Ein Ingress-Objekt ist eine Konfiguration und kein Proxy-Prozess. Es hat keine Wirkung, solange kein passender Controller es überwacht. Überprüfen Sie zunächst, ob beide Infrastrukturkomponenten vorhanden sind: eine IngressClass namens nginx und ein verfügbares ingress-nginx-Controller-Deployment.
cd /home/labex/project/ingress-routing
kubectl get ingressclasses
kubectl get deployments,pods,services -n ingress-nginx
kubectl wait --for=condition=Available deployment/ingress-nginx-controller -n ingress-nginx --timeout=60s
Eine Ingress-Ressource speichert die gewünschte Routing-Konfiguration. Der ingress-nginx-Controller überwacht Ressourcen, deren ingressClassName auf nginx gesetzt ist, und konfiguriert den eigentlichen Proxy.
Der Service des Controllers stellt den Proxy in diesem lokalen Cluster über einen NodePort bereit. Diesen Port ermitteln Sie später, statt ihn fest zu hinterlegen.
Die vorbereitete Umgebung meldet eine nginx-Klasse, einen verfügbaren Controller und einen NodePort-Service:
NAME CONTROLLER
nginx k8s.io/ingress-nginx
deployment.apps/ingress-nginx-controller 1/1 ...
service/ingress-nginx-controller NodePort ... 80:.../TCP,443:.../TCP
Die beiden Completed-Admission-Pods, die Sie möglicherweise ebenfalls sehen, gehören zu bereits abgeschlossenen Installations-Jobs. Es handelt sich nicht um fehlgeschlagene Controller-Replikas.
Zwei Service-Backends bereitstellen
In diesem Schritt erstellen Sie zwei Web-Workloads mit jeweils einer Replik sowie die zugehörigen ClusterIP-Services aus einer Datei mit mehreren Dokumenten.
Diese Backends verwenden Konzepte aus Kubernetes für Einsteiger. Der Schwerpunkt liegt daher auf ihrer Routing-Beziehung und nicht auf der Syntax eines Deployments. Die Datei enthält fünf durch --- getrennte YAML-Dokumente: zunächst einen Namespace, anschließend jeweils ein Deployment und einen Service für beide Anwendungen. Vergleichen Sie bei jedem Service.spec.selector die Auswahlkriterien mit dem Label des zugehörigen Pods. Sie müssen übereinstimmen, bevor Ingress ein Ziel erreichen kann.
cd /home/labex/project/ingress-routing
cat <<'EOF' > backends.yaml
apiVersion: v1
kind: Namespace
metadata: {name: practice-ingress}
---
apiVersion: apps/v1
kind: Deployment
metadata: {name: storefront, namespace: practice-ingress}
spec:
replicas: 1
selector: {matchLabels: {app: storefront}}
template:
metadata: {labels: {app: storefront}}
spec:
containers: [{name: web, image: nginx:1.27-alpine, imagePullPolicy: IfNotPresent, ports: [{name: http, containerPort: 80}]}]
---
apiVersion: v1
kind: Service
metadata: {name: storefront, namespace: practice-ingress}
spec: {selector: {app: storefront}, ports: [{name: http, port: 80, targetPort: http}]}
---
apiVersion: apps/v1
kind: Deployment
metadata: {name: reports, namespace: practice-ingress}
spec:
replicas: 1
selector: {matchLabels: {app: reports}}
template:
metadata: {labels: {app: reports}}
spec:
containers: [{name: web, image: httpd:2.4-alpine, imagePullPolicy: IfNotPresent, ports: [{name: http, containerPort: 80}]}]
---
apiVersion: v1
kind: Service
metadata: {name: reports, namespace: practice-ingress}
spec: {selector: {app: reports}, ports: [{name: http, port: 80, targetPort: http}]}
EOF
Wenden Sie alle fünf Dokumente gemeinsam an und warten Sie anschließend auf beide Deployments. Durch das getrennte Warten ist sofort erkennbar, welches Backend fehlgeschlagen ist, falls ein Image oder Selektor nicht stimmt:
kubectl apply -f backends.yaml
kubectl rollout status deployment/storefront -n practice-ingress --timeout=60s
kubectl rollout status deployment/reports -n practice-ingress --timeout=60s
Ingress leitet ausschließlich an Services weiter. Daher muss jedes Backend bereits über bereite Endpunkte verfügen.
Überprüfen Sie diese Voraussetzung ausdrücklich, bevor Sie die Routing-Regeln erstellen:
kubectl get services,endpointslices -n practice-ingress
Für jeden Service sollte ein zugehöriger EndpointSlice mit einer bereiten Adresse vorhanden sein.
service/reports ClusterIP ... 80/TCP
service/storefront ClusterIP ... 80/TCP
endpointslice.../reports-... IPv4 80 10.244.104...
endpointslice.../storefront-... IPv4 80 10.244.104...
Die generierten Suffixe und Adressen unterscheiden sich, aber jeder Service-Name sollte genau einen nicht leeren EndpointSlice besitzen. Ingress kann einen Service ohne Backend nicht reparieren. Diese Prüfung stellt daher bewusst zuerst die darunterliegende Schicht sicher.
Host-basiertes Routing hinzufügen
In diesem Schritt leiten Sie store.practice.test an den Storefront-Service weiter.
Eine Ingress-Regel trifft drei Routing-Entscheidungen: host, path und den Port des Backend-Services. ingressClassName: nginx wählt den zuständigen Controller aus. Die Rewrite-Annotation ist controllerspezifisch und ändert den an das Backend gesendeten Anfragepfad in /, den beide Demo-Server verarbeiten können.
cd /home/labex/project/ingress-routing
cat <<'EOF' > ingress.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: practice-routing
namespace: practice-ingress
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /
spec:
ingressClassName: nginx
rules:
- host: store.practice.test
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: storefront
port: {name: http}
EOF
Wenden Sie die Regel an und verwenden Sie describe, um die Interpretation durch den Controller einschließlich des aufgelösten Backend-Endpunkts zu überprüfen:
kubectl apply -f ingress.yaml
kubectl describe ingress practice-routing -n practice-ingress
pathType: Prefix trifft auf / und alle darunterliegenden Pfade zu. Die Rewrite-Annotation sendet die ausgewählte Anfrage unter / an das Backend, wo der Demo-Webserver eine Seite bereitstellt. Der Hostname dient als HTTP-Routing-Schlüssel. Für diesen lokalen Test ist dafür kein öffentliches DNS erforderlich.
describe sollte die Regel vollständig bis zu einer Pod-Adresse auflösen:
Rules:
Host Path Backends
store.practice.test
/ storefront:http (10.244.104...:80)
Eine unmittelbar nach der Erstellung noch leere Address auf oberster Ebene ist in dieser lokalen Umgebung kein Fehler. Entscheidend sind das aufgelöste Backend storefront:http und die zugehörige Pod-Adresse.
Pfad-Routing hinzufügen und Anfragen testen
In diesem Schritt fügen Sie das Routing für /reports hinzu und testen beide Regeln über den Einstiegspunkt des Knotens.
Der JSON-Patch-Pfad endet mit /-. Bei einem Array bedeutet -, dass ein neues Element angehängt wird, anstatt das vorhandene /-Routing zu ersetzen. Das neue Backend verweist über seinen benannten http-Port auf den Service reports.
Führen Sie diesen Append-Patch genau einmal aus. Anders als kubectl apply ist das Anhängen an /- nicht idempotent: Bei einer Wiederholung wird ein weiteres identisches Element für /reports hinzugefügt, statt das bereits vorhandene zu erkennen.
Die folgenden beiden Zuweisungen ermitteln den Endpunkt, anstatt ihn fest zu hinterlegen. minikube ip -p labex-v135 gibt die Node-IP für das benannte Minikube-Profil zurück, und die Befehlssubstitution $(...) speichert die Ausgabe jedes Befehls in einer Shell-Variablen. Die JSONPath-Abfrage wählt den Service-Port namens http aus und liest dessen NodePort aus.
kubectl patch ingress practice-routing -n practice-ingress --type='json' -p='[{"op":"add","path":"/spec/rules/0/http/paths/-","value":{"path":"/reports","pathType":"Prefix","backend":{"service":{"name":"reports","port":{"name":"http"}}}}}]'
NODE_IP=$(minikube ip -p labex-v135)
HTTP_NODE_PORT=$(kubectl get service ingress-nginx-controller -n ingress-nginx -o jsonpath='{.spec.ports[?(@.name=="http")].nodePort}')
echo "Ingress endpoint: ${NODE_IP}:${HTTP_NODE_PORT}"
Die beiden Variablen verhindern, dass umgebungsspezifische Adressen fest in den Anweisungen stehen. Senden Sie nun Anfragen mit dem für die Regel erforderlichen Host-Header. Bei jedem curl-Befehl blendet -s die Fortschrittsanzeige aus, --retry 5 wiederholt den Versuch bei vorübergehenden Fehlern, --retry-connrefused wiederholt auch bei einer anfänglich abgelehnten Verbindung und --retry-delay 2 wartet zwischen den Versuchen zwei Sekunden. -H setzt den HTTP-Host-Header. Die Pipe übergibt die Antwort an grep, sodass nur der identifizierende Seitentext angezeigt wird.
curl -s --retry 5 --retry-connrefused --retry-delay 2 -H 'Host: store.practice.test' "http://${NODE_IP}:${HTTP_NODE_PORT}/" | grep 'Welcome to nginx'
curl -s --retry 5 --retry-connrefused --retry-delay 2 -H 'Host: store.practice.test' "http://${NODE_IP}:${HTTP_NODE_PORT}/reports" | grep 'It works'
Die beiden Antworten belegen, dass ein gemeinsamer Einstiegspunkt zu unterschiedlichen Services weiterleitet.
Die erste Antwort stammt von NGINX, die zweite von Apache httpd. Die unterschiedlichen Seitentexte liefern bewusst den Nachweis, dass die Pfadregel ein anderes Backend ausgewählt hat und der Proxy nicht lediglich zweimal den HTTP-Status 200 zurückgegeben hat.
Die erwarteten übereinstimmenden Zeilen sind:
<title>Welcome to nginx!</title>
<h1>Welcome to nginx!</h1>
<title>It works! Apache httpd</title>
<p>It works!</p>
Dieses Ergebnis erklärt auch, warum der benutzerdefinierte Host-Header wichtig ist: Beide Anfragen erreichen dieselbe Node-IP und denselben NodePort. Hostname und Pfad bestimmen, welche Regel und welches Backend ausgewählt werden.
Zusammenfassung
Sie haben den vorbereiteten ingress-nginx-Controller wiederverwendet, Ingress-Regeln mit bereiten Services verbunden und das host- und pfadbasierte Routing über einen gemeinsamen Einstiegspunkt getestet.


