Eine initrd (initial ramdisk) ist ein kleines Dateisystem, das während des Bootvorgangs auf einem Linux-System geladen wird. Eine der Aufgaben, für die die initrd verantwortlich sein könnte, ist die Netzwerkkonfiguration.
Dieser Artikel erläutert die Fälle, in denen eine Netzwerkkonfiguration zu Beginn des Startvorgangs erforderlich ist, wie sie implementiert wird und welche Verbesserungen Red Hat Enterprise Linux 8.3 mit sich bringt.
Die Notwendigkeit einer initrd
Wenn Sie den Netzschalter einer Maschine drücken, beginnt der Bootvorgang mit einem hardwareabhängigen Mechanismus, der einen Bootloader lädt . Die Bootloader-Software findet den Kernel auf der Festplatte und bootet ihn. Als nächstes hängt der Kernel das Root-Dateisystem ein und führt ein init
aus verarbeiten.
Dieser Prozess klingt einfach und könnte auf einigen Linux-Systemen tatsächlich passieren. Moderne Linux-Distributionen müssen jedoch eine Vielzahl von Anwendungsfällen unterstützen, für die dieses Verfahren nicht geeignet ist.
Erstens könnte sich das Root-Dateisystem auf einem Gerät befinden, das einen bestimmten Treiber benötigt. Bevor Sie versuchen, das Dateisystem einzuhängen, muss das richtige Kernelmodul in den laufenden Kernel eingefügt werden. In einigen Fällen befindet sich das Root-Dateisystem auf einer verschlüsselten Partition und benötigt daher einen Userspace-Helfer, der den Benutzer nach der Passphrase fragt und sie an den Kernel weitergibt. Oder das Root-Dateisystem könnte über NFS oder iSCSI über das Netzwerk freigegeben werden, und das Mounten erfordert möglicherweise zuerst konfigurierte IP-Adressen und Routen auf einer Netzwerkschnittstelle.
[Das könnte Ihnen auch gefallen: Linux-Netzwerke:13 Einsatzmöglichkeiten für Netstat]
Um diese Probleme zu lösen, kann der Bootloader ein kleines Dateisystem-Image (die initrd) an den Kernel übergeben, das Skripte und Tools enthält, um das echte Root-Dateisystem zu finden und einzuhängen. Sobald dies erledigt ist, wechselt die initrd zum echten Root und der Bootvorgang wird wie gewohnt fortgesetzt.
Die Dracut-Infrastruktur
Auf Fedora und RHEL wird die initrd durch dracut erstellt . Von seiner Homepage aus ist dracut „eine ereignisgesteuerte initramfs-Infrastruktur. dracut (das Tool) wird verwendet, um ein initramfs-Image zu erstellen, indem Tools und Dateien von einem installierten System kopiert und mit dem dracut-Framework kombiniert werden, das normalerweise in /usr/lib/dracut/modules.d
."
Ein Hinweis zur Terminologie:Manchmal sind die Namen initrd und initramfs werden synonym verwendet. Sie beziehen sich tatsächlich auf verschiedene Arten, das Bild aufzubauen. Eine initrd ist ein Image, das ein echtes Dateisystem (z. B. ext2) enthält, das vom Kernel gemountet wird. Ein initramfs ist ein cpio-Archiv, das einen Verzeichnisbaum enthält, der als tmpfs entpackt wird. Heutzutage sind die initrd-Images zugunsten des initramfs-Schemas veraltet. Der initrd-Name wird jedoch immer noch verwendet, um den Boot-Vorgang mit einem temporären Dateisystem anzuzeigen.
Kernel-Befehlszeile
Sehen wir uns das zuvor erwähnte NFS-Root-Szenario noch einmal an. Eine Möglichkeit, über NFS zu booten, ist die Verwendung einer Kernel-Befehlszeile, die root=dhcp
enthält Argument.
Die Kernel-Befehlszeile ist eine Liste von Optionen, die vom Bootloader an den Kernel übergeben werden und auf die der Kernel und Anwendungen zugreifen können. Wenn Sie GRUB verwenden, kann es durch Drücken des e geändert werden Geben Sie einen Boot-Eintrag ein und bearbeiten Sie die Zeile, die mit linux beginnt .
Der dracut-Code in initramfs analysiert die Kernel-Befehlszeile und startet DHCP auf allen Schnittstellen, wenn die Befehlszeile root=dhcp
enthält . Nach Erhalt einer DHCP-Lease konfiguriert dracut die Schnittstelle mit den erhaltenen Parametern (IP-Adresse und Routen); es extrahiert auch den Wert der Root-Pfad-DHCP-Option aus der Lease. Die Option enthält die Adresse und den Pfad eines NFS-Servers (was beispielsweise 192.168.50.1:/nfs/client
sein könnte ). Dracut mountet dann die NFS-Freigabe an dieser Stelle und fährt mit dem Booten fort.
Wenn es keinen DHCP-Server gibt, der die Adresse und den NFS-Root-Pfad bereitstellt, können die Werte explizit in der Befehlszeile konfiguriert werden:
root=nfs:192.168.50.1:/nfs/client ip=192.168.50.101:::24::ens2:none
Hier gibt das erste Argument die Adresse des NFS-Servers an und das zweite konfiguriert ens2 Schnittstelle mit einer statischen IP-Adresse.
Es gibt zwei Syntaxen, um die Netzwerkkonfiguration für eine Schnittstelle anzugeben:
ip=<interface>:{dhcp|on|any|dhcp6|auto6}[:[<mtu>][:<macaddr>]]
ip=<client-IP>:[<peer>]:<gateway-IP>:<netmask>:<client_hostname>:<interface>:{none|off|dhcp|on|any|dhcp6|auto6|ibft}[:[<mtu>][:<macaddr>]]
Der erste kann für die automatische Konfiguration (DHCP oder IPv6 SLAAC) und der zweite für die statische Konfiguration oder eine Kombination aus automatisch und statisch verwendet werden. Hier einige Beispiele:
ip=enp1s0:dhcp
ip=192.168.10.30::192.168.10.1:24::enp1s0:none
ip=[2001:0db8::02]::[2001:0db8::01]:64::enp1s0:none
Beachten Sie, dass, wenn Sie ein ip=
übergeben Option, aber dracut benötigt kein Netzwerk, um das Root-Dateisystem zu mounten, wird die Option ignoriert. Um die Netzwerkkonfiguration ohne Netzwerkstamm zu erzwingen, fügen Sie rd.neednet=1
hinzu zur Befehlszeile.
Sie haben wahrscheinlich bemerkt, dass es unter den automatischen Konfigurationsmethoden auch ibft gibt . iBFT steht für iSCSI Boot Firmware Table und ist ein Mechanismus, um Parameter über iSCSI-Geräte von der Firmware an das Betriebssystem zu übergeben. iSCSI (Internet Small Computer Systems Interface) ist ein Protokoll für den Zugriff auf Netzwerkspeichergeräte. Die Beschreibung von iBFT und iSCSI würde den Rahmen dieses Artikels sprengen. Wichtig ist, dass Sie ip=ibft
übergeben zum Kernel wird die Netzwerkkonfiguration von der Firmware abgerufen.
Dracut unterstützt auch das Hinzufügen benutzerdefinierter Routen, das Angeben des Maschinennamens und der DNS-Server, das Erstellen von Bindungen, Bridges, VLANs und vieles mehr. Weitere Einzelheiten finden Sie auf der Manpage dracut.cmdline.
Netzwerkmodule
Das im initramfs enthaltene dracut-Framework hat eine modulare Architektur. Es besteht aus einer Reihe von Modulen, die jeweils Skripte und Binärdateien enthalten, um bestimmte Funktionen bereitzustellen. Mit dem Befehl dracut --list-modules
können Sie sehen, welche Module verfügbar sind, um in das initramfs aufgenommen zu werden .
Im Moment gibt es zwei Module, um das Netzwerk zu konfigurieren:network-legacy
und network-manager
. Sie fragen sich vielleicht, warum verschiedene Module die gleiche Funktionalität bieten.
network-legacy
ist älter und verwendet Shell-Skripte, die Dienstprogramme wie iproute2
aufrufen , dhclient
, und arping
Schnittstellen zu konfigurieren. Nach dem Wechsel zum echten Root läuft ein anderer Netzwerkkonfigurationsdienst. Dieser Dienst ist sich der network-legacy
nicht bewusst das vorgesehene Modul und den aktuellen Zustand jeder Schnittstelle. Dies kann zu Problemen führen, den Zustand über die Root-Switch-Grenze hinweg aufrechtzuerhalten.
Ein prominentes Beispiel für einen beizubehaltenden Zustand ist die DHCP-Lease. Wenn sich die Adresse einer Schnittstelle während des Bootens änderte, wurde die Verbindung zu einer NFS-Freigabe unterbrochen, was zu einem Boot-Fehler führte.
Um einen nahtlosen Übergang zu gewährleisten, ist ein Mechanismus erforderlich, um den Zustand zwischen den beiden Umgebungen zu übergeben. Das Übergeben des Zustands zwischen Diensten mit unterschiedlichen Konfigurationsmodellen kann jedoch ein Problem darstellen.
Der network-manager
Das dracut-Modul wurde geschaffen, um diese Situation zu verbessern. Das Modul führt NetworkManager in der initrd aus, um Verbindungsprofile zu konfigurieren, die von der Kernel-Befehlszeile generiert werden. Sobald dies erledigt ist, serialisiert NetworkManager seinen Status, der später von der NetworkManager-Instanz im echten Stammverzeichnis gelesen wird.
Fedora 31 war die erste Distribution, die auf network-manager
umgestellt hat standardmäßig in initrd. Unter RHEL 8.2 network-legacy
ist immer noch der Standard, aber network-manager
ist verfügbar. Unter RHEL 8.3 verwendet dracut network-manager
standardmäßig.
Aktivieren eines anderen Netzwerkmoduls
Während die beiden Module weitgehend kompatibel sein sollten, gibt es einige Unterschiede im Verhalten. Einige davon sind im nm-initrd-generator
dokumentiert Manpage. Generell wird empfohlen, den network-manager
zu verwenden Modul, wenn NetworkManager aktiviert ist.
Verwenden Sie einen der folgenden Befehle, um die initrd mit einem bestimmten Netzwerkmodul neu zu erstellen:
# dracut --add network-legacy --force --verbose
# dracut --add network-manager --force --verbose
Da diese Änderung beim nächsten Neuaufbau der initrd rückgängig gemacht wird, möchten Sie die Änderung vielleicht folgendermaßen dauerhaft machen:
# echo 'add_dracutmodules+=" network-manager "' > /etc/dracut.conf.d/network-module.conf
# dracut --regenerate-all --force --verbose
Der --regenerate-all
Option baut auch alle initramfs-Images für die auf dem System gefundenen Kernel-Versionen neu auf.
Das Dracut-Modul des Netzwerkmanagers
Wie bei allen Dracut-Modulen ist der network-manager
Das Modul ist in Stufen aufgeteilt, die zu unterschiedlichen Zeiten während des Bootvorgangs aufgerufen werden (weitere Einzelheiten finden Sie auf der Manpage dracut.modules).
Die erste Stufe analysiert die Kernel-Befehlszeile durch Aufrufen von /usr/libexec/nm-initrd-generator
um eine Liste von Verbindungsprofilen in /run/NetworkManager/system-connections
zu erstellen . Der zweite Teil des Moduls wird ausgeführt, nachdem sich udev eingerichtet hat, d. h. nachdem der Userspace die Verarbeitung der Kernel-Ereignisse für im System gefundene Geräte (einschließlich Netzwerkschnittstellen) beendet hat.
Wenn NM in der realen Root-Umgebung gestartet wird, registriert es sich auf dem D-Bus, konfiguriert das Netzwerk und bleibt aktiv, um auf Ereignisse oder D-Bus-Anforderungen zu reagieren. In der initrd wird NetworkManager in configure-and-quit=initrd
ausgeführt Modus, der sich nicht auf dem D-Bus registriert (da er in der initrd zumindest vorerst nicht verfügbar ist) und nach Erreichen des startup-complete beendet wird Veranstaltung.
Das Startup-Complete Das Ereignis wird ausgelöst, nachdem alle Geräte mit einem übereinstimmenden Verbindungsprofil versucht haben, sich zu aktivieren, ob erfolgreich oder nicht. Sobald alle Schnittstellen konfiguriert sind, beendet sich NM und ruft Dracut-Hooks auf, um andere Module darüber zu informieren, dass das Netzwerk verfügbar ist.
Beachten Sie, dass /run/NetworkManager
Verzeichnis, das generierte Verbindungsprofile und anderen Laufzeitstatus enthält, wird in das echte Stammverzeichnis kopiert, sodass der neue NetworkManager-Prozess, der dort ausgeführt wird, genau weiß, was zu tun ist.
Fehlerbehebung
Wenn Sie Netzwerkprobleme in dracut haben, enthält dieser Abschnitt einige Vorschläge zur Untersuchung des Problems.
Als erstes müssen Sie rd.debug hinzufügen zur Kernel-Befehlszeile, wodurch die Debug-Protokollierung in Dracut aktiviert wird. Protokolle werden unter /run/initramfs/rdsosreport.txt
gespeichert und sind auch in der Zeitschrift verfügbar.
Wenn das System nicht bootet, ist es hilfreich, eine Shell in die initrd-Umgebung zu bekommen, um manuell zu überprüfen, warum die Dinge nicht funktionieren. Dafür gibt es einen rd.break Kommandozeilenargument. Beachten Sie, dass das Argument eine Shell erzeugt, wenn die initrd ihre Arbeit beendet hat und dabei ist, die Kontrolle an den init-Prozess im echten Root-Dateisystem zu übergeben. Um in einer anderen Phase von dracut zu stoppen (z. B. nach der Befehlszeilenanalyse), verwenden Sie das folgende Argument:
rd.break={cmdline|pre-udev|pre-trigger|initqueue|pre-mount|mount|pre-pivot|cleanup}
Das initrd-Image enthält einen minimalen Satz von Binärdateien; Wenn Sie ein bestimmtes Werkzeug in der Dracut-Shell benötigen, können Sie das Bild neu erstellen und hinzufügen, was fehlt. Zum Beispiel, um den Ping hinzuzufügen und tcpdump Binärdateien (einschließlich aller ihrer abhängigen Bibliotheken), führen Sie aus:
# dracut -f --install "ping tcpdump"
und überprüfen Sie dann optional, ob sie erfolgreich eingefügt wurden:
# lsinitrd | grep "ping\|tcpdump"
Arguments: -f --install 'ping tcpdump'
-rwxr-xr-x 1 root root 82960 May 18 10:26 usr/bin/ping
lrwxrwxrwx 1 root root 11 May 29 20:35 usr/sbin/ping -> ../bin/ping
-rwxr-xr-x 1 root root 1065224 May 29 20:35 usr/sbin/tcpdump
Der Generator
Wenn Sie mit der NetworkManager-Konfiguration vertraut sind, möchten Sie vielleicht wissen, wie eine bestimmte Kernel-Befehlszeile in NetworkManager-Verbindungsprofile übersetzt wird. Dies kann nützlich sein, um den Konfigurationsmechanismus besser zu verstehen und Syntaxfehler in der Befehlszeile zu finden, ohne den Rechner booten zu müssen.
Der Generator wird in /usr/libexec/nm-initrd-generator
installiert und muss mit der Liste der Kernel-Argumente nach einem doppelten Bindestrich aufgerufen werden. Die --stdout
Option gibt die generierten Verbindungen auf der Standardausgabe aus. Versuchen wir, den Generator mit einer Beispielbefehlszeile aufzurufen:
$ /usr/libexec/nm-initrd-generator --stdout -- \
ip=enp1s0:dhcp:00:99:88:77:66:55 rd.peerdns=0
802-3-ethernet.cloned-mac-address: '99:88:77:66:55' is not a valid MAC
address
In diesem Beispiel meldet der Generator einen Fehler, weil nach enp1s0 ein Feld für die MTU fehlt . Sobald der Fehler behoben ist, ist das Parsing erfolgreich und das Tool gibt das generierte Verbindungsprofil aus:
$ /usr/libexec/nm-initrd-generator --stdout -- \
ip=enp1s0:dhcp::00:99:88:77:66:55 rd.peerdns=0
*** Connection 'enp1s0' ***
[connection]
id=enp1s0
uuid=e1fac965-4319-4354-8ed2-39f7f6931966
type=ethernet
interface-name=enp1s0
multi-connect=1
permissions=
[ethernet]
cloned-mac-address=00:99:88:77:66:55
mac-address-blacklist=
[ipv4]
dns-search=
ignore-auto-dns=true
may-fail=false
method=auto
[ipv6]
addr-gen-mode=eui64
dns-search=
ignore-auto-dns=true
method=auto
[proxy]
Beachten Sie, wie rd.peerdns=0 Argument wird in ignore-auto-dns=true übersetzt -Eigenschaft, wodurch NetworkManager über DHCP empfangene DNS-Server ignoriert. Eine Erläuterung der NetworkManager-Eigenschaften finden Sie auf der Manpage nm-settings.
[ Netzwerk gerät außer Kontrolle? Sehen Sie sich Netzwerkautomatisierung für alle an, ein kostenloses Buch von Red Hat. ]
Schlussfolgerung
Das Dracut-Modul NetworkManager ist standardmäßig in Fedora aktiviert und wird bald auch auf RHEL aktiviert. Es bringt eine bessere Integration zwischen dem Netzwerk in der initrd und dem NetworkManager, der im echten Root-Dateisystem läuft.
Obwohl die aktuelle Implementierung gut funktioniert, gibt es einige Ideen für mögliche Verbesserungen. Eine besteht darin, configure-and-quit=initrd
aufzugeben Modus und führen Sie NetworkManager als Daemon aus, der von einem systemd-Dienst gestartet wird. Auf diese Weise wird NetworkManager auf die gleiche Weise ausgeführt, als ob es im echten Stammverzeichnis ausgeführt würde, wodurch der zu wartende und zu testende Code reduziert wird.
Um configure-and-quit=initrd
vollständig zu löschen Modus sollte NetworkManager auch in der Lage sein, sich auf D-Bus in der initrd zu registrieren. Derzeit hat dracut kein Modul, das einen D-Bus-Daemon bereitstellt, da das Bild minimal sein sollte. Es gibt jedoch bereits Vorschläge, es aufzunehmen, da es zur Implementierung einiger neuer Funktionen benötigt wird.
Wenn D-Bus in der initrd ausgeführt wird, wird die leistungsstarke API von NetworkManager für andere Tools verfügbar sein, um den Netzwerkstatus abzufragen und zu ändern, wodurch eine breite Palette von Anwendungen freigeschaltet wird. Eine davon ist das Ausführen von nm-cloud-setup
in der initrd. Der Dienst, der im NetworkManager-cloud-setup
ausgeliefert wird Das Fedora-Paket ruft Metadaten von der Infrastruktur des Cloud-Anbieters (EC2, Azure, GCP) ab, um das Netzwerk automatisch zu konfigurieren.