dm-writecacheを試す

dm-writecacheを試す

dm-writecacheとは

kernel 4.18でマージされたキャッシュの機能

docs.kernel.org www.admin-magazine.com manpages.ubuntu.com

以前から存在したdm-cacheはデフォルトだとwrite throughで読み取りもキャッシュしていた。 dm-writecacheではwrite backのみで書き込みのみをキャッシュして、読み取りは通常のページキャッシュに任せる仕様になっている

続きを読む

zswapを有効化する

参考リンク

UbuntuにおけるSwapのFAQはここ https://help.ubuntu.com/community/SwapFaq

zswapについてはこちら https://www.kernel.org/doc/html/v5.13/vm/zswap.html#

ここのBlogを参考にzswapの設定をする https://ubuntu.com/blog/how-low-can-you-go-running-ubuntu-desktop-on-a-2gb-raspberry-pi-4

設定手順

/boot/firmware/cmdline.txtに設定を追加する

最初に現在の内容

ubuntu@ubuntu:~$ cat /boot/firmware/cmdline.txt
dwc_otg.lpm_enable=0 console=serial0,115200 console=tty1 root=LABEL=writable rootfstype=ext4 elevator=deadline rootwait fixrtc quiet splash

追加

ubuntu@ubuntu:~$  sudo sed -i -e 's/$/ zswap.enabled=1/' /boot/firmware/cmdline.txt

追加後

ubuntu@ubuntu:~$ cat /boot/firmware/cmdline.txt
dwc_otg.lpm_enable=0 console=serial0,115200 console=tty1 root=LABEL=writable rootfstype=ext4 elevator=deadline rootwait fixrtc quiet splash zswap.enabled=1

再起動して設定を反映

有効時のパラメータ

ubuntu@ubuntu:~$ grep -R . /sys/module/zswap/parameters
/sys/module/zswap/parameters/same_filled_pages_enabled:Y
/sys/module/zswap/parameters/enabled:Y
/sys/module/zswap/parameters/max_pool_percent:20
/sys/module/zswap/parameters/compressor:lzo
/sys/module/zswap/parameters/zpool:zbud
/sys/module/zswap/parameters/accept_threshold_percent:90

圧縮形式とアロケータの変更

圧縮形式はデフォルトのlzoだと軽いが代わりに圧縮率が低いので変更する。圧縮率がいいのはzstdだが重いので、lzoより圧縮率が高くてzstdより軽量なlz4にする。 アロケータはデフォルトのzbudだとページごとに2つのオブジェクトを格納する。圧縮率を高めるためにページごとに3つのオブジェクトを格納できるz3foldに変更。

sudo -i
echo lz4 >> /etc/initramfs-tools/modules
echo z3fold >> /etc/initramfs-tools/modules

変更したらinitramfsを更新

update-initramfs -u

cmdline.txtにも追加

sudo sed -i -e 's/$/ zswap.compressor=lz4/' /boot/firmware/cmdline.txt
sudo sed -i -e 's/$/ zswap.zpool=z3fold/' /boot/firmware/cmdline.txt

再起動して設定が正しく反映されているかチェック

ubuntu@ubuntu:~$  grep -R . /sys/module/zswap/parameters
/sys/module/zswap/parameters/same_filled_pages_enabled:Y
/sys/module/zswap/parameters/enabled:Y
/sys/module/zswap/parameters/max_pool_percent:20
/sys/module/zswap/parameters/compressor:lz4
/sys/module/zswap/parameters/zpool:z3fold
/sys/module/zswap/parameters/accept_threshold_percent:90

Raspberry Pi4にLXDをセットアップする

lxd の初期設定

今回はlxdのストレージにzfsを使うので、最初にデータセットを作成

ubuntu@ubuntu:~$ sudo zfs create pool01/lxd_default
ubuntu@ubuntu:~$ zfs list
NAME                 USED  AVAIL     REFER  MOUNTPOINT
pool01              17.9G   373G     5.97G  /pool01
pool01/NFS          12.0G   373G     12.0G  /pool01/NFS
pool01/lxd_default    24K   373G       24K  /pool01/lxd_default

初期設定コマンドで適当にセットアップ

ubuntu@ubuntu:~$ sudo lxd init
Would you like to use LXD clustering? (yes/no) [default=no]:
Do you want to configure a new storage pool? (yes/no) [default=yes]:
Name of the new storage pool [default=default]:
Name of the storage backend to use (btrfs, dir, lvm, zfs, ceph) [default=zfs]: zfs
Create a new ZFS pool? (yes/no) [default=yes]: no
Name of the existing ZFS pool or dataset: pool01/lxd_default
Would you like to connect to a MAAS server? (yes/no) [default=no]:
Would you like to create a new local network bridge? (yes/no) [default=yes]:
What should the new bridge be called? [default=lxdbr0]:
What IPv4 address should be used? (CIDR subnet notation, “auto” or “none”) [default=auto]:
What IPv6 address should be used? (CIDR subnet notation, “auto” or “none”) [default=auto]: none
Would you like the LXD server to be available over the network? (yes/no) [default=no]:
Would you like stale cached images to be updated automatically? (yes/no) [default=yes]:
Would you like a YAML "lxd init" preseed to be printed? (yes/no) [default=no]:

テスト用にコンテナを作成する。ubuntu20.04のイメージでubuntu-containerという名前で作る

ubuntu@ubuntu:~$ sudo lxc launch images:ubuntu/20.04 ubuntu-container
Creating ubuntu-container
Starting ubuntu-container
ubuntu@ubuntu:~$ lxc list
+------------------+---------+-----------------------+------+-----------+-----------+
|       NAME       |  STATE  |         IPV4          | IPV6 |   TYPE    | SNAPSHOTS |
+------------------+---------+-----------------------+------+-----------+-----------+
| ubuntu-container | RUNNING | 10.206.161.151 (eth0) |      | CONTAINER | 0         |
+------------------+---------+-----------------------+------+-----------+-----------+

とりあえず動くことが分かったので消しておく

ubuntu@ubuntu:~$ lxc stop ubuntu-container
ubuntu@ubuntu:~$ lxc list
+------------------+---------+------+------+-----------+-----------+
|       NAME       |  STATE  | IPV4 | IPV6 |   TYPE    | SNAPSHOTS |
+------------------+---------+------+------+-----------+-----------+
| ubuntu-container | STOPPED |      |      | CONTAINER | 0         |
+------------------+---------+------+------+-----------+-----------+
ubuntu@ubuntu:~$ lxc delete ubuntu-container
ubuntu@ubuntu:~$ lxc list
+------+-------+------+------+------+-----------+
| NAME | STATE | IPV4 | IPV6 | TYPE | SNAPSHOTS |
+------+-------+------+------+------+-----------+

ネットワーク設定

今の設定だとコンテナから外部に通信できるけれど、外部からコンテナに通信はできない。外部から通信で起用にmacvlanの設定を作成する。 最初に設定ファイルをコピー

ubuntu@ubuntu:~$ lxc profile copy default macvlan_profile

ファイルを編集してmacvlan用の設定にする。nictypeをmacvlanにしてparentにホストのNICを指定する。

ubuntu@ubuntu:~$ lxc profile edit macvlan_profile
config: {}
description: macvlan profile
devices:
  eth0:
    name: eth0
    nictype: macvlan
    parent: eth0
    type: nic
  root:
    path: /
    pool: default
    type: disk
name: macvlan_profile
used_by: []

作成したプロファイルを指定してコンテナを作成。今回はホストと同じサブネットのIPになっている。

ubuntu@ubuntu:~$ sudo lxc launch -p macvlan_profile images:ubuntu/20.04 macvlan-container
Creating macvlan-container
Starting macvlan-container
ubuntu@ubuntu:~$ lxc list
+-------------------+---------+----------------------+---------------------------------------------+-----------+-----------+
|       NAME        |  STATE  |         IPV4         |                    IPV6                     |   TYPE    | SNAPSHOTS |
+-------------------+---------+----------------------+---------------------------------------------+-----------+-----------+
| macvlan-container | RUNNING | 192.168.11.39 (eth0) | 240b:11:a102:9400:216:3eff:feb6:83ed (eth0) | CONTAINER | 0         |
+-------------------+---------+----------------------+---------------------------------------------+-----------+-----------+
ubuntu@ubuntu:~$ lxc exec macvlan-container /bin/bash
root@macvlan-container:~# ip -4 a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
7: eth0@if2: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000 link-netnsid 0
    inet 192.168.11.39/24 brd 192.168.11.255 scope global dynamic eth0
       valid_lft 172754sec preferred_lft 172754sec

ホストのIPv4フォワード設定を変える。コメント解除してsysctl -p

ubuntu@ubuntu:~$ sudo vi /etc/sysctl.conf
#net.ipv4.ip_forward=1
↓
net.ipv4.ip_forward=1

テスト

試しにApacheを入れてクライアントのブラウザから見えるか試してみる

root@macvlan-container:~# apt install apache2
root@macvlan-container:~# systemctl status httpd
Unit httpd.service could not be found.
root@macvlan-container:~# systemctl status apache2
● apache2.service - The Apache HTTP Server
     Loaded: loaded (/lib/systemd/system/apache2.service; enabled; vendor preset: enabled)
    Drop-In: /run/systemd/system/service.d
             mqzzz-lxc-service.conf
     Active: active (running) since Fri 2022-04-29 02:57:04 UTC; 17s ago
       Docs: https://httpd.apache.org/docs/2.4/
   Main PID: 1167 (apache2)
      Tasks: 55 (limit: 4421)
     Memory: 6.3M
        CPU: 284ms
     CGroup: /system.slice/apache2.service
             tq1167 /usr/sbin/apache2 -k start
             tq1168 /usr/sbin/apache2 -k start
             mq1169 /usr/sbin/apache2 -k start

ブラウザからアクセスして表示されていれば成功

DeskPi ProのSATA SSDでTrimを設定する

DeskPi ProのSATAはUSB接続となっていてSSDを接続しても、Trimを実行することができない。これはLinux側の問題で、USB接続のSSDでのTrimをサポートしていないかららしい。設定を変えることで、USB接続でもTrimができるのでそれを実行する。

forums.raspberrypi.com

SSDがTrimに対応しているかコマンドで確認

ubuntu@ubuntu:~$ sudo hdparm -I /dev/sda | grep TRIM
       *    Data Set Management TRIM supported (limit 8 blocks)

ラズパイにつないでいるSSDは、CSSD-S6B480CG3VXというものでTrimには対応している。 USB接続だとTrimできるSSDでも、zpool status -t やfstrimでTrimできないと表示される。

ubuntu@ubuntu:~$ zpool status -t
  pool: pool01
 state: ONLINE
config:

    NAME        STATE     READ WRITE CKSUM
    pool01      ONLINE       0     0     0
      sda4      ONLINE       0     0     0  (trim unsupported)

errors: No known data errors
ubuntu@ubuntu:~$ sudo fstrim -v /
fstrim: /: the discard operation is not supported

ベンダーIDとプロダクトIDを確認

ubuntu@ubuntu:~$ lsusb -tv
/:  Bus 03.Port 1: Dev 1, Class=root_hub, Driver=dwc2/1p, 480M
    ID 1d6b:0002 Linux Foundation 2.0 root hub
    |__ Port 1: Dev 2, If 0, Class=Hub, Driver=hub/4p, 480M
        ID 1a40:0101 Terminus Technology Inc. Hub
        |__ Port 4: Dev 3, If 0, Class=Vendor Specific Class, Driver=ch341, 12M
            ID 1a86:7523 QinHeng Electronics CH340 serial converter
/:  Bus 02.Port 1: Dev 1, Class=root_hub, Driver=xhci_hcd/4p, 5000M
    ID 1d6b:0003 Linux Foundation 3.0 root hub
    |__ Port 1: Dev 2, If 0, Class=Mass Storage, Driver=uas, 5000M
        ID 174c:55aa ASMedia Technology Inc. ASM1051E SATA 6Gb/s bridge, ASM1053E SATA 6Gb/s bridge, ASM1153 SATA 3Gb/s bridge, ASM1153E SATA 6Gb/s bridge
/:  Bus 01.Port 1: Dev 1, Class=root_hub, Driver=xhci_hcd/1p, 480M
    ID 1d6b:0002 Linux Foundation 2.0 root hub
    |__ Port 1: Dev 2, If 0, Class=Hub, Driver=hub/4p, 480M
        ID 2109:3431 VIA Labs, Inc. Hub

Bus02 Port1 Dev2のASMediaがUSB⇔SATA変換のチップ ID 1a86:7523の左がベンダーIDで右がプロダクトID

/etc/udev/rules.d/にルールファイルを追加する

ubuntu@ubuntu:~$ sudo vi /etc/udev/rules.d/99-usbssd-trim.rules
ACTION=="add|change", ATTRS{idVendor}=="1a86, ATTRS{idProduct}=="7523", SUBSYSTEM=="scsi_disk", ATTR{provisioning_mode}="unmap"

再起動してTrimを実行する

再起動してもTrimが有効にならない

設定前とコマンドの結果が変わらない

ubuntu@ubuntu:~$ zpool status -t
  pool: pool01
 state: ONLINE
config:

    NAME        STATE     READ WRITE CKSUM
    pool01      ONLINE       0     0     0
      sda4      ONLINE       0     0     0  (trim unsupported)

errors: No known data errors
ubuntu@ubuntu:~$ sudo fstrim -v /
fstrim: /: the discard operation is not supported

原因と対処

/sys/block/sda/device/scsi_disk/0:0:0:0/provisioning_modeの値がunmapになっていない

ubuntu@ubuntu:~$ cat /sys/block/sda/device/scsi_disk/0:0:0:0/provisioning_mode
full

/etc/rc.localに以下を追記して、起動時にunmapに変更するようにする

ubuntu@ubuntu:~$ sudo vi /etc/rc.local
#!/bin/sh
echo -n unmap > /sys/block/sda/device/scsi_disk/0:0:0:0/provisioning_mode

ubuntu@ubuntu:~$ sudo chmod 755 /etc/rc.local 

再確認

これでfstrimはできるようになったが、zpool trimはできない

ubuntu@ubuntu:~$ sudo fstrim -v /
/: 27.4 GiB (29468852224 bytes) trimmed

ubuntu@ubuntu:~$ zpool status -t
  pool: pool01
 state: ONLINE
config:

    NAME        STATE     READ WRITE CKSUM
    pool01      ONLINE       0     0     0
      sda4      ONLINE       0     0     0  (trim unsupported)

errors: No known data errors

原因と対処

udev ruleより先にzfsのモジュールがロードされることが原因 www.reddit.com

リンクにあるスクリプトを/usr/share/initramfs-tools/hooks/において権限をつける

Detect and enable trim for usb-connected sata/nvme drives in initramfs/initrd, ideally before zfs modules load. · GitHub

ubuntu@ubuntu:~$ sudo chmod 755 /usr/share/initramfs-tools/hooks/usbtrim 

スクリプトを配置したらinitramfsを更新する オプションはuckを選択

root@ubuntu:~# update-initramfs --help

Usage: update-initramfs {-c|-d|-u} [-k version] [-v] [-b directory]

Options:
 -k version Specify kernel version or 'all'
 -c     Create a new initramfs
 -u     Update an existing initramfs
 -d     Remove an existing initramfs
 -b directory   Set alternate boot directory
 -v     Be verbose

See update-initramfs(8) for further details.

root@ubuntu:~# update-initramfs -u -c -k `uname -r`

終わったら再起動

 再確認

Trimできるようになっている

ubuntu@ubuntu:~$ zpool status -t
  pool: pool01
 state: ONLINE
config:

    NAME        STATE     READ WRITE CKSUM
    pool01      ONLINE       0     0     0
      sda4      ONLINE       0     0     0  (untrimmed)

errors: No known data errors

実際にTrimしてみる

ubuntu@ubuntu:~$ sudo fstrim -v /
/: 27.4 GiB (29443108864 bytes) trimmed
ubuntu@ubuntu:/pool01$ sudo zpool trim pool01 sda4
ubuntu@ubuntu:/pool01$ zpool status -t
  pool: pool01
 state: ONLINE
config:

    NAME        STATE     READ WRITE CKSUM
    pool01      ONLINE       0     0     0
      sda4      ONLINE       0     0     0  (100% trimmed, completed at Sat Apr  2 00:19:37 2022)

errors: No known data errors

OpenZFS+NFSサーバーの設定

Ubuntu 21.10+OpenZFSでNFSサーバーを建てる

パッケージ追加

サーバー用のパッケージを追加する

sudo apt install nfs-kernel-server

NFS用のデータセットを作成

既存のzpoolにNFSでエクスポートするデータセット(ディレクトリのようなもの)を作成

ubuntu@ubuntu:~$ sudo zfs create pool01/NFS
ubuntu@ubuntu:~$ zfs list
NAME         USED  AVAIL     REFER  MOUNTPOINT
pool01       258K   391G       25K  /pool01
pool01/NFS    24K   391G       24K  /pool01/NFS

エクスポート設定

通常/etc/exportsへ設定を記載するが、ZFSだとプロパティのsharenfsをonにするだけでいい

ubuntu@ubuntu:~$ sudo zfs get sharenfs pool01/NFS
NAME        PROPERTY  VALUE     SOURCE
pool01/NFS  sharenfs  off       inherited from pool01
ubuntu@ubuntu:~$ sudo zfs set sharenfs=on pool01/NFS
ubuntu@ubuntu:~$ sudo zfs get sharenfs pool01/NFS
NAME        PROPERTY  VALUE     SOURCE
pool01/NFS  sharenfs  on        local

サービス再起動しておく

systemctl restart nfs-server

クライアントからマウント

hoge@hoge-desktop:~$ sudo mount -t nfs 192.168.11.47:/pool01/NFS /mnt
hoge@hoge-desktop:/mnt$ df -h
Filesystem                 Size  Used Avail Use% Mounted on
tmpfs                      1.5G  2.2M  1.5G   1% /run
/dev/sdf2                  457G   42G  393G  10% /
tmpfs                      7.3G   64M  7.2G   1% /dev/shm
tmpfs                      5.0M  4.0K  5.0M   1% /run/lock
tmpfs                      7.3G     0  7.3G   0% /run/qemu
/dev/nvme0n1p1              96M   33M   64M  34% /boot/efi
/dev/sda                   2.9T  209G  2.1T   9% /data
tmpfs                      1.5G  1.3M  1.5G   1% /run/user/1000
192.168.11.47:/pool01/NFS  392G     0  392G   0% /mnt

Ubuntu 21.10にOpenZFSをセットアップする

Raspberry Pi 4B にインストールしたUbuntu 21.10でZFSを利用するための設定

パッケージ追加

パッケージをapt installするだけ。一応再起動しておく

sudo apt install zfsutils-linux

openzfs.github.io

プールを作成

プール名とデバイスを指定して作成する。RAIDを使用する場合はここで指定する。

ubuntu@ubuntu:~$ sudo zpool create pool01 /dev/sda4
ubuntu@ubuntu:~$ zpool status
  pool: pool01
 state: ONLINE
config:

        NAME        STATE     READ WRITE CKSUM
        pool01      ONLINE       0     0     0
          sda4      ONLINE       0     0     0

errors: No known data errors
ubuntu@ubuntu:~$ df -h
Filesystem      Size  Used Avail Use% Mounted on
tmpfs           380M  3.0M  377M   1% /run
/dev/sda2        32G  3.5G   27G  12% /
tmpfs           1.9G     0  1.9G   0% /dev/shm
tmpfs           5.0M     0  5.0M   0% /run/lock
/dev/sda1       253M  103M  150M  41% /boot/firmware
tmpfs           380M  4.0K  380M   1% /run/user/1000
pool01          392G  128K  392G   1% /pool01

マウントポイントを指定しないとルート直下にマウントされる

各種設定の変更

  • 重複排除

重い&メモリを食うのでoffにする。

ubuntu@ubuntu:~$ zfs get dedup pool01
NAME    PROPERTY  VALUE          SOURCE
pool01  dedup     off            default

デフォルトでoffなのでそのまま

  • 圧縮

デフォルトでoffなので有効化する。

ubuntu@ubuntu:~$ zfs get compression
NAME    PROPERTY     VALUE           SOURCE
pool01  compression  off             default
ubuntu@ubuntu:~$ sudo zfs set compression=lz4 pool01
ubuntu@ubuntu:~$ zfs get compression
NAME    PROPERTY     VALUE           SOURCE
pool01  compression  lz4             local
  • atime

offでも問題なさそうなのでoffにする。デフォルトだと有効

ubuntu@ubuntu:~$ zfs get atime pool01
NAME    PROPERTY  VALUE  SOURCE
pool01  atime     on     default
ubuntu@ubuntu:~$ sudo zfs set atime=off pool01
ubuntu@ubuntu:~$ zfs get atime pool01
NAME    PROPERTY  VALUE  SOURCE
pool01  atime     off    local
  • Trim

サポートされていないので設定しない

ubuntu@ubuntu:~$ sudo zpool trim pool01 sda4
cannot trim 'sda4': trim operations are not supported by this device