مستضاف بشكل مستدام ، مُدار على شكل F / OSS تخزين الكائنات ، Redis ، Prometheus على Hetzner و OVH و LeaseWeb ** tl ؛ dr - شرح سطر بسطر لبرنامج تثبيت ZFS الخاص بي الذي يتم تشغيله بشكل غير مرئي للاستخدام على أجهزة Hetznerà ¢   المخصصة (Ubuntu 20.04 - à ¢   Focalà ¢  Â) à ¢   ità ¢  ليست مثالية / بالحد الأدنى ، لكنها تعمل بالنسبة لي منذ فترة ، بدأت في استخدام ZFS على جميع أجهزتي المعدنية العارية المخصصة والمُستضافة في Hetzner للتشاحن مع محركات الأقراص الثابتة ومحركات الأقراص الثابتة. هناك الكثير من الخيارات في المساحة (LVM القياسي ، مدريد btrfs ، إلخ) ، لكنني اخترت ZFS لمجموعة تجهيزاتها وبيئة العمل. لن أتحمل أي شخص سبب ذلك ، ولكن أحد الأشياء التي احتاجها للتنقل هو كيفية تثبيت إصدارات أحدث من ZFS على Ubuntu 20.04 (أحد أنظمة التشغيل المدعومة في Hetzner). لقد واجهت بعض المشكلات (خاصة بعد التثبيت) أثناء إعداد ZFS على أنظمتي ، لذلك أردت أن أقدم شرحًا تفصيليًا لكيفية القيام بذلك. هذا المنشور عبارة عن شرح مقطع تلو الآخر لنصوص Ansible التي تثبّت ZFS. قبل أن تعرف ما إذا كان ZFS (أو أي نظام ملفات) يستحق التبديل إليه ، ربما سترغب في RTFM. لدى ZFS الكثير من التفاصيل وأنا بالتأكيد لست خبيرًا فيها ، لكن معرفة كيف ولماذا ، بالإضافة إلى المصطلحات وحتى تاريخ المشروع أمر مهم للغاية. بعض الروابط لتبدأ بها: جنبًا إلى جنب مع ZFS (والتي من المحتمل أن تكون أكثر كمية غير معروفة هنا) ، ربما تريد أن تكون على دراية بـ Ubuntu وإدارة الأنظمة العامة. هذا ترك مساحة كبيرة يجب تغطيتها ولكن فيما يلي بعض الروابط: يكاد يكون من نافلة القول ولكن إذا لم تكن على دراية كبيرة بإدارة نظام لينوكس في هذه المرحلة ، فربما لا ينبغي عليك محاولة ذلك. أنا شخصياً أختار أن يكون لدي أقراصي في تكوين مخصص إلى حد ما ¢   لدي إعداد RAID1 (النسخ المتطابق) عبر mdraid ، جنبًا إلى جنب مع الأقسام الموجودة على كل قرص يمكنني منحها لـ ZFS لإدارتها. من الناحية المثالية ، لدي أقراص كاملة لإعطائها لـ ZFS ولكن الأقسام تعمل أيضًا. إعداد نظام التشغيل ( installimage) الذي يتضمن إعداد القرص يتم تشغيله من وضع الإنقاذ Hetznerà ¢  ويمكن إرشاده بملف مثل التالي: # إعلانات محرك الأقراص المستخدمة بواسطة installimage DRIVE0 /dev/nvme0n1 DRIVE1 /dev/nvme1n1 # تمكين Software RAID (لقرص نظام التشغيل) SWRAID 1 SWRAIDLEVEL 1 # Bootloader (بشكل عام grub) BOOTLOADER grub # مضيف الجهاز HOSTNAME Machine01 # تكوين القسم PART Swap Swap 32G PART /boot ext4 1G PART / ext4 128G # سيتم إنشاء هذا القسم الأخير (مسح& تم إعادة إنشائه كـ ZFS لاحقًا) الجزء / القرص الجذر المتبقي ext4 all # يمكنك تحديد الصور التي يستخدمها Hetzner من خلال الوصول إلى مشاركة الشبكة IMAGE /root/.oldroot/nfs/images/Ubuntu-2004-focal-64-minimal.tar. gz من الواضح أن هذا خاص بشركة Hetzner تمامًا ، ولكن افعل كل ما تحتاج إلى القيام به على أنظمتك الخاصة للحصول على أقسام / محركات أقراص متاحة لاستخدام ZFS. zfsutils- لينكساند 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 محل الإصدار المثبت لدينا بإصدار أقدم. بينما نحن هنا ، دعونا نطهر الحزم أيضًا. - الاسم: حزم Purge ZFS upstream (ubuntu) إذا تم تثبيتها ignore_errors: yes ansible.builtin.command: | تطهير apt --allow-change-held -pack zfsutils-linux zfs-zed يمكنك قراءة المستندات على مناسبة لمعرفة ما التطهير يشبه الإزالة ولكنه يزيل أيضًا ملفات التكوين إن وجدت. يمكنك تثبيت التبعيات لـ OpenZFS مثل: - الاسم: متطلبات التثبيت لبناء ZFS ansible.builtin.apt: الاسم: packageupdate_cache: حالة نعم: الحالي vars: الحزم: - build-basic - 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: - الاسم: Create / opt / zfs ansible.builtin.file: path: / opt / zfs state: directory إذا كنت تريد تنزيل ZFS: - الاسم: تنزيل zfs ansible.builtin.get_url: url: "httpsgithub.com/openzfs/zfs/releases/download/zfs _zfs_version zfs _zfs_version tar.gz"المجموع الاختباري: _zfs_tarball_sha256_checksummode: 0755 dests / zfersion / zfersion: .gz "هنا الاستبدال {{_zfs_version}} ( 2.1.1. سوف ترغب أيضًا في إجراء التنزيل بنفسك وجمع / إنشاء مجموع اختباري لاستخدامه. لا تقم أبدًا بتنزيل أشياء من الإنترنت لا ينبغي تغييرها دون الحاجة إلى إجراء عملية جراحية! {{هو تركيب النماذج Ansible) هو وإذا كنت تريد نسخه من الكمبيوتر حيث يعمل Ansible (هذا ما أفعله): - الاسم: نسخ حزمة zfs (تجنب حد المعدل) ansible.builtin.copy: src: files / zfs / zfs _zfs_version tar.gz "الوضع: 0755 dest:"/ opt / zfs / zfs _zfs_version tar.gz "بغض النظر عن الطريقة التي تختارها للحصول على المصدر ، فستحتاج بالطبع إلى فك ضغطه: - الاسم: فك كود zfs ansible.builtin.unarchive: src: "/ opt / zfs / zfs _zfs_version tar.gz"dest: "/ opt / zfs"remote_src: نعم لبدء عملية البناء: - الاسم: إعداد وإنشاء ZFS ansible.builtin.shell: | ./autogen../configure make clean make -j args: chdir: "/ opt / zfs / zfs _zfs_version إذا كنت معتادًا على بناء الأشياء من المصدر ، فإن العديد من المشاريع تستخدم مجموعة الأدوات الشائعة هذه (بعض المتغيرات من إنشاء البرامج النصية وتكوينها تلقائيًا وتكوينها). كما قد تتوقع ، قد يستغرق هذا بعض الوقت ، لذا امنحه بعض الوقت. بعد بناء ZFS - الاسم: تثبيت ZFS ansible.builtin.shell: | اجعل تثبيت args: chdir: "/ opt / zfs / zfs _zfs_version عادة أنت ¢   تعتقد أننا ¢   قد انتهينا * هنا * ، لكن هذا المنشور موجود لأن القيام بذلك بشكل عام لا يكفي! دعنا نضغط إلى الأمام. أولاً فرض تفريغ وحدة (وحدات) ZFS إذا كانت تعمل: - الاسم: قوة تفريغ وحدة (SS) ZFS ansible.builtin.shell: | ./scripts/zfs.-u args: chdir: "/ opt / zfs / zfs _zfs_version سيكون من المثالي عدم * * تشغيل أي أعباء عمل عند حدوث ذلك ، كما قد تتوقع. أثناء تفريغ الوحدات النمطية ، يمكننا تثبيت بعض المساعدين: - الاسم: مساعد ZFS بعد التثبيت 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 (التنسيق المستخدم من قبل دبيان لتثبيت الحزمة) أيضًا في تثبيت التثبيت وعدم استبداله بالإعدادات الافتراضية لحزمة Ubuntu. قم أولاً ببناء حزمة ZFS deb من الكود المصدري: - الاسم: بناء حزمة ZFS deb ansible.builtin.shell: | اجعل 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 نظريًا ، لا ينبغي أن تكون هذه الخطوة * ضرورية (أو يجب استخدامها بمفردها) ، لأننا قمنا بالفعل بتشغيل عملية تثبيت ، لكنني وجدت ذلك عند القيام بواحد أو آخر.  d لديها مواقف تتطلب فيها إعادة التشغيل استخدام إصدار أقدم من ZFS (على الرغم من apt purge) à ¢   خاصة على مستوى النواة. modprobe إذا كنت تريد تمكين وحدة ZFS التي تم تثبيتها على الفور ، فاستخدم modprobe: - الاسم: كتلة الوحدة النمطية Modprobe zfs: - الاسم: تثبيت الوحدة النمطية zfs kernel community.general.modprobe: الاسم: حالة zfs: الحاضر يعني تثبيت ZFS تثبيت وحدة kernel ، ولكن نظرًا لأننا لم نقم بتجهيزها تمامًا عبر Dynamic Kernel Module Support ، فنحن بحاجة إلى تمكين وحدات kernel المثبتة محليًا لاستخدامها: - الاسم: تأكد من وجود إضافي في المقدمة ansible.builtin.lineinfile: path: /etc/modules-load.d/modules.conf regexp: سطر '^ search': "ابحث عن تحديثات إضافية ubuntu built-in"state: present ما يفعله هذا هو التأكد من أن الملف الذي يدير مسار بحث وحدة kernel /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 version zfs-2.1.1-1 zfs-kmod-2.1.1-1 هناك عدد قليل من وحدات SystemD (كالعادة تحتوي Digital Ocean على بعض المستندات الرائعة) التي تم إنشاؤها ولكن يجب تمكينها لاستخدام ZFS: - الاسم: تأكد من تمكين وحدات systemd المرتبطة بـ zfs: - ansible.builtin.systemd: الاسم: حالة العنصر: تم تمكينه: نعم حلقة: - zfs-import-cache.service - zfs-import.target - zfs-mount.service - zfs-share.service - zfs-zed.service - zfs-volume-wait.service - zfs.target المتغيرات التي يتم تكرارها هي مشابهة للتشغيل ابدأ systemd 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).