Archiv des Autors: Jörg Kastning

RHEL System Roles: storage

Willkommen zu Teil 6 meiner losen Reihe über die RHEL System Roles. In diesem Teil stelle ich euch die Rolle storage vor, mit welcher sich unpartitionierte Laufwerke und LVM-Volumes verwalten lassen.

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

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

Hinweis: Zum Zeitpunkt der Erstellung dieses Artikels unterstützt die Rolle die LVM-Konfiguration lediglich auf unpartitionierten Laufwerken, welche komplett als Physical Volume (PV) genutzt werden.

Wer sich an dieser Stelle fragt, was RHEL System Roles sind, wie man sie installiert und nutzt, dem empfehle ich am Anfang zu beginnen: Vorstellung der Red Hat Enterprise Linux (RHEL) System Roles.

Anwendungsfall

Mit der Ansible-Rolle kvm_provision_lab (siehe [1,2]) provisioniere ich virtuelle Maschinen (VM) auf KVM/QEMU-Hypervisoren. In „Labor-Umgebung mit Ansible in KVM erstellen“ habe ich die Anwendung dieser Rolle bereits detailliert beschrieben. Eine VM wird darin als ein YAML-Dictionary nach folgendem Muster definiert:

test-vm1:
    vm_ram_mb: 512
    vm_vcpus: 1
    vm_iftype: network
    vm_net: default
    os_type: rhel9
    file_type: qcow2
    base_image_name: rhel9-template
    vm_template: "rhel9-template"
    second_hdd: true
    second_hdd_size: "2G"

Das Beispiel im Code-Block provisioniert eine VM mit einem zweiten Blocklaufwerk. Dieses wird in der VM als /dev/vdb konfigruiert.

Um das zweite Laufwerk nutzen zu können, müssen zuerst eine Partitionstabelle und eine Partition erstellt und diese mit einem Dateisystem formatiert werden. Alternativ kann das Gerät auch für LVM verwendet werden.

Ich möchte aus /dev/vdb ein PV für LVM machen, um es einer Volume Group (VG) vg_data hinzuzufügen und ein Logical Volume (LV) zu erstellen, welches die gesamte Speicherkapazität von /dev/vdb nutzt.

Die Rolle

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

Example Playbook
----------------

```yaml
- hosts: all

  roles:
    - name: rhel-system-roles.storage
      storage_pools:
        - name: app
          disks:
            - sdb
            - sdc
          volumes:
            - name: shared
              size: "100 GiB"
              mount_point: "/mnt/app/shared"
              #fs_type: xfs
              state: present
            - name: users
              size: "400g"
              fs_type: ext4
              mount_point: "/mnt/app/users"
      storage_volumes:
        - name: images
          type: disk
          disks: ["mpathc"]
          mount_point: /opt/images
          fs_label: images

```

Da ich auf /dev/vdb ein LVM konfigurieren möchte, kopiere ich mir das Dictionary storage_pools aus obigen Beispiel und passe es für mein Playbook an.

Das Playbook

---
- hosts: test-vm1

  roles:
    - name: rhel-system-roles.storage
      storage_pools:
        - name: vg_data
          disks:
            - vdb
          volumes:
            - name: data1
              size: "2 GiB"
              mount_point: "/mnt"
              fs_type: ext4
              state: present

Obiges Playbook führt folgende Schritte auf dem Host test-vm1 durch:

  1. Das Blockgerät /dev/vdb wird als PV für LVM konfiguriert.
  2. Es wird die Volume Group (VG) vg_data auf dem PV /dev/vdb erstellt.
  3. In der VG vg_data wird das LV data1 erstellt.
  4. Das LV wird mit dem Dateisystem Ext4 formatiert.
  5. Das LV wird unterhalb von /mnt eingehängt.

Innerhalb des Gast-Betriebssystems lässt sich mit folgenden Kommandos prüfen, dass die Konfiguration wie gewünscht durchgeführt wurde.

[root@test-vm1 ~]# lsblk vdb
lsblk: vdb: not a block device
[root@test-vm1 ~]# lsblk /dev/vdb
NAME            MAJ:MIN RM SIZE RO TYPE MOUNTPOINTS
vdb             252:16   0   2G  0 disk 
└─vg_data-data1 253:0    0   2G  0 lvm  /mnt
[root@test-vm1 ~]# pvs
  PV         VG      Fmt  Attr PSize  PFree
  /dev/vdb   vg_data lvm2 a--  <2.00g    0 
[root@test-vm1 ~]# vgs
  VG      #PV #LV #SN Attr   VSize  VFree
  vg_data   1   1   0 wz--n- <2.00g    0 
[root@test-vm1 ~]# lvs
  LV    VG      Attr       LSize  Pool Origin Data%  Meta%  Move Log Cpy%Sync Convert
  data1 vg_data -wi-ao---- <2.00g                                                    
[root@test-vm1 ~]# mount | grep mnt
/dev/mapper/vg_data-data1 on /mnt type ext4 (rw,relatime,seclabel)
[root@test-vm1 ~]# echo "Hallo Welt!" >/mnt/world.txt
[root@test-vm1 ~]# cat /mnt/world.txt
Hallo Welt!

Fazit

Der betrachtete Anwendungsfall lässt sich mit der vorgestellten Ansible-Rolle schnell und einfach umsetzen. Man deklariert lediglich die Wunschkonfiguration im Ansible-Playbook und die Rolle kümmert sich um den Rest, wie die Installation der notwendigen Pakete auf den Zielsystemen.

Unterstützt werden als Zielsysteme aktuell EL 7-9 sowie Fedora. Damit ist sie für die Anwendung auf Debian bzw. darauf basierende Systeme nicht geeignet. Wie man auch für diese Systeme ein einfaches Playbook entwirft, um LVM für Blockgeräte zu konfigurieren, werde ich in einem folgenden Artikel zeigen.

Ich hoffe, dass euch auch die Vorstellung dieser Rolle gefallen hat und wünsche euch viel Spaß bei der Nutzung der RHEL System Roles.

  1. https://galaxy.ansible.com/Tronde/kvm_provision_lab
  2. https://github.com/Tronde/kvm_provision_lab
  3. https://github.com/linux-system-roles/storage
  4. Vorstellung der Red Hat Enterprise Linux (RHEL) System Roles
  5. RHEL System Roles: selinux
  6. RHEL System Roles: timesync
  7. RHEL System Roles: sshd
  8. RHEL System Roles: firewall

Utilize PowerCLI to resize VMDK files of multiple VMs

This is the translated version of an article written in German originally. I translated it as a non-German speaking person has shown interest in the topic.

Disclaimer: This tutorial comes without warranty and support. Use at your own risk.

In this tutorial, I would like to show a minimal example on how selected VMDK files of specific VMs can be resized with using the PowerCLI.

This is useful, for example, when so many VMs are affected that the time and effort required to manually enlarge them via the vSphere (web) client seems too great.

Only the resizing of the VMDK file is considered here. The subsequent resizing of the partition and file system within the guest operating system, which is also necessary, is not part of this tutorial.

Goal

For a minimal example, from a group of VMs the second and third hard disk of VM-Test-5 and VM-Test-6 are to be enlarged. The respective second hard disk is to be enlarged from 250 GB to 500 GB and the respective third hard disk is to be enlarged from 400 GB to 800 GB.

Requirements

A working installation of the VMware PowerCLI and the ability to access the vCenter Server is a prerequisite to follow this tutorial.

Here we go

The following code block shows how the necessary information about the VMs is read out to be processed.

PowerCLI C:\Scripts> Get-VM | Where-Object {$_ | Select-String -pattern "VM-Test-\d"}

Name                 PowerState Num CPUs MemoryGB
----                 ---------- -------- --------
VM-Test-5        PoweredOn  4        24.000
VM-Test-7        PoweredOn  4        16.000
VM-Test-6        PoweredOn  4        24.000


PowerCLI C:\Scripts> Get-VM | Where-Object {$_ | Select-String -pattern "VM-Test-[5,6]{1}"}

Name                 PowerState Num CPUs MemoryGB
----                 ---------- -------- --------
VM-Test-5        PoweredOn  4        24.000
VM-Test-6        PoweredOn  4        24.000


PowerCLI C:\Scripts> $VM = Get-VM | Where-Object {$_ | Select-String -pattern "VM-Test-[5,6]{1}"}
PowerCLI C:\Scripts> Get-VM $VM | Get-HardDisk | FT Parent, Name, CapacityGB -AutoSize

Parent        Name        CapacityGB
------        ----        ----------
VM-Test-5 Hard disk 1         40
VM-Test-5 Hard disk 2        250
VM-Test-5 Hard disk 3        400
VM-Test-5 Hard disk 4         80
VM-Test-6 Hard disk 1         40
VM-Test-6 Hard disk 2        250
VM-Test-6 Hard disk 3        400
VM-Test-6 Hard disk 4         80

From the above output you can see that we want to enlarge the VMDK files which are called „Hard disk 2“ and „Hard disk 3“ respectively.

In the code block that follows, I first define a few variables, then double check that I am selecting the correct VMDK files for the operation, and then I resize them.

PowerCLI C:\Scripts> $HardDisk = 2
PowerCLI C:\Scripts> $HardDisk = "Hard disk " + $HardDisk
PowerCLI C:\Scripts> $HardDiskSize = 500
PowerCLI C:\Scripts> Get-HardDisk -vm $VM | where {$_.Name -eq $HardDisk}

CapacityGB      Persistence                                              Filename
----------      -----------                                                    --------
250.000         IndependentPersis... ...STD-2.9T-02] VM-Test-5/VM-Test-5_1.vmdk
250.000         IndependentPersis... ...STD-2.9T-01] VM-Test-6/VM-Test-6_1.vmdk


PowerCLI C:\Scripts> Get-HardDisk -vm $VM | where {$_.Name -eq $HardDisk} | Set-HardDisk -CapacityGB $HardDiskSize -Conf
irm:$false

CapacityGB      Persistence                                                    Filename
----------      -----------                                                    --------
500.000         IndependentPersis... ...STD-2.9T-02] VM-Test-5/VM-Test-5_1.vmdk
500.000         IndependentPersis... ...STD-2.9T-01] VM-Test-6/VM-Test-6_1.vmdk


PowerCLI C:\Scripts> Get-VM $VM | Get-HardDisk | FT Parent, Name, CapacityGB -AutoSize

Parent        Name        CapacityGB
------        ----        ----------
VM-Test-5 Hard disk 1         40
VM-Test-5 Hard disk 2        500
VM-Test-5 Hard disk 3        400
VM-Test-5 Hard disk 4         80
VM-Test-6 Hard disk 1         40
VM-Test-6 Hard disk 2        500
VM-Test-6 Hard disk 3        400
VM-Test-6 Hard disk 4         80


PowerCLI C:\Scripts> $HardDisk = 3
PowerCLI C:\Scripts> $HardDisk = "Hard disk " + $HardDisk
PowerCLI C:\Scripts> $HardDiskSize = 800
PowerCLI C:\Scripts> Get-HardDisk -vm $VM | where {$_.Name -eq $HardDisk}

CapacityGB      Persistence                                                    Filename
----------      -----------                                                    --------
400.000         IndependentPersis... ...STD-2.9T-02] VM-Test-5/VM-Test-5_2.vmdk
400.000         IndependentPersis... ...STD-2.9T-01] VM-Test-6/VM-Test-6_2.vmdk


PowerCLI C:\Scripts> Get-HardDisk -vm $VM | where {$_.Name -eq $HardDisk} | Set-HardDisk -CapacityGB $HardDiskSize -Conf
irm:$false

CapacityGB      Persistence                                                    Filename
----------      -----------                                                    --------
800.000         IndependentPersis... ...STD-2.9T-02] VM-Test-5/VM-Test-5_2.vmdk
800.000         IndependentPersis... ...STD-2.9T-01] VM-Test-6/VM-Test-6_2.vmdk


PowerCLI C:\Scripts>

If the above code block is not self-explanatory, feel free to post your questions about it in the comments. I’ll try to complete the tutorial in a timely manner.

WP fail2ban: Gutes Plugin mit ausbaufähiger Dokumentation

WP fail2ban ist ein Plugin zum Schutz von WordPress-Installationen vor Brute-Force-Angriffen. Installation und Konfiguration habe ich bereits im Artikel WordPress mit Fail2Ban vor Brute-Force-Angriffen schützen dokumentiert. Dieser Text beschäftigt sich mit der offiziellen Dokumentation des Plugins, bzw. dem Text, der sich als Dokumentation ausgibt.

Ich stelle hier meine Erwartung an eine Dokumentation heraus, zeige die Schwächen der exemplarisch ausgewählten Dokumentation heraus und gebe einen Tipp, wie man weniger schlechte Dokus schreibt. Ich schließe mit Fragen an meine Leserinnen und Leser und freue mich auf eure Rückmeldungen.

In meinen Augen sind folgende drei Abschnitte zwingender Bestandteil einer jeden Dokumentation:

  1. Was ist dies für eine Anwendung? Wofür wird sie verwendet und wofür nicht?
  2. Wie wird diese Anwendung installiert?
  3. Wie wird diese Anwendung konfiguriert?

Die ersten beiden Punkte mag ich als erfüllt betrachten. Beim dritten Punkt sehe ich ein Problem.

Bildschirmfoto der WP fail2ban-Installationsanleitung. Zeitstempel 2023-06-04T20:54+02

Die Installationsanleitung ist prägnant. Sie enthält einen Link, der suggeriert, zur Konfigurationsanleitung zu führen. Dort erwartet den neugierigen Leser folgendes Bild.

Bildschirmfoto vom Einstieg in die WB fail2ban-Konfigurationsanleitung. Zeitstempel 2023-06-04T20:59+02

Hier gibt es noch keine nützlichen Informationen zu sehen. Die Seite ist in meinen Augen überflüssig. Aber gut, ein Satz tut nicht weh. Mit einem Klick auf „Next“ geht es weiter.

Bildschirmfoto WP fail2ban-Dokumentation. Zeitstempel 2023-06-04T21:04+02

Hier steht im Wesentlichen, dass Nutzer, welche sich bereits auskennen, zum nächsten Abschnitt gehen können. Leider finden sich für neue Nutzer hier kaum brauchbare Informationen. Der Hinweis, die Datei wp-config.php zu sichern, bevor man diese bearbeitet, ist nett, mehr nicht. Es wird erwähnt, dass die freie (im Sinne von Freibier) Version des Plugins durch Definition von Konstanten in der Datei wp-config.php konfiguriert wird. Wie so eine Konstante aussieht oder wo man weiterführende Informationen dazu findet, steht hier nicht. Ich habe an dieser Stelle entsprechende Hinweise erwartet. Gut, ich kann ja noch auf „Next“ klicken.

Bildschirmfoto WP fail2ban-Dokumentation, Abschnitt Logging. Zeitstempel 2023-06-04T21:14+02

Auch in diesem Abschnitt findet sich keine Information, was man nun mit der Datei wp-config.php soll. Immerhin gibt es in Abschnitt 4.2.1. einen Link, der Nutzer, welche nicht mit der Konfiguration vertraut sind, zur Konfigurationsanleitung führen soll. Ich habe ein Déja Vu und fühle mich langsam ver…hohnepiepelt. Also klicke ich auf den nächsten LInk. Es heißt ja schließlich: „Was lange währt, wird endlich gut.“

TL;DR: Auch auf der nächsten Seite erfahren wir nichts über die wp-config.php.

Bildschirmfoto der URL: https://docs.wp-fail2ban.com/en/5.0/configuration/fail2ban.html#configuration-fail2ban. Zeitstempel 2023-06-04T21:21+02

Zur Erinnerung: Ich nutze die freie Version des Plugins WP fail2ban, welches angeblich durch die Definition von Konstanten in der Datei wp-config.php konfiguriert wird. Welche Konstanten dies sind und wie man diese konfiguriert, wird auch auf Seite 4 immer noch nicht mit einem Wort erklärt.

Stattdessen lernt man in Abschnitt „4.3.1.1. Typical Settings“, dass die Dateien wordpress-hard.conf und wordpress-soft.conf in das Verzeichnis fail2ban/filters.d zu kopieren sind. Hier wurden in meinen Augen zwei Fehler gemacht:

  1. Es wird nicht erwähnt, wie man die Dateien wordpress-,{hard,soft}.conf erhält bzw. erstellt. Als unerfahrener Nutzer strandet man hier. Zum Glück hatte ich mir das damals aufgeschrieben.
  2. Es wird eine relative Pfadangabe fail2ban/filters.d genutzt. Dies ist nicht ganz so wild, ich persönlich bevorzuge es, wenn vollständige Pfadangaben genutzt werden, damit Nutzer das entsprechende Verzeichnis sicher finden.

Fazit

Eine Dokumentation sollte die notwendigen Informationen bereitstellen, mit denen auch neue Nutzer eine Anwendung installieren und konfigurieren können. Dies ist nicht so leicht, wie es auf den ersten Blick erscheint, leiden Autoren, welche die Anwendung bereits kennen, doch häufig unter Betriebsblindheit und können sich nur schwer in die Rolle des unerfahrenen Nutzers versetzen.

Wenn ich selbst Dokumentationen schreibe, gebe ich diese meist Kolleginnen und Kollegen zu lesen und arbeite deren Rückmeldungen mit ein. Dies hat in der Vergangenheit zu deutlich besseren Ergebnissen geführt.

Die hier kritisierte Dokumentation ist ein Beispiel dafür. Sie befindet sich damit leider in guter Gesellschaft im Internet.

Ohne meinen Eingangs erwähnten Artikel hier im Blog wäre ich nicht in der Lage gewesen, mir dieses Plugin wieder einzurichten. Nun werde ich einige Tage prüfen, ob es wie erhofft arbeitet und dann ggf. einen Merge-Request mit einigen Verbesserungsvorschlägen einreichen.

Fragen an meine Leserinnen und Leser

Wie steht ihr zu Dokumentation? Ist das eher etwas für alte weiße Männer mit grauen Bärten? Oder wünscht ihr euch ebenfalls belastbare und ausführliche Dokumentationen zu den von euch verwendeten Anwendungen?

Tragt ihr selbst zu Dokumentationen bei? Welche Erfahrungen habt ihr dabei gemacht? Welche Tipps könnt ihr Schreiberlingen geben, die ihr Projekt dokumentieren möchten?

Bitte hinterlasst mir eure Antworten in den Kommentaren oder im Chat.

Rollen müssen verfügbar sein, nicht einzelne Personen.

In diesem Artikel möchte ich euch ein Modell vorstellen, nach dem sich Wissen auf verschiedene Personen verteilen lässt, um dieses Wissen und die Funktion von Rollen in einem Unternehmen verfügbar zu halten.

Bei den Rollen kann es sich zum Beispiel um den Virtualisierungs-Administrator, den Linux-Admin oder die Rechnungseingangsprüfung sowie den Versand handeln. Die jeweilige Rolle kann dabei von ein oder mehreren Personen ausgefüllt werden. Wichtig ist lediglich, dass die Rolle jederzeit ihre Funktion erfüllen kann.

Das Modell, welches ich gleich vorstelle, stammt nicht von mir. Ein Nerd aus den USA, dessen Namen ich leider nicht mehr weiß, hat es mir am Rande des OpenStack Summit 2018 in Berlin vorgestellt.

RAID – Redundant Array of Independent Dudes

Ja, ihr habt richtig gelesen. Es geht um RAID, aber ohne Festplatten und dafür mit Dudes oder allgemein Personen, die Rollen ausfüllen. Ihr werdet in den folgenden Abschnitten lernen, wie sich die verschiedenen RAID-Level auf die Verfügbarkeit einer Rolle auswirken.

RAID 0 – Nur gemeinsam sind wir stark

Das Bild zeigt zwei Personen, die jeweils zwei Aufgaben wahrnehmen. Die beiden Personen haben nichts weiter miteinander zu tun. Es findet kein Wissensaustausch zwischen ihnen statt.
Zwei Personen nehmen unabhängig voneinander verschiedene Aufgaben wahr.

Dieses Konstrukt habe ich zum Glück noch nicht in der Praxis angetroffen. Hierbei wird eine Rolle von zwei Personen ausgefüllt, welche die Funktion der Rolle jedoch nur im Team sicherstellen können. Fällt eine Person aus, ist die andere allein nicht ausreichend handlungsfähig. Die Funktion der Rolle ist nicht sichergestellt.

RAID 1 – Zwei Personen für eine Rolle

Hier herrscht volle Redundanz. Zwei Personen sind für eine Rolle verantwortlich. Fällt eine Person aus, kann die andere sämtliche damit zusammenhängende Aufgaben allein ausführen. Die Vertretung ist im Falle von Krankheit, Urlaub oder Knast damit zu 100 % sichergestellt.

Gleichzeitig ist der Abstimmungsbedarf minimal, da sich nur zwei Personen miteinander abstimmen müssen.

Das Bild zeigt vier Personen. Jeweils zwei Personen nehmen die gleichen Aufgaben wahr. Pfeile symbolisieren den Informationsfluss zwischen den Personen.
Jeweils zwei Personen stimmen sich miteinander ab, um sich gegenseitig vertreten zu können (RAID 1).

Wenn es gut läuft und man bei der Personal-Akquise ein glückliches Händchen hat, lassen sich vielleicht sogar zwei Personen kombinieren, die zwei oder vielleicht sogar drei Rollen in Personalunion besetzen können.

Zu beachten ist, dass die Leistungsfähigkeit der Rolle beeinträchtigt sein mag, wenn 50 % der normalen Kapazität fehlen. Dies ist von der regelmäßigen Belastung bzw. Auslastung der einzelnen Personen abhängig.

RAID 5 – Parität und Leistung mit erhöhtem Abstimmungsbedarf

Das insgesamt erforderliche Wissen ist in diesem RAID-Level auf mindestens drei oder mehr Personen verteilt. Keine Person verfügt für sich allein über genug Wissen, um eine Rolle vollständig ausfüllen zu können. In der Gesamtheit ist das Wissen jedoch so verteilt, dass bei Ausfall einer Person (Krankheit, Urlaub, Knast, etc.) kein Wissen unwiederbringlich verloren geht, sondern der Verlust durch die verbliebenen Personen aufgefangen werden kann. Dies bezieht sich nicht nur auf das Wissen, sondern auch auf die zu erbringende Leistung.

Das Bild zeigt sechs Personen, von denen jeweils drei die gleichen Aufgaben wahrnehmen. Pfeile unterschiedlicher Farbe zeigen, welche Personen dabei in einer Kommunikationsbeziehung zueinander stehen.
Zwei Teams bestehend aus jeweils drei Personen. Jedes Team stimmt sich zu seinen Aufgaben ab. Es handelt sich quasi um zwei separate RAID-5-Verbünde.

Da jede Person nun mehr als eine Kollegin oder einen Kollegen hat, wird der Abstimmungsbedarf größer. Die einzelnen Personen müssen sich auf dem Laufenden halten, was die Kollegen so tun, um diese bei Bedarf vertreten zu können.

Hat jede Person in diesem RAID-Verbund nur die eine Rolle, für die dieses RAID gebildet wurde, ist das kein Problem. Man hat einfach ein größeres Team, das seinen Job macht. Das funktioniert auch noch, wenn alle in diesem Team/RAID noch eine zweite oder vielleicht auch dritte Rolle ausfüllen. Denn es bleiben dieselben beteiligten Personen, die sich untereinander austauschen können und müssen.

RAID 55 – Wie konnte das passieren?

Ein Bild sagt auf mehr als viele Worte:

Das Bild zeigt sechs Personen, von denen jede zwei Rollen ausfüllt. Jede Rolle ist dreimal im Bild vorhanden. Pfeile verbinden die Personen, die die gleiche Rolle ausfüllen, um darzustellen, wie unübersichtlich es bei ungünstiger Aufgabenverteilung wird.
RAID 55 – Wenn die Aufgabenverteilung unübersichtlich wird

In vorstehendem Bild werden die gleichen Aufgaben durch die gleiche Anzahl von Personen wahrgenommen. Allerdings sind in diesem Bild die Rollen ungeschickt zwischen den Personen verteilt, was einen hohen Kommunikationsaufwand zur Folge hat, da sich mehr Personen zu mehr Themen miteinander abstimmen müssen.

Hinzukommt, dass die Urlaubsplanung in diesem unübersichtlichen Szenario ebenfalls erschwert wird, muss doch darauf geachtet werden, dass die Funktionen der einzelnen Rollen verfügbar bleiben und man nicht versehentlich zwei von drei Personen in den Urlaub schickt, welche die gleiche Rolle ausfüllen und von denen mindestens zwei Personen verfügbar sein müssen.

Leider habe ich dieses Bild in der Praxis schon mehr als einmal gesehen. Es entsteht immer dann, wenn Teams immer weitere Themen übernehmen müssen und man versucht, eine Aufgabe auf immer mehr vorhandene Köpfe zu verteilen, weil gerade jemand da ist, der noch 10 Minuten freie Zeit pro Woche hat.

Dabei mag man sich ausmalen, wie das vorstehende Bild sich verändert, wenn die Anzahl der Personen und Aufgaben unter Beibehaltung der ungeschickten Aufgabenverteilung steigt. Ein Modell, das es in meinen Augen zu verhindern lohnt.

Zusammenfassung

Ich mag RAIDs, da sich mit ihnen auf einfache Weise die Komplexität von Aufgaben-, Arbeitslast-Verteilung und Kommunikations- und Abstimmungs-Aufwände visualisieren und erklären lassen.

Wie gefällt euch das Modell? Habt ihr ähnliche oder ganz andere Erfahrungen in vergleichbaren Team-Strukturen gemacht?

Ehre dem Ehrenamt

In diesem Text geht es einmal nicht um IT. Es ist ein Kommentar zu Tims Artikel „Zum Wochenende: Freiwillige Gesellschaft“ auf GNU/Linux.ch, welcher mir gut gefallen hat.

Tim und ich haben mehrere Dinge gemeinsam. Wir haben beide Familie, einen 40-Stunden-Job, Hobbys und sind Mitglieder einer Freiwilligen Feuerwehr. Ich „leide“ darüber hinaus noch an gewissen Wohlstandkrankheiten und zähle mich selbst daher definitiv nicht zu den fitten Menschen in unserer Gesellschaft. Das hält mich jedoch nicht davon ab, mich ehrenamtlich zu engagieren. Denn es ist mir wichtig, der Gesellschaft etwas zurückzugeben und Menschen in Not zu helfen.

Meine Ausbildung zum Fachinformatiker Systemintegration oder mein Studium der Angewandten Informatik helfen dabei nicht weiter. Das müssen sie aber auch gar nicht. Denn wer sich in der Freiwilligen Feuerwehr engagiert, wird auf Lehrgängen und regelmäßigen Dienstabenden ausgebildet.

Und ja, man muss auch manchmal Kompromisse eingehen. So sind für meine Frau und mich schon gemeinsame Abende ausgefallen, weil Papa zu einem Einsatz musste, um z.B. eine Ölspur abzustreuen, ein Feuer zu löschen, oder die Straße zu sperren, bis das Gasleck geschlossen wurde. Das fällt mir nicht immer leicht.

Erst diese Woche ist unser gemeinsamer Tanzabend ausgefallen, weil ich mit Kameraden zur Unterstützung einer Nachbarwehr gefahren bin. Ein Unwetter hat Massen von Schlamm und Wasser in die Keller, Gärten und Häuser vieler Menschen gespült. Wir konnten sehen, wo der Schlamm ca. 1,60-2,00 Meter hoch in den Kellern stand.

Schön zu sehen war die Hilfsbereitschaft der Menschen. Feuerwehrleute anderer Gemeinden und Städte, Nachbarn und Menschen aus ganz anderen Teilen der Stadt bildeten Eimerketten, um zerstörte Besitztümer und Schlamm aus den Kellern in Mulden zu transportieren. Wer nicht irgendwelchen Unrat schleppte, versorgte die Helfenden mit Verpflegung. In den Straßen gab es Bratwurst, belegte Brötchen, Kuchen, Suppe und Getränke. Es fehlte eigentlich an nichts.

Es war ein gutes Gefühl mitgeholfen zu haben, einen kleinen Teil dazu beigetragen zu haben, anderen Menschen in Not zu helfen. Noch schöner war allerdings, nach nicht ganz 5 Stunden mit langen Armen nach Hause zu kommen und von meiner Frau den Satz zu hören: „Ich bin stolz auf dich und finde es toll, dass du das machst.“

Wenn auch ihr euch ehrenamtlich engagieren möchtet und nicht wisst wie, seid nicht schüchtern oder ängstlich. Schaut bei eurer lokalen Feuerwehr, dem THW, dem Sportverein, der Kleiderkammer, etc. vorbei und fragt, ob ihr euch mal anschauen könnt, was da so passiert und ob das etwas für euch ist. Ich bin mir sicher, man wird euch freundlich empfangen und euch zeigen, was euch erwartet. Und denkt immer daran: „Vieles geht leichter, wenn wir es gemeinsam anpacken.“

Dokumentation meines Proxmox-Setups

Dies ist die lückenhafte Dokumentation meines Proxmox-Setups.

Als langjähriger Administrator von VMware vSphere probiere ich etwas Neues aus. Mein Setup und erste Erkenntnisse halte ich in diesem Artikel fest. Ich werde ihn in der Zukunft weiter ausgestalten und ergänzen.

Ich möchte euch nicht vom Lesen abhalten, doch erwartet nicht zu viel.

Betreiber, Standort und Server-Hardware

Für den Betrieb von Labor-Umgebungen habe ich mir einen Server mit folgender Hardware-Ausstattung in Hetzners Serverbörse gemietet.

Ausstattung:

  • Intel Core i9-9900K (8 Cores/16 Threads)
  • 2x SSD M.2 NVMe 1 TB
  • 4x RAM 32768 MB DDR4
  • NIC 1 Gbit Intel I219-LM
  • Standort: Deutschland, FSN1
  • Rescue-System (Englisch)
  • 1 x Primäre IPv4
  • 1x /64-Subnetz IPv4

Installation

Auf der Hardware habe ich eine Debootstrap-Installation mit Debian 11 (Bullseye) durchgeführt, bei der alle Datenträger mit Ausnahme von /boot LUKS-verschlüsselt sind. Dazu bin ich der hervorragenden Anleitung meines Kollegen Steffen gefolgt: „Manually installing Debian 11 (Bullseye) with fully encrypted LUKS (besides /boot) using debootstrap

Anschließend habe ich die Proxmox-Paketquellen eingebunden und Proxmox VE installiert. Ich weiß nicht mehr genau, welchem Tutorial ich gefolgt bin. Daher habe ich in [1-3] ein paar vielversprechend erscheinende Suchergebnisse verlinkt.

Netzwerkkonfiguration bis 2023-07-21

Die physikalische NIC meines Hosts wird mit meiner öffentlichen IPv4 und einer IPv6-Adresse für die Außenanbindung konfiguriert. Im Betriebssystem erstelle ich eine Bridge, an welche später die virtuellen Maschinen (VMs) angeschlossen werden. Über diese Bridge haben die VMs Zugriff auf das Internet und sind vom Internet aus zu erreichen.

Das folgende Bild stellt die Konfiguration exemplarisch dar. Statt IPv4-Adressen verwende ich für die Bridge und VMs jedoch ausschließlich IPv6-Adressen.

Quelle: Proxmox-Wiki – Routed Configuration

Die Datei /etc/network/interfaces meines Hosts hat folgenden Inhalt. Die realen IP-Adressen habe ich dabei durch Adressen aus RFC 3849 und RFC 5737 ersetzt.

$ cat /etc/network/interfaces
# network interface settings; autogenerated
# Please do NOT modify this file directly, unless you know what
# you're doing.
#
# If you want to manage parts of the network configuration manually,
# please utilize the 'source' or 'source-directory' directives to do
# so.
# PVE will preserve these directives, but will NOT read its network
# configuration from sourced files, so do not attempt to move any of
# the PVE managed interfaces into external files!

source /etc/network/interfaces.d/*

auto lo
iface lo inet loopback

auto eth0
iface eth0 inet static
	address 198.51.100.38/27
	gateway 198.51.100.33
	pre-up /sbin/ip addr flush dev eth0 || true

iface eth0 inet6 static
	address 2001:db8:dead:beef::1
	netmask 128
	gateway fe80::1
	up sysctl -w net.ipv6.conf.all.forwarding=1
	up sysctl -p

auto vmbr0
iface vmbr0 inet6 static
	address 2001:db8:dead:beef::2
	netmask 64
	up ip -6 route add 2001:db8:dead:beef::/64 dev vmbr0
	bridge-ports none
	bridge-stp off
	bridge-fd 0

Erläuterungen dazu folgen ggf. später. Als Einstieg empfehle ich einen Blick in die interfaces(5).

Damit eine VM auf das Routing-Netzwerk zugreifen und darüber das Internet erreichen kann, wird diese an die Bridge vmbr0 angeschlossen. Anschließend wird dieser eine IPv6-Adresse aus dem /64-Addressblock konfiguriert, wie es der folgende Code-Block exemplarisch darstellt, wobei static-ipv6 der Name der Verbindung und ens192 der Name der NIC ist:

# nmcli con add con-name static-ipv6 ifname ens192 type ethernet
# nmcli con mod static-ipv6 ipv6.addresses 2001:db8:dead:beef::3/128 ipv6.method manual ipv6.gateway 2001:db8:dead:beef::2
# nmcli con up static-ipv6

Zur Verwendung von nmcli habe ich die Red Hat Dokumentation unter [4] zu Rate gezogen.

Netzwerkkonfiguration ab 2023-07-21

Ursprünglich habe ich die Absicht verfolgt, alle VMs auf meinem Hetzner-Server ausschließlich mit IPv6 zu betreiben. Wir schreiben ja schließlich das Jahr 2023. Da sollte das doch problemlos möglich sein. Wäre da nicht (mindestens) ein Dienst, der IPv6 nicht unterstützt.

Da es offenbar nicht ganz ohne IPv4 geht, habe ich mir bei Hetzner eine zweite IPv4-Adresse gemietet [5] und bin der Anleitung Netzwerkkonfiguration für Proxmox VE in der Hetzner-Community gefolgt. Da die Anleitung mein bestehendes Setup für IPv6 nicht berücksichtigt, waren ein paar Anpassungen notwendig. Der folgende Code-Block stellt den Inhalt der Dateien /etc/network/interfaces und /etc/network/interfaces.d/vmbr0-extra dar, wobei die IP-Adressen ersetzt wurden.

$ cat /etc/network/interfaces
# network interface settings; autogenerated
# Please do NOT modify this file directly, unless you know what
# you're doing.
#
# If you want to manage parts of the network configuration manually,
# please utilize the 'source' or 'source-directory' directives to do
# so.
# PVE will preserve these directives, but will NOT read its network
# configuration from sourced files, so do not attempt to move any of
# the PVE managed interfaces into external files!

source /etc/network/interfaces.d/*

auto lo
iface lo inet loopback

iface eth0 inet manual
	pre-up /sbin/ip addr flush dev eth0 || true

auto vmbr0
iface vmbr0 inet static
	address 198.51.100.38/27
	gateway 198.51.100.33
	bridge-ports eth0
	bridge-stp off
	bridge-fd 0

iface vmbr0 inet6 static
	address 2001:db8:dead:beef::1/64
	gateway fe80::1

$ cat /etc/network/interfaces.d/vmbr0-extra 
iface vmbr0 inet static
	hwaddress <zweite MAC-Adresse aus dem Kundenportal>

Die virtuelle Netzwerkkarte der VM, welche über die zweite IPv4-Adresse erreichbar sein soll, wird an die Bridge vmbr0 angeschlossen. Das Interface ens18 im Gastbetriebssystem wurde wie folgt konfiguriert:

# nmcli
ens18: connected to ens18
        "Red Hat Virtio"
        ethernet (virtio_net), 00:50:56:00:8C:22, hw, mtu 1500
        ip4 default, ip6 default
        inet4 198.51.100.36/32
        route4 198.51.100.33/32 metric 100
        route4 default via 198.51.100.33 metric 100
        inet6 fe80::250:56ff:fe00:8c22/64
        inet6 2001:db8:dead:beef::2/64
        route6 2001:db8:dead:beef::/64 metric 100
        route6 default via fe80::1 metric 100
        route6 fe80::/64 metric 1024

# cat /etc/resolv.conf
# Generated by NetworkManager
nameserver 185.12.64.1
nameserver 185.12.64.2
nameserver 2a01:4ff:ff00::add:1

Getestet habe ich die Konfiguration, indem ich eine Webseite einmal über IPv4 und einmal über IPv6 abgerufen habe. Dies kann man recht einfach mit curl nach folgendem Muster erledigen:

$ curl -4 [URL]
$ curl -6 [URL]

Erster Eindruck

Wie ESXi und vSphere verfügt auch Proxmox VE über ein WebUI zur Administration der Umgebung und zur Erstellung virtueller Maschinen.

Selbstverständlich gibt es einige Unterschiede und nicht alles wirkt sofort vertraut. Bisher konnten die Proxmox-Dokumentation und das Proxmox-Wiki meine Fragen jedoch schnell beantworten.

Eine erste VM war schnell erstellt, installiert und in ein Template umgewandelt. Interessanterweise kann man Templates im WebUI nicht wieder in VMs umwandeln, was bei vSphere kein Problem ist.

Im Gegenzug können ISO-Images oder sonstige Dateien einfach per rsync auf den Proxmox-Host kopiert werden, was gerade beim erneuten Übertragen vorhandener Dateien eine enorme Zeitersparnis mit sich bringt. Hier muss bei vSphere und ESXi zum Upload von Dateien in den Datenspeicher das WebUI, SCP oder die Powershell bemüht werden und erneut zu kopierende Dateien werden jedes Mal komplett übertragen. Was bei Netzwerkgeschwindigkeiten im Datacenter nicht so dramatisch ist, nervt doch sehr, wenn man große ISO-Images über eine Internetleitung übertragen muss.

Der erste Eindruck ist zufriedenstellend. Als nächstes werde ich mich mal damit beschäftigen, wie man VMs mit Ansible auf Proxmox provisioniert. Das community.general.proxmox_kvm-Modul scheint dafür ein guter Einstiegspunkt zu sein.

  1. Install Proxmox VE on Debian 11 Bullseye
  2. So installieren Sie Proxmox auf einem Debian 11-Server
  3. How To Install Proxmox On Debian 11 – A Step-By-Step Guide
  4. Configuring an Ethernet connection with a static IP address by using nmcli
  5. Zusätzliche IP-Adressen bei Hetzner
  6. Proxmox VE Netzwerkkonfiguration

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.