持続的にホストされ、管理された F/OSS オブジェクトストレージ、Redis、Prometheus Hetzner、OVH、および LeaseWeb で **tl;dr - Hetzner の専用ハードウェア (Ubuntu 20.04 - ã¢ââFocalã¢ââ) で使用するための私の ansible-powered ZFS インストール スクリプトの行ごとの説明â itã¢ââ 完璧/最小限ではありませんが、私にとってはうまくいきます しばらく前に、Hetzner でホストされているすべてのベアメタル専用ハードウェアで ZFS を使用して、接続されている HDD と SSD を管理し始めました。この分野には多くの選択肢があります (標準の LVM、 ムドレイド btrfs など) ですが、機能セットとエルゴノミクスのために ZFS を選択しました。 その理由を説明して退屈させるつもりはありませんが、ナビゲートする必要があったものの 1 つは、ZFS の新しいバージョンを Ubuntu 20.04 (Hetzner でサポートされているオペレーティング システムの 1 つ) にインストールする方法でした。システムに ZFS をセットアップしているときにいくつかの問題 (特にインストール後) に遭遇したので、その方法をウォークスルーしたいと思いました。 この投稿は、ZFS をインストールする Ansible スクリプトのスタンザごとの説明です。 ZFS (または任意のファイルシステム) に切り替える価値があるかどうかを判断する前に、おそらく RTFM を使用することをお勧めします。 ZFS には多くの機能があり、私は確かに ZFS の専門家ではありませんが、その方法と理由、用語、さらにはプロジェクトの歴史を知ることは非常に重要です。 開始するためのいくつかのリンク: ZFS (ここで最も知られていない可能性が高い) に加えて、おそらく Ubuntu と一般的なシステム管理に精通している必要があります。それはカバーする大きな領域をやめましたが、ここにいくつかのリンクがあります: 言うまでもありませんが、この時点で Linux システム管理に精通していない場合は、おそらくこれを試みるべきではありません。 個人的には、ディスクを多少カスタム構成にすることを選択します。RAID1 (ミラーリング) を mdraid、および管理のために ZFS に与えることができる各ディスク上のパーティション。理想的には、ディスク全体を ZFS に渡す必要がありますが、パーティションも機能します。 OS セットアップ ( ディスク セットアップを含む installimage) は、Hetzner のレスキュー モードから実行され、次のようなファイルでガイドできます。 # installimage で使用されるドライブ宣言 DRIVE0 /dev/nvme0n1 DRIVE1 /dev/nvme1n1 # ソフトウェア RAID を有効にする (OS ディスク用) SWRAID 1 SWRAIDLEVEL 1 # ブートローダー (通常は grub) BOOTLOADER grub # マシン ホスト名 HOSTNAME machine01 # パーティションconfiguration PART swap swap 32G PART /boot ext4 1G PART / ext4 128G # この最後のパーティションが作成されます (wiped& 後で ZFS として再作成されます) PART /root-disk-remaining ext4 all # ネットワーク共有 IMAGE /root/.oldroot/nfs/images/Ubuntu-2004-focal-64-minimal.tar にアクセスすることで、Hetzner が使用するイメージを指定できます。 gz これは明らかにHetzner固有のものですが、ZFSが利用できるパーティション/ドライブを利用できるようにするために、自分のシステムで必要なことは何でもしてください。 zfsutils-linuxand zfs-zed Ansible YAML では、ステップは次のようになります。 - name: すべての zfs 関連のアップストリーム パッケージを保持します ansible.builtin.shell: | apt-mark ホールド zfsutils-linux apt-mark ホールド zfs-zed この投稿の執筆時点でのバージョン Ubuntu Focal の zfs-linux は 0.8.3 です。ここでの目標は、新しいバージョンをインストールして使い続けることなので、 apt アップデートは、インストール済みのバージョンを古いバージョンに置き換えるものではありません。 ここにいる間に、パッケージもパージしましょう。 - name: ZFS アップストリーム (ubuntu) パッケージがインストールされている場合はパージする ignore_errors: yes ansible.builtin.command: | apt パージ --allow-change-held-packages zfsutils-linux zfs-zed でドキュメントを読むことができます 何を見る傾向がある purge は remove に似ていますが、存在する場合は構成ファイルも削除します。 次のように OpenZFS の依存関係をインストールできます。 - name: 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"私の Arch システムでは # その行は "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_checksummode: 0755 dest: "/opt/zfs/zfs _zfs_version tar .gz"ここで置換 {{ _zfs_version }} ( 2.1.1.また、自分でダウンロードを行い、使用するチェックサムを収集/生成することもできます。チェックサムなしでは変更できないものをインターネットからダウンロードしないでください。 {{は Ansible テンプレート構文です) は そして、Ansible が実行されているコンピューターからコピーしたい場合 (これが私のやり方です): - name: zfs パッケージをコピー (レート制限を回避) ansible.builtin.copy: src: files/zfs/zfs _zfs_version tar.gz"mode: 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: yes ビルド プロセスを開始するには: - name: ZFS ansible.builtin.shell のセットアップとビルド: | ./autogen../configure make clean make -j args: chdir: "/opt/zfs/zfs _zfs_version ソースからのビルドに慣れている場合、さまざまなプロジェクトでこの共通のツールセットが使用されます (一部のバリアント make、autogen、configure スクリプト)。ご想像のとおり、これには時間がかかる場合がありますので、しばらくお待ちください。 ZFSの構築後 - 名前: ZFS ansible.builtin.shell をインストールします: | make install args: chdir: "/opt/zfs/zfs _zfs_version 通常、私たちは *ここ* で完了すると思いますが、これを行うだけでは一般的に十分ではないため、この投稿が存在します。先に進みましょう。 ZFS モジュールが実行されている場合は、最初に強制的にアンロードします。 - name: 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 モジュールを強制的にリロードします。 - name: ZFS モジュールの強制リロード ansible.builtin.shell: | ./scripts/zfs.args: chdir: "/opt/zfs/zfs _zfs_version 私はその構築と使用を発見しました deb モジュール (パッケージのインストールに Debian で使用される形式) は、インストールを定着させ、Ubuntu パッケージのデフォルトに置き換えられないようにするのにも役立ちました。 まず、ソース コードから ZFS deb パッケージをビルドします。 - 名前: ZFS deb パッケージのビルド ansible.builtin.shell: | make deb args: chdir: "/opt/zfs/zfs _zfs_version そして、それをインストールします - name: ZFS deb パッケージをインストールします ansible.builtin.shell: |はい | dpkg -i --force-overwrite deb apt install -f -y deb args: chdir: "/opt/zfs/zfs _zfs_version 理論的には、この手順は必要ではありません (または単独で使用する必要があります)。既にインストール プロセスを実行しているためです。  再起動すると古いバージョンの ZFS を使用するように促される状況がありました (ただし、 apt purge) (特にカーネル レベルで)。 modプローブ すぐにインストールされた ZFS モジュールを有効にする場合は、 modプローブ: - 名前: Modprobe zfs モジュール ブロック: - 名前: zfs カーネル モジュールをインストールします community.general.modprobe: 名前: zfs 状態: 現在 ZFS をインストールすることは、カーネル モジュールをインストールすることを意味しますが、動的カーネル モジュール サポートを介して完全に焼き付けていないため、ローカルにインストールされたカーネル モジュールを使用できるようにする必要があります。 - 名前: エクストラが前にあることを確認します ansible.builtin.lineinfile: パス: /etc/modules-load.d/modules.conf regexp: '^search'行: "search extra updates ubuntu built-in"状態: present これにより、カーネル モジュールの検索パスを管理するファイルが /etc/modules-load.d/modules.conf には次の行があります。 指定された追加の更新を検索します。通常、で始まる行が少なくとも 1 行あります。 検索し、私たちがやりたいことは確認することです 余分なモジュールの場所は、プロセスの早い段階で検索されます。 DKMS サブシステム経由でインストールします。 - 名前: dkms インストール 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 を使用するには有効にする必要があります。 - name: zfs 関連の systemd ユニットが有効であることを確認します 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 ループされる変数は、実行に似ています 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).