Archiv des Autors: Jörg Kastning

Gold-Images für KVM/QEMU erstellen

Nachdem ich bereits beschrieben habe, wie ich Labor-Umgebungen mit Ansible in KVM erstelle, beschreibe ich in diesem Artikel, wie ich die dort verwendeten Gold-Images erstelle.

Ich erkläre kurz, was ein Gold-Image ist und wofür man es verwendet. Anschließend zeige ich, wie man mit dem Programm qemu-img eine Image-Datei auf der Kommandozeile erzeugt und diese im Installationsprozess für die Partitionierung und Erzeugung des LVM nutzt. Im Anschluss daran dokumentiere ich, welche Laufwerke und Dateisysteme ich für welchen Zweck erstelle und warum ich mich so entschieden habe. Der Text endet mit einer Sammlung von Quellen und weiterführenden Links zum Thema.

Der Text soll mir helfen, in Zukunft nachvollziehen zu können, warum ich mich so entschieden habe. Für euch mag er als Information dienen, wie ich im Unterschied zu euch an das Thema herangehe. Wer noch nie etwas von Gold-Images gehört hat, findet in diesem Text eine Erklärung und passende Quellen dazu.

Was ist ein Gold-Image?

Ein Gold-Image, auch Golden Image oder Baseline-Image genannt, bezeichnet eine Vorlage (engl. template) in virtuellen Umgebungen, woraus sich virtuelle Maschinen (VMs) klonen lassen (siehe [1-5]).

In ein Gold-Image werden all die Softwarekomponenten, Anwendungen und Konfigurationsoptionen aufgenommen, welche Bestandteil aller davon abgeleiteten VMs sein sollen. Klonen ermöglicht die schnelle Bereitstellung neuer Systeme. Dies ist besonders dann nützlich, wenn sich die VMs sehr ähnlich sind und man nur eine geringe Anzahl von Gold-Images pflegen muss.

Ich nutze Gold-Images, um für die von mir verwendeten Linux-Distributionen jeweils eine Installation manuell durchzuführen, welche die minimal erforderlichen Pakete enthält, um die abgeleiteten Klone mit Ansible fertig konfigurieren zu können. Wie ich dabei vorgehe, beschreibe ich in den folgenden Abschnitten.

Erstellung der Image-Datei

Im ersten Schritt erstelle ich Image-Dateien im qcow2-Format. Bei diesem Format handelt es sich um das heute gebräuchliche Format in KVM-/QEMU-Umgebungen. Zur Erstellung verwende ich das QEMU disk image utility qemu-img.

Die allgemeine Form des Befehls lautet (Details siehe Manpage qemu-img(1)):

qemu-img create -f FORMAT DATEINAME GRÖßE

Der folgende Befehl erstellt eine Image-Datei im qcow2-Format, mit 20 Gigabyte Größe und dem Dateinamen debian11-template.qcow2 im Pfad /var/lib/libvirt/images/:

$ qemu-img create -f qcow2 /var/lib/libvirt/images/debian11-template.qcow2 20G
Formatting '/var/lib/libvirt/images/debian11-template.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=21474836480 lazy_refcounts=off refcount_bits=16

Dabei werden die 20 GB nicht sofort alloziert. Zu Beginn belegt die Datei lediglich einige Kilobyte und kann je nach Nutzung auf die maximale Größe von 20 GB anwachsen. Diese Bereitstellungsform ist auch als Thin provisioning bekannt.

ls -sh /var/lib/libvirt/images/debian11-template.qcow2
193K /var/lib/libvirt/images/debian11-template.qcow2

Es lässt sich auf diese Weise mehr Speicherplatz provisionieren, als tatsächlich im System zur Verfügung steht. Dabei gilt jedoch zu beachten, dass sich die Physik nicht betrügen lässt. Man ist gut beraten, den realen Speicherverbrauch zu überwachen, um volllaufende Dateisysteme zu vermeiden.

Installation und Partitionierung

Bei der Installation des Gold-Images für Labor-Umgebungen mache ich es mir relativ einfach. Ich erstelle z.B. im virt-manager oder cockpit eine VM, die ich von einem Installations-ISO-Image der jeweiligen Distribution installiere.

Bei Debian installiere ich für gewöhnlich ein System ohne grafische Oberfläche, welches zusätzlich zur Basis-Installation lediglich die Paketgruppen SSH-Server und System-Werkzeuge umfasst. Bei Fedora oder RHEL führe ich die Minimal-Installation durch.

Ob bzw. welches Passwort für den Benutzer root vergeben wird, ist an dieser Stelle nicht wichtig, da dies beim Klonen in eine neue VM durch die Ansible-Rolle kvm_provision_lab geändert wird.

Der Installer erkennt eine Festplatte, die in diesem Text exemplarisch als /dev/vda bezeichnet wird. Diese wird nun wie folgt konfiguriert.

Vorwort zur Partitionierung

Das optimale Partitionslayout hängt vom konkreten Anwendungsfall ab und kann sich je nach Umgebung stark unterscheiden. Das von mir verwendete Layout passt aktuell am besten zu meinen Anforderungen. Es mag in Zukunft völlig anders aussehen.

Ich beschreibe, welche Partitionen ich erstelle und erläutere, warum ich mich zum Zeitpunkt der Erstellung dieses Textes dafür entschieden habe. Bitte übernehmt dieses Layout nicht stumpf, sondern überlegt, ob es zu euren Anforderungen passt.

Primäre Partition /dev/vda1 für /boot

In dieser Partition werden die Kernel und das initramfs abgelegt. Nach meiner Erfahrung reicht eine Größe von 1 GiB aus, um auch einige ältere Kernel vorzuhalten. Formatiert habe ich diese Partition mit dem Dateisystem ext4.

Ich bevorzuge ext4 gegenüber XFS, da es sich im Gegensatz zu letzterem auch verkleinern lässt. Zugegeben, dass dies notwendig ist, ist mir in 20 Jahren nur einmal untergekommen. Doch in diesem einen Moment war ich froh, dass es möglich war.

LVM, PV, VG, LV, Dateisysteme und Einhängepunkte

Der Logical Volume Manager (LVM) (siehe [11-13]) bietet die Möglichkeit, Partitionen (genaugenommen Logical Volumes) für weitere Einhängepunkte zu erstellen, welche sich später noch flexibel in der Größe anpassen lassen (Vergrößern und Verkleinern). Und dies, ohne die verwendeten Dateisysteme aushängen zu müssen.

Wer mit den für LVM relevanten Begriffen Physical Volume, Volume Group und Logical Volume nicht vertraut ist, findet weiterführende Hinweise in [12] für Debian bzw. [13] für RHEL. Ich werde die Erstellung hier nicht im Detail beschreiben.

Ich erstelle eine zweite primäre Partition /dev/vda2 mit Typ LVM, welcher ich die verbleibende Speicherkapazität von 19 GiB zuweise. Mein fertiges Partitionslayout sieht wie folgt aus:

lsblk -o +FSTYPE
NAME                  MAJ:MIN RM  SIZE RO TYPE MOUNTPOINT FSTYPE
sr0                    11:0    1 1024M  0 rom             
vda                   254:0    0   20G  0 disk            
├─vda1                254:1    0  953M  0 part /boot      ext4
└─vda2                254:2    0 19.1G  0 part            LVM2_member
  ├─vg_system-root    253:0    0  9.3G  0 lvm  /          ext4
  ├─vg_system-var_log 253:1    0  4.7G  0 lvm  /var/log   ext4
  └─vg_system-home    253:2    0  1.9G  0 lvm  /home      ext4

Vorstehendem Code-Block ist zu entnehmen, dass ich drei Logical Volumes für die Einhängepunkte /, /var/log und /home verwende. Ich verwende auch hier durchgängig das ext4-Dateisystem.

Log-Dateien und unkontrolliert wachsende Daten in HOME-Verzeichnissen führen schnell dazu, dass das Root-Dateisystem (/) vollläuft. Dies lässt sich mit der Verwendung separater Einhängepunkte sicher verhindern.

Eurem aufmerksamen Auge ist sicher aufgefallen, dass ich keine Swap-Partition verwende. Da ich sie für die meist kurzlebigen Labor-VMs nicht benötige, lasse ich diese in der Regel weg. Für Systeme, die ich für langfristigen Betrieb installiere, füge ich diese nachträglich hinzu. Dank LVM ist dies kein Problem.

Darüber, ob man eine Swap-Partition braucht und wie groß diese sein sollte, werden teils esoterische Diskussionen geführt. Ich selbst orientiere mich an Table B.1. Recommended system swap space aus [14].

Damit habe ich ein Gold-Image erstellt, welches mir als Vorlage für weitere VMs dient und dabei nur wenig Platz auf der Festplatte des Hypervisor belegt:

ls -sh /var/lib/libvirt/images/debian11-template.qcow2
2.3G /var/lib/libvirt/images/debian11-template.qcow2

Sysprep

Sysprep ist ursprünglich ein Programm von Microsoft, mit welchem Gold-Images für die automatische Verteilung von Microsoft Windows vorbereitet werden. Heute taucht dieser Begriff in den Programmbezeichnungen weiterer Projekte auf und beschreibt gleichzeitig die Tätigkeit, ein Gold-Image für die weitere Verwendung vorzubereiten. Ich selbst verwende das Programm virt-sysprep von Richard W.M. Jones (Red Hat) und Wanglong Gao (Fujitsu Ltd.).

Virt-sysprep entfernt Einstellungen, User, Host-spezifische Dateien und leert Protokolldateien in dem erzeugten Image. Damit soll sichergestellt werden, dass die von dem Gold-Image abgeleiteten VMs keine Eigenschaften besitzen, die spezifisch für das Original sind, wie z.B. der Hostname, MAC-Adressen oder die SSH-Host-Keys, um nur drei Beispiele zu nennen. Die Anwendung ist daher dringend empfohlen.

Mit dem Befehl virt-sysprep --list-operations kann man sich die Aktionen anzeigen lassen, die virt-sysprep ausführen kann. Die Standard-Aktionen sind in der Ausgabe mit einem ‚*‘ markiert. Unter RHEL 9 sieht die Ausgabe wie folgt aus:

$ virt-sysprep --list-operations
abrt-data * Remove the crash data generated by ABRT
backup-files * Remove editor backup files from the guest
bash-history * Remove the bash history in the guest
blkid-tab * Remove blkid tab in the guest
ca-certificates   Remove CA certificates in the guest
crash-data * Remove the crash data generated by kexec-tools
cron-spool * Remove user at-jobs and cron-jobs
customize * Customize the guest
dhcp-client-state * Remove DHCP client leases
dhcp-server-state * Remove DHCP server leases
dovecot-data * Remove Dovecot (mail server) data
firewall-rules   Remove the firewall rules
flag-reconfiguration   Flag the system for reconfiguration
fs-uuids   Change filesystem UUIDs
ipa-client * Remove the IPA files
kerberos-data   Remove Kerberos data in the guest
kerberos-hostkeytab * Remove the Kerberos host keytab file in the guest
logfiles * Remove many log files from the guest
lvm-system-devices * Remove LVM2 system.devices file
lvm-uuids * Change LVM2 PV and VG UUIDs
machine-id * Remove the local machine ID
mail-spool * Remove email from the local mail spool directory
net-hostname * Remove HOSTNAME and DHCP_HOSTNAME in network interface configuration
net-hwaddr * Remove HWADDR (hard-coded MAC address) configuration
net-nmconn * Remove system-local NetworkManager connection profiles (keyfiles)
pacct-log * Remove the process accounting log files
package-manager-cache * Remove package manager cache
pam-data * Remove the PAM data in the guest
passwd-backups * Remove /etc/passwd- and similar backup files
puppet-data-log * Remove the data and log files of puppet
rh-subscription-manager * Remove the RH subscription manager files
rhn-systemid * Remove the RHN system ID
rpm-db * Remove host-specific RPM database files
samba-db-log * Remove the database and log files of Samba
script * Run arbitrary scripts against the guest
smolt-uuid * Remove the Smolt hardware UUID
ssh-hostkeys * Remove the SSH host keys in the guest
ssh-userdir * Remove ".ssh" directories in the guest
sssd-db-log * Remove the database and log files of sssd
tmp-files * Remove temporary files
udev-persistent-net * Remove udev persistent net rules
user-account   Remove the user accounts in the guest
utmp * Remove the utmp file
yum-uuid * Remove the yum UUID
customize * Customize the guest
dhcp-client-state * Remove DHCP client leases
dhcp-server-state * Remove DHCP server leases
dovecot-data * Remove Dovecot (mail server) data
firewall-rules   Remove the firewall rules
flag-reconfiguration   Flag the system for reconfiguration
fs-uuids   Change filesystem UUIDs
ipa-client * Remove the IPA files
kerberos-data   Remove Kerberos data in the guest
kerberos-hostkeytab * Remove the Kerberos host keytab file in the guest
logfiles * Remove many log files from the guest
lvm-system-devices * Remove LVM2 system.devices file
lvm-uuids * Change LVM2 PV and VG UUIDs
machine-id * Remove the local machine ID
mail-spool * Remove email from the local mail spool directory
net-hostname * Remove HOSTNAME and DHCP_HOSTNAME in network interface configuration
net-hwaddr * Remove HWADDR (hard-coded MAC address) configuration
net-nmconn * Remove system-local NetworkManager connection profiles (keyfiles)
pacct-log * Remove the process accounting log files
package-manager-cache * Remove package manager cache
pam-data * Remove the PAM data in the guest
passwd-backups * Remove /etc/passwd- and similar backup files
puppet-data-log * Remove the data and log files of puppet
rh-subscription-manager * Remove the RH subscription manager files
rhn-systemid * Remove the RHN system ID
rpm-db * Remove host-specific RPM database files
samba-db-log * Remove the database and log files of Samba
script * Run arbitrary scripts against the guest
smolt-uuid * Remove the Smolt hardware UUID
ssh-hostkeys * Remove the SSH host keys in the guest
ssh-userdir * Remove ".ssh" directories in the guest
sssd-db-log * Remove the database and log files of sssd
tmp-files * Remove temporary files
udev-persistent-net * Remove udev persistent net rules
user-account   Remove the user accounts in the guest
utmp * Remove the utmp file
yum-uuid * Remove the yum UUID

Selbstverständlich gibt es mit virt-sysprep(1) auch eine Manpage, welche die Nutzung des Programms und sämtliche Optionen erläutert.

Es ist sehr wichtig, dass die zu behandelnde Domain (VM) ausgeschaltet ist, bevor virt-sysprep gestartet wird, um eine Korruption der Image-Datei zu vermeiden.

Der nun folgende Code-Block zeigt die Anwendung von virt-sysprep auf die qcow2-Datei meines debian11-templates. Die dabei verwendeten Option --operations defaults,-ssh-userdir sorgt dafür, dass alle Standard-Operationen mit der Ausnahme durchgeführt werden, dass die .ssh-Verzeichnisse der User erhalten bleiben. Die Option --firstboot-command 'dpkg-reconfigure openssh-server' stellt sicher, dass beim ersten Start des Klons neue SSH-Hostkeys generiert werden. Andernfalls kann der SSH-Dienst nicht starten und ich wäre nicht in der Lage mich via SSH anzumelden. Anschließend ist das Image bereit, um geklont bzw. kopiert zu werden.

$ virt-sysprep -a /var/lib/libvirt/images/debian11-template.qcow2 --operations defaults,-ssh-userdir --firstboot-command 'dpkg-reconfigure openssh-server'
[   0.0] Examining the guest ...
[   2.0] Performing "abrt-data" ...
[   2.0] Performing "backup-files" ...
[   2.1] Performing "bash-history" ...
[   2.1] Performing "blkid-tab" ...
[   2.1] Performing "crash-data" ...
[   2.1] Performing "cron-spool" ...
[   2.1] Performing "dhcp-client-state" ...
[   2.1] Performing "dhcp-server-state" ...
[   2.1] Performing "dovecot-data" ...
[   2.1] Performing "ipa-client" ...
[   2.1] Performing "kerberos-hostkeytab" ...
[   2.2] Performing "logfiles" ...
[   2.2] Performing "lvm-system-devices" ...
[   2.2] Performing "machine-id" ...
[   2.2] Performing "mail-spool" ...
[   2.2] Performing "net-hostname" ...
[   2.2] Performing "net-hwaddr" ...
[   2.3] Performing "net-nmconn" ...
[   2.3] Performing "pacct-log" ...
[   2.3] Performing "package-manager-cache" ...
[   2.3] Performing "pam-data" ...
[   2.3] Performing "passwd-backups" ...
[   2.3] Performing "puppet-data-log" ...
[   2.3] Performing "rh-subscription-manager" ...
[   2.3] Performing "rhn-systemid" ...
[   2.4] Performing "rpm-db" ...
[   2.4] Performing "samba-db-log" ...
[   2.4] Performing "script" ...
[   2.4] Performing "smolt-uuid" ...
[   2.4] Performing "ssh-hostkeys" ...
[   2.4] Performing "sssd-db-log" ...
[   2.4] Performing "tmp-files" ...
[   2.4] Performing "udev-persistent-net" ...
[   2.4] Performing "utmp" ...
[   2.4] Performing "yum-uuid" ...
[   2.4] Performing "customize" ...
[   2.4] Setting a random seed
[   2.5] Setting the machine ID in /etc/machine-id
[   2.5] Installing firstboot command: dpkg-reconfigure openssh-server
[   2.5] SELinux relabelling
[   2.5] Performing "lvm-uuids" ...

Das Programm ist nicht auf qcow2-Images beschränkt. Einen weiteren Anwendungsfall habe ich bereits hier im Blog beschrieben: VMware ESXi: VMDK-Datei einer Gast-VM mit virt-sysprep bereinigen.

Verwendung der Gold-Images

Die Gold-Images werden verwendet, um durch Klonen neue VMs zu erstellen. Ich verwende dazu die Eingangs erwähnte Ansible-Rolle kvm_provision_lab.

Was tun, wenn der Platz knapp wird?

Wird im Laufe des Lebenszyklus einer VM mehr Speicherplatz benötigt, so lässt sich das Vorgehen wie folgt skizzieren:

  1. Neue virtuelle Festplatte mit ausreichend Speicherkapazität der VM hinzufügen.
  2. Eine Partition auf der neuen virtuellen Festplatte erstellen (optional).
  3. Mit pvcreate ein neues Physical Volume erstellen.
  4. Das Physical Volume mit vgextend der Volume Group hinzufügen.
  5. Das Logical Volume mit lvextend vergrößern.

Die Schritte 3-5 werden ausführlich in der RHEL-9-Dokumentation in Chapter 5. Modifying the size of a logical volume beschrieben. Dort wird auch beschrieben, wie ein Logical Volume verkleinert werden kann.

Falls ihr euch hierzu ein Tutorial wünscht, lasst es mich bitte in den Kommentaren wissen. Dann liefere ich ein entsprechendes Beispiel nach.

  1. Was ist ein Golden Image? URL: https://www.redhat.com/de/topics/linux/what-is-a-golden-image.
  2. What is a golden image? On opensource.com by Seth Kenlon (Team, Red Hat). URL: https://opensource.com/article/19/7/what-golden-image.
  3. What is a golden image? Definition by Nick Martin on TechTarget. URL: https://www.techtarget.com/searchitoperations/definition/golden-image
  4. Definition Golden Image (auch Master Image oder Goldenes Abbild). ComputerWeekly.de. URL: https://www.computerweekly.com/de/definition/Golden-Image-auch-Master-Image-oder-Goldenes-Abbild
  5. Was ist ein Golden Image? 21.11.2018: Autor / Redakteur: Dipl. Betriebswirt Otto Geißler / Ulrike Ostler. URL: https://www.datacenter-insider.de/was-ist-ein-golden-image-a-775197/
  6. Wikipedia-Artikel zu qcow {EN}
  7. QEMU disk image utility
  8. Wikepdia-Artikel Thin zu provisioning {EN}
  9. Performing a standard RHEL 9 installation; Appendix B. Partitioning reference; URL: https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/9/html/performing_a_standard_rhel_9_installation/partitioning-reference_installing-rhel#recommended-partitioning-scheme_partitioning-reference
  10. Debian: Empfohlene Partitionsschemata. URL: https://www.debian.org/releases/bullseye/amd64/apcs03.de.html
  11. Wikipedia-Artikel zu LVM
  12. LVM – Debian Wiki {EN}
  13. Configuring and managing logical volumes. Red Hat Enterprise Linux 9. A guide to the configuration and management of LVM logical volumes. {EN}
  14. Appendix B. Partitioning reference. Performing a standard RHEL 9 installation. {EN}
  15. VMware ESXi: VMDK-Datei einer Gast-VM mit virt-sysprep bereinigen

Der Irrsinn mit den Zeitzonen

In diesem Beitrag möchte ich eine Lanze für die koordinierte Weltzeit (UTC) [1] brechen.

Die Geschichte dazu

Es waren einmal Alice und Bob. Diese lebten in unterschiedlichen Ländern auf unterschiedlichen Kontinenten unserer schönen Erde. Beide wollten sich zu einer Videokonferenz verabreden, am Samstag, dem 1.4.2023 um 11:00 Uhr (IST). Wobei (IST) die Abkürzung für die verwendete Zeitzone ist (siehe [2]).

Leider verharrten Alice und Bob jeweils allein im Videokonferenzraum und fanden nicht zueinander. Denn während Alice (IST) als Irish Standard Time (UTC+01) interpretierte, richtete sich Bob nach (IST) wie in Indian Standard Time (UTC+05:30). Schade, so haben sich die zwei um 4,5 Stunden verpasst.

Das Problem

Die Angabe der Zeitzone erfolgt überwiegend als Drei-Buchstaben-Akronym. Ungünstigerweise sind diese Akronyme häufig nicht eindeutig.

So findet das Akronym IST z.B. für folgende Zeitzonen Verwendung:

  • Indian Standard Time (UTC+05:30)
  • Irish Standard Time (UTC+01)
  • Israel Standard Time (UTC+02)

Und es lassen sich weitere schöne Beispiele finden. Hier nur eine kleine Auswahl:

AMT für:

  • Amazon Time (Brazil) (UTC-04)
  • Armenia Time (UTC+04)

AST für:

  • Arabia Standard Time (UTC+03)
  • Atlantic Standard Time (UTC-04)

CST für:

  • Central Standard Time (UTC-06)
  • China Standard Time (UTC+08)
  • Cuba Standard Time (UTC-05)

Hach, was habe ich es gut. Ich lebe im Winter in den Zeitzonen CET und MET. Bzw. im Sommer dementsprechend in CEST und MEST. Da ist es dann auch genauso spät

wie in IST. Ach Moment, welches IST ist das denn jetzt schon wieder?

Von der zusätzlichen Komplexität, welche durch die Zeitumstellung zum Winter bzw. Sommer entsteht, möchte ich gar nicht erst anfangen.

Doch verzagt nicht, es besteht Hoffnung, dass Alice und Bob doch noch zueinander finden.

Die koordinierte Weltzeit (UTC)

Wie bei allen anderen Zeitzonen auch wird bei der UTC [1] die Welt in Zonen eingeteilt. Der Vorteil in der Verwendung besteht darin, dass Alice und Bob sich nicht mehr darum kümmern müssen, in welcher Zeitzone der jeweils andere lebt und wie viel Uhr 10:00 (EDT) wohl in IST oder GMT+8 sein mag. Sie müssen sich nur merken, wie viele Stunden sie selbst der UTC-Zeit voraus bzw. hinterher sind.

Beispiel:
Meine lokale Zeit entspricht im Winter der Zone UTC+01 und im Sommer, wenn wir die Uhr eine Stunde vorstellen, der Zone UTC+02. Das kann ich mir einfach merken. Wenn sich jemand mit mir um 15:00 (UTC) treffen möchte, weiß ich abhängig von der Jahreszeit, dass ich entweder um 16:00 Uhr oder um 17:00 Uhr meiner lokalen Zeit am vereinbarten Treffpunkt sein muss.

Möchte ich mich selbst verabreden und meinem Besuch ersparen, meine Zeitzone zu raten oder die Zeit umrechnen zu müssen, rechne ich meine lokale Zeit einfach in UTC um. So entspricht in diesem Monat 15:00 Uhr (UTC+02) ganz einfach 13:00 Uhr (UTC). Lebt mein Besuch in UTC-03, so kann er leicht bestimmen, dass ich ihn um 10:00 Uhr seiner lokalen Zeit erwarte.

Das Happy End

Alice und Bob haben sich darauf geeinigt, zukünftig die koordinierte Weltzeit zu verwenden. Alice lebt in Irland und möchte sich mit Bob verabreden, wenn es bei ihr 10:00 Uhr ist. Die Zeitzone von Alice entspricht UTC+01. Sie verabredet sich mit Bob um 09:00 Uhr (UTC).

Bob weiß, dass er 5,5 Stunden zur UTC-Zeit hinzuaddieren muss, um seine lokale Zeit zu bestimmen. Er wählt sich also um 14:30 Uhr (UTC+05:30) in die Videokonferenz ein.

Und wenn sie nicht gestorben sind, so zoomen sie noch heute.

Zusammenfassung

Ich hoffe, diese kleine Geschichte hat euch ein wenig unterhalten und die Vorteile, die sich aus der Verwendung der koordinierten Weltzeit ergeben, deutlich gemacht.

Bis neulich (in UTC).

  1. https://de.wikipedia.org/wiki/Koordinierte_Weltzeit
  2. https://en.wikipedia.org/wiki/List_of_time_zone_abbreviations (EN)
  3. https://de.wikipedia.org/wiki/Drei-Buchstaben-Akronym

Virtuellen Maschinen mithilfe der PowerCLI RAM hinzufügen oder entfernen

In diesem Tutorial beschreibe ich, wie mithilfe der PowerCLI die RAM-Größe einer virtuellen Maschine (VM) bearbeitet werden kann. Diese Methode lässt sich auch anwenden, um mehrere VMs in einem Arbeitsablauf zu bearbeiten. Dies bietet sich z.B. immer dann an, wenn so viele VMs betroffen sind, dass der Aufwand der manuellen Bearbeitung im vSphere-Client zu groß erscheint.

Die Idee hierzu stammt ursprünglich aus dem Artikel PowerShell Friday: Adding Memory with PowerCLI von Anne Jan Elsinga aus dem Jahr 2015.

Zielstellung

Es soll die Größe des Arbeitsspeichers von zunächst einer und anschließend mehrerer VMs bearbeitet werden. Dabei wird gezeigt, wie RAM im laufenden Betrieb erhöht und bei ausgeschalteten VMs reduziert werden kann.

Voraussetzungen

Eine funktionsfähige Installation der VMware PowerCLI und die Möglichkeit den vCenter Server über diese ansprechen zu können, ist Voraussetzung, um diesem Tutorial zu folgen.

Um den RAM einer VM im laufenden Zustand erhöhen zu können, muss die Option Memory Hot Plug der betreffenden VM aktiviert sein.

Anmeldung am vCenter

Zu Beginn verbindet man sich zu der vCenter-Instanz, deren VMs man bearbeiten möchte. Das Kommando hat folgenden Aufbau:

Connect-VIServer [-Server] <String[]> [-Protocol {http | https}] [-User <String>]

Beispiel:

Connect-VIServer -Server vcsa.beispiel.de -Protocol https -User alice@vsphere.local

Beispiel 1: RAM einer einzelnen VM erhöhen

Dieses Beispiel ist direkt dem Artikel PowerShell Friday: Adding Memory with PowerCLI entnommen.

Der Befehl ist ein Einzeiler:

Get-VM -Name MeineVM | Set-VM -MemoryGB 2

Werte kleiner GB werden dezimal spezifiziert:

Get-VM -Name MeineVM |Set-VM -MemoryGB 0.75

Beispiel 2: RAM mehrerer VMs erhöhen

Angenommen in meiner Umgebung existieren mehrere VMs, die nach dem Muster VM-Test- benannt sind, deren RAM auf 24 GB erhöht werden soll.

Zuerst kann man sich die gewünschte Zielgruppe anzeigen lassen:

PS C:\Users\joerg> Get-VM | Where-Object {$_ | Select-String -pattern "VM-Test-\d"} | Sort

Name          PowerState Num CPUs MemoryGB
----          ---------- -------- --------
VM-Test-01    PoweredOn  4        16.000
VM-Test-02    PoweredOn  4        16.000
VM-Test-03    PoweredOn  4        16.000
VM-Test-04    PoweredOn  4        16.000
VM-Test-05    PoweredOn  4        16.000
VM-Test-07    PoweredOn  4        16.000
VM-Test-08    PoweredOn  4        16.000
VM-Test-09    PoweredOn  4        16.000
VM-Test-10    PoweredOn  4        16.000
VM-Test-11    PoweredOn  4        16.000
VM-Test-12    PoweredOn  4        16.000
VM-Test-13    PoweredOn  4        16.000
VM-Test-14    PoweredOn  4        16.000
VM-Test-15    PoweredOn  4        16.000
VM-Test-17    PoweredOn  4        16.000
VM-Test-18    PoweredOn  4        16.000

Der Platzhalter ‚\d‘ steht dabei für beliebige Dezimalzahl.

Der RAM kann nun wie folgt auf jeweils 24 GB erhöht werden:

PS C:\Users\joerg> Get-VM | Where-Object {$_ | Select-String -pattern "VM-Test-\d"} | Set-VM -MemoryGB 24

Confirmation
Proceed to configure the following parameters of the virtual machine with name 'VM-Test-01'?
New MemoryMB: 24765MB
[Y] Yes  [A] Yes to All  [N] No  [L] No to All  [S] Suspend  [?] Help (default is "Y"): A

Name          PowerState Num CPUs MemoryGB
----          ---------- -------- --------
VM-Test-01    PoweredOn  4        24.000
VM-Test-02    PoweredOn  4        24.000
VM-Test-03    PoweredOn  4        24.000
VM-Test-04    PoweredOn  4        24.000
VM-Test-05    PoweredOn  4        24.000
VM-Test-07    PoweredOn  4        24.000
VM-Test-08    PoweredOn  4        24.000
VM-Test-09    PoweredOn  4        24.000
VM-Test-10    PoweredOn  4        24.000
VM-Test-11    PoweredOn  4        24.000
VM-Test-12    PoweredOn  4        24.000
VM-Test-13    PoweredOn  4        24.000
VM-Test-14    PoweredOn  4        24.000
VM-Test-15    PoweredOn  4        24.000
VM-Test-17    PoweredOn  4        24.000
VM-Test-18    PoweredOn  4        24.000

Beispiel 3: RAM einer VM reduzieren

Auch dieses Beispiel ist direkt dem Artikel PowerShell Friday: Adding Memory with PowerCLI entnommen.

Die betroffene VM muss dazu ausgeschaltet werden:

Get-VM -Name MeineVM | Shutdown-VMGuest|Set-VM -MemoryGB 0.25

Zusammenfassung

Mit der PowerCLI ist es möglich sich wiederholende Tätigkeiten abarbeiten zu lassen. Dies spart Zeit und Nerven.

Mir hat der Tipp von Anne Jan Elsinga sehr geholfen, weshalb ich die Methode hier für mich, euch und die Nachwelt dokumentiert habe.

RHEL System Roles: firewall

In Teil 5 meiner losen Reihe über die RHEL System Roles stelle ich die Rolle firewall vor. Diese dient der Konfiguration des Regelwerks für firewalld. Möchte man bestimmte Regelsätze für alle bzw. eine Gruppe von Servern konfigurieren, erleichtert der Einsatz dieser Rolle die Arbeit und reduziert den administrativen Aufwand.

Im Folgenden stelle ich meinen Anwendungsfall vor. Anschließend beschreibe ich, wie ich diesen mithilfe der RHEL System Role löse.

Während mir dieser Artikel zur Dokumentation dient, soll er euch den Einsatz von RHEL Roles verdeutlichen.

Warnung: Die Firewall-Konfiguration eines Hosts über das Netzwerk birgt die Gefahr, sich selbst auszusperren. Wenn dies passiert, benötigt man höchstwahrscheinlich physischen Zugriff auf den verkonfigurierten Host.

Anwendungsfall

Ich möchte sicherstellen, dass auf allen RHEL-Systemen in meiner Labor-Umgebung das Paket firewalld installiert ist, der Service aktiviert ist und läuft. Darüber hinaus möchte ich sicherstellen, dass ausschließlich der SSH-Zugriff in der lokalen Hostfirewall freigegeben ist und alle übrigen Regeln entfernt werden.

Die Rolle

Durch die Installation des Pakets rhel-system-roles existiert diese Rolle bereits auf meinem System und muss nur noch konfiguriert werden. Die Rolle selbst findet man im Pfad /usr/share/ansible/roles/rhel-system-roles.firewall/ und die Dokumentation in /usr/share/doc/rhel-system-roles/firewall/README.md. Aus letzterer stammt auch folgendes Beispiel:

---
- name: Erase existing config and enable ssh service
  hosts: myhost

  vars:
    firewall:
      - previous: replaced
      - service: 'ssh'
        state: 'enabled'
  roles:
    - rhel-system-roles.firewall

Dieses Beispiel kann ich direkt in das folgende Playbook übernehmen.

Das Playbook

Das Playbook ist kompakt und übersichtlich:

---
- name: Ensure firewalld is started with SSH-acess only
  hosts: all

  vars:
    firewall:
      - previous: replaced
      - service: 'ssh'
        state: 'enabled'
  roles:
    - rhel-system-roles.firewall

Der folgende Playbook-Lauf in meiner Labor-Umgebung zeigt, dass sich die RHEL System Role auch um die Installation, Aktivierung und den Start des Dienstes firewalld kümmert, wenn dies erforderlich ist.

[root@ansible-ctrl ansible]# ansible-playbook firewall_config.yml 

PLAY [Ensure firewalld is started with SSH-acess only] ************************************

TASK [Gathering Facts] ********************************************************************
ok: [rhel7]
ok: [ansible-pctrl]
ok: [rhel9]
ok: [rhel8]

TASK [rhel-system-roles.firewall : include_tasks] *****************************************
included: /usr/share/ansible/roles/rhel-system-roles.firewall/tasks/firewalld.yml for ansible-pctrl, rhel7, rhel8, rhel9

TASK [rhel-system-roles.firewall : Ensure ansible_facts used by role] *********************
ok: [rhel7]
ok: [rhel9]
ok: [ansible-pctrl]
ok: [rhel8]

TASK [rhel-system-roles.firewall : Install firewalld] *************************************
ok: [ansible-pctrl]
changed: [rhel9]
changed: [rhel8]
changed: [rhel7]

TASK [rhel-system-roles.firewall : Install python-firewall] *******************************
skipping: [ansible-pctrl]
skipping: [rhel8]
skipping: [rhel9]
ok: [rhel7]

TASK [rhel-system-roles.firewall : Install python3-firewall] ******************************
skipping: [rhel7]
ok: [rhel9]
ok: [ansible-pctrl]
ok: [rhel8]

TASK [rhel-system-roles.firewall : Enable and start firewalld service] ********************
ok: [ansible-pctrl]
changed: [rhel7]
changed: [rhel9]
changed: [rhel8]

TASK [rhel-system-roles.firewall : Check if previous replaced is defined] *****************
ok: [rhel7]
ok: [ansible-pctrl]
ok: [rhel9]
ok: [rhel8]

TASK [rhel-system-roles.firewall : Get config files, checksums before and remove] *********
ok: [rhel9]
ok: [rhel7]
ok: [rhel8]
ok: [ansible-pctrl]

TASK [rhel-system-roles.firewall : Configure firewall] ************************************
ok: [rhel7] => (item={'service': 'ssh', 'state': 'enabled'})
ok: [rhel9] => (item={'service': 'ssh', 'state': 'enabled'})
ok: [rhel8] => (item={'service': 'ssh', 'state': 'enabled'})
ok: [ansible-pctrl] => (item={'service': 'ssh', 'state': 'enabled'})

TASK [rhel-system-roles.firewall : gather firewall config information] ********************
skipping: [ansible-pctrl] => (item={'service': 'ssh', 'state': 'enabled'}) 
skipping: [rhel9] => (item={'service': 'ssh', 'state': 'enabled'}) 
skipping: [rhel7] => (item={'service': 'ssh', 'state': 'enabled'}) 
skipping: [rhel8] => (item={'service': 'ssh', 'state': 'enabled'}) 

TASK [rhel-system-roles.firewall : update firewalld_config fact] **************************
skipping: [rhel7]
skipping: [ansible-pctrl]
skipping: [rhel9]
skipping: [rhel8]

TASK [rhel-system-roles.firewall : gather firewall config if no arguments] ****************
skipping: [ansible-pctrl]
skipping: [rhel7]
skipping: [rhel9]
skipping: [rhel8]

TASK [rhel-system-roles.firewall : update firewalld_config fact] **************************
skipping: [ansible-pctrl]
skipping: [rhel7]
skipping: [rhel9]
skipping: [rhel8]

TASK [rhel-system-roles.firewall : Get config files, checksums after] *********************
ok: [rhel7]
ok: [rhel9]
ok: [ansible-pctrl]
ok: [rhel8]

TASK [rhel-system-roles.firewall : Calculate what has changed] ****************************
changed: [ansible-pctrl]
changed: [rhel7]
changed: [rhel9]
changed: [rhel8]

TASK [rhel-system-roles.firewall : Show diffs] ********************************************
skipping: [ansible-pctrl]
skipping: [rhel8]
skipping: [rhel7]
skipping: [rhel9]

PLAY RECAP ********************************************************************************
ansible-pctrl              : ok=11   changed=1    unreachable=0    failed=0    skipped=6    rescued=0    ignored=0   
rhel7                      : ok=11   changed=3    unreachable=0    failed=0    skipped=6    rescued=0    ignored=0   
rhel8                      : ok=11   changed=3    unreachable=0    failed=0    skipped=6    rescued=0    ignored=0   
rhel9                      : ok=11   changed=3    unreachable=0    failed=0    skipped=6    rescued=0    ignored=0

Fazit

Ich beginne, mich an dieser Stelle zu wiederholen. Auch diesmal war es möglich, mithilfe einer RHEL System Role einen einfachen Anwendungsfall schnell und unkompliziert zu lösen, ohne selbst eine Ansible-Rolle schreiben zu müssen. Ein einfaches Copy-Past-and-Modify genügte.

In meinen Augen ist es Red Hat gelungen, den System-Administratoren mit den RHEL System Roles etwas Arbeit abzunehmen und sie beim Einsatz von Ansible zu unterstützen.

Lasst euch überraschen, welche Rolle ich mir als nächstes herauspicke.

Quellen und weiterführende Links

  1. Red Hat Enterprise Linux (RHEL) System Roles {en}
  2. Ansible Documentation: Role Directory Structure {en}
  3. Red Hat Software and Download Center {en}
  4. Die Vorteile einer Red Hat Subskription
  5. RHEL System Roles: selinux
  6. RHEL System Roles: timesync
  7. RHEL System Roles: sshd

Ansible: Seafile Professional Edition in Rootless-Podman-Umgebung bereitstellen

Wer diesen Blog regelmäßig liest, kann den Eindruck gewinnen, es sei mein Hobby, Ansible-Rollen zu schreiben, mit denen von mir genutzte Web-Anwendungen auf Servern bereitgestellt werden können. Dieses Mal habe ich es mit Seafile getan und möchte in diesem Beitrag darüber berichten.

Was ist Seafile?

Seafile ist eine Sync&Share- bzw. Private-Cloud-Lösung ähnlich wie Nextcloud, ownCloud oder TeamDrive. Auf mich erweckt Seafile den Eindruck, als wenn der Schwerpunkt jedoch auf der Synchronisation und dem Teilen von Dateien liegt und damit genau meinem Suchmuster entspricht.

Seafile gibt es in einer Community und einer Professional Edition. Die Professional Edition darf mit bis zu drei Benutzern kostenlos verwendet werden.

Für weiterführende Informationen wird auf die Seiten des Herstellers und den Wikipedia-Artikel verwiesen.

Was ist das Ziel?

Nun, es gibt nicht das eine Ziel. Ich habe mit diesem kleinen Wochenendprojekt folgende Ziele verfolgt:

  • Beschäftige dich mit Ansible.
  • Beschäftige dich mit der Collection Containers.Podman.
  • Beschäftige dich mit rootless Podman.
  • Deploye Seafile Professional Edition in einer rootless-Podman-Umgebung, um es als Sync&Share-Lösung nutzen zu können.

Die Vorgehensweise

Zuerst habe ich mich informiert, ob es Container-Images für Seafile gibt und ob entsprechende Installationswege in der Dokumentation beschrieben sind. Meine Recherche förderte folgende Treffer zutage:

Ansible-Rollen haben eine einheitliche Struktur. Mit dem Befehl ansible-galaxy role init ansible_role_deploy_seafile_with_rootless_podman habe ich das Grundgerüst für meine Rolle erstellt. Anschließend habe ich die notwendigen Dateien {defaults,meta,tasks,vars}/main.yml mit Inhalt gefüllt und nicht benötigte Verzeichnisse wie handlers gelöscht. Mir ist dabei wichtig, dass alle notwendigen Parameter über Variablen definiert werden, die in defaults/main.yml zu finden sind. In vars/main.yml befinden sich hingegen nur Variablen, welche intern von der Rolle verwendet werden und vom Benutzer nicht explizit gesetzt werden sollen. So lässt sich die Rolle leicht wiederverwenden, um verschiedene Seafile-Instanzen auf dem gleichen Host oder in unterschiedlichen Umgebungen zu deployen.

Bevor ich die Rolle zum ersten Mal auf meinen Server angewendet habe, habe ich sie mit yamllint und ansible-lint geprüft und vorhandene Warnungen und Fehler behoben. Allerdings lassen sich mit den Lint-Werkzeugen und der Option --syntax-check nicht alle Fehler im Vorfeld finden. Da mir ein zweites Augenpaar fehlte, habe ich die letzten Tippfehler erst durch die Verwendung des Ansible Playbook Debugger gefunden.

Das Ergebnis

Das Ergebnis findet ihr auf:

Unter allen drei URLs könnt ihr meine Rolle herunterladen. Es ist damit möglich, eine lauffähige Seafile Pro Instanz bereitzustellen. Ein Test auf Idempotenz und ob diese Rolle auch zur Aktualisierung einer bestehenden Umgebung genutzt werden kann, steht noch aus.

Ihr seid herzlich eingeladen, die Rolle bei Interesse zu testen. Ich freue mich über Rückmeldungen zur Rolle und Dokumentation (Readme.md).

Ich habe das Deployment bisher nur auf Debian Buster getestet. Daher freue ich mich besonders über Rückmeldungen, wenn ihr die Rolle erfolgreich auf anderen Plattformen angewendet habt. Dann kann ich die entsprechenden Angaben für Ansible Galaxy ergänzen.

Eure Rückmeldungen nehme ich in den Kommentaren zu diesem Beitrag, per E-Mail oder in meinem neuen Matrix-Kanal #my-it-brain:matrix.org entgegen.

Fragen an meine Leser*innen

Ich interessiere mich für Themen rund um Ansible und Podman und frage mich, wie dies bei euch aussieht. Daher freue ich mich, wenn ihr in den Kommentaren oder gern auch per E-Mail und Chat folgende Fragen beantworten mögt:

  • Verwendet ihr Ansible für Software-Deployments?
  • Kennt ihr Podman und nutzt ihr es im privaten und/oder beruflichen Umfeld?
  • Findet ihr die Nutzung von Ansible zur Bereitstellung von Software auf (rootless) Podman sinnvoll? Oder bevorzugt ihr andere Bereitstellungsverfahren?

Ich freue mich auf eure Antworten.

Erfahrungsbericht zu den Chemnitzer Linux-Tagen 2023

Endlich sind wieder Chemnitzer Linux-Tage vor Ort in der Karl-Marx-Stadt. Für mich beginnen diese schon Wochen vorher, wenn die Vorfreude auf dieses Ereignis einsetzt.

Wenn dieser Erlebnisbericht veröffentlicht wird, ist die Konferenz leider schon wieder vorbei. Wie es war, erfahrt ihr im nun folgenden Text.

Anreise

Nach der Vorfreude kommt die Anreise. Bisher bin ich immer mit dem Auto nach Chemnitz gefahren. Von meinem Wohnort aus war ich regelmäßig nach 3,5-4,5 Std. im Hotel, inkl. Pause, Tanken, Essen und Erleichtern.

Ich mag Autofahrten. Ich kann während der Fahrt entspannen, meine Musik so laut hören, wie ich mag und muss keine anderen Menschen neben mir dulden. Es ist für mich eine komfortable Art zu reisen. Einziger Nachteil, ich kann während der Fahrt nicht arbeiten, bloggen, etc.

Da mich diesmal mein Umweltgewissen plagte und ich die Zeit besser nutzen wollte, habe ich meine Reise mit der Bahn geplant. Um nicht ganz so unkomfortabel zu reisen, habe ich 1. Klasse gebucht. Kann man frühzeitig planen und Sparpreisangebote nutzen, ist der Preis gegenüber der 2. Klasse durchaus gerechtfertigt, zumal die Sitzplatzreservierung schon mit inbegriffen ist.

Ganz ohne Auto geht es dennoch nicht. Da ich den ersten Fernverkehrsbahnhof mit dem ÖPNV erst nach 1-1,5 Std. erreicht hätte, bin ich in 40 Min. mit dem Auto zum nächsten kostenlosen Park&Ride-Parkplatz gefahren und von dort mit der Stadtbahn weiter zum Hauptbahnhof. Hier ging meine Reise mit 7 Minuten Zugverspätung weiter. Bei einer geplanten Umstiegszeit von 8 Minuten sah ich meinen Anschlusszug schon ohne mich fahren. Doch auf unsere Bahn ist Verlass. Auch der Anschlusszug hatte Verspätung, sodass ich wie geplant mit diesem weiterreisen konnte.

In Leipzig wurde es dann auch nochmal kurz hektisch, da für den Umstieg nur 4 Minuten verblieben. Für derartige Sprints bin ich definitiv zu unsportlich. Doch auch hier habe ich den Anschluss noch erreicht und traf in einem sehr vollen RE auf die ersten CLT-Teilnehmerinnen und Teilnehmer. So verging auch die letzte Stunde der Anreise wie im Flug.

Insgesamt war die Anreise sehr entspannt, bequem und angenehm. WLAN funktionierte im ICE und IC durchgängig und ich konnte so mobil arbeiten.

Die Chemnitzer Linux-Tage 2023

Nun habe ich der Anreise soviel Raum gewidmet und weiß gar nicht, was ich groß über die Veranstaltung selbst schreiben soll. Dies ist vielleicht noch dem tollen Gefühl geschuldet, die Community endlich mal wieder vor Ort getroffen zu haben.

Laut Resümee der Veranstalter kamen rund 3000 Besucherinnen und Besucher zur Veranstaltung. Somit gab es reichlich Gelegenheit zum Fachsimpeln, Netzwerken und es einfach mal zu genießen, unter normalen Menschen zu sein.

Am Samstag habe ich zwei Vorträge besucht:

Mehr war nicht drin. Denn es war einfach zu schön, alte Bekannte wiederzutreffen und neue Nerds kennenzulernen. Nach drei Jahren Pause war mir dies ein Fest.

Das Bild zeigt Mitglieder der Red Hat Accelerators und Ubuntuusers Community vor dem Ubuntu Stand auf den Chemnitzer LInux-Tagen 2023.
Gruppenfoto mit Mitgliedern der Red Hat Accelerators und Ubuntuusers Community vor dem Ubuntu-Stand auf den Chemnitzer Linux-Tagen 2023.

Im Laufe des Tages haben Dirk, Sujeevan und ich noch unseren Gemeinschaftsvortrag geprobt. Wir konnten während des Tages bereits auffällig oft vernehmen, dass etliche Personen diesen unbedingt hören wollten. Bloß keinen Druck aufkommen lassen. ;-)

Die Samstagabendveranstaltung fand in diesem Jahr in der Mensa statt, welche schräg gegenüber dem Hörsaalgebäude liegt. In meinen Augen war es eine gute Entscheidung, das Abendprogramm hierhin zu verlegen. Hier konnte man gemütlich zusammensitzen und ein wenig essen, trinken und plaudern. Das Essen war übrigens großartig!

Nur die Musik passte meiner Meinung nach nicht so recht zum Publikum. Statt Gesang mit musikalischer Begleitung auf dem Flügel hätte ich mir eher ein paar Arcade-Sounds aus 8-Bit-Midi-Prozessoren gewünscht.

Am Sonntag hatte ich die Ehre, um 10:00 Uhr einen der ersten Vorträge (Link zur Aufzeichnung) des Tages zu halten. Der Raum war voll, die Moderation spitze (Danke Henning) und auch die kleine Live-Demo hat geklappt. Im Anschluss konnte ich noch einige Fragen zu Ansible beantworten und durfte positives Feedback entgegennehmen. Lieben Dank an meine Hörerinnen und Hörer. Es war mir ein Fest, vor euch sprechen zu dürfen.

Viel Zeit zum Ausruhen gab es nicht, denn um 13:00 Uhr erläuterten Dirk, Sujeevan und ich, warum man nicht in der IT arbeiten sollte und warum wir es trotzdem tun (Link zur Aufzeichnung). Ich glaube, das Publikum im gut gefüllten Hörsaal V5 hatte Spaß mit uns. :-)

Auch nach diesem Vortrag durften wir einiges an positivem Feedback entgegennehmen und haben Fragen beantwortet. Ich wiederhole mich gern: „Es war mir auch diesmal ein Fest.“ :-)

Fazit

Danke an das Veranstaltungs-Team der Chemnitzer Linux-Tage für die Ausrichtung dieser großartigen Veranstaltung und auch allen Besucherinnen und Besuchern, dass sie diese Konferenz zu einem der schönsten Community-Treffen in Deutschland machen. Ich freue mich schon heute auf ein Wiedersehen im nächsten Jahr!

Dank der Deutschen Bahn habe ich die Rückreise nicht entspannt im Zug, sondern in einem Mietwagen zurückgelegt. Doch dieses Ärgernis soll das schöne Wochenende nicht trüben.

Wie hat euch die Veranstaltung insgesamt gefallen? Welche Vorträge oder Workshops habt ihr besucht und wie fandet ihr sie? Schreibt mir eure Erfahrungen gern in die Kommentare oder hinterlasst einen Link zu eurem Erfahrungsbericht. Dann freue ich mich. :-)

RHEL System Roles: sshd

In Teil 4 meiner losen Reihe über die RHEL System Roles stelle ich die Ansible-Rolle sshd vor. Diese dient der Konfiguration des OpenSSH-Servers, einem der wichtigsten Dienste in Linux- und UNIX-Systemen.

Wer die ersten Teile dieser Reihe gelesen hat, ist inzwischen mit der grundsätzlichen Anwendung dieser Ansible-Rollen vertraut. Die Rolle sshd bildet hier keine Ausnahme. Wendet man die Rolle ohne weitere Konfiguration auf Ziel-Systeme an, konfiguriert sie den OpenSSH-Server entsprechend der Standard-Konfiguration des jeweiligen Betriebssystems. Es werden alle Optionen der sshd_config(5) unterstützt.

Ein Wort der Warnung: Mit dieser Rolle konfiguriert ihr den SSH-Dienst der Zielsysteme. Wenn dabei ein Fehler passiert, könnt ihr euch und euren Ansible-Controller aussperren und verliert ggf. den Zugriff auf die Systeme. Behaltet dies bitte im Hinterkopf und sorgt ggf. für alternative Zugänge, wie z.B. über eine lokale Konsole.

Bei der Konfiguration meiner Server ist mir persönlich wichtig, dass

  • der Benutzer root sich nur mittels SSH-Public-Key-Verfahren anmelden kann,
  • die Public-Key-Authentifizierung aktiviert ist,
  • die Passwort-Authentifizierung deaktiviert ist und
  • in der Datei .ssh/authorized_keys des jeweiligen Benutzers nach dem SSH-Public-Key gesucht wird.

Darüber hinaus möchte ich alle Git-bezogenen Umgebungsvariablen (GIT_*) nutzen. Die übrigen Einstellungen möchte ich auf den Standard-Werten des jeweiligen Betriebssystems belassen.

Im Folgenden beschreibe ich, wie sich diese mit der RHEL System Role sshd umsetzen lässt.

Voraussetzungen

Wie bei allen RHEL System Roles müssen auch hier die Pakete ansible-core und rhel-system-roles inkl. ihrer Abhängigkeiten auf dem Ansible-Controller installiert sein. Der Ansible-Controller muss die Ziel-Hosts über SSH erreichen können und über einen Benutzer mit sudo-Berechtigungen verfügen.

Das Playbook

Es werden bereits zwei Beispiel-Playbooks mitgeliefert, die sich im Pfad /usr/share/doc/rhel-system-roles/sshd/ befinden. Diese heißen:

  • example-accept-env-playbook.yml und
  • example-root-login-playbook.yml.

Aus diesen beiden Beispieldateien habe ich das folgende Playbook für meine Labor-Umgebung erstellt:

---
- hosts: all
  tasks:
  - name: Configure sshd to accept some useful environment variables
    include_role:
      name: rhel-system-roles.sshd
    vars:
      sshd:
        PermitRootLogin: without-password
        PasswordAuthentication: no
        PubkeyAuthentication: yes
        AuthorizedKeysFile: .ssh/authorized_keys
        # there are some handy environment variables to accept
        AcceptEnv:
          LANG
          LS_COLORS
          EDITOR
          GIT_*

Wie zu sehen ist, habe ich mich entschieden, noch ein paar weitere Umgebungsvariablen zu konfigurieren. Diese habe ich aus dem Beispiel example-accept-env-playbook.yml übernommen.

Testlauf in Labor-Umgebung

Auch dieses Playbook habe ich in meiner Labor-Umgebung, bestehend aus einem RHEL8-Ansible-Controller und jeweils einem rhel{7..9}-Client laufen lassen. Mit den Optionen -C -D ist die Ausgabe 707 Zeilen lang, weswegen der folgende Code-Block nur den Aufruf und das Ergebnis zeigt.

[root@ansible-ctrl ansible]# ansible-playbook sshd_config.yml -C -D

PLAY [all] ************************************************************************************************************
[...]
PLAY RECAP *******************************************************************************************************************************
ansible-pctrl              : ok=20   changed=2    unreachable=0    failed=0    skipped=13   rescued=0    ignored=0   
rhel7                      : ok=20   changed=2    unreachable=0    failed=0    skipped=13   rescued=0    ignored=0   
rhel8                      : ok=20   changed=2    unreachable=0    failed=0    skipped=13   rescued=0    ignored=0   
rhel9                      : ok=21   changed=2    unreachable=0    failed=0    skipped=12   rescued=0    ignored=0

Zusammenfassung

Die RHEL System Role sshd wurde kurz vorgestellt und genutzt, um meine bevorzugten Einstellungen für den OpenSSH-Dienst in meiner Labor-Umgebung zu konfigurieren. Alle Optionen in der sshd_config(5), welche ich nicht explizit über die Ansible-Rolle konfiguriert habe, werden auf die Standardwerte des Betriebssystems eingestellt. Es ist also ggf. Vorsicht geboten, wenn Systeme mit bestehender Konfiguration bearbeitet werden.

Selbstverständlich schützt ein einmaliger Playbook-Lauf nicht davor, dass ein Benutzer mit root-Berechtigungen lokale Änderungen an der Datei /etc/ssh/sshd_config vornimmt. Dies mag vorübergehend für Tests auch so gewollt sein. Damit die Konfiguration nicht dauerhaft vom SOLL-Zustand abweicht, kann man das Playbook regelmäßig durch cron(8) ausführen lassen, um evtl. Abweichungen zu korrigieren.

Quellen und weiterführende Links

  1. Red Hat Enterprise Linux (RHEL) System Roles {en}
  2. Ansible Documentation: Role Directory Structure {en}
  3. Red Hat Software and Download Center {en}
  4. Die Vorteile einer Red Hat Subskription
  5. RHEL System Roles: selinux
  6. RHEL System Roles: timesync
  7. RHEL System Roles: firewall

Meine neue berufliche Herausforderung in 2023

Wenn dieser Artikel erscheint, habe ich das Bielefelder IT-Service-Zentrum (BITS) der Universität Bielefeld und damit den öffentlichen Dienst nach acht Jahren verlassen. Seit dem 1. März arbeite ich als Senior Technical Account Manager – Platforms für die Red Hat GmbH in München. Ja, ich bin jetzt tatsächlich auf dem besten Weg, ein echter Red Hatter zu werden.

Warum?

Seit 2016 arbeite ich beruflich mit Red Hat Enterprise Linux (RHEL). Und seit 2019 bin ich stolz, zu den Red Hat Accelerators zu gehören. Beruflich habe ich mich jedoch nicht nur um Linux gekümmert.

Es fielen noch etliche weitere Themen in meinen Aufgabenbereich. In mir wuchs jedoch der Wunsch, meinen beruflichen Schwerpunkt in Richtung Linux und Open Source zu verlagern. So ist meine Motivation zum Jobwechsel, dass ich nun in einem Unternehmen arbeite, wo ich von Linux- und Open-Source-Experten umgeben bin. Hier kann ich jeden Tag mit und an Technologien arbeiten, die mich interessieren und meinen Kunden dabei helfen, diese in ihrem Umfeld optimal einzusetzen. Darüber hinaus habe ich hier die besten Chancen, mein Wissen zu erweitern und zu vertiefen. Dies freut mich sehr.

Hey, ich tue Dinge für und mit Open Source und werde dafür bezahlt. Was kann sich ein Linux-Nerd denn mehr wünschen?

Was ändert sich für das BITS?

Na hoffentlich nichts. :-)

Ich hoffe, dass ich euch in guter Erinnerung bleibe und euch von Zeit zu Zeit besuchen darf. Ich beobachte übrigens den Mensaplan. Wenn mal wieder der Burrito mit Wedges auf dem Speiseplan steht, begleite ich die Post-Pandemische-Peer-Group-01 gern zum Essen. ;-)

Was ändert sich für Red Hat?

Ich hoffe, dass durch meine Anstellung nicht gleich ein Ruck durch das ganze Unternehmen geht. Mein Team hat mit mir jetzt ein Mitglied mehr, welches neugierig ist, jeden Tag dazulernen möchte und bereit ist, euch mit Fragen zu löchern.

Habt vielen Dank für den tollen Empfang und die Aufnahme in den ersten Tagen. Ich freue mich auf die weitere Zusammenarbeit mit euch und darauf noch viele weitere Kolleg*innen kennenzulernen.

Was ändert sich für My-IT-Brain?

Hier ändert sich auch nichts. Dies ist und bleibt mein persönlicher Blog, in dem ich meine Meinung zu allen Themen schreibe, die mich interessieren. Die Artikel spiegeln dabei meine persönlichen Ansichten wider. Diese können mit denen meines Arbeitgebers übereinstimmen, müssen dies aber nicht.

Evtl. wird es hier in der nächsten Zeit ruhiger, während ich mich voll und ganz auf das Onboarding bei Red Hat konzentriere. In Zukunft dürft ihr aber wieder mit Artikeln, Anleitungen und Wochenend-Projekten rund um Linux und Open Source rechnen.

Wenn sich die Artikel zukünftig thematisch stärker mit RHEL und Fedora beschäftigen, liegt dies schlicht daran, dass ich mich mit diesen Distributionen stärker beschäftige als mit anderen. Berufliches und privates Interesse liegen bei mir schon immer eng beieinander.

Jetzt stürze ich mich ins Onboarding und versuche, so viel wie möglich von dieser neuen Welt im ersten Anlauf aufzunehmen. Bis neulich. :-)

RHEL System Roles: timesync

In diesem dritten Teil meiner Serie über RHEL System Roles nutze ich die Rolle timesync, um die NTP-Pool-Zone de.pool.ntp.org für meine Hosts zu konfigurieren.

Ich möchte mit diesem Artikel zeigen, wie einfach die Nutzung der RHEL System Roles ist, um eine Gruppe von RHEL-Servern zu konfigurieren. Dabei muss ich mich nicht um Details wie die Frage kümmern, ob auf meinen Zielhosts ntpd oder chronyd für die Zeitsynchronisierung genutzt wird. Diese Aufgabe löst die Ansible-Rolle für mich.

Bevor ich fortfahre, habe ich eine Warnung: Diese Rolle ersetzt die Konfiguration auf den Zielsystemen. Alle zuvor dort getroffenen Einstellungen werden verloren gehen.

Man muss sich also entscheiden, ob man die Zeitsynchronisation komplett über diese Rolle steuern möchte oder gar nicht.

Voraussetzungen

Auf dem Ansible-Controller müssen die Pakete ansible-core und rhel-system-roles installiert sein.

Das Playbook

Ich möchte mehrere NTP-Server konfigurieren. Für diesen Anwendungsfall liefert die Rolle timesync bereits ein Beispiel mit, welches ich mittels Copy-Paste-and-Modify in mein Playbook übernehme.

[root@ansible-ctrl ]# cp /usr/share/doc/rhel-system-roles/timesync/example-multiple-ntp-servers-playbook.yml ansible/use_de_ntp_servers.yml

Das Playbook sieht nach der Anpassung wie folgt aus:

- hosts: all
  vars:
    timesync_ntp_servers:
      - hostname: 0.de.pool.ntp.org
        iburst: yes
      - hostname: 1.de.pool.ntp.org
        iburst: yes
      - hostname: 2.de.pool.ntp.org
        iburst: yes
      - hostname: 3.de.pool.ntp.org
        iburst: yes
  roles:
    - rhel-system-roles.timesync

Testlauf in Labor-Umgebung

Um zu sehen, wie die Datei /etc/chrony.conf vor und nach dem Playbook-Lauf aussieht, lasse ich das Playbook zuerst mit den Optionen -C (aktiviert Check-Mode) und -D (zeigt die Änderungen an) laufen. So kann ich vorab prüfen, welche Änderungen vorgenommen werden, bevor es ernst wird. Die Ausgabe ist über 500 Zeilen lang. Ich habe sie auf Gist gepostet und hier eingebunden. Wer sich für die Ausgabe nicht interessiert, kann direkt zur Zusammenfassung springen.

Anschließend habe ich das Playbook ohne die Optionen -C und -D ausgeführt und meine Hosts wie gewünscht konfiguriert.

Zusammenfassung

Mit der RHEL System Role timesync kann die Zeitsynchronisation verschiedener RHEL-Releases schnell und einfach konfiguriert werden, ohne Kenntnis über die konkrete Implementierung auf den Zielsystemen zu besitzen.

Gleichzeitig kann ein Blick in die Struktur der Rolle und den Inhalt der dazugehörigen Dateien Aufschluss darüber geben, wie Ansible-Rollen für mehrere RHEL-Major-Releases erstellt werden können. Man kann dies für die Erstellung eigener Rollen mit ein wenig Transferleistung wiederverwenden.

  1. Red Hat Enterprise Linux (RHEL) System Roles {en}
  2. Ansible Documentation: Role Directory Structure {en}
  3. Red Hat Software and Download Center {en}
  4. Die Vorteile einer Red Hat Subskription
  5. RHEL System Roles: selinux
  6. RHEL System Roles: sshd
  7. RHEL System Roles: firewall