CentOS8をKickstartでネットワークインストールする。

# はじめに
以前、Ubuntuの`自動インストール機能`を使用したネットワークインストールの記事を投稿しましたが、せっかくなのでRHEL系でよく使われる`Kickstart`についても残しておこうと思います。

Ubuntu Server 20.04の`自動インストール機能`を使用したネットワークインストールは以下の記事をご参照下さい。

- [Ubuntu Server 20.04の自動インストール機能でネットワークインストールする。](https://qiita.com/sakai00kou/items/7ce4a8a410251b98b2ac)

また、この記事は以下記事の続きとなります。
以下記事でPXEサーバを構築してから行って下さい。

- [OS自動インストールを行うためのPXEブート環境を作る](https://qiita.com/sakai00kou/items/bc6ae4d6b4cacc4b8af9)

# Kickstartとは
`RHEL`系でよく使われるネットワークインストール方式です。

多分、`Fedora Core`が登場したころから機能が実装されていたと思うので、15年以上は世の中で使われていると思います。

[Red Hatのマニュアル](https://access.redhat.com/documentation/ja-jp/red_hat_enterprise_linux/8/html/performing_an_advanced_rhel_installation/index)でも書式や設定など細かく書かれているため、他のOSのネットワークインストールよりとっつきやすいと思います。

# 構成
VirtualBoxに以下構成の仮想マシンを作成しました。

[PXEサーバの構築](https://qiita.com/sakai00kou/items/bc6ae4d6b4cacc4b8af9)はリンクの記事を参照してください。

以下PXEサーバ側の操作は`VirtualBox`上`CentOS8`での操作となります。

メモリサイズは[CentOS 8.2.2004のリリースノート](https://wiki.centos.org/action/show/Manuals/ReleaseNotes/CentOS8.2004?action=show&redirect=Manuals%2FReleaseNotes%2FCentOSLinux8)によると最低限2GB必要とのことなので、2GBとします。

**・自動インストール対象マシン構成**

|構成|種別|
|:--|:--|
|CPU|1 vCPU|
|メモリサイズ|2048 MB|
|ストレージ|16.00 GB|
|ネットワーク1|ホストオンリーアダプター|
|ネットワーク2|NAT|

**・PXEサーバディレクトリ構成**

|ディレクトリ|パス|
|:--|:--|
|TFTPディレクトリ|/tftpboot|
|HTTPディレクトリ|/pxeboot|

**・アドレス構成**

|対象|アドレス|
|:--|:--|
|PXEサーバ|192.168.56.105|
|自動インストール対象マシン|192.168.56.131|

※自動インストール対象マシンのアドレスは自動インストール後のアドレスです。

# 構築の流れ
PXEサーバは構築済みの前提となります。

**・PXEサーバ側手順**
1. CentOS 8.2.2004のISOファイルマウント
2. CentOS 8.2.2004のカーネルイメージのコピー
3. TFTPブート構成ファイルの作成
4. 自動インストール用ディレクトリ作成
5. Kickstart用anacondaファイル作成

**・自動インストール対象マシン側手順**
1. 自動インストール対象マシンの設定
2. 自動インストール

# Kickstartによるインストール
`Kickstart`では`anaconda`ファイルに記載された設定に従ってセットアップされます。

`anaconda`ファイルはRHEL系であれば、`/root`配下に初期インストール時の設定が記載されているため、`/root/anaconda-ks.cfg`ファイルを参考にして`Kickstart`用の設定ファイルを作成していきます。

## CentOS 8.2.2004のISOファイルマウント
今回は[Ubuntu Serverインストール](https://qiita.com/sakai00kou/items/7ce4a8a410251b98b2ac)のようにISOイメージをインストール対象サーバに直接転送するようなことを行わなくて済むので`PXEサーバ`でISOマウントだけ行います。

[CentOSのサイト](https://www.centos.org/)より`CentOS 8.2.2004`をダウンロードし、`PXEサーバ`の「デバイス」→「光学ドライブ」からダウンロードしたISOファイル（CentOS-8.2.2004-x86_64-dvd1.iso）を選択します。

後ほど`Kickstart`で指定するため、マウント先は`/pxeboot/repo/CentOS/8/cdrom`として、ディレクトリを作成しておきます。

```shell:ISOイメージマウント用ディレクトリ作成
sudo mkdir -p /pxeboot/repo/CentOS/8/cdrom
```

## CentOS 8.2.2004のカーネルイメージのコピー
先ほど読み込んだISOファイルをマウントして`CentOS 8.2.2004`のカーネルイメージを取得します。

```shell:カーネルイメージ格納ディレクトリ作成
sudo mkdir /tftpboot/CentOS
```

```shell:ISOイメージマウント
sudo mount /dev/sr0 /pxeboot/repo/CentOS/8/cdrom
```

```shell:カーネルイメージコピー
sudo cp /pxeboot/repo/CentOS/8/cdrom/images/pxeboot/{vmlinuz,initrd.img} /tftpboot/CentOS
```

# TFTPブート構成ファイルについて
以前も紹介しましたが、PXEブートする際に取得するブート構成ファイルの名前は決められており、以下の様な規則になります。
※参考：[BIOSベースのPXEクライアントのブート・ローダー構成](https://docs.oracle.com/cd/E77565_01/install/ol7-install-pxe-boot-bios.html)

- **UUID** (例: a8943708-c6f6-51b9-611e-74e6ac80b93d)
- **01-MAC_address** (例: 01-80-00-27-c6-a1-16)
- **IPアドレスの完全32ビット** (例: 0A0000FD)
- **IPアドレスの最上位28ビット** (例: 0A0000F)
- **IPアドレスの最上位24ビット** (例: 0A0000)
- **IPアドレスの最上位20ビット** (例: 0A000)
- **IPアドレスの最上位16ビット** (例: 0A00)
- **IPアドレスの最上位12ビット** (例: 0A0)
- **IPアドレスの最上位8ビット** (例: 0A)
- **IPアドレスの最上位4ビット** (例: 0)
- **default** (デフォルト構成ファイル)

例えばMACアドレスのファイルを格納した場合、ホストごとにブート構成ファイルを固定できるため、それぞれのホスト専用の定義を指定することができます。

また、ブート構成ファイルの設定の書き方によっては、起動時に読み込むOSファイルやOSイメージをユーザに選択させることもできるので、`default`に複数の起動定義を記載して選択することも可能です。

## TFTPブート構成ファイルの作成
今回はインストール対象マシンのMACアドレスのファイルに`Kickstart`インストール用定義を記載します。

インタフェース名とMACアドレスは以下の想定で進めますので、自身の環境に合わせて適宜読み替えて下さい。

|インタフェース|MACアドレス|
|:--|:--|
|enp0s3|08:00:27:1d:57:34|

尚、今回は`VirtualBox`で作成したため、インタフェースは`enp0s3`となっておりますが、インタフェース名は環境によって変わるので、事前にインストールしてみるなどしてインタフェース名を確認しておいてください。

```shell:/tftpboot/pxelinux.cfg/01-08-00-27-1d-57-34
sudo cat << _EOF_ | sudo tee /tftpboot/pxelinux.cfg/01-08-00-27-1d-57-34
default kickstart
label kickstart
  kernel CentOS/vmlinuz
  initrd CentOS/initrd.img
  append ks=http://192.168.56.105/pxeboot/vmhost.cfg load initrd=CentOS/initrd.img devfs=nomount ksdevice=enp0s3
_EOF_
```

## Anacondaファイルの設定について
`anacondaファイル`はいくつかのセクションに分かれており、セクションごとに指定の設定を行います。

前述の通り、RHEL系のマシンの`/root`にはインストール時に使用した`anacondaファイル`が置かれているので、どのようなインストールを行ったのか分かるようになっています。

<details><summary>DVDインストールした場合のAnacondaファイル例（展開して下さい）</summary><div>

```shell:Anacondaファイル例
#version=RHEL8
ignoredisk --only-use=sda
autopart --type=lvm
# Partition clearing information
clearpart --none --initlabel
# Use graphical install
graphical
# Use CDROM installation media
cdrom
# Keyboard layouts
keyboard --vckeymap=jp --xlayouts='jp'
# System language
lang ja_JP.UTF-8

# Network information
network  --bootproto=static --device=enp0s3 --ip=192.168.56.105 --netmask=255.255.255.0 --ipv6=auto --activate
network  --bootproto=dhcp --device=enp0s8 --ipv6=auto --activate
network  --hostname=vmpxe01
repo --name="AppStream" --baseurl=file:///run/install/repo/AppStream
# Root password
rootpw --iscrypted $6$GT/YYwgPk.wHIkLs$StfR0tXBveOrReUe95oqGuIdqxBCBgtZaPF2lZYWT/ciPVyvYwt9Jwc4lFQ0jC1LvYy6iBS6.zezUm69I2iST1
# Run the Setup Agent on first boot
firstboot --enable
# Do not configure the X Window System
skipx
# System services
services --enabled="chronyd"
# System timezone
timezone Asia/Tokyo --isUtc
user --name=centos --password=$6$Z9TXdeskUsRw0rwJ$4p.CPUlkJ.yzkN9i8iJVd1mItlkMgQzVUFPg0YcPh0nsghV5wD7El9wkukt5Cni/iDEdWc49KnIcoNeTHi5QU1 --iscrypted --gecos="vmware"

%packages
@^minimal-environment

%end

%addon com_redhat_kdump --disable --reserve-mb='auto'

%end

%anaconda
pwpolicy root --minlen=6 --minquality=1 --notstrict --nochanges --notempty
pwpolicy user --minlen=6 --minquality=1 --notstrict --nochanges --emptyok
pwpolicy luks --minlen=6 --minquality=1 --notstrict --nochanges --notempty
%end
```
</div></details>

## Anacondaファイルのセクションについて
いくつもセクションが分かれていますが、基本設定以外は`%[セクション名]`で始まり、`%end`で終わる必要があります。

また、`Kickstart`によるインストールを行う際によく使われるであろうスクリプトセクションですが、`pre`、`pre-install`はOSが完全にインストールされていない状況での処理のため、基本的には使用する必要はありません。

そのため、OSインストール後に何か処理を行わせたい場合は`post`スクリプトセッションに書けば問題ないです。

|セクション|セクションコマンド|用途|
|:--|:--|:--|
|基本設定|無し|ネットワークやディスク設定などの基本設定全般|
|パッケージセクション|%packages|インストールするパッケージを記載|
|アドオンセクション|%addon *[addon_name]*|アドオンで提供される機能の設定|
|Anaconda設定セクション|%anaconda|現状パスワードポリシーのためだけの設定|
|preスクリプトセクション|%pre|Kickstartファイル読み込み直後に実行される処理|
|pre-installスクリプトセクション|%pre-install|ネットワーク設定後に実行される処理|
|postスクリプトセクション|%post|インストール完了後、最初に再起動されるまでに実行される処理|

## Kickstartファイルの作成前準備
今回は前述の構成に以下の設定を加えることを想定して`Kickstart`用のAnacondaファイルを作成してみようと思います。

- firewalldとSELinuxを無効にする。
- Python3.8をインストールする。
- chronyでNICTのサーバに問い合わせを行うようにする。
- dnf updateでパッケージを最新化する。

AnacondaファイルはTFTPブート構成ファイル内で指定した通り、以下に作成します。

|ファイル|パス|
|:--|:--|
|anacondaファイル|/pxeboot/vmhost.cfg|

また、`anaconda`ファイルに記載されているパスワードもハッシュ値で記載する必要があるので以下の様な方法でハッシュ値を生成しておきます。
※今回はパスワード`centos`で生成します。

```shell:パスワードハッシュ化
sudo openssl passwd -6 centos
```

もし、`/root`の`anaconda`ファイルをコピーして作成している場合、権限が`0600`となっており、`Kickstart`で読み取る際、読み取れずに失敗するため、修正しておきます。

```shell:anacondaファイルの権限変更
sudo chmod 644 /pxeboot/vmhost.cfg
```

### firewalldとSELinuxの無効化
基本設定として定義が存在するので、以下で無効化するだけです。

```shell:firewalldとSELinuxの無効化
selinux --disabled
firewall --disabled
```

### Python3.8のインストール
dnfのパッケージインストールとPython3.8の使用設定を行います。

ついでにpipも使用できるようにしておきます。

```shell:Python3.8インストール（Packagesセクション）
python38
```

```shell:Python3.8設定（Postセクション）
alternatives --set python /usr/bin/python3.8
update-alternatives --install /usr/bin/pip pip /usr/bin/pip3.8 1
```

### chronyの設定
chronyのアドレスを設定するような定義は存在しないため、`post`セクションで`sed`を使用して直接ファイルを書き換えてしまいます。

```shell:chronyの設定
sed -i -e "s/^pool/#pool/g" \
       -e "/^#pool 2/a \
pool ntp.nict.jp prefer iburst" /etc/chrony.conf
```

### dnf update
`dnf update`も`post`セクションに直接書き込みます。

```shell:dnf_update
dnf -y update
```

### Kickstartファイルの作成
コメントを加えたりしつつ、作成したAnacondaファイルが以下となります。

細かくは説明しませんが、`Kickstart`用にいくつかパラメータを修正、追加も行っています。

コツとしては、`eula --agreed`で同意の選択を省くことと、`repo`の指定は行わないこと（`AppStream`リポジトリは`Kickstart`インストール時に指定されるため）、最後に再起動するよう`reboot`設定をすることでしょうか。

<details><summary>Kickstart用Anacondaファイル例（展開して下さい）</summary><div>

```shell:Kickstart用Anacondaファイル例
##################################################################
# 基本セクション
##################################################################
#version=RHEL8
zerombr
ignoredisk --only-use=sda
autopart --type=lvm
# Partition clearing information
clearpart --all --initlabel

# Kickstartインストール
text
url --url=http://192.168.56.105/pxeboot/repo/CentOS/8/cdrom/
eula --agreed
reboot

# Keyboard layouts
keyboard --vckeymap=jp --xlayouts='jp'
# System language
lang ja_JP.UTF-8

# Network information
network  --bootproto=static --device=enp0s3 --ip=192.168.56.131 --netmask=255.255.255.0 --nodefroute --noipv6 --onboot=on --activate
network  --bootproto=dhcp --device=enp0s8 --noipv6 --onboot=on --activate
network  --hostname=vmhost

# Root password
rootpw --iscrypted $6$BQJphupSd1P6pREf$RDUQt69lV0np1OZpZ7I9MmpkYzPV7QMJ.Pz5TOKsXusEF.qmnmrcqOF6D5LXfLTciLLB2QIEyXriDhzyMLluv/
# Run the Setup Agent on first boot
firstboot --disable
# Do not configure the X Window System
skipx
# System services
services --enabled="chronyd"
# System timezone
timezone Asia/Tokyo --isUtc
user --name=centos --password=$6$BQJphupSd1P6pREf$RDUQt69lV0np1OZpZ7I9MmpkYzPV7QMJ.Pz5TOKsXusEF.qmnmrcqOF6D5LXfLTciLLB2QIEyXriDhzyMLluv/ --iscrypted --gecos="centos"

# firewalld、SELinuxの無効化
selinux --disabled
firewall --disabled

##################################################################
# %packageセクション
##################################################################
%packages
@^minimal-environment

# Python3.8インストール
python38

%end

##################################################################
# %addonセクション
##################################################################
%addon com_redhat_kdump --disable --reserve-mb='auto'

%end

##################################################################
# %anacondaセクション
##################################################################
%anaconda
pwpolicy root --minlen=6 --minquality=1 --notstrict --nochanges --notempty
pwpolicy user --minlen=6 --minquality=1 --notstrict --nochanges --emptyok
pwpolicy luks --minlen=6 --minquality=1 --notstrict --nochanges --notempty
%end

##################################################################
# %postセクション（インストール後に実行する初期設定）
##################################################################
# post処理をログに残す
%post --log=/root/anaconda-post.log --erroronfail

# NTP設定 (chronyd)
sed -i -e "s/^pool/#pool/g" \
       -e "/^#pool 2/a \
pool ntp.nict.jp prefer iburst" /etc/chrony.conf

# Python設定
alternatives --set python /usr/bin/python3.8
update-alternatives --install /usr/bin/pip pip /usr/bin/pip3.8 1

# dnf update
dnf -y update

%end
```
</div></details>

# 自動インストール対象マシンの設定
自動インストール対象マシンは`PXEブート`できるようにしておけば基本的には設定は必要ありません。

但し、インストールディスクに既にOSがインストールされているような場合は各種BIOSの起動デバイス選択から`PXEブート`が先になるように変更します。

`VirtualBox`の場合、仮想ストレージが空の状態であれば、以下のように`起動順序`で`ネットワーク`にチェックされていることを確認すれば問題ありません。

![01_boot.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/569912/132ce3fd-f000-5fb4-a2de-b1ba3ba9556d.jpeg)

# 自動インストール
自動インストール対象マシンの電源を入れることで`ネットワークインストール`が始まります。

あとは待つだけなので気長に待ちましょう。

# まとめ
最近はAWSなどのクラウド環境が増えてきたので`Kickstart`を使う機会も減っていますが、オンプレミスのサーバ等を構築する際にはまだまだ使える機能なので、選択肢の一つとして覚えておくと、何かの役に立つかもしれません。