← Übersicht  ·  Skripte & Dateien  ·  OpenShift · Netzwerk · Service Mesh

Netzwerkpfad: OVN, Router und Service Mesh

Du baust zwei kleine Test-Workloads, verfolgst den internen Weg vom Service bis zur Pod-IP und liest anschließend die von OpenShift generierte HAProxy-Konfiguration der Route. Zum Schluss erkennst du, ob Service Mesh 3 oder die frühere Maistra-Generation installiert ist und entscheidest, ob die zusätzliche Proxy-Schicht wirklich nötig ist.

Stand: 5. September 2026OCP / OKD 4.xService Mesh 3.2Atlas F1, F3, F4ca. 45 Minuten

1 Drei Datenpfade auseinanderhalten

OVN, Router und Service Mesh lösen unterschiedliche Aufgaben. Sie liegen bei einem Request hintereinander, sind aber keine austauschbaren Produkte.

Pod zu PodDer Client verwendet Service-DNS. OVN ersetzt die virtuelle Service-IP durch eine bereite Pod-IP. Nur zwischen verschiedenen Nodes wird das Paket im Geneve-Overlay transportiert.
Außen nach innenDer OpenShift-Router nimmt eine Route an. HAProxy wählt anhand Host und Pfad ein Backend. Danach erreicht der Request über Service und EndpointSlice den Pod.
Mit MeshEin Envoy-Proxy im Pod fängt Anwendungsverkehr ab. Istio verteilt Identitäten, mTLS-Regeln und Traffic-Richtlinien. OVN transportiert die Pakete darunter weiterhin.

Begriffe: Ein Overlay ist ein virtuelles Netz über dem physischen Node-Netz. DNAT ersetzt die Zieladresse eines Pakets. Eine EndpointSlice enthält die aktuell bereiten Pod-Adressen eines Service. Ein Sidecar ist ein zusätzlicher Container im selben Pod.

2 Netzwerktyp und Komponenten prüfen

Diese Befehle lesen nur. Für System-Namespaces und spätere OVN-Vertiefung brauchst du cluster-admin.

Laptop · PowerShell oder Bash · nur lesen
oc whoami
oc get network.operator.openshift.io cluster -o jsonpath='{.spec.defaultNetwork.type}{"\n"}'
oc get network.config.openshift.io cluster -o yaml
oc get co network ingress
oc get pods -n openshift-ovn-kubernetes -o wide
oc get pods -n openshift-ingress -o wide

Erwartung: Der Netzwerktyp ist OVNKubernetes. Die ClusterOperatoren network und ingress melden Available=True und Degraded=False.

3 Zwei isolierte Test-Workloads anlegen

Die beiden Deployments dienen nur als Quell- und Ziel-Pod. Das Ziel erhält zusätzlich einen Service und eine Route.

Laptop · PowerShell oder Bash · Lab-Projekt
oc new-project network-path-lab
oc create deployment source --image=quay.io/openshifttest/nginx
oc create deployment destination --image=quay.io/openshifttest/nginx
oc expose deployment destination --port=80
oc expose service destination
oc wait --for=condition=Available deployment/source deployment/destination --timeout=120s
oc get pod,service,route -o wide

Die Deployments und ihre Pods werden von dir angefordert. ReplicaSets und Pods werden von Kubernetes generiert. Die ClusterIP des Service und der Hostname der Route werden vom Cluster vergeben.

4 Service bis zur Pod-IP verfolgen

Eine ClusterIP ist kein Prozess und keine Netzwerkkarte. Sie ist eine virtuelle Adresse, für die OVN Regeln mit den EndpointSlice-Adressen programmiert.

Laptop · PowerShell oder Bash · nur lesen
oc get service destination -o yaml
oc get endpointslice -l kubernetes.io/service-name=destination -o yaml
oc get pods -l app=destination -o wide
oc describe service destination
Laptop · Verbindung aus temporärem Pod
oc run probe --rm -i --restart=Never --image=registry.access.redhat.com/ubi9/ubi-minimal:latest --command -- curl -sS http://destination:80/
Objektentscheidender WertWirkung
Servicespec.clusterIP und Port 80stabile virtuelle Adresse und Name
EndpointSliceendpoints[].addresses und conditions.readyaktuelle erreichbare Ziele
Podstatus.podIP und Nodereales Ziel des umgeschriebenen Pakets

Wenn der Curl-Aufruf funktioniert, wurden DNS-Auflösung, Service-Auswahl, OVN-Regeln und Zielprozess gemeinsam bestätigt. Eine leere EndpointSlice bedeutet meist, dass Selector oder Readiness nicht passen.

5 Geneve und OVN am Node sehen

Geneve kapselt Podverkehr nur dann, wenn Quell- und Ziel-Pod auf verschiedenen Nodes liegen. Auf einer SNO bleibt der Verkehr lokal und zeigt keinen echten Tunnel-Hop.

Das CNI-Plugin. Jeder Node führt OVN lokal, darüber liegt eine logische Netz-Topologie (Switches, ein verteilter Router) auf dem physischen Netz. Pods auf demselben Node reden über die lokale OVS-Bridge, Pods auf verschiedenen Nodes über einen Geneve-Tunnel. Services (B3) sind OVN-Load-Balancer – kein kube-proxy.

Gleicher Node: die lokale Bridge. Anderer Node: ein Geneve-Tunnel. Node A Pod-CIDR-Ausschnitt 10.128.2.0/23 · ovnkube-node-Pod Pod api-gateway 10.128.2.11 Pod catalog 10.128.2.12 OVS-Bridge br-int – ein logischer Switch verbindet alle Pods des Nodes, kennt ihre MAC/IP 1 · api-gateway → catalog auf demselben Node: das Paket geht nur durch br-int, verlässt den Node nie der Pod hat ein veth-Paar in die Bridge, sonst nichts Besonderes Node B Pod-CIDR-Ausschnitt 10.129.0.0/23 Pod keycloak 10.129.0.7 OVS-Bridge br-int packt das Tunnel-Paket aus und stellt es lokal zu 2 · api-gateway → keycloak auf Node B: OVS auf einem Node A kapselt in Geneve (UDP 6081) über das physische Node-Netz zu Node B Node B packt aus → br-int → Pod Geneve-Tunnel · UDP 6081 die logische Topologie über dem physischen Netz liegt ein Modell aus logischen Switches (einer je Node) und einem verteilten logischen Router, der sie verbindet der Pod sieht ein flaches Netz – jede Pod-IP ist von jeder anderen erreichbar (ohne NetworkPolicy, F2) Steuerung: ovnkube-control-plane schreibt die OVN-Datenbank, ovn-controller je Node setzt sie um alles in openshift-ovn-kubernetes was OVN sonst noch macht Services (B3): als OVN-Load-Balancer, DNAT direkt in der Datapath – kein kube-proxy, keine iptables-Regeln NetworkPolicy (F2): OVN setzt die Allow/Deny-Regeln EgressIP: ausgehender Verkehr bekommt eine feste Quell-IP EgressFirewall: Ziel-Regeln je Namespace OVN-Kubernetes hat OpenShift SDN abgelöst (SDN ab 4.17 raus) Tunnel-Overhead: das MTU je Pod ist ~50 Byte kleiner als das Node-MTU nachsehen oc get pods -n openshift-ovn-kubernetes oc get node -o jsonpath='{.items[*].spec.podCIDR}' die Nodes-Annotation k8s.ovn.org/node-subnets Cluster-Netze im Network-Objekt (clusterNetwork, serviceNetwork) oc get co network zeigt den Zustand des CNI (G6) auf SNO läuft alles auf einem Node – nie ein Geneve-Tunnel Bibliothek: die 8 Dienste im selben Namespace, Verkehr bleibt im Overlay OCP-Unterschied: OVN-Kubernetes ist in OKD und OCP gleich – SDN als älteres Plugin ist entfernt.
Ein flaches Netz auf zwei Ebenen. Jeder Node führt OVN lokal (ovnkube-node), die Datenbank schreibt ovnkube-control-plane. Pods bekommen eine IP aus dem Ausschnitt ihres Nodes. Reden zwei Pods auf demselben Node, geht das Paket nur durch die OVS-Bridge br-int. Sind sie auf verschiedenen Node, kapselt OVN es in einen Geneve-Tunnel (UDP 6081) über das Node-Netz. Services sind OVN-Load-Balancer, NetworkPolicy (F2) OVN-Regeln – kein kube-proxy.
  • das CNI-Plugin: jeder Node führt OVN lokal (ovnkube-node-Pod + ovn-controller), die Datenbank schreibt ovnkube-control-plane in openshift-ovn-kubernetes
  • jeder Node bekommt einen Ausschnitt des Cluster-Pod-CIDR, ein Pod bekommt eine IP daraus über ein veth-Paar in die OVS-Bridge br-int
  • Pod zu Pod auf demselben Node: das Paket geht nur durch br-int und verlässt den Node nie
  • Pod zu Pod auf verschiedenen Nodes: OVS kapselt in einen Geneve-Tunnel (UDP 6081) über das physische Node-Netz, der Ziel-Node packt aus
  • über dem physischen Netz liegt eine logische Topologie aus Switches (einer je Node) und einem verteilten logischen Router
  • der Pod sieht ein flaches Netz – jede Pod-IP ist von jeder anderen erreichbar, solange keine NetworkPolicy (F2) greift
  • Services (B3) sind OVN-Load-Balancer: ruft api-gateway den catalog-service, macht OVN das DNAT direkt in der Datapath – kein kube-proxy, keine iptables-Regeln
  • OVN erzwingt auch NetworkPolicy (F2), EgressIP (feste Quell-IP nach außen) und EgressFirewall (Ziel-Regeln je Namespace)
  • OVN-Kubernetes hat OpenShift SDN abgelöst – SDN ist ab OCP 4.17 entfernt
  • Tunnel-Overhead: das Pod-MTU ist rund 50 Byte kleiner als das Node-MTU – wichtig bei Jumbo Frames oder VPN darunter
  • auf der SNO: die 8 Dienste + Postgres/Redis/Kafka/Keycloak sind alle Pods auf einem Node – jeder Hop bleibt in br-int, nie ein Geneve-Tunnel
  • nachsehen: oc get pods -n openshift-ovn-kubernetes zeigt auf der SNO genau einen ovnkube-node-Pod, dazu die Nodes-Annotation k8s.ovn.org/node-subnets und das Network-Objekt
  • ein lokaler 2-Node-kind-Cluster zeigt das Kapselungs-Prinzip – für echtes OVN-K mit Geneve das ovn-kubernetes-kind-Setup
  • OCP-Unterschied: identisch – OVN-Kubernetes ist in OKD und OCP gleich, SDN als älteres Plugin ist weg
  • von Hand verfolgen: Service-DNAT und Geneve – ClusterIP, EndpointSlice und Pod-IP zusammenführen und den berechneten OVN-Pfad optional mit ovnkube-trace simulieren
Laptop · PowerShell · nur lesen
$node = oc get pod -l app=destination -o jsonpath='{.items[0].spec.nodeName}'
$ovnPod = oc get pod -n openshift-ovn-kubernetes -l app=ovnkube-node --field-selector spec.nodeName=$node -o jsonpath='{.items[0].metadata.name}'
"Node: $node"
"OVN-Pod: $ovnPod"
oc debug --as-root node/$node -- chroot /host ip -d link show genev_sys_6081
oc logs -n openshift-ovn-kubernetes pod/$ovnPod -c ovnkube-node --since=5m
Bash-Variante anzeigen
Laptop · Bash · nur lesen
node=$(oc get pod -l app=destination -o jsonpath='{.items[0].spec.nodeName}')
ovn_pod=$(oc get pod -n openshift-ovn-kubernetes -l app=ovnkube-node --field-selector "spec.nodeName=$node" -o jsonpath='{.items[0].metadata.name}')
printf 'Node: %s\nOVN-Pod: %s\n' "$node" "$ovn_pod"
oc debug --as-root "node/$node" -- chroot /host ip -d link show genev_sys_6081
oc logs -n openshift-ovn-kubernetes "pod/$ovn_pod" -c ovnkube-node --since=5m

Versionsgrenze: Container- und Interface-Namen können sich ändern. Wenn ovnkube-node oder genev_sys_6081 fehlt, zuerst die tatsächlichen Container mit oc get pod -n openshift-ovn-kubernetes $ovnPod -o jsonpath='{.spec.containers[*].name}' und die Interfaces mit oc debug --as-root node/$node -- chroot /host ip -d link lesen.

6 Optional: den OVN-Pfad simulieren

ovnkube-trace simuliert einen TCP- oder UDP-Pfad durch logische OVN- und OpenFlow-Regeln. Diese Vertiefung läuft in Linux oder WSL mit funktionierendem oc-Zugang.

WSL oder Linux · erzeugt lokales Werkzeug
pod=$(oc get pods -n openshift-ovn-kubernetes -l app=ovnkube-control-plane -o name | head -1 | cut -d/ -f2)
oc cp -n openshift-ovn-kubernetes "$pod:/usr/bin/ovnkube-trace" -c ovnkube-cluster-manager ./ovnkube-trace
chmod +x ./ovnkube-trace

./ovnkube-trace \
  -src source -src-namespace network-path-lab \
  -dst destination -dst-namespace network-path-lab \
  -service destination -tcp -dst-port 80 -loglevel 2

ovnkube-trace wird aus dem laufenden Control-Plane-Pod kopiert. Es ist ein temporäres Diagnosewerkzeug und gehört nicht ins Repository. Entferne es danach mit rm -- ./ovnkube-trace.

Leseschlüssel: Ein erfolgreicher Trace bestätigt nur die berechneten OVN-Regeln. Ein echter Curl-Aufruf bestätigt zusätzlich DNS, Prozesse, Ports und den realen Datenpfad. Beide Tests beantworten unterschiedliche Fragen.

7 Route bis zur generierten HAProxy-Konfiguration verfolgen

Der Ingress Operator verwaltet einen IngressController. Dieser erzeugt das Router-Deployment. Der Router beobachtet Routes und Endpoints und rendert daraus seine HAProxy-Konfiguration.

B4 hat den Router als Kasten gezeigt – hier von innen. Ein Controller im Router-Pod beobachtet Route und Endpoints, rendert daraus die haproxy.config neu und lädt HAProxy neu. Jede Route wird zu einem Frontend-Match plus einem Backend mit einer server-Zeile je bereitem Pod. Mehrere IngressController teilen die Routes per Selektor auf.

Route + Endpoints → haproxy.config gerendert → Reload. Eingaben, die der Controller beobachtet Route-Objekte (B4): Host, Pfad, TLS-Modus, Service EndpointSlice (B3): die bereiten Pod-IPs der IngressController-Spec (global) jede Änderung → neu rendern Route wird Admitted, wenn ihr Host frei ist HostAlreadyClaimed: zwei Routes, ein Host Router-Pod (router-default, openshift-ingress) 1 · Controller rendert aus einer Go-Template die Datei /var/lib/haproxy/conf/haproxy.config 2 · HAProxy wird graceful neu geladen (alte Verbindungen laufen aus) frontend fe_sni # matcht den Host (SNI / Host-Header) use_backend be_library_frontend if host_frontend backend be_library_frontend server pod:10.128.2.11:8080 ... # je bereitem Endpoint server pod:10.128.2.12:8080 ... # 10.128.3.9 not ready -> keine server-Zeile 3 · das Paket geht dann an den Service (B3), der zum Pod DNAT-et edge/reencrypt: Host-Header lesbar, Pfad-Routing geht · passthrough: nur SNI oc rsh <router-pod> cat /var/lib/haproxy/conf/haproxy.config Sharding mehrere IngressController-Objekte, je einer: eigene domain, eigene Node (nodePlacement) routeSelector und/oder namespaceSelector Beispiel: ein interner Router (nur im Firmennetz) und ein internetseitiger Router eine Route wird von den Controllern Admitted, deren Selektoren sie matcht (kann auch mehrere sein) Skalierung: replicas am IngressController – mehr HAProxy-Pods TLS-Vorgabe, Ciphers, HTTP/2: spec.tlsSecurityProfile Logging: spec.logging.access (aus, sidecar, oder syslog) oc get ingresscontroller -n openshift-ingress-operator oc get route -A -o wide zeigt die Admitted-Spalte Feintuning je Route – Annotationen haproxy.router.openshift.io/… timeout: 30s · balance: roundrobin (auch leastconn, source = sticky) disable_cookies · rate-limit-connections · ip_whitelist set-forwarded-headers steuert, was der Router an X-Forwarded-* setzt (B4) global im IngressController: tuningOptions, httpErrorCodePages, httpHeaders der Reload-Sturm jede Route-/Endpoint-Änderung rendert die ganze Datei neu bei tausenden Routes: ständige Reloads, hohe CPU Abhilfe: RELOAD_INTERVAL bündelt, maxConnections deckelt bei Rollouts (B1) flackern server-Zeilen – sporadische 502/503 Merksatz: der Controller macht aus Route + Endpoints eine haproxy.config, lädt neu, und HAProxy verteilt auf die server-Zeilen Sharding = mehrere IngressController mit Selektoren – intern/extern trennen, oder Last auf mehr Router-Pods verteilen Bibliothek: ein Default-Router reicht – bei einem internen und einem externen Zugang wäre ein zweiter IngressController der Weg OCP-Unterschied: identisch – der HAProxy-Router und der IngressController-Operator sind Kern-OpenShift, in OKD und OCP gleich.
Aus Objekten wird HAProxy-Konfig. Ein Controller im router-default-Pod beobachtet Route und Endpoints, rendert daraus die haproxy.config aus einer Go-Template und lädt HAProxy graceful neu. Jede Route wird zu einem Frontend-Match (SNI bei passthrough, Host-Header sonst) plus einem Backend mit einer server-Zeile je bereitem Endpoint. Mit mehreren IngressController-Objekten und routeSelector teilt man die Routes auf – intern vs extern, oder mehr Router-Pods gegen Last.
  • ein Controller im Router-Pod beobachtet Route und EndpointSlice (B3) und rendert daraus die /var/lib/haproxy/conf/haproxy.config aus einer Go-Template
  • nach jedem Rendern wird HAProxy graceful neu geladen – bestehende Verbindungen laufen aus
  • jede der 3 Bibliothek-Routes (library-frontend, keycloak, api-gateway) wird zu einem Frontend-Match auf den Host-Header (bei edge) plus einem Backend
  • im Backend steht eine server-Zeile je bereitem Endpoint – ein not-ready catalog-service-Pod (B5) bekommt keine Zeile und damit keinen Verkehr
  • eine Route wird Admitted, wenn ihr Host frei ist – HostAlreadyClaimed bei zwei Routes auf denselben Host
  • Sharding: mehrere IngressController-Objekte, je einer mit eigener domain, eigenen Nodes und einem routeSelector oder namespaceSelector
  • typisch: ein interner und ein internetseitiger Router – auf der SNO mit einem Node und einem router-default-Pod ist das gegenstandslos, es gibt genau einen
  • Feintuning je Route: Annotationen haproxy.router.openshift.io/timeout, balance, disable_cookies, rate-limit-connections, ip_whitelist
  • global im IngressController: tuningOptions, logging.access, tlsSecurityProfile, httpErrorCodePages, replicas
  • der Reload-Sturm: bei tausenden Routes rendert jede Änderung die ganze Datei neu → ständige Reloads, die RELOAD_INTERVAL bündelt – bei 3 Routes nie ein Thema
  • bei Rollouts (B1) flackern die server-Zeilen – das erklärt die sporadischen 502/503 aus B4
  • nachsehen auf der SNO: oc rsh -n openshift-ingress deploy/router-default cat /var/lib/haproxy/conf/haproxy.config, oc get route -n library -o wide
  • Bibliothek: der Default-Router reicht – seine selbstsignierte Wildcard bedient alle 3 edge-Routes, ein zweiter IngressController wäre erst bei getrenntem internem und externem Zugang nötig
  • OCP-Unterschied: identisch – HAProxy-Router und IngressController-Operator sind Kern-OpenShift
  • von Hand nachsehen: Route bis HAProxy verfolgen – eine eigene Lab-Route in der generierten Konfiguration finden, TLS-Termination umstellen und Sharding-Felder lesen
Laptop · PowerShell · nur lesen
$hostName = oc get route destination -o jsonpath='{.spec.host}'
$hostName
curl.exe -i "http://$hostName"

oc get ingresscontroller default -n openshift-ingress-operator -o yaml
oc get deployment router-default -n openshift-ingress -o yaml
oc exec -n openshift-ingress deployment/router-default -- cat /var/lib/haproxy/conf/haproxy.config | Select-String -Pattern 'network-path-lab'
Bash-Variante anzeigen
Laptop · Bash · nur lesen
host_name=$(oc get route destination -o jsonpath='{.spec.host}')
printf '%s\n' "$host_name"
curl -i "http://$host_name"

oc get ingresscontroller default -n openshift-ingress-operator -o yaml
oc get deployment router-default -n openshift-ingress -o yaml
oc exec -n openshift-ingress deployment/router-default -- cat /var/lib/haproxy/conf/haproxy.config | grep -n 'network-path-lab'

/var/lib/haproxy/conf/haproxy.config wird vom Router generiert. Du liest sie zur Diagnose, bearbeitest sie aber nie. Eine direkte Änderung würde beim nächsten Reconcile überschrieben.

TLS am eigenen Lab einschalten

Laptop · PowerShell · ändert nur die Lab-Route
oc patch route destination --type=merge -p '{"spec":{"tls":{"termination":"edge","insecureEdgeTerminationPolicy":"Redirect"}}}'
oc get route destination -o yaml
$hostName = oc get route destination -o jsonpath='{.spec.host}'
curl.exe -Ik "https://$hostName"
Bash-Variante anzeigen
Laptop · Bash · ändert nur die Lab-Route
oc patch route destination --type=merge -p '{"spec":{"tls":{"termination":"edge","insecureEdgeTerminationPolicy":"Redirect"}}}'
oc get route destination -o yaml
host_name=$(oc get route destination -o jsonpath='{.spec.host}')
curl -Ik "https://$host_name"

Bei edge endet TLS am Router. Zwischen Router und Pod läuft hier HTTP. reencrypt baut eine zweite TLS-Verbindung zum Backend auf. passthrough lässt die verschlüsselte Verbindung bis zum Pod durch und kann deshalb nur anhand des TLS-Servernamens auswählen.

8 Ingress-Sharding verstehen, ohne es anzulegen

Sharding bedeutet, dass mehrere IngressController jeweils nur ausgewählte Namespaces oder Routes übernehmen. So lassen sich intern, extern oder nach Mandant getrennte Router betreiben.

Laptop · PowerShell oder Bash · nur lesen
oc get ingresscontroller -n openshift-ingress-operator
oc explain ingresscontroller.spec.domain
oc explain ingresscontroller.spec.namespaceSelector
oc explain ingresscontroller.spec.routeSelector
oc get route destination --show-labels
Feldentscheidettypisches Beispiel
spec.domainDNS-Zone des Shardsinterne und öffentliche Apps trennen
spec.namespaceSelectorwelche Namespaces der Router beobachteteigener Router für Produktionsprojekte
spec.routeSelectorwelche gelabelten Routes übernommen werdensensible Route auf einen privaten Router legen

Nicht nur Router anlegen: Ein zusätzlicher IngressController braucht eine erreichbare Veröffentlichungsstrategie und passende DNS-Einträge. Auf Hetzner-UPI entsteht das nicht automatisch durch das OpenShift-Objekt.

9 Service-Mesh-Generation erkennen

OpenShift Service Mesh 3 nutzt den OpenShift Service Mesh Operator und Sail-APIs. Die frühere Generation nutzte Maistra-Ressourcen wie ServiceMeshControlPlane.

OpenShift Service Mesh ist Istio als Operator. In jeden Pod wird ein Envoy-Sidecar eingespritzt, das allen Verkehr abfängt. Der Sidecar bringt automatisches mTLS, feingranulares Routing (Canary, Retries, Timeouts) und L7-Telemetrie – kostet aber Latenz, Speicher und Betrieb. Für 8 Dienste ist das oft zu viel.

Ein Envoy-Sidecar je Pod – fängt allen Verkehr ab, macht mTLS, meldet alles. der Pod mit Sidecar App-Container redet mit localhost Envoy-Sidecar fängt in + out ab Einspritzung: Namespace-Label + Pod-Annotation sidecar.istio.io/inject: "true" – ein initContainer setzt iptables-Regeln, alles läuft durch Envoy Kosten: ~50–100 MiB und etwas Latenz je Pod die App ändert sich nicht – sie merkt vom Mesh nichts istiod – die Control Plane konfiguriert alle Sidecars: Routing, Zertifikate, Policy verteilt kurzlebige mTLS-Zertifikate an jeden Sidecar automatisches mTLS zwischen den Sidecars PeerAuthentication: STRICT → nur verschlüsselter Verkehr Zero-Trust ohne App-Änderung konfiguriert über CRDs (kein App-Code): Deployment via ServiceMeshControlPlane / Istio-CR ServiceMeshMemberRoll listet die Member-Namespaces oc get smcp,smmr -n istio-system Traffic-Management & Observability VirtualService: Routing, Canary-%, Retries, Timeouts, Fault-Injection DestinationRule: Subsets, Load-Balancing, Circuit-Breaking Gateway: Mesh-Ingress – eine Alternative zur Route (B4) Kiali: Topologie-Graph, wer redet mit wem Tracing: Jaeger / Tempo · Metriken: Prometheus / Grafana (G1) Retry/Timeout im Mesh statt im App-Code – über Dienste hinweg gleich Canary: 5 % auf v2, Rest auf v1 – ohne zwei Deployments zu jonglieren Mesh-Traffic kann trotzdem durch NetworkPolicy (F2) begrenzt sein wann es sich lohnt viele Dienste, die viel untereinander reden Bedarf an feinem Traffic-Shifting (Canary, A/B, Blue-Green je Request) mTLS überall als Compliance-Vorgabe, ohne jede App anzufassen einheitliche Retries / Timeouts / Circuit-Breaker zentral reiche L7-Telemetrie und ein Abhängigkeitsgraph (Kiali) typisch ab ~15–20 Diensten oder bei strengen Sicherheitsanforderungen Alternativen für einzelne Aspekte: NetworkPolicy (F2), serving-certs (F5), Gateway API, Resilience-Libraries in der App wann Overkill eine Handvoll Dienste, klare Aufrufwege NetworkPolicy (F2) + Routes (B4) + App-Retries reichen der Sidecar kostet Latenz und ~50–100 MiB je Pod istiod, Kiali, Jaeger sind eigene Betriebsobjekte mit Upgrades Debugging wird schwerer: ein Hop mehr, Envoy-Konfig lesen Bibliothek: wahrscheinlich nicht nötig für 8 Dienste notiert als Option, falls die App auf viele Dienste wächst mTLS-Bedarf allein → erst serving-certs (F5) prüfen Merksatz: Sidecar fängt den Verkehr ab, istiod konfiguriert ihn – mTLS, Routing und Telemetrie ohne App-Code, aber mit Overhead je Pod Entscheidung: Mesh erst, wenn NetworkPolicy + Routes + App-Retries nicht mehr reichen istioctl proxy-config zeigt die effektive Envoy-Konfig eines Pods · oc get vs,dr,gw -A OCP-Unterschied: OSSM ist Istio als unterstützter Operator (früher mit ServiceMeshControlPlane, neu die Istio-CR / Sail-Operator) – das Kubernetes-Original ist Upstream-Istio von Hand.
Ein Proxy je Pod. In jeden Pod eines Member-Namespace wird ein Envoy-Sidecar eingespritzt, das allen Verkehr abfängt; istiod konfiguriert alle Sidecars und verteilt kurzlebige Zertifikate. Zwischen den Sidecars läuft automatisch mTLS. Über CRDs (VirtualService, DestinationRule, Gateway) steuert man Routing, Canary und Retries ohne App-Code; Kiali zeigt den Graphen. Der Preis: Latenz, ~50–100 MiB je Pod und ein weiterer Betriebs-Stack – für 8 Dienste meist zu viel.
  • OpenShift Service Mesh = Istio als Operator-Paket – ein Envoy-Sidecar wird in jeden Pod eines Member-Namespace eingespritzt (Namespace-Label + Pod-Annotation)
  • der Sidecar fängt allen ein- und ausgehenden Verkehr ab – die App redet nur mit localhost und merkt vom Mesh nichts
  • istiod ist die Control Plane: konfiguriert alle Sidecars und verteilt kurzlebige mTLS-Zertifikate
  • automatisches mTLS zwischen den Sidecars (PeerAuthentication STRICT) – Zero-Trust ohne App-Änderung
  • Traffic-Management über CRDs: VirtualService (Routing, Canary-Anteil, Retries, Timeouts, Fault-Injection), DestinationRule (Subsets, Circuit-Breaking), Gateway (Mesh-Ingress statt Route)
  • Observability: Kiali (Topologie-Graph), Tracing (Jaeger/Tempo), Metriken (Prometheus/Grafana, G1)
  • Retries und Timeouts im Mesh statt im App-Code – in der Bibliothek macht das heute das api-gateway selbst (Spring), das Mesh würde es über alle Dienste zentralisieren
  • wann es sich lohnt: viele Dienste, feines Traffic-Shifting, mTLS als Compliance-Vorgabe, reiche L7-Telemetrie – typisch ab rund 15 bis 20 Diensten
  • wann Overkill: eine Handvoll Dienste, wo NetworkPolicy (F2) plus Routes (B4) plus App-Retries reichen – genau der Bibliothek-Fall
  • der Preis: Latenz, ~50–100 MiB je Pod – bei einem guten Dutzend Bibliothek-Pods fast 1 GB nur für Sidecars, plus istiod/Kiali/Jaeger als eigene Betriebsobjekte
  • Debugging wird schwerer: ein Hop mehr, die Envoy-Konfig lesen (istioctl proxy-config)
  • Bibliothek: nicht nötig für das gute Dutzend Pods – notiert als Option, wenn die App wächst. Reiner mTLS-Bedarf zwischen zwei Diensten → erst serving-certs (F5)
  • OCP-Unterschied: OSSM ist Istio als unterstützter Operator (ServiceMeshControlPlane, neu die Istio-CR) – Kubernetes pur ist Upstream-Istio von Hand
  • Generation und Bedarf prüfen: Service Mesh erkennen – Sail- und Maistra-Ressourcen unterscheiden, Sidecars im Pod nachweisen und gegen Service-CA oder NetworkPolicy abwägen
Laptop · PowerShell · nur lesen
oc get csv -A | Select-String -Pattern 'servicemesh|sail|istio|maistra'
oc api-resources | Select-String -Pattern 'Istio|ServiceMeshControlPlane|ServiceMeshMemberRoll'
oc get istio.sailoperator.io -A
oc get istiorevision.sailoperator.io -A
oc get servicemeshcontrolplane.maistra.io -A
oc get pod -n network-path-lab -o jsonpath='{range .items[*]}{.metadata.name}{": "}{.spec.containers[*].name}{"\n"}{end}'
Bash-Variante anzeigen
Laptop · Bash · nur lesen
oc get csv -A | grep -Ei 'servicemesh|sail|istio|maistra'
oc api-resources | grep -E 'Istio|ServiceMeshControlPlane|ServiceMeshMemberRoll'
oc get istio.sailoperator.io -A
oc get istiorevision.sailoperator.io -A
oc get servicemeshcontrolplane.maistra.io -A
oc get pod -n network-path-lab -o jsonpath='{range .items[*]}{.metadata.name}{": "}{.spec.containers[*].name}{"\n"}{end}'
FundBedeutung
Istio und IstioRevision aus sailoperator.ioService Mesh 3. Der Operator erzeugt aus der Istio-CR die Control Plane.
ServiceMeshControlPlane aus maistra.iofrühere Service-Mesh-Generation. Keine Mesh-3-Manifeste blind darüber anwenden.
Container istio-proxy im PodSidecar-Datenpfad ist für diesen Pod aktiv.
keine dieser Ressourcenkein Service Mesh installiert. OVN und Router funktionieren trotzdem vollständig.

Nicht nebenbei installieren: Service Mesh 3 benötigt Operator, Istio-CR, IstioCNI und eine bewusst begrenzte Discovery-Konfiguration. Mesh 2 und Mesh 3 dürfen nicht unkontrolliert im selben Cluster betrieben werden.

10 Entscheiden, ob ein Mesh nötig ist

Anforderungkleinste passende Lösung
Nur interner Service-Aufruf und LastverteilungService und OVN. Kein Mesh.
Öffentliche HTTP- oder TLS-AdresseOpenShift Route und Router. Kein Mesh erforderlich.
Interne TLS-Zertifikate für wenige DiensteService-CA aus der Reconcile- und Service-CA-Anleitung.
Netzwerkzugriff zwischen Namespaces begrenzenNetworkPolicy aus der NetworkPolicy-Anleitung.
Identitätsbasiertes mTLS, Traffic-Splitting und gemeinsame Telemetrie für viele DiensteService Mesh prüfen.

Auf einer kleinen SNO kostet ein Sidecar pro Pod zusätzlichen RAM und CPU. Für die Bibliothek ist Service-CA plus NetworkPolicy meist die kleinere und verständlichere Lösung. Ein Mesh lohnt sich erst, wenn seine zentralen Regeln mehrere Anwendungen konsistent entlasten.

11 Fehler an der richtigen Schicht eingrenzen

  1. DNS: Löst destination.network-path-lab.svc auf?
  2. Service: Stimmen Selector, Port und targetPort?
  3. EndpointSlice: Gibt es eine bereite Pod-IP?
  4. NetworkPolicy: Ist Quell- oder Zielverkehr erlaubt?
  5. OVN: Sind Netzwerk-Operator und Node-Pod gesund? Was zeigt ovnkube-trace?
  6. Route: Hat der Router die Route in die generierte HAProxy-Konfiguration übernommen?
  7. Mesh: Ist ein Sidecar injiziert und akzeptieren mTLS- sowie AuthorizationPolicy-Regeln den Request?

Die Grundlagen für Service, Route und Readiness stehen in der Service-, Route- und Probes-Anleitung. Policy-Fehler werden in der NetworkPolicy-Anleitung praktisch isoliert.

12 Lab vollständig aufräumen

Laptop · löscht nur das Lab-Projekt
oc delete project network-path-lab

Falls du ovnkube-trace kopiert hast, entferne zusätzlich die lokale Binärdatei. Das Service Mesh und die OpenShift-Systemkomponenten wurden durch dieses Lab nicht verändert.