پائیدار میزبانی، F/OSS کا نظم آبجیکٹ اسٹوریج، Redis، Prometheus Hetzner، OVH اور LeaseWeb پر **tl;dr - ہیٹزنر کے وقف شدہ ہارڈویئر (اوبنٹو 20.04 - â فوکلâÂÂ) پر استعمال کے لیے میرے جوابی طاقت سے چلنے والے ZFS انسٹال اسکرپٹ کی سطر بہ سطر وضاحت  یہ کامل/کم سے کم نہیں ہے، لیکن یہ میرے لیے کام کرتا ہے۔ تھوڑی دیر پہلے میں نے منسلک HDDs اور SSDs کو جھنجھوڑنے کے لیے Hetzner میں میزبان اپنے تمام ننگے دھاتی وقف شدہ ہارڈ ویئر پر ZFS کا استعمال شروع کیا۔ جگہ میں بہت سے انتخاب ہیں (معیاری LVM، mdraid btrfs، وغیرہ)، لیکن میں نے ZFS کو اس کے فیور سیٹ اور ایرگونومکس کے لیے منتخب کیا۔ میں کسی کو اس کی وجہ سے تنگ نہیں کروں گا، لیکن ایک چیز جس کی مجھے نیویگیٹ کرنے کی ضرورت تھی وہ یہ تھی کہ Ubuntu 20.04 (Hetzner میں تعاون یافتہ آپریٹنگ سسٹمز میں سے ایک) پر ZFS کے نئے ورژن کیسے انسٹال کیے جائیں۔ مجھے اپنے سسٹمز پر ZFS ترتیب دینے کے دوران کچھ مسائل (خاص طور پر انسٹال کرنے کے بعد) کا سامنا کرنا پڑا لہذا میں یہ بتانا چاہتا ہوں کہ میں نے یہ کیسے کیا۔ یہ پوسٹ ZFS انسٹال کرنے والی میری جوابی اسکرپٹس کی ایک سٹانزا بہ سٹینزا وضاحت ہے۔ اس سے پہلے کہ آپ یہ جان لیں کہ آیا ZFS (یا کوئی فائل سسٹم) سوئچ کرنے کے قابل ہے، آپ شاید RTFM کرنا چاہیں گے۔ ZFS کے پاس بہت سارے انس ہیں اور میں یقینی طور پر اس کا ماہر نہیں ہوں، لیکن یہ جاننا کہ کیسے اور کیوں، نیز اصطلاحات اور یہاں تک کہ پروجیکٹ کی تاریخ جاننا بہت ضروری ہے۔ آپ کو شروع کرنے کے لیے چند لنکس: ZFS کے ساتھ (جو کہ ممکنہ طور پر یہاں سب سے زیادہ نامعلوم مقدار ہے) آپ شاید Ubuntu اور جنرل سسٹم ایڈمنسٹریشن سے واقف ہونا چاہتے ہیں۔ یہ احاطہ کرنے کے لئے ایک بڑا علاقہ چھوڑ دیتا ہے لیکن یہاں کچھ لنکس ہیں: یہ تقریباً کہے بغیر جاتا ہے لیکن اگر آپ اس وقت لینکس سسٹم ایڈمنسٹریشن سے زیادہ واقف نہیں ہیں، تو شاید آپ کو اس کی کوشش نہیں کرنی چاہیے۔ میں ذاتی طور پر اپنی ڈسکوں کو کسی حد تک حسب ضرورت ترتیب میں رکھنے کا انتخاب کرتا ہوں - میرے پاس RAID1 (مررنگ) سیٹ اپ ہے mdraid، ہر ڈسک پر پارٹیشنز کے ساتھ جو میں ZFS کو انتظام کرنے کے لیے دے سکتا ہوں۔ مثالی طور پر، ZFS کو دینے کے لیے میرے پاس پوری ڈسکیں ہیں لیکن پارٹیشنز بھی کام کرتی ہیں۔ OS سیٹ اپ ( installimage) جس میں ڈسک سیٹ اپ شامل ہے Hetznerâ کے ریسکیو موڈ سے چلایا جاتا ہے اور درج ذیل جیسی فائل کے ساتھ رہنمائی کی جا سکتی ہے۔ # installimage کے ذریعے استعمال ہونے والے Drive declarations DRIVE0 /dev/nvme0n1 DRIVE1 /dev/nvme1n1 # سافٹ ویئر RAID کو فعال کریں (OS ڈسک کے لیے) SWRAID 1 SWRAIDLEVEL 1 # بوٹ لوڈر (عام طور پر گرب) BOOTLOADER Partine grub #1 MaHOSTine machine #1 کنفیگریشن PART swap swap 32G PART/boot ext4 1G PART/ext4 128G # یہ آخری پارٹشن بن جائے گا (صاف& بعد میں ZFS کے طور پر دوبارہ بنایا گیا) PART /root-disk-remaining ext4 all # آپ ان تصاویر کی وضاحت کر سکتے ہیں جو Hetzner ان کے نیٹ ورک شیئر IMAGE /root/.oldroot/nfs/images/Ubuntu-2004-focal-64-minimal.tar تک رسائی حاصل کر کے استعمال کرتا ہے۔ gz یہ واضح طور پر بالکل ہیٹزنر کے لیے مخصوص ہے، لیکن ZFS کے استعمال کے لیے پارٹیشنز/ڈرائیو دستیاب رکھنے کے لیے آپ کو اپنے سسٹمز پر جو کچھ بھی کرنے کی ضرورت ہے وہ کریں۔ zfsutils-linuxand zfs-zed جوابی YAML میں قدم اس طرح لگتا ہے: - نام: تمام زیڈ ایف ایس سے متعلقہ اپ اسٹریم پیکجوں کو ہولڈ کریں ansible.builtin.shell: | apt-mark ہولڈ zfsutils-linux apt-mark ہولڈ zfs-zed اس پوسٹ کی تحریر کے مطابق کا ورژن اوبنٹو فوکل میں zfs-linux 0.8.3 ہے۔ چونکہ یہاں ہمارا مقصد ایک نئے ورژن کو انسٹال کرنا اور استعمال کرتے رہنا ہے، اس لیے ہم یہ یقینی بنانا چاہتے ہیں کہ کوئی بھی apt اپ ڈیٹس ہمارے انسٹال شدہ ورژن کو پرانے ورژن سے تبدیل نہیں کرتے ہیں۔ جب ہم یہاں ہیں، آئیے پیکجز کو بھی صاف کریں۔ - نام: ZFS upstream (ubuntu) پیکجوں کو صاف کریں اگر انسٹال ہو تو ignore_errors: yes ansible.builtin.command: | apt purge --allow-change-hold-packages zfsutils-linux zfs-zed آپ اس پر موجود دستاویزات کو پڑھ سکتے ہیں۔ کیا دیکھنے کے لئے موزوں ہے purge یہ ہٹانے کے مترادف ہے لیکن اگر موجود ہو تو کنفیگریشن فائلوں کو بھی ہٹا دیتا ہے۔ آپ OpenZFS کے لیے اس طرح انحصار انسٹال کر سکتے ہیں: - نام: ZFS ansible.builtin.apt بنانے کے لیے تقاضے انسٹال کریں: name:packagesupdate_cache: yes state: present 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 # نیچے کی لائن `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/zfs_tx/zfs_56/zfs_check: .gz"یہاں متبادل {{ _zfs_version }} ( 2.1.1 آپ خود بھی ڈاؤن لوڈ کرنا چاہیں گے اور استعمال کرنے کے لیے ایک چیکسم جمع/جنریٹ کرنا چاہیں گے۔ کبھی بھی انٹرنیٹ سے ایسی چیزیں ڈاؤن لوڈ نہ کریں جو چیکسم کے بغیر تبدیل نہ ہو! {{Asible templating syntax) ہے۔ اور اگر آپ اسے کمپیوٹر سے کاپی کرنا چاہتے ہیں جہاں 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: | install args بنائیں: chdir: "/opt/zfs/zfs _zfs_version عام طور پر آپ کو لگتا ہے کہ ہم *یہاں* مکمل کر لیں گے، لیکن یہ پوسٹ موجود ہے کیونکہ عام طور پر ایسا کرنا کافی نہیں ہے! آئیے آگے دبائیں۔ پہلے ZFS ماڈیول (زبانیں) کو ان لوڈ کرنے پر مجبور کریں اگر وہ چل رہے ہیں: - نام: ZFS ماڈیول (ss) کو زبردستی اتاریں 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 ماڈیول (پیکج کی تنصیب کے لیے ڈیبین کے ذریعے استعمال ہونے والا فارمیٹ) نے انسٹالیشن کو قائم رکھنے اور اوبنٹو پیکیج ڈیفالٹس سے تبدیل نہ ہونے میں مدد کی۔ پہلے سورس کوڈ سے ZFS deb پیکیج بنائیں: - نام: ZFS deb پیکیج کی تعمیر کریں ansible.builtin.shell: | deb args بنائیں: chdir: "/opt/zfs/zfs _zfs_version اور پھر انسٹال کریں۔ - نام: ZFS deb پیکیجز انسٹال کریں ansible.builtin.shell: | ہاں | dpkg -i --force-overwrite deb apt install -f -y deb args: chdir: "/opt/zfs/zfs _zfs_version نظریاتی طور پر یہ قدم *ضروری نہیں ہونا چاہیے (یا اکیلے استعمال کیا جانا چاہیے)، کیونکہ ہم نے پہلے سے ہی انسٹال کرنے کا عمل چلا رکھا ہے، لیکن میں نے پایا ہے کہ جب ایک یا دوسرا Iâ کرتے ہیں Âd ایسے حالات ہیں جہاں دوبارہ شروع ہونے سے ZFS کے پرانے ورژن کو استعمال کرنے کا اشارہ ملے گا (باوجود apt purge) â خاص طور پر دانا کی سطح پر۔ modprobe اگر آپ ZFS ماڈیول کو فعال کرنا چاہتے ہیں جو فوری طور پر انسٹال ہوا تھا، استعمال کریں۔ modprobe: - نام: Modprobe zfs ماڈیول بلاک: - نام: zfs kernel module community.general.modprobe انسٹال کریں: نام: zfs ریاست: موجودہ ZFS کو انسٹال کرنے کا مطلب ہے کرنل ماڈیول انسٹال کرنا، لیکن چونکہ ہم نے اسے ڈائنامک کرنل ماڈیول سپورٹ کے ذریعے مکمل طور پر بیک نہیں کیا ہے، اس لیے ہمیں مقامی طور پر نصب کرنل ماڈیولز کو استعمال کرنے کے لیے فعال کرنے کی ضرورت ہے: - نام: یقینی بنائیں کہ اضافی سامنے ہے ansible.builtin.lineinfile: path: /etc/modules-load.d/modules.conf regexp: '^search'لائن: "Search extra updates 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 کچھ سسٹم ڈی یونٹس ہیں (معمول کی طرح ڈیجیٹل اوقیانوس میں کچھ عمدہ دستاویزات ہیں) جو بنائے گئے ہیں لیکن ZFS کو استعمال کرنے کے لیے فعال کرنے کی ضرورت ہے: - نام: یقینی بنائیں کہ zfs سے متعلق سسٹمڈ یونٹس فعال ہیں بلاک: - ansible.builtin.systemd: name:itemstate: start 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 جن متغیرات کو لوپ کیا جا رہا ہے وہ چلنے کے مترادف ہے۔ 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).