Einführung in User-Defined Networks

Red Hat OpenShift Networking

Einführung in User-Defined Networks

Im herkömmlichen Red Hat OpenShift Cluster wird mit dem OVN-Kubernetes allen Pods eine IP-Adresse eines einzigen geteilten Overlay Netzwerk zugewiesen. Typischerweise 10.128.0.0/14, oder ähnlich. Dieses Netzwerk spannt sich über den gesamten Cluster. Es besteht aus einem zentralisierten logischen Router und einem Set von miteinander verbundenen, pro Knoten, logischen Switches. Somit sind alle Pods Bestandteil des gleichen Layer 3 Netzwerk Segments.

Das bringt einige einschneidende Limitationen mit sich:

Keine Layer 3 Tenant Isolation

Pods in verschiedenen Namespaces können direkt miteinander kommunizieren, sofern keine Network Policy es blockiert.

Keine überschneidende IP Subnetze

Unterschiedliche Tenants können nicht die gleichen privaten IP Subnetze verwenden, da IP-Adressen Cluster-weit einmalig sein müssen.

Das Konzept wendet auf alle Workloads eine einheitliche Topologie an

Die Pods haben somit die gleiche Charakteristik wie z.B. MTU, Enkapsulierung, Routerverhalten etc. Das kann mit Anforderungen von VMs, legacy Applikationen etc im Konflikt stehen.

Pod IP Adressen sind nicht persistent

Die Live-Migration von virtuellen Maschinen stellt eine Herausforderung dar, da die Pod-IP-Adresse an das lokale Subnetz des Knotens gebunden ist.

Das Design limitiert die multi-Netzwerk Flexibilität

Bis jetzt mussten Betreiber den Multi-Netzwerk Support manuell über zusätzliche Network Attachment Definitions (NADs) erstellen.

Diese Einschränkungen stellen eine Herausforderung für Multi-Tenant Umgebungen dar, vor allem für Organisationen die eine strikte Isolation oder “IP-Flexibilität” benötigen.

User Defined Networks

User Defined Networks (UDN) ermöglichen Administratoren und Entwicklern die Erstellung eigener, isolierter Layer 3 Netzwerke im selben Cluster. In UDNs ist jedes Netzwerk Segment eine unabhängige logische Einheit.

Obwohl das OVN-Kubernetes standard Netzwerk die logische Isolation durch NetworkPolicies aufbaut, bietet das UDN eine strikte, echte Isolation auf dem OVN Routing Level.

Jedes UDN erhält seine eigenen dedizierten Konstrukte:

  • Logical Switches
  • Logical Routers
  • IP Address CIDR
  • Broadcast Domäne

Dieses Design bietet eine strikte Layer-3-Isolierung. Der Datenverkehr wird auf Routing-Ebene physisch segmentiert, wodurch sichergestellt ist, dass Datenverkehr aus einem UDN ein anderes UDN nicht erreichen kann. Eine UDN-übergreifende Kommunikation ist standardmässig unmöglich.

Kompatibilität mit bestehenden Features

UDNs ersetzen das OVN-Kubernetes weder noch beeinträchtigen sie es. Sie erweitern es! Um ein UDN einzuführen muss keiner der bestehenden Workloads angepasst werden. Kernfunktionen von Service Discovery bis Policy Enforcement verhalten sich identisch mit dem standard OVN-Kubernetes Netzwerk.

Folgende OpenShift Kern Netzwerk Features bleiben bei UDNs unverändert:

  • Kubernetes Services funktionieren native innerhalb von UDNs

    • Der ClusterIP Service Typ stellt ein internes Load Balancing für Pods im gleichen UDN zu Verfügung. Weil das UDN ein isoliertes Layer 3 Segments ist, ist der ClusterIP Service nicht von einem anderen UDN erreichbar, auch nicht vom Default OVN-Kubernetes Netzwerk.
    • Der NodePort sowie der LoadBalancer Service ermöglichen externen Zugriff auf UDN gestützte Anwendungen.
  • Jedes UDN setzt Netzwerkrichtlinien unabhängig durch, um eine Mikrosegmentierung zu steuern.

    • Obwohl UDNs NetworkPolicy unterstützen, können sie den Datenverkehr zwischen UDNs nicht überbrücken. Weil jedes UDN eine eigene Layer-3-Domäne ist, braucht es für die Kommunikation zwischen UDNs einen Layer 3 Router oder einen geteilten Gateway - als wären die Netzwerke auf zwei verschieden Clustern.
  • Egress Kontrollmechanismen verhalten sich ähnlich zum Default OVN-Kubernetes Netzwerk, aber benötigen UDN spezifisches Routing

    • Standard Features, wie EgressIP und EgressFirewall, bleiben erhalten. Aber auch diese benötigen den unabhängigen UDN routing Stack.
    • UDN unterstützen das Border Gateway Protokoll und können somit effizienter mit externen Netzwerken kommunizieren.

UDNs stellen mehrere isolierte Netzwerke zur Verfügung anstelle des default OVN-Kubernetes Netzwerkes. Jedoch sind nicht ganz alle Features unterstützt wie z.B. OpenShift routes und multicast Datenverkehr. Ein Pod in einem UDN ist isoliert von standard Netzwerk Services. Das hat Einfluss auf den Zugriff zu der Image Registry und source-to-image Builds.
Eine komplette List mit unterstützen Features und bekannten Limitationen findet man hier: UDN and NAD Support Matrix and Limitations of a User-defined Network

Praxisnahe Anwendungsfälle

Die folgenden Szenarien verdeutlichen, wie UDNs gängige Netzwerk-Herausforderungen lösen:

Mandantentrennung:

Ein Finanzdienstleistungsunternehmen betreibt Workloads für mehrere Kunden im selben OpenShift-Cluster. Das Unternehmen weist jedem Kunden ein separates UDN zu, wodurch eine Layer-3-Mandantentrennung erreicht wird. Der Datenverkehr von den Pods eines Kunden kann die Pods eines anderen Kunden nicht erreichen – selbst wenn Netzwerkrichtlinien Fehlkonfigurationen aufweisen.

Namensraumübergreifende Konnektivität:

Ein Entwicklerteam stellt Mikrodienste wie Frontend, Backend und Datenbank in separaten Namespaces bereit. Alle Namespaces verbinden sich mit demselben clusterweiten UDN. Dies ermöglicht eine namensraumübergreifende Konnektivität innerhalb der Gruppe und wahrt gleichzeitig die Isolierung gegenüber anderen Namespaces im Cluster.

Überlappende IP-Adressbereiche:

Zwei unabhängige Teams benötigen aufgrund fest codierter Konfigurationen in ihren Anwendungen dasselbe IP-Subnetz. Die Plattform weist jedem Team ein eigenes UDN zu, sodass beide Teams denselben CIDR-Bereich konfliktfrei wiederverwenden können.

Persistente IP-Adressen für virtuelle Maschinen:

Ein Telekommunikationsanbieter betreibt virtuelle Netzwerkfunktionen (VNFs) als virtuelle Maschinen auf OpenShift Virtualization. Der Anbieter erstellt ein Layer-2-UDN für die VMs, das unterschiedliche Topologien unterstützt und es den VMs ermöglicht, ihre IP-Adresse bei einer Live-Migration zwischen Knoten beizubehalten. Die IP-Adresse ist an das UDN gebunden und nicht an das lokale Subnetz des Knotens.

Bereitstellen von Workloads in UDNs

Das UDN Feature verwendet eine spezifische CRD. Admins definieren ihre Netzwerk Konfigurationen in der UserDefinedNetwork Ressource. Dieses CRD spezifiziert die Netzwerk Rolle, Topologie und die Subnetze. Die UserDefinedNetwork Ressource ist Namespace scoped im Gegensatz zur ClusterUserDefinedNetwork welche auf mehrere Namespaces angewendet werden kann.

Netzwerk Rollen für UDNs

Wenn man in UDN definiert muss die Netzwerk Rolle für Pods definiert werden. Ein UDN kann entweder als primäres (primary) oder sekundäres (secondary) Netzwerk konfiguriert werden. Jedes integriert sich anders in das Pod-Netzwerk und hat unterschiedlichen Einfluss auf die gesamte Netzwerk Architektur.

Primäres Netzwerk

Primäre Netzwerke kümmern sich um standard Datenverkehr für Pods. Wenn ein Pod ein primäres UDN verwendet, verbindet sich das primäre NIC (eth0), mit diesen Netzwerken. Der Default Gateway für den Pod zeigt auf das UDN und nicht auf das default Cluster Netzwerk (OVN-Kubernetes).

Sekundäres Netzwerk

Sekundäre Netzwerke stellen zusätzliche NICs den Pods zur Verfügung. Diese Konfiguration ist hilfreich, wenn ein Pod auf spezifische Netzwerke zugreifen muss und zudem auch auf default Cluster Services auf dem primären NICs zugreifen muss. Sekundäre UDNs werden typischerweise für spezialisierte Workloads, die auf Zugriff auf spezifische Netzwerk Segmente, wie z.B. Datenbanken, haben müssen.

Netzwerk Topologien für UDNs

Administratoren können primäre Netzwerke als Layer 2 oder als Layer 3 Typen konfigurieren. Somit können verschiedene Netzwerk-Topologien und Anwendungsfälle angewendet werden. Sei es ein simples flaches Netzwerk oder komplexe segmentierte Netzwerke. Bei Layer 2 UDN sind alle Pods im selben flachen Netzwerk und auf derselben Broadcast Domäne. Hingegen können bei Layer 3 UDNs isolierte routing Domänen for jedes Netzwerk eingerichtet werden. Zum Beispiel können überlappende IP Adress Räume und erweiterte Security mittels Routing-Policies verwendet werden.

Implementationsarchitektur

UDNs verwendet das standard OVN-Kubernetes von OpenShift. Wenn man einen UserDefinedNetwork Customer Resource (CR) erstellt, übersetzt OVN-Kubernetes in eine Network Attachment Definition (NAD). Somit entfällt das händische erstellen eines NADs.

Der OVN-Kubernetes Kontroller überwacht die UDN CRs und den dazugehörigen Namespace. Sobald die CR erkannt wurde, konfiguriert der Kontroller die logischen Switches und Router im darunter liegenden OVN.

Primäre Layer 3 UDN Architektur

Das folgende Diagramm zeigt die Architektur eines primären UDNs. In dieser Konfiguration verwenden die Pods zwei unterschiedliche NICs um den Tenant Datenverkehr vom default Netzwerk des Clusters zu isolieren.

  • eth0 default cluster network interface (schwarz): Verbindung zum Standard‑OpenShift/Kubernetes‑Netzwerk. Hier läuft der Infrastruktur Datenverkehr wie, Readyness Probes, metrics, etc.

  • udn0 network interface (blau): Verbindung zum isolierten UDN.

  • Kennzeichnung des Primärnetzwerks (wichtig): Die Architektur kennzeichnet das UDN-Netzwerk als Primärnetzwerk. Infolgedessen nutzt der Pod die udn0-Schnittstelle für den gesamten Anwendungs-Datenverkehr, und die Schnittstelle wird zum Default Gateway für die externe sowie die Pod-übergreifende Kommunikation innerhalb dieses UDNs.

Topologie und Isolation

Wir haben gesehen, dass OVN-Kubernetes einen parallelen Netzwerk Stack hochzieht und somit eine Isolierung erzwingt. UDN teilen weder Routing Tabellen noch Switch Domänen mit dem Default Cluster Network.

  • Logische Switches: Datenverkehr vom udn0 interface fliesst in einen dezidierten UDN Knoten-Switch aus dem 10.150.0.0/16 Netz, während eth0 Datenverkehr über den Default Cluster-Knoten Switch fliesst.

  • Cluster Routers: Jeder Netzwerk Stack hat seinen eigenen ovn-cluster-router logischen Router. Diese Unabhängigkeit ermöglicht es dem UDN eigene Routing Regeln zu haben wie auch überlappende IP Adress-Bereiche zu haben.

Traffic-Flow-Analyse

East-west pod-zu-pod Datenverkehr

Wenn der Pod1 mit dem Pod2 spricht und UDN verwendet, fliessen die Datenpakete den folgenden Pfad:

  1. Paket verlässt den Pod1 durch udn0.
  2. Das Paket reist weiter über den UDN Knoten Switch zum OVN Cluster Router.
  3. Nun wandert es weiter über den zentralen Transit Switch, den Geneve Tunnel.
  4. Der Datenverkehr wird auf den logischen Stack des Zielknotens umgeleitet, um den Ziel-Workload zu erreichen.

North-South egress Datenverkehr

Folgende Schritte zeigen auf wie UDN externe Verbindungen herstellt

  1. Paket verlässt den Pod1 durch das udn0 und erreicht den Gateway Router via den OVN Cluster-Router. Der Join-Switch verbindet die zwei Router
  2. Der Gateway Router wendet das UDN-spezifische Source Natting an (SNAT) Regeln an. Die IP-Adresse des Pods wird in eine Adresse des Masquerade Subnets übersetzt.
  3. Der Kernel des Nodes wendet das SNAT auf die Konten-IP an bevor der eigentliche Datenverkehr startet.
    1. Der Verkehr kommt auf dem br-ex und verlässt den Knoten via dem physischen Interface ens3.

Bereitstellung von Workloads mithilfe von UDNs

Hierzu müssen Namespaces und dann schliesslich die Netzwerkkonfigurationen erstellen.

Namespace creation

Wichtig ist hier das der Namespace die k8s.ovn.org/primary-user-defined-network enthält. Diese Label kann nicht auf Existierende Namespaces angewendet werden. Zudem muss man cluster-adminsein oder die view und edit Rolle um einen Namespace mit dieser Annotation zu versehen.

apiVersion: v1
kind: Namespace
metadata:
  name: mplf-udn
  labels:
    k8s.ovn.org/primary-user-defined-network: ""

Erstellen eines UDNs

Hierzu müssen wir eine UserDefinedNetwork Customer Ressource (CR) definieren. Auch dazu müssen wir entweder Cluster Admin oder die read und edit RBAC rule haben.

apiVersion: k8s.ovn.org/v1
kind: UserDefinedNetwork
metadata:
  name: mplf-l3-network
  namespace: mplf-udn
spec:
  topology: Layer3      # Setzt die Topologie auf Layer 3.
  layer3:
    role: Primary       # Kennzeichnet dieses Netzwerk als Primärnetzwerk für Pods im Namespace.
    subnets:
    - cidr: 10.0.1.0/24 # Definiert den IP-Adressbereich für das benutzerdefinierte Netzwerk. Wird cluster weit angewendet
      hostSubnet: 27    # Definiert das Subnetz-Präfix pro Knoten. Jeder Konten erhält hier eine /27 (30 IPs). Max 8 nodes

Zum Kontrollieren ob die UDNs auch erstellt wurden verwenden wir folgende Kommandos:

$ oc get userdefinednetworks.k8s.ovn.org
NAME              AGE
mplf-l3-network   20m

Gleichermassen erstellt folgendes Beispiel ein primäres Layer 2 UDN. Achtung, das Erstellen von zwei Primären Ressourcen schlägt fehl und ist nicht erlaubt.

apiVersion: k8s.ovn.org/v1
kind: UserDefinedNetwork
metadata:
  name: mplf-l2-network
  namespace: mplf-udn
spec:
  topology: Layer2
  layer2:
    role: Primary
    subnets:
      - "10.200.0.0/16"
    ipam:
      lifecycle: Persistent # Der einzige zulässige Wert ist Persistent. Verwende diese Einstellung für virtuelle Workloads, um sicherzustellen, dass diese über Neustarts und Migrationen hinweg über permanente IP-Adressen verfügen.

Multiple Namespaces with Cluster User-defined Networks (CUDN)

Using CUDN für Tenant Isolation

Anders als UDN, welches auf einen Namespace beschränkt ist, ist CUDN eine Cluster-Scoped CR für UDN. Ein CUDN kann mehrere Namespaces in das selbe Netzwerk einbinden. Ein CUDN kann ein primäres oder sekundäres Netzwerk sein.

In einem primären CUDN, ist das Netzwerk das primäre Network Interface und ersetzt das Standard Netzwerk für alle Workloads der eingebunden Namespace. East-West Traffic verkehrt nahtlos über mehrere Namespaces, die im selben CUDN sind. Die Kommunikation findet über einen privaten logischen Switch statt oder über ein geroutetes Subnetz. Zudem wird dafür gesorgt, dass es kein direkter Verkehr zu anderen CUDNs gibt. Ein integrierter SDN Router verwaltet den North-South mittels einem Default Gateway innerhalb des CUDN. Dieser Gateway sorgt dafür, dass externe Netzwerke erreichbar sind, eingehender Verkehr sein Ziel erreicht ohne, dass die Daten den isolierten Tenant verlässt.

Obwohl ein CUDN eine nahtlose Kommunikation über mehrere Namespaces hinweg – wie etwa tenant1 und tenant2 – ermöglicht, schafft es gleichzeitig eine strikte Isolationsgrenze. Workloads innerhalb eines CUDNs können ohne explizite, manuelle Routing- oder Proxy-Konfiguration weder Workloads im Standard-Clusternetzwerk noch in anderen CUDNs erreichen oder Datenverkehr von diesen empfangen. So kann eine wirkliche Isolation zwischen verschiedenen Tenant-Umgebungen geschaffen werden.

Namespace Configuration

Um eine CUDN zu erstellen, müssen wir wie beim UDN einen Namespace erstellen, der auch die Annotation k8s.ovn.org/primary-user-defined-network setzen:

apiVersion: v1
kind: Namespace
metadata:
  name: tenant1
  labels:
    k8s.ovn.org/primary-user-defined-network: ""
    workload: citrix

Sobald diese Annotation gesetzt ist, wird den Workloads in diesem Namespace nicht mehr das Default Cluster Network zugewiesen, sondern das CUDN in dem Namespace. Fall kein CUDN existiert werden keine Workloads gestartet werden und in etwa diese Fehlermeldung ausgegeben.

addLogicalPort failed for my-namespace/my-pod: invalid primary network state for namespace "my-namespace": a valid primary user defined network or network attachment definition custom resource, and required namespace label "k8s.ovn.org/primary-user-defined-network" must both be present

Topologien und deren Workload Kompatibilität

Bevor wir ein CUDN erstellen, müssen wir uns entscheiden welche Topologie und welche Rolle für den Workload passen. Speziell für VM Workload sind die Vorgaben sehr strikt, z.B. braucht Live Migration eine Layer 2 Topologie.

Hier ein Überblick über die Topologien die OpenShift für VMs und Pods supported:

WorkloadTopologieRolleUnterstütztGründe / Details
PodLayer 2Primary & SecondaryJaPods arbeiten innerhalb eines flachen logischen Switches. Layer-2-Adjazenz ist nützlich für spezielle Anwendungen, die Broadcast- oder Multicast-Datenverkehr benötigen.
PodLayer 3Primary & SecondaryJaDiese Topologie nutzt Standard-Kubernetes-Routing. Pods sind ephemeral (flüchtig). Bei einem Node-Ausfall wird der Pod mit einer neuen IP-Adresse aus dem Subnetz des neuen Nodes neu angesetzt.
PodLocalnetSecondaryJa (CUDN)Bietet direkten Zugriff auf physische VLANs über Host-Bridges. Red Hat unterstützt dies nur als Sekundärnetzwerk, da Pods das primäre OVN-Kubernetes-Netzwerk für clusterweite Dienste (z. B. DNS, Service-IPs) benötigen.
VMLayer 2PrimaryJaEntscheidend für die Live-Migration. Ein einziger logischer Switch erstreckt sich über den gesamten Cluster. Die VM behält bei Knotenwechseln ihre IP- und MAC-Adresse bei, was Verbindungsabbrüche verhindert.
VMLayer 3Primary & SecondaryNeinBeeinträchtigt/unterbricht die Migration. Layer-3-UDNs weisen jedem Node ein eigenes Subnetz zu. Wandert eine VM auf einen anderen Host, wird ihre IP-Adresse für die Routing-Tabelle dieses Nodes ungültig.
VMLocalnetSecondaryJa (CUDN)Ermöglicht VMs die Anbindung an externen Speicher oder Produktions-VLANs. Red Hat beschränkt dies auf Sekundärnetzwerke, damit die VM eine stabile primäre OVN-Kubernetes-Schnittstelle behält.

Ein CUDN erstellen

Nun können wir ein CUDN mittels der CR ClusterUserDefinedNetwork auf Cluster Level erstellen.

apiVersion: k8s.ovn.org/v1
kind: ClusterUserDefinedNetwork
metadata:
  name: mkdir-cudn
spec:
  namespaceSelector:
  # Gibt Labels an, die OpenShift verwendet, um die Namespaces zu identifizieren, die dem Netzwerk beitreten.
  # Wenn mehr als ein Namespace das Label development besitzt, wird die Kommunikation zwischen den Workloads aktiviert.
    matchLabels:
      workload: citrix
  network:
    layer2:
      ipam:
        lifecycle: Persistent
      # Diese Einstellung steuert, ob IP-Adressen freigegeben werden, wenn eine Workload stoppt.
      # Für Pods ist diese Einstellung in der Regel optional, da Pods gewöhnlich ephemeral (flüchtig) sind.
      # Für VMs ist diese Einstellung für die Live-Migration zwingend erforderlich.
      # Sie stellt sicher, dass sich die IP-Adresse der VM während des Migrationsprozesses nicht ändert oder freigegeben wird, um unterbrochene Netzwerk-Sitzungen zu verhindern.
      role: Primary
      # Gibt an, ob das UDN primär oder sekundär ist.
      # Die Rolle Primary bedeutet, dass das UDN als Primärnetzwerk für Pods und VMs fungiert und der gesamte Standard-Datenverkehr über dieses Netzwerk läuft.
      # Sowohl Layer-2- als auch Layer-3-Topologien können entweder als primäre oder als sekundäre Netzwerksegmente fungieren.
      subnets:
      - 192.168.3.0/24
      # Gibt die Netzwerk-Subnetze im CIDR-Format an.
      # Definieren Sie ein Subnetz für IPv4 und optional eines für IPv6.
      # Wenn Sie das Subnetz weglassen, müssen Benutzer statische IP-Adressen für Workloads konfigurieren.
      # Dieses Feld ist optional, wenn das CUDN über die CLI erstellt wird.
    topology: Layer2
    # Gibt die Topologie des Netzwerks an.
    # Zulässige Werte sind Layer2 und Layer3.
    # Die Angabe des Topologietyps Layer2 erzeugt einen einzelnen logischen Switch, den sich alle Knoten teilen.
    # Während Pods von der Layer2-Topologie für eine flache, nicht-geroutete Konnektivität profitieren,
    # benötigen VMs die Layer2-Topologie zur Unterstützung der Live-Migration, da diese Topologie es der VM ermöglicht,
    # ihre MAC- und IP-Adresse beim Wechsel zwischen physischen Knoten beizubehalten.

Nun verwenden wir oc get clusteruserdefinednetwork um zu prüfen ob das Estellen funktionert hat.

$ oc get clusteruserdefinednetworks
NAME         AGE
mkdir-cudn   32d

Um nicht mit matchLabels zu verwenden können wir auch den matchExpressions selector verwenden. So können wir die spezifischen Namespaces explizit angeben:

...
spec:
  namespaceSelector:
    matchExpressions:
      - key: kubernetes.io/metadata.name
        operator: In
        values:
          - tenant1
          - tenant2
...