Βιώσιμη φιλοξενία, Διαχειριζόμενο F/OSS Αποθήκευση αντικειμένων, Redis, Prometheus σε Hetzner, OVH και LeaseWeb **tl;dr - Επεξήγηση γραμμή προς γραμμή του σεναρίου εγκατάστασης του ZFS με δυνατότητα τροφοδοσίας για χρήση σε αποκλειστικό υλικό του Hetzner (Ubuntu 20.04 - ¢ÂÂFocalâÂÂ) â «Δεν είναι τέλειο/ελάχιστο, αλλά λειτουργεί για μένα Πριν από λίγο καιρό άρχισα να χρησιμοποιώ το ZFS σε όλο μου το ειδικό υλικό από γυμνό μέταλλο που φιλοξενείται στο Hetzner για να τσακώνω τους συνδεδεμένους σκληρούς δίσκους και SSD. Υπάρχουν πολλές επιλογές στο χώρο (κανονικό LVM, mdraid btrfs, κλπ), αλλά επέλεξα το ZFS για το σετ χαρακτηριστικών και την εργονομία του. Δεν θα κουράσω κανέναν με το γιατί, αλλά ένα από τα πράγματα που χρειαζόμουν να πλοηγηθώ ήταν πώς να εγκαταστήσω νεότερες εκδόσεις του ZFS στο Ubuntu 20.04 (ένα από τα υποστηριζόμενα λειτουργικά συστήματα στο Hetzner). Αντιμετώπισα ορισμένα προβλήματα (ιδιαίτερα μετά την εγκατάσταση) κατά την εγκατάσταση του ZFS στα συστήματά μου, γι'αυτό ήθελα να δώσω μια αναλυτική περιγραφή του τρόπου με τον οποίο το έκανα. Αυτή η ανάρτηση είναι μια εξήγηση στροφή προς στροφή των σεναρίων μου Ansible που εγκαθιστούν το ZFS. Προτού μάθετε εάν αξίζει να μεταβείτε στο ZFS (ή σε οποιοδήποτε σύστημα αρχείων), πιθανότατα θα θέλετε να κάνετε RTFM. Το ZFS έχει πολλά μυστικά και σίγουρα δεν είμαι ειδικός σε αυτό, αλλά το να γνωρίζω το πώς και το γιατί, καθώς και την ορολογία και ακόμη και την ιστορία του έργου είναι πολύ σημαντικό. Μερικοί σύνδεσμοι για να ξεκινήσετε: Μαζί με το ZFS (που είναι πιθανώς η πιο άγνωστη ποσότητα εδώ) πιθανότατα θέλετε να εξοικειωθείτε με το Ubuntu και τη γενική διαχείριση συστημάτων. Αυτό εγκαταλείπει μια μεγάλη περιοχή για να καλύψει, αλλά εδώ είναι μερικοί σύνδεσμοι: Είναι σχεδόν αυτονόητο, αλλά αν δεν είστε πολύ εξοικειωμένοι με τη διαχείριση συστήματος linux σε αυτό το σημείο, μάλλον δεν θα έπρεπε να το επιχειρήσετε. Προσωπικά επιλέγω να έχω τους δίσκους μου σε μια κάπως προσαρμοσμένη διαμόρφωση â Έχω ρυθμίσεις RAID1 (mirroring) μέσω mdraid, μαζί με κατατμήσεις σε κάθε δίσκο που μπορώ να δώσω στην ZFS για διαχείριση. Στην ιδανική περίπτωση, θα έχω ολόκληρους δίσκους να δώσω στο ZFS, αλλά και τα διαμερίσματα λειτουργούν. Ρύθμιση λειτουργικού συστήματος ( installimage) που περιλαμβάνει τη ρύθμιση του δίσκου εκτελείται από τη λειτουργία διάσωσης του Hetzner και μπορεί να καθοδηγηθεί με ένα αρχείο όπως το ακόλουθο: # Δηλώσεις μονάδας δίσκου που χρησιμοποιούνται από installimage DRIVE0 /dev/nvme0n1 DRIVE1 /dev/nvme1n1 # Ενεργοποίηση λογισμικού RAID (για το δίσκο του λειτουργικού συστήματος) SWRAID 1 SWRAIDLEVEL 1 # Bootloader (γενικά grub) BOOTLOADER grub #Όνομα μηχανής Partame1 διαμόρφωση PART swap swap 32G PART /boot ext4 1G PART / ext4 128G # Αυτή η τελευταία κατάτμηση θα γίνει (wiped& αναδημιουργήθηκε ως ZFS αργότερα) PART /root-disk-remaining ext4 all # Μπορείτε να καθορίσετε εικόνες που χρησιμοποιεί ο Hetzner αποκτώντας πρόσβαση στο κοινόχρηστο στοιχείο δικτύου IMAGE /root/.oldroot/nfs/images/Ubuntu-2004-focal-64-minimal.tar. gz Αυτό είναι προφανώς πολύ συγκεκριμένο για το Hetzner, αλλά κάντε ό,τι χρειάζεται να κάνετε στα δικά σας συστήματα για να έχετε διαθέσιμα διαμερίσματα/δίσκους για χρήση της ZFS. zfsutils-linuxand zfs-zed Στο Ansible YAML το βήμα μοιάζει με αυτό: - όνομα: Κρατήστε όλα τα πακέτα που σχετίζονται με το zfs ansible.builtin.shell: | apt-mark hold zfsutils-linux apt-mark hold zfs-zed Μέχρι τη σύνταξη αυτής της ανάρτησης η έκδοση του Το zfs-linux στο Ubuntu Focal είναι 0.8.3. Δεδομένου ότι ο στόχος μας εδώ είναι να εγκαταστήσουμε και να συνεχίσουμε να χρησιμοποιούμε μια νεότερη έκδοση, θέλουμε να βεβαιωθούμε ότι υπάρχει κάποια Οι ενημερώσεις apt δεν αντικαθιστούν την εγκατεστημένη έκδοση μας με μια παλαιότερη έκδοση. Ενώ είμαστε εδώ, ας καθαρίσουμε και τα πακέτα. - όνομα: Εκκαθάριση πακέτων ZFS upstream (ubuntu) εάν είναι εγκατεστημένα ignore_errors: ναι ansible.builtin.command: | apt purge --allow-change-held-packages zfsutils-linux zfs-zed Μπορείτε να διαβάσετε τα έγγραφα στο ταιριαστο να δεις τι Το purge είναι παρόμοιο με το αφαίρεση, αλλά αφαιρεί επίσης τα αρχεία διαμόρφωσης εάν υπάρχουν. Μπορείτε να εγκαταστήσετε τις εξαρτήσεις για το OpenZFS ως εξής: - όνομα: Απαιτήσεις εγκατάστασης για τη δημιουργία ZFS ansible.builtin.apt: όνομα:packagesupdate_cache: ναι κατάσταση: παρούσες vars: πακέτα: - 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 # Η παρακάτω γραμμή ζητά την έξοδο του "uname -r", για παράδειγμα "5.16.5-arch1- 1"για το σύστημα αψίδας μου # οπότε η γραμμή θα επιλύεται σε κάτι σαν "linux-headers-5.16.5-arch1-1"(δεν ισχύει φυσικά στο Ubuntu, αλλά ως παράδειγμα) - linux-headers uname_r.stdout }} - python3 - python3-dev - python3-setuptools - python3-cffi - libffi-dev - python3-packaging - git - libcurl4-openssl-dev Μπορεί να υπάρχουν μερικές εξαρτήσεις που δεν είναι απολύτως απαραίτητες, αλλά σχεδόν όλες θα πρέπει να απαιτούνται. /opt/zfs Εδώ είναι το ZFS: - όνομα: Δημιουργία /opt/zfs ansible.builtin.file: διαδρομή: /opt/zfs κατάσταση: κατάλογος Εάν θέλετε να κατεβάσετε το ZFS: - όνομα: Λήψη zfs ansible.builtin.get_url: url: "httpsgithub.com/openzfs/zfs/releases/download/zfs _zfs_version zfs _zfs_version tar.gz"checksum:_zfs_tarball_sha256_checksum:_zfs_tarball_sha256_checksum:_zfs_tarball_sha256_sfsz7 .gz"Εδώ η αντικατάσταση {{ _zfs_version }} ( 2.1.1. Θα θέλετε επίσης να κάνετε τη λήψη μόνοι σας και να συλλέξετε/δημιουργήσετε ένα άθροισμα ελέγχου για χρήση. Ποτέ μην κατεβάζετε πράγματα από το Διαδίκτυο που δεν πρέπει να αλλάξουν χωρίς τσεκ! {{είναι η σύνταξη προτύπου Ansible) είναι Και αν θέλετε να το αντιγράψετε από τον υπολογιστή όπου εκτελείται το Ansible (αυτό κάνω): - όνομα: Αντιγραφή πακέτου zfs (αποφυγή ορίου ποσοστού) ansible.builtin.copy: src: files/zfs/zfs _zfs_version tar.gz"mode: 0755 προορισμό: "/opt/zfs/zfs _zfs_version tar.gz"Ανεξάρτητα από το πώς θα επιλέξετε να λάβετε την πηγή, θα πρέπει φυσικά να την αποσυμπιέσετε: - όνομα: Αποσυμπιέστε τον κωδικό zfs ansible.builtin.unarchive: src: "/opt/zfs/zfs _zfs_version tar.gz"προορισμό: "/opt/zfs"remote_src: ναι Για να ξεκινήσετε τη διαδικασία κατασκευής: - όνομα: Setup and Build ZFS ansible.builtin.shell: | ./autogen../configure make clean make -j args: chdir: "/opt/zfs/zfs _zfs_version Εάν είστε εξοικειωμένοι με την κατασκευή πραγμάτων από την πηγή, διάφορα έργα χρησιμοποιούν αυτό το κοινό σύνολο εργαλείων (κάποια παραλλαγή του δημιουργία, αυτόματη δημιουργία και διαμόρφωση σεναρίων). Όπως μπορείτε να περιμένετε, αυτό μπορεί να διαρκέσει λίγο, οπότε δώστε του λίγο χρόνο. Μετά την κατασκευή του ZFS - όνομα: Εγκατάσταση ZFS ansible.builtin.shell: | make install args: chdir: "/opt/zfs/zfs _zfs_version Κανονικά πιστεύετε ότι θα τελειώνουμε *εδώ*, αλλά αυτή η ανάρτηση υπάρχει γιατί αυτό γενικά δεν είναι αρκετό! Ας πατήσουμε παρακάτω. Αρχικά, αναγκάστε την αποφόρτωση της μονάδας(ών) ZFS εάν εκτελούνται: - όνομα: Αναγκαστική εκφόρτωση της μονάδας(ων) ZFS ansible.builtin.shell: | ./scripts/zfs.-u args: chdir: "/opt/zfs/zfs _zfs_version Θα ήταν ιδανικό να *μην* εκτελείτε κανέναν φόρτο εργασίας όταν συμβαίνει αυτό, όπως θα περιμένατε. Ενώ οι μονάδες εκφορτώνονται, μπορούμε να εγκαταστήσουμε ορισμένους βοηθούς: - όνομα: Μετά την εγκατάσταση ZFS Helpers ansible.builtin.shell: | ./scripts/zfs-helpers.-i args: chdir: "/opt/zfs/zfs _zfs_version Αφού εγκατασταθούν οι βοηθοί, ας φορτίσουμε ξανά τη μονάδα ZFS: - όνομα: Αναγκαστική επαναφόρτωση της μονάδας ZFS ansible.builtin.shell: | ./scripts/zfs.args: chdir: "/opt/zfs/zfs _zfs_version Βρήκα ότι οικοδομώντας και χρησιμοποιώ το Η ενότητα deb (η μορφή που χρησιμοποιείται από το Debian για την εγκατάσταση πακέτων) βοήθησε επίσης στο να κολλήσει η εγκατάσταση και να μην αντικατασταθεί από τις προεπιλογές του πακέτου Ubuntu. Κατασκευάστε πρώτα το πακέτο deb ZFS από τον πηγαίο κώδικα: - όνομα: Build ZFS deb πακέτο ansible.builtin.shell: | make deb args: chdir: "/opt/zfs/zfs _zfs_version Και μετά εγκαταστήστε το - όνομα: Εγκατάσταση πακέτων deb ZFS ansible.builtin.shell: | ναι | dpkg -i --force-overwrite deb apt install -f -y deb args: chdir: "/opt/zfs/zfs _zfs_version Θεωρητικά αυτό το βήμα *δεν* πρέπει* να είναι απαραίτητο (ή θα πρέπει να χρησιμοποιείται μόνο του), καθώς έχουμε ήδη εκτελέσει μια διαδικασία εγκατάστασης, αλλά διαπίστωσα ότι όταν κάνω το ένα ή το άλλο.  θα υπήρχαν περιπτώσεις όπου η επανεκκίνηση θα προκαλούσε τη χρήση μιας παλαιότερης έκδοσης του ZFS (παρά την apt purge) â ιδιαίτερα σε επίπεδο πυρήνα. modprobe Εάν θέλετε να ενεργοποιήσετε τη μονάδα ZFS που εγκαταστάθηκε αμέσως, χρησιμοποιήστε το modprobe: - name: Modprobe zfs module module: - name: Install zfs kernel module community.general.modprobe: name: zfs state: present Η εγκατάσταση του ZFS σημαίνει εγκατάσταση μιας λειτουργικής μονάδας πυρήνα, αλλά επειδή δεν την έχουμε προετοιμάσει αρκετά μέσω της Υποστήριξης Dynamic Kernel Module, πρέπει να ενεργοποιήσουμε τη χρήση τοπικά εγκατεστημένων λειτουργικών μονάδων πυρήνα: - όνομα: Βεβαιωθείτε ότι το extra είναι μπροστά ansible.builtin.lineinfile: διαδρομή: /etc/modules-load.d/modules.conf regexp: '^αναζήτηση'γραμμή: "αναζήτηση επιπλέον ενημερώσεων ενσωματωμένο ubuntu"κατάσταση: παρούσα Αυτό που κάνει είναι να διασφαλίζει ότι το αρχείο που διαχειρίζεται τη διαδρομή αναζήτησης της μονάδας πυρήνα Το /etc/modules-load.d/modules.conf έχει μια γραμμή που έχει προσδιορίζονται επιπλέον ενημερώσεις αναζήτησης. Κανονικά υπάρχει τουλάχιστον μία γραμμή που ξεκινά με αναζήτηση και αυτό που θέλουμε να κάνουμε είναι να βεβαιωθούμε Οι επιπλέον τοποθεσίες της μονάδας αναζητούνται νωρίς στη διαδικασία. Θα θέλουμε να εγκαταστήσουμε μέσω του υποσυστήματος DKMS: - όνομα: dkms install zfs ansible.builtin.shell: | dkms install zfs _zfs_version }} args: chdir: "/opt/zfs/zfs _zfs_version Σε αυτό το σημείο, θα πρέπει να μπορείτε να ελέγξετε την τρέχουσα ενεργή έκδοση ZFS και θα πρέπει να σας δείξει κάτι σαν αυτό: root@machine01 ~ # zfs έκδοση zfs-2.1.1-1 zfs-kmod-2.1.1-1 Υπάρχουν μερικές μονάδες SystemD (ως συνήθως το Digital Ocean έχει μερικά υπέροχα έγγραφα) που δημιουργούνται αλλά πρέπει να ενεργοποιηθούν για χρήση του ZFS: - όνομα: Βεβαιωθείτε ότι οι μονάδες systemd που σχετίζονται με το zfs είναι ενεργοποιημένες μπλοκ: - ansible.builtin.systemd: name:itemstate: ενεργοποιήθηκε: yes βρόχος: - zfs-import-cache.service - zfs-import.target - zfs-mount.service - zfs-share.service - zfs-zed.service - zfs-volume-wait.service - zfs.target Οι μεταβλητές που επαναλαμβάνονται είναι παρόμοιες με την εκτέλεση 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).