ディスクレスシステム

提供: ArchWiki
2018年2月17日 (土) 20:39時点におけるKusakata (トーク | 投稿記録)による版 (同期)
(差分) ← 古い版 | 最新版 (差分) | 新しい版 → (差分)
ナビゲーションに移動 検索に移動

関連記事

Wikipedia:Diskless node より:

ディスクレスノード (またはディスクレスワークステーション) とは、ディスクドライブを使わずに、ネットワークブートを利用してサーバーからオペレーティングシステムをロードするワークステーション、またはパーソナルコンピュータのことである。

サーバー設定

まず最初に、以下をインストールする必要があります:

  • ディスクレスノードに IP アドレスを割り当てるための DHCP サーバー。
  • ブートイメージを転送するための TFTP サーバー (全ての PXE オプション ROM の必須要件)。
  • Arch 環境をディスクレスノードにエクスポートするためのネットワークストレージ (NFS または NBD)。
ノート: dnsmasq は DHCP と TFTP サーバーの両方として使うことができます。詳しくは dnsmasq の記事を参照。

DHCP

ISC dhcp をインストールして設定:

/etc/dhcpd.conf
allow booting;
allow bootp;

authoritative;

option domain-name-servers 10.0.0.1;

option architecture code 93 = unsigned integer 16;

group {
    next-server 10.0.0.1;

    if option architecture = 00:07 {
        filename "/grub/x86_64-efi/core.efi";
    } else {
        filename "/grub/i386-pc/core.0";
    }

    subnet 10.0.0.0 netmask 255.255.255.0 {
        option routers 10.0.0.1;
        range 10.0.0.128 10.0.0.254;
    }
}
ノート: next-server は TFTP サーバーのアドレスにしてください。他の値はネットワークにあわせて変更してください。

RFC 4578 には "Client System Architecture Type" dhcp オプションが定義されています。上記の設定の場合、PXE クライアントが x86_64-efi バイナリ (タイプ 0x7) をリクエストした場合、適切に返答し、そうでない場合はレガシーなバイナリを使います。これによって、同一のネットワークセグメント上で同時に UEFI とレガシーな BIOS のクライアントを起動できるようにしています。

ISC DHCP の systemd サービスを起動してください。

TFTP

TFTP サーバーはブートローダーやカーネル、initramfs などをクライアントに転送にするのに使います。

TFTP の root は /srv/arch/boot に設定してください。詳しくは TFTP を参照。

ネットワークストレージ

NFS と NBD どちらを使用する場合でも複数のクライアントを扱うことができますが、大きな違いとして、NBD では (ファイルシステムを直接操作するため) copyonwrite モードを使う必要があります。そのため、クライアントが切断すると全ての書き込みが破棄されます。ただし、場合によってはこれが望ましいということも考えられます。

NFS

サーバーに nfs-utils をインストールしてください。

Arch 環境の root を NFS の exports に追加する必要があります:

/etc/exports
/srv       *(rw,fsid=0,no_root_squash,no_subtree_check)
/srv/arch  *(rw,no_root_squash,no_subtree_check)

そして、NFS サービスを起動してください: rpc-idmapd rpc-mountd

NBD

nbd をインストールして設定します。

# vim /etc/nbd-server/config
[generic]
    user = nbd
    group = nbd
[arch]
    exportname = /srv/arch.img
    copyonwrite = false
ノート: 複数のクライアントで NBD 共有を同時に使用したい場合 copyonwrite を true に設定してください。詳しくは nbd-server(5) を参照。

nbd systemd サービスを起動してください。

クライアントのインストール

次に、サーバーのサブディレクトリに完全な Arch Linux 環境を構築します。起動時、ディスクレスノードは DHCP サーバーから IP アドレスを取得して、PXE を使ってホストから起動し、構築した環境を root としてマウントします。

ディレクトリのセットアップ

最低でも1ギガバイトのスパースファイルを作成して、ファイル上に btrfs ファイルシステムを作成してください (もちろん、必要であればブロックデバイスや LVM を使うこともできます)。

# truncate -s 1G /srv/arch.img
# mkfs.btrfs /srv/arch.img
# export root=/srv/arch
# mkdir -p "$root"
# mount -o loop,discard,compress=lzo /srv/arch.img "$root"
ノート: NBD ではファイルシステムを作成する必要がありますが NFS では必須ではありません。

ブートストラップのインストール

devtoolsarch-install-scripts をインストールしてから mkarchroot を実行してください。

# pacstrap -d "$root" base mkinitcpio-nfs-utils nfs-utils
ノート: どんな場合でも mkinitcpio-nfs-utils は必要です。初期ブート空間で使われる ipconfig が入っているためです。

そして initramfs を生成してください。

NFS

NFSv4 のマウントをするためには net フックに細かい修正を加える必要があります (net フックのデフォルトである nfsmount はサポートされていません)。

# sed s/nfsmount/mount.nfs4/ "$root/usr/lib/initcpio/hooks/net" > "$root/usr/lib/initcpio/hooks/net_nfs4"
# cp $root/usr/lib/initcpio/install/net{,_nfs4}

クライアント側で mkinitcpio-nfs-utils がアップデートされたときに上書きされないように net のコピーを作成する必要があります。

$root/etc/mkinitcpio.conf を編集して MODULESnfsv4 を、HOOKSnet_nfs4 を、BINARIES/usr/bin/mount.nfs4 を追加してください。

そして、作成した環境に chroot して mkinitcpio を実行します:

# arch-chroot "$root" mkinitcpio -p linux

NBD

クライアントに mkinitcpio-nbdAUR パッケージをインストールする必要があります。makepkg でビルドしてインストールしてください:

# pacman --root "$root" --dbpath "$root/var/lib/pacman" -U mkinitcpio-nbd-0.4-1-any.pkg.tar.xz

HOOKS 行の net の後ろに nbd を追加する必要があります。net はネットワークの設定を行いますが、カーネル行で nfsroot が指定されていない場合 NFS のマウントは行いません。

クライアント設定

以下の設定の他に、ホストネームタイムゾーンロケールキーマップなども設定する必要があります。インストールガイドを見て下さい。

ブートローダー

GRUB

ドキュメントで明記はされていませんが、GRUB は PXE によるロードをサポートしています。

# pacman --root "$root" --dbpath "$root/var/lib/pacman" -S grub

grub-mknetdir を使用してターゲット環境に grub プレフィックスを作成してください:

# arch-chroot "$root" grub-mknetdir --net-directory=/boot --subdir=grub

grub-mknetdir は現在コンパイル・インストールされているターゲット全てのプレフィックスを作成し、grub のメンテナは同じパッケージで両方のアーキテクチャを提供しているため、grub-mknetdir を実行するのは一度だけですみます。

以下のような GRUB の設定を作成します:

# vim "$root/boot/grub/grub.cfg"
menuentry "Arch Linux" {
    linux /vmlinuz-linux quiet add_efi_memmap ip=:::::eth0:dhcp nfsroot=10.0.0.1:/arch
    initrd /initramfs-linux.img
}

GRUB の黒魔術によって set root=(tftp,10.0.0.1) が自動的に設定されるため、特に設定をしなくてもカーネルと initramfs は TFTP で転送されます。TFTP 以外のメニューエントリが必要な場合、明示的に設定すると良いでしょう。

ノート: kernel 行を必要に応じて変更してください。NBD 関連のオプションは Pxelinux を参照。

Pxelinux

syslinux には Pxelinux が含まれています。詳しくは Syslinux#Pxelinux を参照。

マウントポイントの追加

NBD root

NFS と比べて高いディスク性能を発揮するために、ルートファイルシステムのマウントを rw に切り替えて compress=lzo を有効にすると良いでしょう:

# vim "$root/etc/fstab"
/dev/nbd0  /  btrfs  rw,noatime,discard,compress=lzo  0 0

プログラムステートディレクトリ

例えば /var/log を tmpfs でマウントして、複数のホストのログが混ざらないようにしたり、同じように /var/spool/cups を tmpfs でマウントして、同じスプールを使用する cups のインスタンスが互いに干渉しないようにする場合:

# vim "$root/etc/fstab"
tmpfs   /var/log        tmpfs     nodev,nosuid    0 0
tmpfs   /var/spool/cups tmpfs     nodev,nosuid    0 0

一番良いのは個々のホストごとにソフトウェアの状態やデータベースが保存されるように設定することです。例として Puppet を実行したい場合、puppet のユニットファイルで %H を使う方法があります:

# vim "$root/etc/systemd/system/puppetagent.service"
[Unit]
Description=Puppet agent
Wants=basic.target
After=basic.target network.target

[Service]
Type=forking
PIDFile=/run/puppet/agent.pid
ExecStartPre=/usr/bin/install -d -o puppet -m 755 /run/puppet
ExecStart=/usr/bin/puppet agent --vardir=/var/lib/puppet-%H --ssldir=/etc/puppet/ssl-%H

[Install]
WantedBy=multi-user.target

Puppet-agent は vardir と ssldir を作成します (存在しない場合)。

上記のどちらの方法も使えない場合、systemd ジェネレータ を作成してホストごとにマウントユニットを作成するという選択肢があります (残念ながらマウントユニットで記述子は使えません)。

クライアントの起動

NBD

NBD を使用する場合、クライアントを起動する前に arch.img をアンマウントする必要があります。

カーネルをアップデートするとき、クライアントを起動している間にクライアントのファイルシステムをマウントすることはできないため、クライアントのファイルシステムからカーネルを分離しなくてはなりません。

クライアント環境から tftp のルートディレクトリ (/srv/boot) に $root/boot をコピーしてください:

# cp -r "$root/boot" /srv/boot

クライアントを起動する前に $root をアンマウントする必要があります:

# umount "$root"
ノート: この構成でカーネルをアップデートするには、fstabNFS を使って /srv/boot を (カーネルをアップデートする前に) クライアントにマウントするか、NBD からクライアントを切断した後にクライアントファイルシステムをマウントする必要があります。

参照