Găzduit durabil, F/OSS gestionat Depozitare obiecte, Redis, Prometheus pe Hetzner, OVH și LeaseWeb **tl;dr - Explicație rând cu linie a scriptului meu de instalare ZFS alimentat de ansible pentru utilizare pe hardware-ul dedicat Hetzner (Ubuntu 20.04 - âÂÂFocalâÂÂ) â  nu este perfect/minimal, dar funcționează pentru mine Cu ceva timp în urmă, am început să folosesc ZFS pe tot hardware-ul meu dedicat bare metal găzduit la Hetzner pentru a dispută HDD-urile și SSD-urile atașate. Există o mulțime de opțiuni în spațiu (standard LVM, mdraid btrfs, etc), dar am ales ZFS pentru setul de funcții și ergonomie. Nu voi plictisi pe nimeni cu motivul, dar unul dintre lucrurile pe care aveam nevoie pentru a naviga era cum să instalez versiuni mai noi de ZFS pe Ubuntu 20.04 (unul dintre sistemele de operare acceptate la Hetzner). Am întâmpinat unele probleme (în special după instalare) în timpul instalării ZFS pe sistemele mele, așa că am vrut să vă ofer o prezentare a modului în care am făcut-o. Această postare este o explicație strofă cu strofă a scripturilor mele Ansible care instalează ZFS. Înainte de a ști dacă ZFS (sau orice sistem de fișiere) merită să treceți la, probabil că veți dori să faceți RTFM. ZFS are o mulțime de informații și, cu siguranță, nu sunt un expert în asta, dar cunoașterea cum și de ce, precum și terminologia și chiar istoria proiectului este foarte importantă. Câteva link-uri pentru a începe: Împreună cu ZFS (care este probabil cea mai necunoscută cantitate de aici) probabil că doriți să vă familiarizați cu Ubuntu și cu administrarea generală a sistemelor. Aceasta este o zonă mare de acoperit, dar iată câteva link-uri: Este aproape de la sine înțeles, dar dacă nu sunteți foarte familiarizat cu administrarea sistemului Linux în acest moment, probabil că nu ar trebui să încercați acest lucru. Eu personal aleg să am discurile într-o configurație oarecum personalizată â Am configurarea RAID1 (oglindire) prin mdraid, împreună cu partițiile de pe fiecare disc pe care le pot da lui ZFS pentru a le gestiona. În mod ideal, aș avea discuri întregi de oferit ZFS, dar și partițiile funcționează. Configurarea sistemului de operare ( installimage), care include configurarea discului, este rulat din modul de salvare Hetzner și poate fi ghidat cu un fișier ca următorul: # Declarații de unitate utilizate de installimage DRIVE0 /dev/nvme0n1 DRIVE1 /dev/nvme1n1 # Activați RAID software (pentru discul OS) SWRAID 1 SWRAIDLEVEL 1 # Bootloader (în general grub) BOOTLOADER grub # Hostame mașinii HOSTNAME machine01 # Partiție configurație PART swap swap 32G PART /boot ext4 1G PART / ext4 128G # Această ultimă partiție va fi făcută (ștersă& recreat ca ZFS mai târziu) PARTEA /root-disk-remaining ext4 all # Puteți specifica imaginile pe care Hetzner le folosește accesând partajarea rețelei IMAGE /root/.oldroot/nfs/images/Ubuntu-2004-focal-64-minimal.tar. gz Acest lucru este, evident, destul de specific lui Hetzner, dar faceți tot ce trebuie să faceți pe propriile sisteme pentru a avea partiții/unități disponibile pentru ca ZFS să le utilizeze. zfsutils-linuxand zfs-zed În Ansible YAML, pasul arată astfel: - nume: Deține toate pachetele din amonte legate de zfs ansible.builtin.shell: | apt-mark hold zfsutils-linux apt-mark hold zfs-zed În momentul scrierii acestei postări, versiunea zfs-linux în Ubuntu Focal este 0.8.3. Deoarece scopul nostru aici este să instalăm și să folosim în continuare o versiune mai nouă, vrem să ne asigurăm că există actualizările apt nu înlocuiesc versiunea noastră instalată cu o versiune mai veche. Cât suntem aici, haideți să curățăm și pachetele. - nume: Eliminați pachetele ZFS în amonte (ubuntu) dacă sunt instalate ignore_errors: da ansible.builtin.command: | apt purge --allow-change-held-packages zfsutils-linux zfs-zed Puteți citi documentele pe apt pentru a vedea ce purge face â este similar cu eliminarea, dar elimină, de asemenea, fișierele de configurare, dacă sunt prezente. Puteți instala dependențele pentru OpenZFS astfel: - nume: Cerințe de instalare pentru construirea ZFS ansible.builtin.apt: nume:packagesupdate_cache: da stare: prezent vars: pachete: - 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 # Linia de mai jos solicită ieșirea lui `uname -r`, de exemplu, "5.16.5-arch1- 1"pentru sistemul meu arch #, astfel încât linia s-ar rezolva la ceva de genul "linux-headers-5.16.5-arch1-1"(nu este valabil pe Ubuntu desigur, dar ca exemplu) - linux-headers uname_r.stdout }} - python3 - python3-dev - python3-setuptools - python3-cffi - libffi-dev - python3-packaging - git - libcurl4-openssl-dev Pot exista câteva dependențe care nu sunt strict necesare, dar aproape toate ar trebui să fie necesare. /opt/zfs Aici este ZFS: - nume: Creați /opt/zfs ansible.builtin.file: cale: /opt/zfs stare: director Dacă doriți să descărcați ZFS: - nume: Descărcați zfs ansible.builtin.get_url: url: "httpsgithub.com/openzfs/zfs/releases/download/zfs _zfs_version zfs _zfs_version tar.gz"sumă de control:_zfs_tarball_sha256_checksumo5/tarball_sha256_checksummode_07/5/256_checksummode_ tarball_sha256_checksummode_: _zfs_version tar. .gz"Aici înlocuirea {{ _zfs_version }} ( 2.1.1. De asemenea, veți dori să descărcați singur și să colectați/generați o sumă de control pe care să o utilizați. Nu descărcați niciodată lucruri de pe internet care nu ar trebui să se schimbe fără o sumă de control! {{este sintaxa șablonului Ansible) este Și dacă doriți să îl copiați de pe computerul pe care rulează Ansible (asta fac eu): - nume: Copiați pachetul zfs (evitați limita de rată) ansible.builtin.copy: src: files/zfs/zfs _zfs_version tar.gz"mod: 0755 dest: "/opt/zfs/zfs _zfs_version tar.gz"Indiferent de modul în care alegeți să obțineți sursa, desigur, va trebui să o dezarhivați: - nume: Dezarhivați codul zfs ansible.builtin.unarchive: src: „/opt/zfs/zfs _zfs_version tar.gz” dest: „/opt/zfs” remote_src: da Pentru a începe procesul de construire: - nume: Setup and Build ZFS ansible.builtin.shell: | ./autogen../configure make clean make -j args: chdir: "/opt/zfs/zfs _zfs_version Dacă sunteți familiarizat cu construirea lucrurilor de la sursă, diverse proiecte folosesc acest set de instrumente comun (o variantă de create, autogen și configurați scripturi). După cum vă puteți aștepta, acest lucru ar putea dura ceva timp, așa că acordați-i ceva timp. După construirea ZFS - nume: Instalați ZFS ansible.builtin.shell: | make install args: chdir: "/opt/zfs/zfs _zfs_version În mod normal, ați crede că am terminat *chiar aici*, dar această postare există pentru că, în general, nu este suficient să faceți acest lucru! Să apăsăm mai departe. Mai întâi forțați descărcarea modulelor ZFS dacă rulează: - nume: descărcarea forțată a modulului (ss) ZFS ansible.builtin.shell: | ./scripts/zfs.-u args: chdir: „/opt/zfs/zfs _zfs_version Ideal ar fi să *nu* rulați nicio sarcină de lucru atunci când se întâmplă acest lucru, așa cum v-ați aștepta. În timp ce modulele sunt descărcate, putem instala câțiva ajutoare: - nume: post-instalare ZFS Helpers ansible.builtin.shell: | ./scripts/zfs-helpers.-i args: chdir: „/opt/zfs/zfs _zfs_version După ce ajutoarele sunt instalate, să forțăm reîncărcarea modulului ZFS: - nume: Reîncărcarea forțată a modulului ZFS ansible.builtin.shell: | ./scripts/zfs.args: chdir: „/opt/zfs/zfs _zfs_version Am găsit acea clădire și folosind Modulul deb (formatul folosit de Debian pentru instalarea pachetului) a ajutat, de asemenea, la menținerea instalării și să nu fie înlocuită de valorile implicite ale pachetului Ubuntu. Mai întâi construiți pachetul deb ZFS din codul sursă: - nume: Build ZFS deb package ansible.builtin.shell: | faceți argumente deb: chdir: "/opt/zfs/zfs _zfs_version Și apoi instalează-l - nume: Instalați pachetele deb ZFS ansible.builtin.shell: | da | dpkg -i --force-overwrite deb apt install -f -y deb args: chdir: "/opt/zfs/zfs _zfs_version Teoretic, acest pas *nu ar trebui* să fie necesar (sau ar trebui să fie folosit singur), deoarece am rulat deja un proces de instalare, dar am constatat că atunci când fac una sau alta I⢠Âaș avea situații în care repornirea ar solicita utilizarea unei versiuni mai vechi de ZFS (în ciuda apt purge) â în special la nivelul nucleului. modprobe Dacă doriți să activați modulul ZFS care a fost instalat imediat, utilizați modprobe: - nume: bloc modul Modprobe zfs: - nume: Instalează modulul kernel zfs community.general.modprobe: nume: stare zfs: prezent Instalarea ZFS înseamnă instalarea unui modul de nucleu, dar din moment ce nu l-am introdus deloc prin intermediul Dynamic Kernel Module Support, trebuie să permitem utilizarea modulelor de kernel instalate local: - nume: Asigurați-vă că suplimentar este în față ansible.builtin.lineinfile: cale: /etc/modules-load.d/modules.conf regexp: '^search'line: "căutați actualizări suplimentare încorporate în ubuntu"stare: prezent Acest lucru face este să vă asigurați că fișierul care gestionează calea de căutare a modulului kernel /etc/modules-load.d/modules.conf are o linie în el care are căutați actualizări suplimentare specificate. În mod normal, există cel puțin o linie care începe cu caută, iar ceea ce vrem să facem este să ne asigurăm locațiile modulelor suplimentare sunt căutate la începutul procesului. Vom dori să instalăm prin subsistemul DKMS: - nume: dkms install zfs ansible.builtin.shell: | dkms install zfs _zfs_version }} args: chdir: "/opt/zfs/zfs _zfs_version În acest moment, ar trebui să puteți verifica versiunea curentă ZFS activă și ar trebui să vă arate ceva de genul acesta: root@machine01 ~ # zfs versiunea zfs-2.1.1-1 zfs-kmod-2.1.1-1 Există câteva unități SystemD (ca de obicei Digital Ocean are niște documente grozave) care sunt create, dar trebuie să fie activate pentru ca ZFS să le poată utiliza: - nume: Asigurați-vă că unitățile systemd legate de zfs sunt activate bloc: - ansible.builtin.systemd: nume:itemstate: început activat: da buclă: - zfs-import-cache.service - zfs-import.target - zfs-mount.service - zfs-share.service - zfs-zed.service - zfs-volume-wait.service - zfs.target Variabilele care se fac în buclă sunt asemănătoare cu rularea 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).