今回は、Ubuntu Serverの完全自動インストール方法を紹介します。
PXEブートを利用した完全自動インストール
サーバーの自動インストール自体は第615回で紹介済みですが、ごく僅かではあるものの、対話での入力が必要な箇所が存在していたり、イメージファイルを書き込んだUSBスティックをインストール先のマシンに挿しておく必要があるため、完全な自動化には至っていませんでした。複数台のマシンに対するインストールや、サーバールームなどの日常作業を行っている場所とは離れた場所に設置されたマシンに対するインストールでは対話作業の手間が大きくなるため、せっかく自動インストールを導入した恩恵が得られなくなってしまいます。そのため、このような環境下で自動化の恩恵を十分に受けるためには、インストール作業を完全自動で行わせる必要が出てきます。
完全自動インストールは、自動インストールサーバーと、インストール対象のマシンのPXEブートを使用します。
自動インストール作業は以下の順番で行われます。
- インストール対象のマシンがPXEブートし、DHCPリクエストを送信する。
- 自動インストールサーバーのDHCPサーバーが一時的なIPアドレスを割り当て、ブートローダーの位置を教える。
- マシンが、自動インストールサーバーのTFTPサーバーに置かれたブートローダーやブート設定ファイル、カーネル、初期RAMディスクなどをダウンロードし、自動インストール
(用OS) を起動する。 - マシンが、自動インストールサーバーのwebサーバーに置かれた自動インストール設定ファイルや、インストールメディアをダウンロードして、自動インストールを実施する。
自動インストールサーバーの構築
つまり、自動インストールサーバーには以下の機能が必要です。
- インストール対象マシンの自動インストール中に一時的なIPアドレスを割り当てるDHCPサーバー
- マシンにブートローダーやカーネルをダウンロードさせるためのTFTPサーバー
- マシンに自動インストール設定ファイルやインストールメディアをダウンロードさせるためのwebサーバー
この項では、これらの機能を持ったサーバーを構築します。
dnsmasq(DHCPサーバー兼TFTPサーバー)のインストール
DHCPサーバーとTFTPサーバーとしてdnsmasqを自動インストールサーバーにインストールします。また、TFTPサーバーのルートディレクトリとして/tftpboot
ディレクトリを作成します。
$ sudo apt install dnsmasq $ sudo mkdir /tftpboot
続いてdnsmasqにDHCPサーバー兼TFTPサーバーの設定を行います。
$ sudo tee /etc/dnsmasq.conf <<'EOF' interface=eno1 # dnsmasqをlistenさせるインターフェイス名 bind-interfaces # DNSサーバー機能を無効化 port=0 # TFTPサーバー機能を有効化 enable-tftp tftp-root=/tftpboot # DHCPサーバーの設定 dhcp-leasefile=/var/lib/misc/dnsmasq.leases dhcp-option=option:domain-name,"example.com" # ドメイン名 dhcp-option=option:router,192.168.10.1 # ルータのIPアドレス dhcp-option=option:netmask,255.255.255.0 # サブネットマスク dhcp-option=option:dns-server,192.168.10.11,192.168.10.12 # DNSサーバーのIPアドレス dhcp-match=set:efi-x86_64,option:client-arch,7 # EFI bytecode dhcp-match=set:efi-x86_64,option:client-arch,9 # EFI x86-64 dhcp-boot=tag:efi-x86_64,"/grubnetx64.efi" dhcp-match=set:bios,option:client-arch,0 # Intel x86PC dhcp-boot=tag:bios,"pxelinux.0" dhcp-range=192.168.10.0,static # ネットワークアドレス EOF
各設定のポイントです。
# UEFI PXEブート用設定 dhcp-match=set:efi-x86_64,option:client-arch,7 # EFI bytecode dhcp-match=set:efi-x86_64,option:client-arch,9 # EFI x86-64 # UEFI boot時のブートローダー設定 dhcp-boot=tag:efi-x86_64,"/grubnetx64.efi" # BIOS PXEブート用設定 dhcp-match=set:bios,option:client-arch,0 # Intel x86PC # grub boot時のブートローダー設定 dhcp-boot=tag:bios,"pxelinux.0"
自動インストールサーバーは、インストール対象マシンのアーキテクチャーによって適切なブートローダーを提供する必要があります。PXEブート時、マシンはRFC4578に従ってアーキテクチャーのタイプをヘッダーに設定してDHCPリクエストを送信するため、それを提供するブートローダーの条件分岐に使用します[1]。
dhcp-range=192.168.10.0,static # ネットワークアドレス
今回、各マシンのIPアドレス割当設定は個別に設定します。しかし、dhcp-range
を定義しないとDHCPサーバー機能が動かないため、
dnsmasqの設定が完了したら、一度再起動を行います。
$ sudo systemctl restart dnsmasq.service
ブートローダーの設置
まず、BIOSブート用のMBRブートローダー
$ sudo apt install pxelinux syslinux $ sudo cp /usr/lib/syslinux/modules/bios/ldlinux.c32 /tftpboot/ $ sudo cp /usr/lib/PXELINUX/pxelinux.0 /tftpboot/
続いて、UEFIブート用のブートローダー
$ sudo wget -O /tftpboot/grubnetx64.efi http://archive.ubuntu.com/ubuntu/dists/jammy/main/uefi/grub2-amd64/current/grubnetx64.efi
最後に各インストール対象マシンごとのブート設定ファイル置き場を作成し、UEFIブート時のメインのブート設定ファイルを設置します
$ sudo mkdir -p /tftpboot/grub/system $ sudo mkdir -p /tftpboot/pxelinux.cfg $ sudo tee /tftpboot/grub/grub.cfg <<'EOF' set timeout=2 loadfont unicode set menu_color_normal=white/black set menu_color_highlight=black/light-gray if [ -s "${prefix}/system/${net_default_mac}" ]; then source "${prefix}/system/${net_default_mac}" echo "Machine specific grub config file ${prefix}/system/${net_default_mac} loaded" else echo "Could not find machine specific grub config file ${prefix}/system/${net_default_mac}" sleep 30 fi EOF
Nginx(Webサーバー)のインストール
WebサーバーとしてNginxを自動インストールサーバーにインストールします。
$ sudo apt install nginx
インストール対象マシンから、http://自動インストールサーバー/autoinstall
で自動インストール設定ファイル、http://自動インストールサーバー/iso
でインストールメディアが取得できるように設定します。
まず、置き場となるディレクトリを作成します。
$ sudo mkdir /var/www/autoinstall /var/www/iso
続いて、/etc/
のserver句にlocation設定を追加します。
server {
...
location / {
# First attempt to serve request as file, then
# as directory, then fall back to displaying a 404.
try_files $uri $uri/ =404;
}
location /autoinstall {
root /var/www/;
autoindex on;
}
location /iso {
root /var/www/;
autoindex on;
}
...
}
設定を追加したら、反映のためにNginxをreloadします。
$ sudo systemctl reload nginx.service
インストール用ディストリビューションの用意
今回は、Ubuntu 22.
まず、インストール用ISOファイルをダウンロードします。
$ wget https://releases.ubuntu.com/jammy/ubuntu-22.04.3-live-server-amd64.iso
ISOファイルをマウントして、その中にあるカーネルと初期RAMディスクを抽出してTFTPサーバーに設置します。
抽出が完了したら、ISOファイルをアンマウントして、Webサーバーのインストールメディア置き場に設置します。
$ sudo mkdir -p /tftpboot/images/jammy $ sudo cp /mnt/casper/initrd /mnt/casper/vmlinuz /tftpboot/images/jammy/ $ sudo umount /mnt $ sudo mv ubuntu-22.04.3-live-server-amd64.iso /var/www/iso/
これで、自動インストールサーバーとしての最低限の設定は完了で、インストール対象マシン個別の設定を行っていくことになります。
自動インストールの設定
自動インストールの設定ですが、BIOSブートと、UEFIブートで必要な設定ファイルのパスや様式が若干異なります。以下ではそれぞれに対して個別に説明します。
なお、以下の説明ではインストール対象マシンを08:00:27:84:bd:fe
のMACアドレスを持つNICからPXEブートさせることを前提とします。
BIOSブートの場合
TFTPサーバーへ自動インストールを行わせるためのブート設定ファイルを設置します。
設定ファイルの名前は、ブートローダーによって固定化されていて、01-MACアドレス
の様式である必要があります。そして、MACアドレスの表記は、オクテットごとに-
で分け、a-fは小文字である必要があります。今回のケースでは、01-08-00-27-84-bd-fe
である必要があり、01:08:00:27:84:bd:fe
や01-08-00-27-84-BD-FE
ではダウンロードに失敗します。
sudo tee /tftpboot/pxelinux.cfg/01-08-00-27-84-bd-fe <<'EOF' default linux prompt 0 timeout 30 label linux kernel /images/jammy/vmlinuz ipappend 2 append initrd=/images/jammy/initrd autoinstall ip=dhcp url=http://自動インストールサーバーのIPアドレス/iso/ubuntu-22.04.3-live-server-amd64.iso ds=nocloud-net;s=http://自動インストールサーバーのIPアドレス/autoinstall/08:00:27:84:bd:fe/ --- EOF
append
に設定されていることの意味は第615回で説明されていることと一部重複しますが、ここでも改めて説明します。
- 「autoinstall」
:cloud-configファイルの中にautoinstallキーが存在しているとき、ユーザーの操作なしに自動インストールを開始するためのオプション。 - 「ip=dhcp」
:DHCPで一時的なIPアドレスを割り当てるオプション。 - 「url=…」
:インストールメディアの場所を指定するためのオプション。ここでは、先程Webサーバーに設置したUbuntu22. 04. 3のISOファイルのパスを指定しています。 - 「ds=nocloud-net;s=…」
:cloud-configファイルの場所 (データストア) を指定するためのオプション。これから、この場所に設定ファイルを設置します。
続いて、自動インストールのための設定ファイルをWebサーバーに設置します。
ファイル置き場として、/var/
ディレクトリを作成します。ここでのMACアドレスの表記は、オクテットごとに:
で分け、a-fは小文字である必要があります。
$ sudo mkdir /var/www/autoinstall/08:00:27:84:bd:fe
MACアドレスの名前のディレクトリを作成しているのは、複数マシンの設定ファイルを設置するための便宜です。すべてのマシンで同一の設定ファイルで良いのであれば/var/
以下にファイルを設置で問題ないのですが、IPアドレスの静的設定など、各マシンで設定ファイルの内容に個性を出す必要がある場合はマシンごとに別な設定ファイルを用意する必要があります。しかし、user-data
、meta-data
というファイル名自体は任意のものに変更できないため、各マシンごとの設定を識別できるものとしてMACアドレスのディレクトリを作成して、その下に設定ファイルを設置する形式を採っています[3]。
ファイル置き場にcloud-configフォーマットのファイルuser-data
)meta-data
ファイルを設置します。meta-dataファイルは空ファイルで問題ありませんが、存在しないと自動インストールに失敗します。
$ sudo tee /var/www/autoinstall/08:00:27:84:bd:fe/user-data <<'EOF' #cloud-config autoinstall: version: 1 identity: hostname: ubuntu-server username: ubuntu password: "$6$/X6MRgjz4jCIK8.G$FhJbD17m9qTcMA8FHMPcFvp7v2wvgmRBdvdEdTiZXZRwuZFUVsear9.vYY01QcwPuYAMRMvSJoJKfUlaBviU3/" ssh: install-server: yes EOF $ sudo touch /var/www/autoinstall/08:00:27:84:bd:fe/meta-data
設定ファイルはYAML形式です。ただし、ファイルの先頭に#cloud-config
を必ず付ける必要があります。個別の設定値の説明は公式のAutomated Server installer config file referenceを参照してください。
今回は次のような設定を行っています。
- ホスト名を
「ubuntu-server」 にする - ユーザー名を
「ubuntu」 にする - パスワードを
「ubuntu」 にする[4] - sshサーバーをインストールする
最後にdnsmasqへ、インストール対象マシンのDHCPエントリを追加します。
$ sudo tee -a /etc/dnsmasq.conf <<'EOF' dhcp-host=08:00:27:84:bd:fe,192.168.118.161,ubuntu-server EOF $ sudo systemctl restart dnsmasq.service
この設定で、インストール対象マシンから
自動インストール完了後、自動でrebootし、インストールされたOSが起動します。
UEFIブートの場合
BIOSブートの場合と同じに、TFTPサーバーへ自動インストール設定行わせるためのブート設定ファイルを設置します。
ただし、ファイルのパスやファイル名がBIOSブートとは異なります。
PXEブート時に/tftpboot/
をロードすることが、ブートローダーによって固定化されています。
このままではインストール対象マシンごとのカーネルコマンドラインや、初期ramディスクの設定ができません。そこで、grub.
/tftpboot/
からロードするように設定を施します。
${net_
はPXEブートしたマシンのMACアドレスです。
すなわち、マシンごとの設定ファイルの名前は、/tftpboot/
である必要があります[5]。
MACアドレスの表記は、オクテットごとに:
で分け、a-fは小文字である必要があります。
$ sudo tee /tftpboot/grub/system/08:00:27:84:bd:fe <<'EOF' menuentry "AutoInstall Ubuntu Server (jammy)" { set gfxpayload=keep linux /images/jammy/vmlinuz autoinstall ip=dhcp url=http://自動インストールサーバーのIPアドレス/iso/ubuntu-22.04.3-live-server-amd64.iso ds=nocloud-net\;s=http://自動インストールサーバーのIPアドレス/autoinstall/${net_default_mac}/ --- initrd /images/jammy/initrd } EOF
続いて、自動インストールのための設定ファイルをWebサーバーに設置します。ファイルの置き場所や様式、内容はBIOSブートの場合と基本的に同一なのですが、追加の設定が必要になります。
UEFIブートの場合、デフォルトでは自動インストール中にBIOS設定を更新して、最初のブートデバイスをNIC
この振る舞いは、MAASの自動インストール機能との兼ね合いに依るものなのですが、今回のケースではPXEブートと自動インストールが永遠に繰り返されてしまうことになるため、無効化する必要があります。
具体的にはuser-data
のautoinstall.
中にあるgrub.
設定をfalse
に設定します。ただし、uefi_
は、storage
で暗黙に定義されているlayout
キーlvm
が指定されている)config
キーにのみ反応する振る舞いをします。
まとめると、自動インストールに最初のブートデバイスをNICにさせないためには以下の設定が必要になります。
autoinstall.
をstorate. grub. uefi_ reorder false
にする。autoinstall.
に明示的なパーティショニング設定をする。storage. config
autoinstall.
は、CurtinのStorage設定を直接記載します。
以下が、先頭にEFIシステムパーティション
#cloud-config autoinstall: version: 1 ... storage: version: 2 grub: # ブートオーダーを更新させない reorder_uefi: false # パーティショニング設定。config句で設定しないとreorder_uefiの設定が反映されない config: # パーティションテーブルの作成 - type: disk id: sda ptable: gpt path: /dev/sda wipe: superblock preserve: false name: '' grub_device: false # パーティションの作成 # ESP - type: partition id: sda1 device: sda number: 1 flag: boot wipe: superblock preserve: false offset: 1073741824 # 1GiB size: 1073741824 # 1GiB; 末尾は先頭から2GiB grub_device: true # スワップ - type: partition id: sda2 device: sda number: 2 flag: swap wipe: superblock preserve: false offset: 2147484160 # 前のパーティションの末尾+512バイト => 2GiB+512 size: 34359738368 # 32GiB; 末尾は先頭から34GiB+512 grub_device: false # ルートファイルシステム - type: partition id: sda3 device: sda number: 3 wipe: superblock preserve: false offset: 36507223040 # 前のパーティションの末尾+512バイト => 34GiB+512+512 size: -1 # -1で100%指定 grub_device: false # ファイルシステムの作成 # ESP - type: format id: fs-sda1 volume: sda1 # パーティションの作成で設定したidを指定する fstype: fat32 # ESPはfat32でフォーマットする preserve: false # スワップ - type: format id: fs-sda2 volume: sda2 fstype: swap # スワップ領域はswapを指定する label: swap preserve: false # ルートファイルシステム - type: format id: fs-sda3 volume: sda3 fstype: ext4 preserve: false # マウントポイント # ESP - type: mount id: mount-efi device: fs-sda1 # ファイルシステムの作成で設定したidを指定する path: /boot/efi # スワップ - type: mount id: mount-swap device: fs-sda2 path: none # スワップ領域はnoneを指定する # ルートファイルシステム - type: mount id: mount-root device: fs-sda3 path: /
必要な設定項目は多いですが、
上記の設定を含んだuser-data
と、空ファイルmeta-data
を/var/
へ設置し、dnsmasqへのDHCPエントリを追加すれば、UEFIブートマシンでも自動インストールが可能になります。
$ sudo mkdir /var/www/autoinstall/08:00:27:84:bd:fe $ sudo tee /var/www/autoinstall/08:00:27:84:bd:fe/user-data <<'EOF' #cloud-config autoinstall: version: 1 identity: hostname: ubuntu-server username: ubuntu password: "$6$/X6MRgjz4jCIK8.G$FhJbD17m9qTcMA8FHMPcFvp7v2wvgmRBdvdEdTiZXZRwuZFUVsear9.vYY01QcwPuYAMRMvSJoJKfUlaBviU3/" ssh: install-server: yes storage: version: 2 grub: reorder_uefi: false config: ... EOF $ sudo touch /var/www/autoinstall/08:00:27:84:bd:fe/meta-data $ sudo tee -a /etc/dnsmasq.conf <<'EOF' dhcp-host=08:00:27:84:bd:fe,192.168.118.161,ubuntu-server EOF $ sudo systemctl restart dnsmasq.service