So schreiben und führen Sie unbeaufsichtigte Ubuntu-Installationen mit autoinstall durch
Die Möglichkeit, replizierbare Installationen eines Betriebssystems bereitzustellen und zu erstellen, ist insbesondere in Unternehmensumgebungen von entscheidender Bedeutung. Um unbeaufsichtigte Installationen durchzuführen, unterstützte Ubuntu Debian-Preseed- und Kickstart-Dateien. Beginnend mit Ubuntu Server 20.04 und Version 23.04 des Ubuntu-Desktops wurden diese Installationsmethoden veraltet, und die Distribution übernahm ein neues Autoinstall-Format, das die Vorteile von cloud-init nutzt.
In diesem Tutorial lernen wir, wie man eine Ubuntu-Autoinstall-Datei schreibt und wie man sie verwendet, um unbeaufsichtigte, replizierbare Installationen durchzuführen.
In diesem Tutorial lernen Sie:
- Wie man eine Autoinstall-Datei schreibt und eine Ubuntu-Installation in all ihren Aspekten definiert
- So übergeben Sie die Autoinstall-Datei an die Ubuntu-Desktop- und -Server-Installationsprogramme
Einführung in die Autoinstall-Datei
Da es sich um eine von Debian abgeleitete Distribution handelt, unterstützte Ubuntu ursprünglich Preseed-Dateien als Methode zur Durchführung unbeaufsichtigter und replizierbarer Installationen. Die Unterstützung der Kickstart-Installationssyntax wurde später als Kompatibilitätsebene hinzugefügt, aber nicht alle Kickstart-Befehle wurden implementiert. Beginnend mit dem Ubuntu-Server 20.04 und seit dem Ubuntu-Desktop 23.04 hat Ubuntu eine eigene Methode zur automatischen Installation eingeführt, die auf der YAML-Syntax basiert: autoinstall.
Das erste, was wir normalerweise in Autoinstall-Dateien sehen, ist der Kommentar "#cloud-config": Dieser ist erforderlich, wenn wir möchten, dass die Datei von cloud-init verarbeitet wird (dazu später mehr). Der Hauptschlüssel, der in der Konfigurationsdatei verwendet wird, ist autoinstall. Stattdessen wird die Version der Dateisyntax mit dem Versionsschlüssel angegeben. Zum Zeitpunkt des Schreibens ist nur Version 1 verfügbar:
#cloud-config
autoinstall:
version: 1Auswahl einer Quelle
Um die "Umgebung" anzugeben, die wir installieren möchten, können wir den Quellschlüssel verwenden, der ein Mapping als Wert annimmt. In dieser Zuordnung übergeben wir den Namen der Umgebung, die wir installieren möchten, als Wert des ID-Schlüssels. Bei der Installation des Ubuntu-Desktops können wir beispielsweise zwischen ubuntu-minimal-desktop und dem vollwertigen ubuntu-desktop wählen. Wenn der Schlüssel weggelassen wird, wird die erste verfügbare Quelle verwendet:
#cloud-config
autoinstall:
source:
id: ubuntu-desktop-minimal
Festlegen des Systemgebietsschemas, der Zeitzone und des Tastaturlayouts
Um das Gebietsschema des Systems festzulegen, verwenden wir den Schlüssel locale. Tastatureinstellungen werden stattdessen über die Tastaturtaste festgelegt. Dieser Schlüssel nimmt eine Zuordnung als Wert an. Im folgenden Beispiel geben wir nur das Layout an, das wir verwenden möchten (uns); Es ist auch möglich, andere Parameter anzugeben, wie z.B. die Layout-Variante. Um schließlich die Systemzeitzone festzulegen, verwenden wir den Zeitzonenschlüssel:
#cloud-config
autoinstall:
locale: en_US.UTF-8
keyboard:
layout: us
timezone: Europe/Rome
Konfigurieren von Netzwerkschnittstellen
Um das Systemnetzwerk zu konfigurieren, verwenden wir den Netzwerkschlüssel mit der netplan-Syntax. Im folgenden Beispiel gebe ich an, dass die enp1s0-Ethernet-Schnittstelle automatisch über dhcp4 konfiguriert werden soll:
#cloud-config
autoinstall:
network:
version: 2
ethernets:
enp1s0:
dhcp4: true
Konfigurieren des Hostnamens und des anfänglichen Systembenutzers
Um unser System sicher nutzen zu können, müssen wir mindestens einen unprivilegierten Benutzer erstellen. Wir müssen auch den Hostnamen des Systems festlegen. Beide Aspekte werden über den Identitätsschlüssel verwaltet. Der Schlüssel nimmt eine Zuordnung als Wert an; Wir definieren den Benutzernamen, das Passwort und den Hostnamen mit den entsprechenden Schlüsseln:
#cloud-config
autoinstall:
identity:
username: egidio
hostname: linuxconfig
password: '$6$mzOdSSVUfhWRNhcX$mkm.drDfOLfpZRX/58ouJqMvitV2O0147VgKzKGYE6Qx4adJ8TXqMHs2dh2L7kT4TW5e97FCRDkGK1J.LouyV.'
Wie Sie im Beispiel sehen können, muss das von uns bereitgestellte Passwort bereits mit dem sha512-Algorithmus gehasht worden sein.
Einrichten des SSH-Servers
In der Autoinstall-Datei haben wir die Möglichkeit anzugeben, ob wir den SSH-Server installieren und konfigurieren möchten. Wir können die Passwortauthentifizierung aktivieren oder deaktivieren und schließlich die Liste der autorisierten öffentlichen Schlüssel übergeben, die der authorized_keys Datei des ersten Benutzers hinzugefügt werden:
#cloud-config
autoinstall:
ssh:
install-server: true
allow-pw: true
authorized-keys: []
Installieren zusätzlicher Pakete
Um eine Liste von zusätzlichen Paketen zu spezifizieren, die vom apt-get-Paketmanager als Teil der Systeminstallation abgerufen werden sollen, können wir den Schlüssel packages verwenden. Hier ist ein Beispiel:
#cloud-config
autoinstall:
packages:
- git
- python3-pip
Um Snap-Pakete zu installieren, verwenden wir stattdessen das Schlüsselwort snaps. Das Schlüsselwort akzeptiert eine Liste von Zuordnungen als Wert. In jedem Mapping verwenden wir den Schlüssel, den Kanal und den klassischen Schlüssel, um den Namen des zu installierenden Snap-Pakets, den Kanal, von dem aus der Snap installiert werden soll (der Standardwert ist "stable") und ob das Snap-Paket im klassischen Modus installiert werden soll (der Standardwert ist "false"):
#cloud-config
autoinstall:
snaps:
- name: pycharm-community
channel: stable
classic: trueDefinieren der Aktion nach der Installaktion
Um die Aktion nach der Installation zu definieren, verwenden wir den Schlüssel shutdown. Dieser Schlüssel akzeptiert zwei mögliche Werte: "poweroff" und "reboot":
#cloud-config
autoinstall:
shutdown: reboot
Definieren der Speichereinrichtung
Einer der wichtigsten Aspekte der Systeminstallation ist die Einrichtung der Partitionierung. Bei der interaktiven Installation von Ubuntu können wir zwischen einigen vordefinierten Layouts wählen oder ein benutzerdefiniertes Setup erstellen. Das Gleiche können wir bei automatischen Installationen tun. Die verfügbaren vordefinierten Layouts sind: lvm, direct und zfs.
Das LVM-Layout ist die Standardeinstellung: Es erstellt die EFI- (im Falle moderner UEFI-Systeme) und Boot-Standardpartitionen und installiert den Rest des Systems auf einem logischen LVM-Volume. Die Größe des logischen Root-Volumes wird gemäß einer Richtlinie bestimmt: Wenn es auf "skaliert" (Standard) festgelegt ist, hängt die Menge an Speicherplatz, die dem logischen Volume zugewiesen ist, von der Größe der Volume-Gruppe ab. Wenn möglich, wird etwas Platz ungenutzt gelassen, um die Erstellung von Snapshots zu ermöglichen:
| VG Größe | Größe der Wurzel-LV |
|---|---|
| Weniger als 10 GiB | 100% des verfügbaren Platzes |
| Zwischen 10 GiB und 20 GiB | 10 GiB |
| Zwischen 20 GiB und 200 GiB | 50% des verfügbaren Platzes |
| Mehr als 200 GiB | 100 GiB |
Wenn die Richtlinie auf "all" festgelegt ist, wird stattdessen der gesamte verfügbare Speicherplatz dem logischen Root-Volume zugewiesen. In diesem Zusammenhang kann derPasswortschlüssel verwendet werden, um die LUKS-Verschlüsselung zu aktivieren und das Verschlüsselungspasswort bereitzustellen:
#cloud-config
autoinstall:
storage:
layout:
name: lvm
policy: all
password: mysecretpassword
Das direkte Layout installiert Ubuntu auf Standardpartitionen. Auf UEFI-Systemen wird eine EFI-Partition mit einer Größe von 1 GiB erstellt und der Rest des Speicherplatzes der Stammpartition zugewiesen.
Schließlich installiert das zfs-Layout das System in einem ZFS-Pool, wodurch mehrere Volumes erstellt werden. Unten sehen Sie einen Screenshot des zfs-Setups nach einer Neuinstallation von Ubuntu:
Auswählen eines Datenträgers für die Installation
Zusätzlich zu den Partitionslayouts können wir explizit festlegen, welche Festplatte für die Installation verwendet werden soll. Wir tun dies über den Match-Key. Wir können eine Festplatte nach Pfad, Hersteller, Modell, Seriennummer und mehr auswählen. Wenn das Schlüsselwort weggelassen wird, erfolgt die Installation auf dem größten verfügbaren Datenträger. Im folgenden Beispiel wählen wir eine Festplatte über den Pfad (/dev/vda) aus:
#cloud-config
autoinstall:
storage:
layout:
name: lvm
match:
path: /dev/vda
Erstellen eines benutzerdefinierten Layouts
Um ein benutzerdefiniertes Partitionslayout zu definieren, verwenden wir das Schlüsselwort config. Dieses Schlüsselwort akzeptiert eine Liste von Zuordnungen als Wert, die jeweils einen Befehl des Curtin-Installers beschreiben. Sehen wir uns ein Beispiel an. Angenommen, wir möchten Ubuntu auf einem LVM auf LUKS-Setup installieren und die folgenden Partitionen erstellen:
- Eine kleine EFI-Partition von 600 MiB, formatiert in fat32, die auf /boot/efi gemountet werden soll
- Eine Boot-Partition von 1 GiB, formatiert in ext4, um auf /boot gemountet zu werden
- Eine dritte Partition, die sich über den Rest des Speicherplatzes erstreckt, mit LUKS verschlüsselt und als physisches LVM-Volume formatiert ist
- Ein logisches LVM-Volume mit 45 GiB, das auf /
- Ein logisches LVM-Volume mit 50 GiB, das auf /home gemountet werden kann
So gehen wir vor. Das erste, was wir tun müssen, ist den Befehl disk zu verwenden. Es wird verwendet, um Festplatten einzurichten und Partitionstabellen zu erstellen:
#cloud-config
autoinstall:
storage:
config:
- id: disk-vda
type: disk
ptable: gpt
path: /dev/vda
wipe: superblock-recursive
Mit dem Schlüsselwort id geben wir eine Kennung für die Sektion und den Befehl an: Dies ermöglicht es uns, die Festplatte zu referenzieren, wenn wir andere Befehle verwenden. Mit dem Schlüsselwort type geben wir stattdessen den Befehl an, den wir ausführen möchten, in diesem Fall "disk".
Wenn der Schlüssel ptable vorhanden ist, wird eine Partitionstabelle des angegebenen Typs auf der Festplatte erstellt. In diesem Fall haben wir "gpt" als Wert verwendet. Das Schlüsselwort path wird verwendet, um den Datenträger anhand seines Pfads (/dev/vda) zu identifizieren.
Das Schlüsselwort wipe ist sehr wichtig: Wenn es verwendet wird, zerstört es den Inhalt von Festplatten oder Partitionen. Es gibt viele Arten von "Wipe", die wir verwenden können: Superblock, Superblock-rekursiv, Null, Zufall und pvremove. Wir verwenden superblock, wenn wir nur den Superblock der Festplatte löschen möchten, und superblock-rekursiv, wenn wir auch eventuelle Einbettungs-Superblöcke löschen möchten (sie können z.B. bei der Verwendung von LVM vorhanden sein). Mit den Zero- oder Rando-m-Wipes können wir die Festplatte mit Nullen bzw. zufälligen Daten überschreiben. Schließlich löscht pvremove speziell LVM-Metadaten, um sicherzustellen, dass die Festplatte nicht Teil eines LVM-Setups ist. Im obigen Beispiel haben wir superblock-recursive verwendet, was in den meisten Fällen ausreichen sollte.
Erstellen von Standardpartitionen mit dem Befehl "partition"
Wir müssen nun die drei "Standard"-Partitionen auf der Festplatte erstellen. Die erste ist die EFI-Partition, die zweite die Partition, die auf /boot gemountet wird, und die dritte ist die Partition, die mit LUKS verschlüsselt und als physisches LVM-Volume verwendet wird. Um eine Partition zu erstellen, verwenden wir den Befehl partition. In den folgenden Beispielen konzentrieren wir uns der Übersichtlichkeit halber auf die aktuellen Befehle und lassen die zuvor verwendeten aus:
#cloud-config
autoinstall:
storage:
config:
# [...]
- id: efipart
type: partition
device: disk-vda
offset: 1048576
size: 600M
flag: boot
grub_device: true
- id: bootpart
type: partition
device: disk-vda
size: 1G
- id: pvpart
type: partition
device: disk-vda
size: -1
Da die "efipart"-Partition die erste ist, haben wir das Schlüsselwort offset verwendet, um sicherzustellen, dass sie mit 1 MiB vom Anfang der Festplatte an erstellt wird (der Wert wird in Bytes angegeben: 1048576). Wir haben das Schlüsselwort flag verwendet, um ein Flag anzugeben, das auf der Partition gesetzt werden soll, in diesem Fall "boot". Schließlich haben wir das Schlüsselwort grub_device verwendet, um sicherzustellen, dass GRUB auf der Partition installiert ist.
In allen Definitionen haben wir den Geräteschlüssel verwendet, um auf die Festplatte zu verweisen, auf der die Partition erstellt werden muss, und den Größenschlüssel, um die Partitionsgröße anzugeben. Im Fall der "pvpart"-Partition verwenden wir "-1" als Wert: Dies stellt sicher, dass die Partition den gesamten verbleibenden Speicherplatz auf der Festplatte belegt.
Erstellen eines verschlüsselten LUKS-Volumes mit dem Befehl dm_crypt
Als nächsten Schritt wollen wir LUKS verwenden, um die "pvpart"-Partition zu verschlüsseln. Wir können dies mit dem Befehl dm_crypt tun:
#cloud-config
autoinstall:
storage:
config:
# [...]
- id: pvpart-crypt
type: dm_crypt
volume: pvpart
key: mysecretpassword
Wenn wir den Befehl dm_crypt verwenden, übergeben wir die Kennung der Partition, die wir verschlüsseln möchten, als Wert des Volume-Schlüssels, und wir verwenden den Schlüssel, um die Verschlüsselungspassphrase bereitzustellen.
Erstellen der LVM-Datenträgergruppe und der logischen Datenträger
Um eine LVM-Volume-Gruppe zu erstellen, verwenden wir den Befehl lvm_volgroup und verwenden das Schlüsselwort devices, um die physischen Volumes aufzulisten, die wir der Gruppe hinzufügen möchten:
#cloud-config
autoinstall:
storage:
config:
# [...]
- id: vg0
type: lvm_volgroup
name: vg0
devices:
- pvpart-crypt
Um logische Volumes zu erstellen, verwenden wir den Befehl lvm_partition. Wir geben den LV-Namen mit dem Namensschlüssel, die Volume-Gruppe, auf der der LV als Wert von volgroup erstellt werden soll, und seine Größe über den Größenschlüssel an:
#cloud-config
autoinstall:
storage:
config:
# [...]
- id: root_lv
type: lvm_partition
name: root_lv
volgroup: vg0
size: 45G
- id: home_lv
type: lvm_partition
name: home_lv
volgroup: vg0
size: 50G
Formatieren der Partitionen
Um Dateisysteme auf den von uns definierten Partitionen zu erstellen und ihre Einhängepunkte zu setzen, verwenden wir den Befehl format. Wir verwenden das Schlüsselwort volume, um die Partition anhand der ID zu referenzieren, und das Schlüsselwort fstype, um anzugeben, welches Dateisystem erstellt werden soll:
#cloud-config
autoinstall:
storage:
config:
# [...]
- id: efipart_fs
type: format
volume: efipart
fstype: fat32
- id: bootpart_fs
type: format
volume: bootpart
fstype: ext4
- id: root_lv_fs
type: format
volume: root_lv
fstype: ext4
- id: home_lv_fs
type: format
volume: home_lv
fstype: ext4
Um schließlich anzugeben, wo das Dateisystem eingehängt werden soll, verwenden wir den Befehl mount. Mit dem Geräteschlüssel geben wir die Dateisystem-ID an; mit path stattdessen seinen Mountpoint:
#cloud-config
autoinstall:
storage:
config:
# [...]
- id: efipart-mount
type: mount
device: efipart_fs
path: /boot/efi
- id: bootpart-mount
type: mount
device: bootpart_fs
path: /boot
- id: root_lv_mount
type: mount
device: root_lv_fs
path: /
- id: home_lv_mount
type: mount
device: home_lv_fs
path: /home
Übergeben der Konfiguration an das Ubuntu-Installationsprogramm
So sieht unsere Konfigurationsdatei für die automatische Installation in ihrer Gesamtheit aus:
#cloud-config
autoinstall:
version: 1
source:
id: ubuntu-server-minimal
locale: en_US.UTF-8
keyboard:
layout: us
timezone: Europe/Rome
network:
version: 2
ethernets:
enp1s0:
dhcp4: true
identity:
username: egidio
hostname: linuxconfig
password: '$6$mzOdSSVUfhWRNhcX$mkm.drDfOLfpZRX/58ouJqMvitV2O0147VgKzKGYE6Qx4adJ8TXqMHs2dh2L7kT4TW5e97FCRDkGK1J.LouyV.'
ssh:
install-server: true
allow-pw: true
authorized-keys: []
packages:
- git
- python3-pip
snaps:
- name: pycharm-community
channel: stable
classic: true
shutdown: reboot
storage:
config:
- id: disk-vda
type: disk
ptable: gpt
path: /dev/vda
wipe: superblock-recursive
- id: efipart
type: partition
device: disk-vda
offset: 1048576
size: 600M
flag: boot
grub_device: true
- id: bootpart
type: partition
device: disk-vda
size: 1G
- id: pvpart
type: partition
device: disk-vda
size: -1
- id: pvpart-crypt
type: dm_crypt
volume: pvpart
key: mysecretpassword
- id: vg0
type: lvm_volgroup
name: vg0
devices:
- pvpart-crypt
- id: root_lv
type: lvm_partition
name: root_lv
volgroup: vg0
size: 45G
- id: home_lv
type: lvm_partition
name: home_lv
volgroup: vg0
size: 50G
- id: efipart_fs
type: format
volume: efipart
fstype: fat32
- id: bootpart_fs
type: format
volume: bootpart
fstype: ext4
- id: root_lv_fs
type: format
volume: root_lv
fstype: ext4
- id: home_lv_fs
type: format
volume: home_lv
fstype: ext4
- id: efipart-mount
type: mount
device: efipart_fs
path: /boot/efi
- id: bootpart-mount
type: mount
device: bootpart_fs
path: /boot
- id: root_lv_mount
type: mount
device: root_lv_fs
path: /
- id: home_lv_mount
type: mount
device: home_lv_fs
path: /homeWie übergebe ich die Konfiguration an das Ubuntu-Installationsprogramm? Bei der Installation der Desktop-Version von Ubuntu besteht die einfachste und bequemste Methode darin, unsere Konfigurationsdatei über HTTP oder FTP zur Verfügung zu stellen und ihre URL im entsprechenden Abschnitt des grafischen Installationsprogramms zu übergeben:
Eine Autoinstall-Konfigurationsdatei wird automatisch nach jeder Ubuntu-Installation erstellt, auch nach solchen, die interaktiv durchgeführt werden. Sie finden die Datei als /var/log/installer/autoinstall-user-data gespeichert. Die Datei kann verwendet werden, um die Installation zu replizieren.
Wenn wir eine vollständig automatisierte Installation durchführen oder die Autoinstall-Konfiguration bei der Installation des Ubuntu-Servers verwenden möchten, müssen wir cloud-init verwenden und die Konfiguration als cloud-config-Datendatei verwenden: Dafür ist der Kommentar "#cloud-config" ganz am Anfang der Autoinstall-Datei gedacht.
Damit cloud-init die Datei beim Booten lesen kann, müssen wir sie in user-data umbenennen und eine leere Datei mit dem Namen meta-data im selben Verzeichnis erstellen. Wir drücken "e", um den ersten Eintrag des Live-ISO-GRUB-Menüs zu ändern:
Dann ändern wir die Zeile, die mit "linux" beginnt, und fügen den folgenden String vor die drei Bindestriche ein (das Semikolon zu vermeiden ist wichtig!):
autoinstall ds=nocloud-net\;s=<directory-URL>Dabei ist <Verzeichnis-URL> die URL des Verzeichnisses, das die Benutzerdaten- und Metadatendateien enthält:
Um die Installation zu starten, drücken wir an dieser Stelle einfach Strg-x.
Abschließende Gedanken
Seit Ubuntu Server 20.04 und Ubuntu Desktop 23.04 ist es möglich, unbeaufsichtigte und reproduzierbare Systeminstallationen im nativen Autoinstall-Format durchzuführen. In diesem Tutorial haben wir gesehen, wie man eine Autoinstall-Datei schreibt, und einige der Schlüssel, die darin verwendet werden können. Schließlich haben wir gesehen, wie die Datei an die Ubuntu-Desktop- und Server-Installationsprogramme übergeben wird. Eine vollständige Referenz zur Ubuntu-Autoinstallation finden Sie in der offiziellen Dokumentation.




