2
0

More than 1 year has passed since last update.

自宅サーバー構築譚:Ubuntu on ZFS in Hyper-V (第1世代)

Last updated at Posted at 2022-02-27

私はこれで ArchLinux を止めました。

声高に宣言するような話でもありませんが。

今年2022年の1月、archisoにzfsを埋め込む事に失敗し、私の中で何かが切れました。

こんなのもう嫌だ!ジリジリなジリ貧もビリビリな閃きでガチガチのバチバチでうおおおお!

そして閃いた、訳ではありませんが。世界一無難だと思われるUbuntuに乗り換える事にしました。今まで ArchLinux on ZFS を楽しみにしていた方々には大変申し訳ありません。そんな奇特な方々がいらっしゃったとも思えませんけど。

参考文献

Ubuntu on ZFS も、少ないながら先行事例があるようです。日本語の記事も少々。

参考文献:ルートパーティションをZFSにしてUbuntu 20.04 LTSをインストールしてみた

これと全く同じでも面白くないので一捻りします。ストレージを2台用意して、メインのディスクはパーティションを切らずに丸ごと全部zfsに任せます。その方が良いと言っていた参考文献、今は消滅してしまったようですね。残念。

環境

ホストマシン

Windows10Proです。これで使えるHyper-Vにインストールを試みます。以前の記事を参照。

ゲストマシン

  • Hyper-V。上述の通り。
  • 第1世代(BIOS起動)
  • メモリ: 1024MB、動的メモリを有効にする
  • 仮想プロセッサの数: 1
  • ハードドライブ: 16GB を2台。異なる容量にすると /dev/sda /dev/sdb が思った形にならないようなので、同容量を2台にしました。インストール手順の確認が目的なら十分かと。
  • チェックポイント: どーでもいいんですが、自動チェックポイントは使用しない方向で。

インストール環境の整備

デスクトップインストーラーを起動しsshの環境整備

サーバーをインストールする場合でもデスクトップ版のisoを使用します。

尚、sshで接続するのはコマンドをコピペできるから。私もやってみてわかりましたが、これ良いですな。

GUI インストーラーが立ち上がって Welcome という画面が表示されたら、 TAB キーを押して Try Ubuntu ボタンにフォーカスを移動して(ボタンにオレンジの枠がつきます) Enter キーを押します。

ウィンドウ環境に切り替わったらターミナルを起動しますが、マウスが繋がっていない場合はショートカットキー Ctrl+Alt+T でどうぞ。

そして下記の2つのコマンドを実行。

sudo apt-add-repository universe
sudo apt update

OpenSSHサーバーをインストール。

sudo apt install --yes openssh-server

ssh接続先のIPアドレスを確認。

ip a

ssh接続用にユーザー ubuntu のパスワードを設定します。

passwd

別のマシンから対象のサーバーに ssh してインストール作業を続行

ssh はほとんどのOSで利用可能でしょう。Windows10でもコマンドプロンプトからsshコマンドを実行できます。

ssh ubuntu@接続先のIPアドレス

rootユーザーになります。

sudo -i

ディスクのフォーマット

まずはフォーマットすべきディスクを確認します。

lsblk

ディスクの指定にはIDを使います。

ls -l /dev/disk/by-id

これを変数に設定するのがubuntu流らしいですが、長大で無意味な文字の羅列を間違い無く打つのが苦痛なので、私の流儀で取得する事にします。

因みにHyper-Vの場合、BOOTDISKは /dev/sda でないと駄目のようです。/dev/sdb にしたら起動しなくなりました。

BOOTDISK=$(cd /dev/disk/by-id; ls ata-* scsi-* | while read d; do if [ "$(readlink -f $d)" = "/dev/sda" ]; then echo "/dev/disk/by-id/$d"; fi; done)
DISK=$(cd /dev/disk/by-id; ls ata-* scsi-* | while read d; do if [ "$(readlink -f $d)" = "/dev/sdb" ]; then echo "/dev/disk/by-id/$d"; fi; done)

ディスクのパーティションを全削除します。

wipefs -a $BOOTDISK
sgdisk --zap-all $BOOTDISK

パーティションを作成。

sgdisk -a1 -n1:24K:+1000K -t1:EF02 $BOOTDISK
sgdisk     -n2:0:+1G      -t2:BF01 $BOOTDISK
sgdisk     -n3:0:0        -t3:0700 $BOOTDISK

設定を確認するコマンドは下記になります。

sgdisk -p $BOOTDISK

$DISKはパーティションに分けません。

wipefs -a $DISK

いよいよzfsフォーマットします。ここが今回最大のコピペポイント!これをコピペする為にssh経由で接続していると言っても過言ではありません。

zpool create -o ashift=12 -d \
    -o feature@async_destroy=enabled \
    -o feature@bookmarks=enabled \
    -o feature@embedded_data=enabled \
    -o feature@empty_bpobj=enabled \
    -o feature@enabled_txg=enabled \
    -o feature@extensible_dataset=enabled \
    -o feature@filesystem_limits=enabled \
    -o feature@hole_birth=enabled \
    -o feature@large_blocks=enabled \
    -o feature@spacemap_histogram=enabled \
    -o feature@userobj_accounting=enabled \
    -O acltype=posixacl -O canmount=off -O devices=off \
    -O normalization=formD -O relatime=on -O xattr=sa \
    -O mountpoint=/ -R /mnt bpool $BOOTDISK-part2

参考文献には下記のように書かれていました。

normalization=formD は Unicode の normalization の NFD に相当します。 昔 Subversion で Windows は NFC, Mac OS X は NFD と違うせいで全角カナの濁点が分かれない、分かれるで苦労したので NFC にしようかと思いましたが、 formD でも Windows と mac から繋いで問題ないと聞いたので formD にしておきました。

私は最近この件で苦労したのでformCにしたいのですが、そもそものwikiには改変しない方が良いと書いてあったので止めておきます。

そしてもう1つのディスクもzfsフォーマットします。こちらはオプションがすっきりしてます。

zpool create -o ashift=12 \
    -O acltype=posixacl -O canmount=off \
    -O dnodesize=auto -O normalization=formD -O relatime=on -O xattr=sa \
    -O mountpoint=/ -R /mnt tank $DISK

作成したプール一覧の確認は下記。ここはコピペではなくて zpool list と手打ちでお願いします。

# zpool list
NAME   SIZE  ALLOC   FREE  CKPOINT  EXPANDSZ   FRAG    CAP  DEDUP    HEALTH  ALTROOT
bpool  960M   540K   959M        -         -     0%     0%  1.00x    ONLINE  /mnt
tank   125G   648K   125G        -         -     0%     0%  1.00x    ONLINE  /mnt

システムのインストール

ディレクトリ構造に合わせたデータセット作成

ルート用データセットを作成します。

zfs create -o canmount=off -o mountpoint=none tank/main
zfs create -o canmount=noauto -o mountpoint=/ tank/main/ubuntu
zfs mount tank/main/ubuntu

ブート用データセットを作成します。

zfs create -o canmount=off -o mountpoint=none bpool/boot
zfs create -o canmount=noauto -o mountpoint=/boot bpool/boot/ubuntu
zfs mount bpool/boot/ubuntu

一般的なデータセットを作成します。

zfs create -o canmount=off                 tank/sub0
zfs create -o mountpoint=/home             tank/sub0/home
zfs create -o mountpoint=/root             tank/sub0/root
zfs create -o canmount=off                 tank/sub0/var
zfs create -o canmount=off                 tank/sub0/var/lib
zfs create -o mountpoint=/var/log          tank/sub0/var/log
zfs create -o mountpoint=/var/spool        tank/sub0/var/spool
zfs create -o mountpoint=/var/snap         tank/sub0/var/snap
zfs create -o canmount=off                 tank/sub0/usr
zfs create -o mountpoint=/usr/local        tank/sub0/usr/local
zfs create -o com.sun:auto-snapshot=false -o mountpoint=/var/lib/docker tank/sub0/var/lib/docker

debootstrap

debootstrapではなくてmmdebstrapを使ってみようかと考えたのですが、残念ながら失敗しました。mdebstrapではインストール先ディレクトリが空でなければならないようです。

参考文献:第594回 mmdebstrapで最小のルートファイルシステムを作る - Ubuntu Weekly Recipe

そういう訳で、debootstrapを入れてから Ubuntu 20.04 LTS 通称 focal をインストール。

apt install --yes debootstrap
debootstrap focal /mnt

終わったら以下のコマンドを実行します。

zfs set devices=off tank

システム設定

マシン名

まずはマシン名を決めます。

HOSTNAME=<マシン名>
echo $HOSTNAME >/mnt/etc/hostname

ネットワーク関連

hostsファイルを修正。

sed -i -e"/^127.0.0.1/a 127.0.1.1\t$HOSTNAME" /mnt/etc/hosts

netplan のネットワーク設定ファイル/mnt/etc/netplan/01-netcfg.yamlを作成します。今回はIPv6は使わないようにするので下記のようにしてみました。

我が家のIPアドレス事情に基づき、ひとまずIPv4アドレスは固定で、172.16.5.10 とします。

参考文献:固定IPアドレスの割当(IPv4、IPv6) - Netplanの使い方 - komeの備忘録

cat > /mnt/etc/netplan/01-netcfg.yaml <<___
network:
  version: 2
  renderer: networkd
  ethernets:
    $(for d in `find /sys/devices -name net | grep -v virtual`; do ls $d; done | head -n1):
      dhcp4: no
      addresses: [172.16.5.10/16]
      gateway4: 172.16.0.1
      nameservers:
        addresses: [172.16.0.1]
___

参考文献には/mnt/etc/apt/sources.listの変更に言及がありますが、省略可との事ですし、今回は省略します。

chroot

Live CD 環境の仮想ファイルシステムをバインドマウントして、上記でセットアップした環境に chroot します( --bind ではなく --rbind を使っていることに注意)。

mount --rbind /dev  /mnt/dev
mount --rbind /proc /mnt/proc
mount --rbind /sys  /mnt/sys
chroot /mnt /usr/bin/env DISK=$DISK BOOTDISK=$BOOTDISK bash --login

chroot 環境内の apt のインデクスを更新します。

apt update

ロケール

en_US.UTF-8 と ja_JP.UTF-8 と、後は個人的な好みで。

locale-gen --purge en_US.UTF-8 ja_JP.UTF-8 ja_JP.EUC-JP
update-locale LANG=en_US.UTF-8 LANGUAGE=en_US
dpkg-reconfigure --frontend noninteractive locales

タイムゾーン

日本なら Asia/Tokyo です。

ln -sf /usr/share/zoneinfo/Asia/Tokyo /etc/localtime
dpkg-reconfigure -f noninteractive tzdata

カーネルイメージなど

Linux のカーネルイメージと ZFS を chroot 環境にインストールします。

apt install --yes --no-install-recommends linux-image-generic zfs-initramfs

上記のコマンド実行の出力の最後に以下のようなメッセージが出ます。 update-initramfs/boot/initrd.img-5.4.0-26-genericを生成したという点が重要だそうです。この後 grub のインストール時に必要になる為です。

update-initramfs: Generating /boot/initrd.img-5.4.0-26-generic

GRUB をレガシー BIOS 用にインストール

参考文献に従って以下のコマンドを実行。

DEBIAN_FRONTEND=noninteractive apt-get -y -o Dpkg::Options::="--force-confdef" -o Dpkg::Options::="--force-confold" install grub-pc

rootパスワード

パスワードを設定します。

passwd

zfsのzpool関係

bpool を確実にインポートするためのサービスのユニットファイルを作成します。

cat >/etc/systemd/system/zfs-import-bpool.service <<___
[Unit]
DefaultDependencies=no
Before=zfs-import-scan.service
Before=zfs-import-cache.service

[Service]
Type=oneshot
RemainAfterExit=yes
ExecStart=/sbin/zpool import -N -o cachefile=none bpool

[Install]
WantedBy=zfs-import.target
___

このサービスの自動起動を有効にします。

systemctl enable zfs-import-bpool.service

tmpfs

次回起動時に tmpfs を /tmp にマウントするようにします。

cp /usr/share/systemd/tmp.mount /etc/systemd/system/
systemctl enable tmp.mount

GRUB のインストール

ZFS のブートファイルシステムが認識されていることを確認します。zfs と出力されれば OK です。

grub-probe /boot

grub の設定ファイルを修正します。sed コマンドにすると少々複雑ですが。

sed -i -e '/^GRUB_TIMEOUT=/{s/=.*/=5/;a\
GRUB_RECORDFAIL_TIMEOUT=5
}
/^GRUB_CMDLINE_LINUX_DEFAULT=/s/quiet splash//
s|^GRUB_CMDLINE_LINUX=.*|GRUB_CMDLINE_LINUX="root=ZFS=tank/main/ubuntu"|
/^#GRUB_TERMINAL=console/s/#//
' /etc/default/grub

修正結果は下記の通り。

# If you change this file, run 'update-grub' afterwards to update
# /boot/grub/grub.cfg.
# For full documentation of the options in this file, see:
#   info -f grub -n 'Simple configuration'

GRUB_DEFAULT=0
GRUB_TIMEOUT_STYLE=hidden
GRUB_TIMEOUT=5
GRUB_RECORDFAIL_TIMEOUT=5
GRUB_DISTRIBUTOR=`lsb_release -i -s 2> /dev/null || echo Debian`
GRUB_CMDLINE_LINUX_DEFAULT=""
GRUB_CMDLINE_LINUX="root=ZFS=tank/main/ubuntu"

# Uncomment to enable BadRAM filtering, modify to suit your needs
# This works with Linux (no patch required) and with any kernel that obtains
# the memory map information from GRUB (GNU Mach, kernel of FreeBSD ...)
#GRUB_BADRAM="0x01234567,0xfefefefe,0x89abcdef,0xefefefef"

# Uncomment to disable graphical terminal (grub-pc only)
GRUB_TERMINAL=console

# The resolution used on graphical terminal
# note that you can use only modes which your graphic card supports via VBE
# you can see them in real GRUB with the command `vbeinfo'
#GRUB_GFXMODE=640x480

# Uncomment if you don't want GRUB to pass "root=UUID=xxx" parameter to Linux
#GRUB_DISABLE_LINUX_UUID=true

# Uncomment to disable generation of recovery mode menu entries
#GRUB_DISABLE_RECOVERY="true"

# Uncomment to get a beep at grub start
#GRUB_INIT_TUNE="480 440 1"

この設定変更を反映します。

update-grub

が、この結果はエラーが発生します。osprober でbusyエラーが出ますが OK らしい。Found linux image と Found initrd image の行が出ていれば大丈夫との事。

# update-grub
Sourcing file `/etc/default/grub'
Sourcing file `/etc/default/grub.d/init-select.cfg'
Generating grub configuration file ...
Found linux image: vmlinuz-5.4.0-26-generic in rpool/ROOT/ubuntu
Found initrd image: initrd.img-5.4.0-26-generic in rpool/ROOT/ubuntu
device-mapper: reload ioctl on osprober-linux-sda3  failed: Device or resource busy
Command failed.
done

レガシー BIOS 用に GRUB をインストールします。

grub-install $BOOTDISK

ZFS のモジュールがインストールされていることを確認します。

ls /boot/grub/*/zfs.mod

初回のブート

スナップショット

初回インストールのスナップショットを作成しておきます。こういう事をしたいが為にZFSを使うのです。

zfs snapshot bpool/boot/ubuntu@$(date +%Y%m%d_%H%M%S)_install
zfs snapshot tank/main/ubuntu@$(date +%Y%m%d_%H%M%S)_install
zfs snapshot -r tank/sub0@$(date +%Y%m%d_%H%M%S)_install

スナップショットの一覧を表示して確認します。

zfs list -t snapshot

リブート

chroot 環境から抜けて Live CD 環境に戻ります。

exit

Live CD 環境でマウント中のファイルシステムを全てアンマウントします。

mount | grep -v zfs | tac | awk '/\/mnt/ {print $3}' | xargs -n 1 -r umount -lf
zpool export -a

そしてシャットダウン。

shutdown -h now

その後、インストールメディアを取り出して、それからマシンの電源を入れます。

rootログイン

ここからはsshは使えません。

サーバーのコンソールで root ユーザーでパスワードを入力してログインします。

日本語キーボード配列

記号を打ってみるとわかりますが、英語配列になっています。日本語配列に変更する手順は以下の参考文献を参照。バージョンは古いですが、画面キャプチャがあるのでわかりやすいです。

参考文献:Ubuntuでキーボードレイアウト変更 - Ragnite Blue

コマンドは下記。

dpkg-reconfigure keyboard-configuration

設定後、次のコマンドを打つ必要があるようです。

setupcon

スワップ

物理メモリを十分に積んでいてもスワップは重要だそうです。

容量(4Gの箇所)はマシンの状況に合わせて検討して下さい。

zfs create -V 4G -b $(getconf PAGESIZE) \
    -o logbias=throughput -o sync=always \
    -o primarycache=metadata -o secondarycache=none \
    -o com.sun:auto-snapshot=false tank/swap

次にスワップを設定します。

mkswap -f /dev/zvol/tank/swap
echo /dev/zvol/tank/swap none swap discard 0 0 >> /etc/fstab
echo RESUME=none > /etc/initramfs-tools/conf.d/resume

スワップを有効にします。

swapon -av

有効になったかどうか確認。

swapon --show

フルのソフトウェアインストール

最小インストールをアップグレードします。

apt dist-upgrade -y

サーバ用としてコマンドライン環境のみをインストールします。

apt install -y ubuntu-standard

再起動して確認

reboot

まだ一般ユーザーが居ないので、rootでログインします。
そして色々確認。

  • キーボードが日本の配列になっている事。アットマーク @ を打ってみて確認。
  • スワップが有効になっている事。上述のswapon --showコマンドで確認。
  • ネットワ-クが有効になっている事。仮想環境など状況によってNICの名称が変わる事があり、その場合は上述の設定/etc/netplan/01-network.yamlのNIC名eth0を変更する必要があります。

ネットワークに関しては、次のようなコマンドを試してみればわかります。
※ example.com はドメインの例示の際に使うべしとRFC2606で定められています。何か適当なサーバーを選んで下さい。

ping -c2 example.com

失敗した場合には、上述のネットワーク設定ファイル/mnt/etc/netplan/01-netcfg.yamlを修正します。その為のNIC名取得は下記のコマンドで。

参考文献:Linux から認識されている、すべてのネットワークインターフェイス名だけを取得する - Qiita

for d in `find /sys/devices -name net | grep -v virtual`; do ls $d; done

手打ちのコマンドとしてはip aの方が簡単ですが、上記のコマンドならNIC名だけを取り出せますので自動化が可能です。

結び

これで本当に最小限の、起動するカーネルに毛が生えた程度のシステムになりました。ここから本当に必要なツールだけ1つずつ入れて育てていく予定です。
え?そんなのUbuntuじゃない?
良いんです。元々ArchLinuxの代わりとして選択したディストリビューションなので。
これでいいのだ :thumbsup_tone1:

2
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
0