Nachhaltig gehostetes, verwaltetes F/OSS
Objektspeicher, Redis, Prometheus
auf Hetzner, OVH und LeaseWeb
**tl;dr - Zeile für Zeile Erklärung meines Ansible-betriebenen ZFS-Installationsskripts zur Verwendung auf der dedizierten Hardware von Hetzner (Ubuntu 20.04 - „Focal“). „Es ist nicht perfekt/minimal, aber es funktioniert für mich
Vor einiger Zeit habe ich damit begonnen, ZFS auf all meiner Bare-Metal-Hardware zu verwenden, die bei Hetzner gehostet wird, um die angeschlossenen HDDs und SSDs zu reparieren. Es gibt viele Möglichkeiten im Raum (Standard-LVM,
mdraid
Btrfs usw.), aber ich habe ZFS wegen seiner Funktionen und seiner Ergonomie gewählt.
Ich möchte niemanden mit dem Warum langweilen, aber eines der Dinge, die ich navigieren musste, war, wie man neuere Versionen von ZFS auf Ubuntu 20.04 (einem der unterstützten Betriebssysteme bei Hetzner) installiert. Beim Einrichten von ZFS auf meinen Systemen bin ich auf einige Probleme (insbesondere nach der Installation) gestoßen, daher wollte ich kurz erläutern, wie ich vorgegangen bin.
Dieser Beitrag ist eine zeilenweise Erklärung meiner Ansible-Skripte, die ZFS installieren.
Bevor Sie wissen, ob es sich lohnt, zu ZFS (oder einem beliebigen Dateisystem) zu wechseln, werden Sie wahrscheinlich zu RTFM wechseln wollen. ZFS hat viele Ins und Ich bin sicherlich kein Experte darin, aber es ist sehr wichtig, das Wie und Warum sowie die Terminologie und sogar die Geschichte des Projekts zu kennen.
Ein paar Links zum Einstieg:
Zusammen mit ZFS (das hier wahrscheinlich die unbekannteste Größe ist) möchten Sie wahrscheinlich mit Ubuntu und der allgemeinen Systemverwaltung vertraut sein. Das ist ein ziemlich großer Bereich, den es abzudecken gilt, aber hier sind ein paar Links:
Es versteht sich fast von selbst, aber wenn Sie mit der Linux-Systemadministration zu diesem Zeitpunkt nicht sehr vertraut sind, sollten Sie dies wahrscheinlich nicht versuchen.
Ich persönlich entscheide mich dafür, meine Festplatten in einer etwas benutzerdefinierten Konfiguration zu haben – ich habe RAID1 (Spiegelung) eingerichtet
mdraid, zusammen mit Partitionen auf jeder Festplatte, die ich ZFS zur Verwaltung geben kann. Idealerweise hätte ich ganze Festplatten, die ich ZFS übergeben könnte, aber Partitionen funktionieren auch.
Betriebssystem-Setup (
installimage), das das Festplatten-Setup enthält, wird im Rettungsmodus von Hetzner ausgeführt und kann mit einer Datei wie der folgenden gesteuert werden:
# Vom Installationsimage verwendete Laufwerksdeklarationen DRIVE0 /dev/nvme0n1 DRIVE1 /dev/nvme1n1 # Software-RAID aktivieren (für die Betriebssystemfestplatte) SWRAID 1 SWRAIDLEVEL 1 # Bootloader (im Allgemeinen grub) BOOTLOADER grub # Hostname der Maschine HOSTNAME machine01 # Partition Konfiguration PART swap swap 32G PART /boot ext4 1G PART / ext4 128G # Diese letzte Partition wird erstellt (wiped& später als ZFS neu erstellt) PART /root-disk-remaining ext4 all # Sie können Images angeben, die Hetzner verwendet, indem Sie auf ihre Netzwerkfreigabe zugreifen IMAGE /root/.oldroot/nfs/images/Ubuntu-2004-focal-64-minimal.tar. gz
Dies ist offensichtlich ziemlich Hetzner-spezifisch, aber tun Sie alles, was Sie auf Ihren eigenen Systemen tun müssen, um Partitionen/Laufwerke für ZFS zur Verfügung zu haben.
zfsutils-linuxand
zfs-zed
In Ansible YAML sieht der Schritt so aus:
- name: Enthält alle zfs-bezogenen Upstream-Pakete ansible.builtin.shell: | apt-mark hold zfsutils-linux apt-mark hold zfs-zed
Zum Zeitpunkt des Schreibens dieses Beitrags ist die Version von
zfs-linux in Ubuntu Focal ist 0.8.3. Da unser Ziel hier darin besteht, eine neuere Version zu installieren und weiterhin zu verwenden, möchten wir sicherstellen, dass alle
apt-Updates ersetzen unsere installierte Version nicht durch eine ältere Version.
Während wir hier sind, lasst uns auch die Pakete löschen.
- name: ZFS-Upstream-Pakete (Ubuntu) löschen, falls installiert.ignore_errors: ja ansible.builtin.command: | apt purge --allow-change-held-packages zfsutils-linux zfs-zed
Sie können die Dokumente weiter lesen
geeignet zu sehen, was
purge funktioniert ähnlich wie remove, entfernt aber auch Konfigurationsdateien, falls vorhanden.
Sie können die Abhängigkeiten für OpenZFS wie folgt installieren:
- name: Installationsanforderungen zum Erstellen von ZFS ansible.builtin.apt: name:packagesupdate_cache: ja state: vorhanden vars: packages: - build-essential - autoconf - automake - libtool - gawk - alien - fakeroot - dkms - libblkid-dev - uuid -dev - libudev-dev - libssl-dev - zlib1g-dev - libaio-dev - libattr1-dev - libelf-dev # Die folgende Zeile fordert die Ausgabe von `uname -r`, zum Beispiel "5.16.5-arch1- 1"für mein Arch-System #, also würde die Zeile zu etwas wie "linux-headers-5.16.5-arch1-1"auflösen (natürlich nicht gültig auf Ubuntu, aber als Beispiel) - linux-headers uname_r.stdout }} - python3 - python3-dev - python3-setuptools - python3-cffi - libffi-dev - python3-packaging - git - libcurl4-openssl-dev
Es kann ein paar Abhängigkeiten geben, die nicht unbedingt erforderlich sind, aber fast alle sollten erforderlich sein.
/opt/zfs
Hier ist ZFS:
- name: /opt/zfs ansible.builtin.file erstellen: Pfad: /opt/zfs state: Verzeichnis
Wenn Sie ZFS herunterladen möchten:
- Name: Download zfs ansible.builtin.get_url: URL: "httpsgithub.com/openzfs/zfs/releases/download/zfs _zfs_version zfs _zfs_version tar.gz"Prüfsumme:_zfs_tarball_sha256_checksummode: 0755 Ziel: "/opt/zfs/zfs _zfs_version tar .gz"Hier die Substitution
{{ _zfs_version }} (
2.1.1. Sie sollten den Download auch selbst durchführen und eine zu verwendende Prüfsumme sammeln/generieren. Laden Sie niemals Dinge aus dem Internet herunter, die sich ohne Prüfsumme nicht ändern sollen!
{{ist die Ansible-Template-Syntax) ist
Und wenn Sie es von dem Computer kopieren möchten, auf dem Ansible läuft (das mache ich):
- Name: zfs-Paket kopieren (Ratenbegrenzung vermeiden) ansible.builtin.copy: src: files/zfs/zfs _zfs_version tar.gz"Modus: 0755 dest: "/opt/zfs/zfs _zfs_version tar.gz"Unabhängig davon, wie Sie die Quelle erhalten, müssen Sie sie natürlich entpacken:
- name: ZFS-Code entpacken ansible.builtin.unarchive: src: "/opt/zfs/zfs _zfs_version tar.gz"dest: "/opt/zfs"remote_src: ja
So starten Sie den Build-Prozess:
- Name: ZFS einrichten und erstellen ansible.builtin.shell: | ./autogen../configure make clean make -j args: chdir: "/opt/zfs/zfs _zfs_version
Wenn Sie mit dem Erstellen von Dingen aus dem Quellcode vertraut sind, verwenden verschiedene Projekte dieses gemeinsame Toolset (einige Varianten von
Erstellen, Autogen und Konfigurieren von Skripten). Wie Sie vielleicht erwarten, kann dies eine Weile dauern, also geben Sie ihm etwas Zeit.
Nach dem Aufbau von ZFS
- name: Installieren Sie ZFS ansible.builtin.shell: | make install args: chdir: "/opt/zfs/zfs _zfs_version
Normalerweise würde man meinen, wir wären *genau hier* fertig, aber dieser Beitrag existiert, weil es im Allgemeinen nicht ausreicht, dies zu tun! Lasst uns weitermachen.
Erzwingen Sie zuerst das Entladen der ZFS-Module, falls sie ausgeführt werden:
- name: Entladen von ZFS-Modul(en) erzwingen ansible.builtin.shell: | ./scripts/zfs.-u args: chdir: "/opt/zfs/zfs _zfs_version
Es wäre ideal, wenn dies der Fall ist, *keine* Arbeitslasten auszuführen, wie Sie vielleicht erwarten.
Während die Module entladen werden, können wir einige Helfer installieren:
- Name: ZFS-Hilfsprogramme nach der Installation ansible.builtin.shell: | ./scripts/zfs-helpers.-i args: chdir: "/opt/zfs/zfs _zfs_version
Lassen Sie uns nach der Installation der Hilfsprogramme das Neuladen des ZFS-Moduls erzwingen:
- name: Neuladen des ZFS-Moduls erzwingen ansible.builtin.shell: | ./scripts/zfs.args: chdir: „/opt/zfs/zfs _zfs_version
Ich habe dieses Gebäude gefunden und benutze das
Das deb-Modul (das von Debian für die Paketinstallation verwendete Format) half auch dabei, die Installation festzuhalten und nicht durch Ubuntu-Paketstandards zu ersetzen.
Erstellen Sie zuerst das ZFS-Deb-Paket aus dem Quellcode:
- Name: ZFS-Deb-Paket erstellen ansible.builtin.shell: | make deb args: chdir: "/opt/zfs/zfs _zfs_version
Und dann installieren
- name: Installieren Sie die ZFS-Deb-Pakete ansible.builtin.shell: | ja | dpkg -i --force-overwrite deb apt install -f -y deb args: chdir: "/opt/zfs/zfs _zfs_version
Theoretisch *sollte* dieser Schritt nicht notwendig sein (oder allein verwendet werden), da wir bereits einen Installationsprozess ausgeführt haben, aber ich habe festgestellt, dass ich das bei dem einen oder anderen getan habe Es gab Situationen, in denen Neustarts dazu führten, dass eine ältere Version von ZFS verwendet wurde (trotz der
apt purge) â besonders auf der Kernel-Ebene.
modprobe
Wenn Sie das installierte ZFS-Modul sofort aktivieren möchten, verwenden Sie
Modprobe:
- Name: Modprobe zfs-Modulblock: - Name: ZFS-Kernelmodul installieren community.general.modprobe: Name: zfs-Status: vorhanden
Die Installation von ZFS bedeutet die Installation eines Kernel-Moduls, aber da wir es noch nicht ganz über Dynamic Kernel Module Support eingebaut haben, müssen wir die Verwendung lokal installierter Kernel-Module aktivieren:
- Name: Stellen Sie sicher, dass Extra im Vordergrund steht ansible.builtin.lineinfile: path: /etc/modules-load.d/modules.conf regexp: '^search'line: "search extra updates ubuntu built-in"state: present
Dadurch wird sichergestellt, dass die Datei, die den Suchpfad des Kernelmoduls verwaltet
/etc/modules-load.d/modules.conf hat eine Zeile darin, die hat
Suche nach zusätzlichen Updates angegeben. Normalerweise gibt es mindestens eine Zeile, die mit beginnt
suchen, und was wir tun wollen, ist sicherzustellen
Zusätzliche Modulstandorte werden früh im Prozess gesucht.
Wir möchten über das DKMS-Subsystem installieren:
- name: dkms install zfs ansible.builtin.shell: | dkms install zfs _zfs_version }} args: chdir: "/opt/zfs/zfs _zfs_version
An diesem Punkt sollten Sie in der Lage sein, die aktuell aktive ZFS-Version zu überprüfen, und sie sollte Ihnen etwa so zeigen:
root@machine01 ~ # zfs-Version zfs-2.1.1-1 zfs-kmod-2.1.1-1
Es gibt ein paar SystemD-Einheiten (wie üblich hat Digital Ocean einige großartige Dokumente), die erstellt werden, aber für die Verwendung durch ZFS aktiviert werden müssen:
- name: Stellen Sie sicher, dass zfs-bezogene systemd-Einheiten aktiviert sind block: - ansible.builtin.systemd: name:itemstate: started enabled: yes loop: - zfs-import-cache.service - zfs-import.target - zfs-mount.service - zfs-share.service - zfs-zed.service - zfs-volume-wait.service - zfs.target
Die Variablen, die durchlaufen werden, ähneln dem Laufen
systemd start and
systemd enable .
The security-minded reader at home is no doubt cringing into the atmosphere by now, but making sure my kernel upgrades are manual is the only way IâÂÂve found to ensure that the installed version of ZFS was not disabled/unexpectedly altered/broken by kernel upgrades:
- name: Hold all kernel upgrades to prevent custom built ZFS from doing fallback ansible.builtin.shell: | apt-mark hold linux-headers-generic apt-mark hold linux-image-generic apt-mark hold {{ uname_r.stdout }} # you'll need that `uname -r` output again here
I personally prefer to hold back any kernel upgrades and instead perform them at machine setup rather than during operation. DKMS *should* ensure that with the building of any new kernel the ZFS code is rebuilt but itâÂÂs been flaky in the past so I find it hard to trust.
Along with all the kernel changes weâÂÂve made so far (good and questionable), one thing weâÂÂll want to do is add the configuration necessary to ensure the kernel module is loaded:
- name: Ensure zfs kernel module comes up with next restart tags: [ "zfs:post-install:config" ] block: - name: Add zfs module load file ansible.builtin.template: src: templates/kernel-modules/zfs.conf.j2 dest: /etc/modules-load.d/zfs.conf owner: root group: root mode: 0644
Now that we have ZFS installed (restart once to check IâÂÂm going to leave the rest of the cluster setup to you. There are a *lot* of ways to use ZFS and setup zpools (RAID0/1/5/Z
Actually using ZFS properly is out of scope (I can only hope IâÂÂve covered *installing* it properly, at least), but please refer to the usual manuals there to set up your ZFS pool and storage requirements. Trying to cover even the basics of how to setup ZFS for your drives once itâÂÂs been installed is certainly a lot of reading so weâÂÂll leave it there for today.
This is the part where you âÂÂdraw the rest of the owlâ (sorry).
txg_timeout
While experimenting with some write modes for Postgres on ZFS, I looked into an optimization modes that involved reducing the
txg_timeout from itâÂÂs default of 5 seconds to 1 second. While I wonâÂÂt get into the tradeoffs implied by that move (please read my post on Postgres + ZFS), here is the setup that IâÂÂve used for modifying
txg_timeout per-machine (some machines might use the optimization some might not):
- name: Add systemd unit to support txg timeout customization tags: [ "zfs:post-install:config" ] block: - name: Set current ZFS txg_timeout (to 1) ansible.builtin.shell: | echo 1 > /sys/module/zfs/parameters/zfs_txg_timeout - name: install zfs-config-txg-timeout service ansible.builtin.template: src: templates/zfs-config-txg-timeout.service.j2 dest: /etc/systemd/system/zfs-config-txg-timeout.service owner: root group: root mode: 0644 - name: start & enable zfs-config-txg-timeout service ansible.builtin.systemd: name: zfs-config-txg-timeout.service state: started enabled: yes daemon_reload: yes
The template that goes with that looks like this:
[Unit] Description=Set ZFS txg_timeout After=zfs.target ConditionPathIsDirectory=/sys/module/zfs [Service] Type=oneshot RemainAfterExit=yes ExecStart=/usr/bin/bash -c 'echo {{ _zfs_txg_timeout_seconds | default(zfs_txg_timeout_seconds) }} > /sys/module/zfs/parameters/zfs_txg_timeout' # Not needed since we want it to always be whatever the setting is # ExecStop=/usr/bin/bash -c 'echo {{ _zfs_txg_timeout_seconds | default(zfs_txg_timeout_seconds) }} > /sys/module/zfs/parameters/zfs_txg_timeout' [Install] WantedBy=multi-user.target
Obviously youâÂÂll want to define
{{ _zfs_txg_timeout_seconds }} and the
zfs_txg_timeout_seconds. In general, this will make sure that the
txg_timeout is set to what you want it to be upon startup after ZFS has started.
WasnâÂÂt that easy? If youâÂÂre answering no, it wasnâÂÂt easy for me to figure out either! I spent a lot of time wondering why DKMS wasnâÂÂt working properly (which is why the hack of preventing kernel upgrades is still included) and dealing with other issues. The OpenZFS documentation is pretty great but seems to be missing a guide somewhat like this, so hopefully this post will save people some time going forward when trying to experiment with new ZFS setups on Hetzner.
Another thing IâÂÂm hoping for with this post is to be corrected â if you see something glaringly wrong in my setup, please reach out.
The more people can use low cost infrastructure providers like Hetzner, the more cool software we get and the more interesting/innovative products can be built. To that end IâÂÂm working on NimbusWS (IâÂÂm behind on this but should launch by end of Q1 2022) â if youâÂÂre interested please sign up for the service and kick the tires (free tier usage will be available).