Überblick in einem Bild
Die Beteiligten lassen sich wie auf einer Baustelle ordnen: einer plant, einer übersetzt, einer führt aus.
| Ebene | Rolle | Wo |
|---|---|---|
| NetworkManager | Elektriker. Setzt die echte Konfiguration um und speichert sie als Keyfile | Host, systemd-Dienst |
| nmstate | Bauplan-Übersetzer. Deklaratives YAML → NetworkManager-Profile | Host, CLI nmstatectl und Bibliothek, in RHCOS enthalten |
| Kubernetes NMState Operator | Bauleiter. Verteilt Baupläne als Kubernetes-Objekte auf alle Nodes | Cluster, Namespace openshift-nmstate |
Vom Cluster-Objekt bis zum Kernel-Device
Die drei Ebenen im Detail
Wer was tut, wo es liegt und mit welchem Befehl man nachsieht.
NetworkManager · der Ausführende
Der Dienst, der auf RHCOS die Netzwerkschnittstellen tatsächlich konfiguriert. Zwei Begriffe muss man auseinanderhalten:
- Device: die reale Schnittstelle im Kernel (
eno1,bond0,br-ex). - Connection/Profil: eine gespeicherte Konfiguration, die auf ein Device passt. Profile liegen als Keyfiles unter
/etc/NetworkManager/system-connections/(persistent) oder/run/NetworkManager/system-connections/(flüchtig, nur bis zum Reboot).
Ein Profil wird aktiv, wenn es zu einem Device passt – standardmäßig über den Interface-Namen (connection.interface-name), optional über die MAC-Adresse (ethernet.mac-address).
nmcli -f NAME,UUID,TYPE,DEVICE,AUTOCONNECT,FILENAME con show
nmcli con show <profil> | grep -E 'interface-name|mac-address|ipv4\.'
ls -la /etc/NetworkManager/system-connections/
nmstate · der deklarative Übersetzer
Eine deklarative API für Linux-Netzwerk. Statt einzelner nmcli-Befehle beschreibt man den Zielzustand in YAML; nmstate berechnet die Differenz zum Ist-Zustand und setzt sie über NetworkManager um.
- Eigenschaften, die im YAML nicht vorkommen, bleiben erhalten – Merge statt Überschreiben.
- Änderungen werden transaktional angewendet: Scheitert die Überprüfung nach dem Anwenden, wird zurückgerollt.
nmstatectl show # Ist-Zustand als YAML
nmstatectl show eno1 # nur eine Schnittstelle
nmstatectl apply ziel.yml # Zielzustand anwenden
Ein nmstate-Dokument hat im Kern vier Blöcke:
interfaces: # Ethernet, Bond, VLAN, Bridge, OVS-Bridge …
routes: # statische Routen
route-rules: # Policy-Based Routing
dns-resolver: # DNS-Server und Suchdomänen
Kubernetes NMState Operator · der Verteiler
Macht nmstate über die Kubernetes-API nutzbar. Nach der Installation läuft ein DaemonSet (in der Doku „NMState State Controller“ bzw. Handler) auf allen Nodes. Jeder Handler
- wendet Policies (NNCP) auf seinem Node über nmstate an,
- meldet regelmäßig den Ist-Zustand des Node-Netzwerks an den API-Server (NNS),
- schreibt das Ergebnis jeder Anwendung zurück (NNCE).
Die Objekte des Operators
Vier CRDs, zwei Richtungen: Der Admin schreibt nur eine davon, die anderen melden zurück.
| Objekt | Kurz | Richtung | Inhalt |
|---|---|---|---|
NMState | – | Admin → Operator | Singleton, muss nmstate heißen; aktiviert Handler, Webhook, Console-Plugin |
NodeNetworkState | nns | Node → Cluster | Ist-Zustand je Node (Interfaces, Routen, DNS), regelmäßig aktualisiert |
NodeNetworkConfigurationPolicy | nncp | Admin → Nodes | gewünschter Zustand, optional per nodeSelector eingeschränkt |
NodeNetworkConfigurationEnactment | nnce | Node → Cluster | Ergebnis je Node + Policy, read-only, Name <node>.<policy>, bei Fehler mit Traceback |
Eine Policy, viele Nodes
Installation per CLI
apiVersion: v1
kind: Namespace
metadata:
name: openshift-nmstate
---
apiVersion: operators.coreos.com/v1
kind: OperatorGroup
metadata:
name: openshift-nmstate
namespace: openshift-nmstate
spec:
targetNamespaces:
- openshift-nmstate
---
apiVersion: operators.coreos.com/v1alpha1
kind: Subscription
metadata:
name: kubernetes-nmstate-operator
namespace: openshift-nmstate
spec:
channel: stable
installPlanApproval: Automatic
name: kubernetes-nmstate-operator
source: redhat-operators
sourceNamespace: openshift-marketplace
Danach die Instanz anlegen – ohne sie passiert nichts:
apiVersion: nmstate.io/v1
kind: NMState
metadata:
name: nmstate # Name ist fest vorgegeben
oc wait --for=condition=Available nmstate/nmstate --timeout=600s
oc get pod -n openshift-nmstate
oc get -A nncp -o yaml > nncp-backup.yamlLebenszyklus einer Policy
Vom oc apply bis zum Enactment – inklusive des automatischen Rollbacks, das vor dem Aussperren schützt.
Der Ablauf
- Admin wendet die NNCP an
oc apply– der API-Server verteilt sie an die Handler. - Handler nehmen die Policy entgegen
maxUnavailablebegrenzt, wie viele Nodes gleichzeitig drankommen. - nmstate wendet den desiredState anLegt NetworkManager-Profile an oder ändert sie.
- Probes prüfen die ErreichbarkeitGateway, DNS, API-Server.
- Erfolg: NNCE wird
AvailableDie Konfiguration bleibt stehen. - Fehler: automatischer Rollbacknmstate setzt zurück, das NNCE meldet
Failingmit Traceback.
Was man daraus ableiten muss
- Parallelität: Standardmäßig wird eine Policy auf 50 % der passenden Nodes gleichzeitig angewendet.
maxUnavailableakzeptiert eine Zahl (3) oder einen Prozentwert ("10%"). - Rollback schützt nur bedingt: Scheitert die Konfiguration oder verliert der Node die Verbindung, rollt nmstate zurück – aber nur, solange der Handler läuft.
- Reihenfolge: Mehrere Policies werden nach alphanumerischem Namen angewendet. Nach einem Node-Reboot gibt es aber keine garantierte Reihenfolge.
maxUnavailable gilt pro Policy, nicht cluster-weit.DNS-Probe in disconnected Umgebungen
Die Health-Probe löst standardmäßig einen öffentlichen Namen auf (Root-Server). Ohne Internet schlägt sie fehl. Abhilfe über die NMState-CR:
apiVersion: nmstate.io/v1
kind: NMState
metadata:
name: nmstate
spec:
probeConfiguration:
dns:
host: intern.example.com
Löschen ist nicht Zurücksetzen
oc delete nncp entfernt nur das Objekt – die Konfiguration auf dem Node bleibt. Zum Entfernen erst state: absent setzen und anwenden, dann löschen.
Wird eine Bridge oder ein Bond entfernt, gehen die darunterliegenden NICs auf down. Deshalb die NIC in derselben Policy mit state: up und IP versehen:
desiredState:
interfaces:
- name: br1
type: linux-bridge
state: absent
- name: eth1
type: ethernet
state: up
ipv4:
enabled: true
dhcp: true
Status prüfen
oc get nncp
oc get nnce
oc get nnce <node>.<policy> -o yaml # Fehlerdetails / Traceback
oc get nns <node> -o yaml # tatsächlicher Zustand
Drei Wege, wie Netzwerk-Konfiguration auf einen Node kommt
Das ist der Kern für das Verständnis: Nicht jede nmstate-Konfiguration kommt vom Operator. Alle drei Wege enden im selben Keyfile.
Drei Quellen, ein Ziel
| Weg | Wann aktiv | Braucht kubelet/API? | Typischer Inhalt |
|---|---|---|---|
| Installationszeit | einmalig beim Install | nein | statische IPs, Bonds, VLANs der Primär-NIC |
| Boot-Zeit per MachineConfig | bei jedem Boot | nein | angepasstes br-ex, Grundkonnektivität |
| Laufzeit per NNCP | sobald Handler läuft | ja | Sekundär-NICs, Bridges für VMs, VLANs, DNS, Routen |
Installationszeit: Agent-based Installer
Im agent-config.yaml wird pro Host die Netzwerk-Konfiguration im nmstate-Format hinterlegt, plus eine Zuordnung Interface-Name ↔ MAC:
hosts:
- hostname: master-0
interfaces:
- name: eno1
macAddress: 00:ef:44:21:e6:a5
networkConfig:
interfaces:
- name: eno1
type: ethernet
state: up
mac-address: 00:ef:44:21:e6:a5
ipv4:
enabled: true
dhcp: false
address:
- ip: 192.168.111.80
prefix-length: 23
dns-resolver:
config:
server:
- 192.168.111.1
routes:
config:
- destination: 0.0.0.0/0
next-hop-address: 192.168.111.2
next-hop-interface: eno1
table-id: 254
Aus networkConfig entstehen NetworkManager-Keyfiles, die auf dem installierten Node weiterleben.
interfaces[] und networkConfig nicht überein, kann das bei Bonds, VLANs und Bridges unbemerkt schiefgehen.Boot-Zeit: MachineConfig + nmstate.service
Legt eine MachineConfig eine Datei unter /etc/nmstate/ ab, wendet nmstate.service beim Boot alle *.yml dort an. Laut Manpage wird eine verarbeitete Datei standardmäßig in *.applied umbenannt, damit sie nicht erneut angewendet wird.
Mit keep_state_file_after_apply = true in /etc/nmstate/nmstate.conf bleibt das Original erhalten und es wird nur eine .applied-Kopie angelegt. Was auf einem konkreten Node gilt, zeigt ls -la /etc/nmstate/.
Für den Spezialfall br-ex gibt es das Verzeichnis /etc/nmstate/openshift/, das von nmstate-configuration.service ausgewertet wird (Abschnitt 5).
Boot-Zeit: configure-ovs.sh
Der Standardweg für br-ex bei OVN-Kubernetes: Das Skript configure-ovs.sh (Unit ovs-configuration.service) baut beim Boot die OVS-Bridge br-ex, hängt die Primär-NIC hinein und zieht die IP-Konfiguration auf die Bridge um. Die entstehenden Profile heißen typischerweise ovs-if-br-ex, ovs-if-phys0, ovs-port-*.
journalctl -b -u ovs-configuration --no-pager | tail -50
nmcli con show | grep -E 'ovs-|br-ex'
Sonderfall br-ex
br-ex ist die externe OVS-Bridge von OVN-Kubernetes. Über sie läuft der Node-Traffic nach außen; die Node-IP liegt auf ihr, nicht auf der physischen NIC.
Die IP zieht um
Zwei Wege, br-ex zu bauen
configure-ovs.sh (Standard) | Angepasstes br-ex per NMState | |
|---|---|---|
| Wer baut | Skript beim Boot | nmstate-configuration.service + nmstate.service |
| Konfigurationsquelle | leitet aus vorhandener NIC-Konfig ab | MachineConfig legt /etc/nmstate/openshift/cluster.yml (alle Nodes) oder <kurzer-hostname>.yml (je Node) ab |
| Wann festgelegt | automatisch | bei der Installation als Manifest, nachträglich per Migration |
| Deklarativ | nein | ja |
| Rückweg | – | Migration ist laut Red Hat nicht umkehrbar |
Beispiel: nmstate-Datei für ein angepasstes br-ex
interfaces:
- name: enp2s0
type: ethernet
state: up
ipv4:
enabled: false
ipv6:
enabled: false
- name: br-ex
type: ovs-bridge
state: up
bridge:
options:
mcast-snooping-enable: true
port:
- name: enp2s0
- name: br-ex
- name: br-ex
type: ovs-interface
state: up
copy-mac-from: enp2s0
ipv4:
enabled: true
dhcp: true
ipv6:
enabled: false
Die Datei wird base64-kodiert in eine MachineConfig eingebettet:
apiVersion: machineconfiguration.openshift.io/v1
kind: MachineConfig
metadata:
labels:
machineconfiguration.openshift.io/role: worker
name: 10-br-ex-worker
spec:
config:
ignition:
version: 3.2.0
storage:
files:
- contents:
source: data:text/plain;charset=utf-8;base64,<base64>
mode: 0644
overwrite: true
path: /etc/nmstate/openshift/cluster.yml
br-ex kann auf den meisten On-Prem-Netzen zum vollständigen Netzwerkverlust des Nodes führen, der nur manuell behebbar ist. Ausnahme: Auf Bare Metal ist das Ändern von br-ex per NNCP unterstützt, wenn br-ex als angepasste Bridge per NMState definiert wurde.Reservierte Interface-Namen
Diese Namen dürfen in nmstate-Konfigurationen nicht verwendet werden:
br-ext br-int br-local br-nexthop br0
ext-vxlan ext genev_sys_* int k8s-*
ovn-k8s-* patch-br-* tun0 vxlan_sys_*
Woran man erkennt, welcher Weg aktiv ist
ls -la /etc/nmstate/openshift/ 2>/dev/null # Dateien da → NMState-br-ex
systemctl status nmstate-configuration --no-pager
journalctl -b -u ovs-configuration --no-pager | tail -20
oc get mc | grep -i br-ex
Interface-Identität: Name oder MAC
Standardmäßig identifizieren nmstate und NetworkManager eine Schnittstelle über ihren Namen. Namen sind aber nicht stabil – sie hängen vom systemd-Naming-Scheme, von Kernel-Argumenten, von udev-Regeln und der Hardware-Topologie ab.
Was bei einem OS-Update passiert
Identifikation per MAC
Funktioniert in NNCPs genauso wie in /etc/nmstate/*.yml:
interfaces:
- name: eth1 # darf bleiben, ist dann nur noch Etikett
profile-name: uplink0 # Name des NetworkManager-Profils
type: ethernet
state: up
identifier: mac-address
mac-address: 8A:8C:92:1A:F6:98
ipv4:
enabled: true
dhcp: false
address:
- ip: 192.0.2.21
prefix-length: 24
identifierkenntname(Standard) undmac-address.- Bei
identifier: mac-addressist die MAC der primäre Anker; eine falsche MAC quittiert nmstate mit einem Invalid-Argument-Fehler. - Direkt in NetworkManager entspricht das einem Profil ohne
connection.interface-name, dafür mitethernet.mac-address.
Praxisbeispiele für NNCPs
Drei Fälle zum Nachbauen, dazu die Hinweise aus der Doku, die man sonst erst nach dem ersten Fehlschlag findet.
Bond (active-backup) mit VLAN in einer Policy
OpenShift unterstützt die Bond-Modi active-backup, balance-xor und 802.3ad. Die beiden letzten brauchen passende Switch-Konfiguration. Auf Bare Metal ist für VLANs nur das Namensschema <interface>.<vlan-id> unterstützt.
apiVersion: nmstate.io/v1
kind: NodeNetworkConfigurationPolicy
metadata:
name: bond10-vlan103
spec:
nodeSelector:
node-role.kubernetes.io/worker: ""
maxUnavailable: 1
desiredState:
interfaces:
- name: bond10
type: bond
state: up
link-aggregation:
mode: active-backup
options:
miimon: '140'
port:
- eth2
- eth3
- name: bond10.103
type: vlan
state: up
vlan:
base-iface: bond10
id: 103
ipv4:
enabled: true
dhcp: true
Linux-Bridge für VMs (OpenShift Virtualization)
apiVersion: nmstate.io/v1
kind: NodeNetworkConfigurationPolicy
metadata:
name: br1-eth1
spec:
nodeSelector:
node-role.kubernetes.io/worker: ""
desiredState:
interfaces:
- name: br1
type: linux-bridge
state: up
ipv4:
enabled: false
bridge:
options:
stp:
enabled: false
port:
- name: eth1
Schnittstelle ohne IP
Werden ipv4.enabled und ipv6.enabled auf false gesetzt, muss state: up bleiben. Mit state: down holt sich die Schnittstelle durch automatisches DHCP eine Adresse.
Weitere Hinweise aus der Doku
- Gleiche Standardkonfiguration auf mehreren Interfaces kann dazu führen, dass ein NetworkManager-Profil auf mehreren Devices gleichzeitig aktiv wird (identische UUID). Jedes Interface braucht eine eigene, vom Standard abweichende Konfiguration.
- VRF: Routing-Tabellen-IDs unter 1000 wählen; höhere sind für OpenShift reserviert.
- Dynamisches Matching mit
capture(etwa IP der NIC auf eine Bridge übertragen) ist Technology Preview. - Routen ändern: alte Route mit
state: absent, neue mitstate: presentin derselben Policy angeben. - DNS auf Interface-Ebene kann Namensauflösung stören, sobald das Interface in eine Bridge oder einen Bond wandert. Standardmäßig speichert nmstate DNS global.
Diagnose, Fallstricke, Checkliste
Drei typische Symptome, die zugehörigen Befehle und die Fehler, die sich immer wiederholen.
Wo schaue ich nach?
| Symptom | Zuerst | Dann |
|---|---|---|
NNCP hängt oder Failing |
oc get nnceoc get nnce <node>.<policy> -o yaml |
Traceback lesen – unbekannter Port? falscher Name? Dann oc get nns <node> -o yaml mit der Policy vergleichen. |
| Node ohne IP nach Reboot | Über Konsole/BMC: ip -br link, nmcli con show |
Passen die Profile noch zum Device (Name geändert)? ls /etc/nmstate/ /etc/nmstate/openshift/, dann journalctl -b -u NetworkManager -u nmstate -u nmstate-configuration |
br-ex fehlt oder ist falsch |
journalctl -b -u ovs-configuration |
Liegen Dateien in /etc/nmstate/openshift/? Daran erkennt man, welcher der beiden Wege aktiv ist. |
Befehle auf einen Blick
| Ebene | Befehl | Zeigt |
|---|---|---|
| Cluster | oc get nncp | Policies und Gesamtstatus |
| Cluster | oc get nnce | Ergebnis je Node |
| Cluster | oc get nns <node> -o yaml | Ist-Zustand, lastSuccessfulUpdateTime |
| Cluster | oc get mc | grep -iE 'nmstate|br-ex' | MachineConfigs mit Netzwerkbezug |
| Node | nmcli -f NAME,DEVICE,TYPE,FILENAME con show | Profile und ihre Bindung |
| Node | nmstatectl show | Ist-Zustand im nmstate-Format |
| Node | ls -la /etc/nmstate/ /etc/nmstate/openshift/ | Boot-Zeit-Konfiguration |
| Node | journalctl -b -u nmstate -u nmstate-configuration -u ovs-configuration | Boot-Zeit-Logs |
| Node | udevadm info /sys/class/net/<nic> | grep ID_NET_NAME | warum ein Interface so heißt |
Typische Fallstricke
| Fallstrick | Warum | Gegenmittel |
|---|---|---|
| NIC-Namen ändern sich nach OS-Update | Profile per Name gebunden | identifier: mac-address bzw. ethernet.mac-address; stabile Namen per .link-Datei |
| Policy löschen setzt nichts zurück | NNCP ist nur Wunsch, Keyfile bleibt | erst state: absent, dann löschen |
| Abhängige Policies nach Reboot kaputt | Reihenfolge nach Reboot nicht garantiert | Zusammengehöriges in eine Policy |
| Bridge entfernt, NIC tot | Ports gehen auf down | NIC in derselben Policy mit IP hochziehen |
| NNCP auf Primär-NIC oder br-ex | vollständiger Netzwerkverlust möglich | Primärnetz per Install oder MachineConfig, nicht per NNCP |
| Probes scheitern disconnected | DNS-Probe will ins Internet | probeConfiguration.dns.host setzen |
| CNI-Wechsel weg von OVN-Kubernetes | br-ex und seine Profile hängen an OVN; NMState-br-ex bleibt als Datei bestehen | vorher klären, wie br-ex gebaut wurde, und Primärnetz-Profile für die Zeit danach bereitstellen |
Namen in agent-config.yaml inkonsistent | Zuordnung Profil ↔ Device scheitert | interfaces[].name = Namen in networkConfig |
Checkliste
- Weiß ich, auf welchem Weg die Primärnetz-Konfiguration auf den Node kam – Install, MachineConfig, configure-ovs?
- Sind Primär-NICs per MAC statt per Name gebunden?
- Liegen keine NNCPs auf Primär-NIC oder
br-ex(außer angepasstem br-ex auf Bare Metal)? - Stehen abhängige Interfaces in einer Policy?
- Ist
maxUnavailableso gesetzt, dass ein Fehler nicht den halben Cluster trifft? - Ist in disconnected Umgebungen die DNS-Probe angepasst?
- Gibt es für jede Node einen Konsolenzugang (BMC/iLO), falls das Netz weg ist?