【LINUXカーネル再構築】バージョンアップ（4.18.0→5.8.8）

##目標
AWS EC2（Red Hat Enterprise Linux 8 (HVM), SSD Volume Type）に搭載されているカーネルのバージョンアップ（4.18.0→5.8.8）を完了すること。

##前提
AWS EC2サーバ1台（Red Hat Enterprise Linux 8 (HVM), SSD Volume Type）が構築済みであること。
なお、カーネル再構築はコンパイルやインストール時にある程度高いシステムリソース（CPU、メモリ等）を用意した方が時間短縮されスムーズになります。
また、ある程度のディスク容量がないとコンパイル時にエラーとなる可能性があります。
本記事ではインスタンスタイプ`m5a.xlarge`（0.344USD/時間）、ディスク容量は`50GB`としました。
![tempsnip.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/647616/5d01a05e-6b7f-d3e4-6653-6aa60676ecb8.png)
また、コンパイルやインストールにはスペックにもよりますが**1時間以上かかる可能性がある**ことを留意してください。

##カーネル再構築とは（LPICテキストより）
カーネルを必要に応じてコンパイルし、インストールすることを「カーネルの再構築」といいます。
以下のパターンにおいて、カーネル再構築を検討する必要があるようです。

・必要なデバイスドライバ（カーネルモジュール）がカーネルに含まれていない。
・使用しているハードウェアに最適化したカーネルを利用したい。
・カーネルの最新機能を使いたい。

カーネルを再構築するにはgccコンパイラやmakeユーティリティ、カーネルソース、カーネルヘッダが必要となります、
また、カーネル再構築時にはカーネルモジュールも合わせてコンパイルし直す必要があります。

##作業の流れ
| 項番 | タイトル |
|:----:|:-------------|
| 1 | [カーネルソースを用意する](#1カーネルソースを用意する) |
| 2 | [カーネルの設定](#2カーネルの設定)|
| 3 | [カーネルとカーネルモジュールのコンパイル](#3カーネルとカーネルモジュールのコンパイル)|
| 4 | [カーネルモジュールとカーネルのインストール](#4カーネルモジュールとカーネルのインストール)|
| 5 | [完了確認](#5完了確認)|

##参考書籍と参考サイト
[Linux教科書 LPICレベル2 Version4.5対応](https://www.shoeisha.co.jp/book/detail/9784798151250)
[CentOSでカーネルの再構築を行いカーネルモジュールを有効にする方法](https://oxynotes.com/?p=6670)
[カーネル(Linux-4.8.6)をコンパイルしてインストールしてみた](https://qiita.com/tutuz/items/f824475d00b35dd39e6b)

##手順
###1.カーネルソースを用意する
**①開発ツールのインストール**
OSログイン後、ルートスイッチ

```
sudo su -
```

現在のカーネルバージョンを`uname -r`で確認

```bash
# 現在のカーネルバージョンは4.18.0
[root@ip-172-31-42-117 ~]# uname -r
4.18.0-193.el8.x86_64
```


カーネル再構築に必要なツールをインストールします（※）。
インストールされていないツールが異様に多かったですが、気にしないことにします。。

※参考にさせて頂いた記事
[カーネル(Linux-4.8.6)をコンパイルしてインストールしてみた(1-1.開発ツールのインストール)](https://qiita.com/tutuz/items/f824475d00b35dd39e6b#1-1%E9%96%8B%E7%99%BA%E3%83%84%E3%83%BC%E3%83%AB%E3%81%AE%E3%82%A4%E3%83%B3%E3%82%B9%E3%83%88%E3%83%BC%E3%83%AB)

```bash

# 参考サイトを基にインストール
yum groupinstall "Development Tools"
yum install kernel-devel
yum install rpm-build redhat-rpm-config unifdef
yum install ncurses ncurses-devel

# 以降はmake（コンパイル）時に実際に発生したエラーを基に追加インストール
yum install elfutils-libelf-devel
yum install openssl-devel
yum install bc
```

**②カーネルソースのダウンロード**
wgetコマンド（URLを指定してファイルをダウンロードする）をインストールします。

```
yum install wget
```

カーネルソースを[https://www.kernel.org/](https://www.kernel.org/)から選び、ダウンロードします。
今回はカーネルバージョン`5.8.8`（09-Sep-2020）を取得します。

```
wget https://mirrors.edge.kernel.org/pub/linux/kernel/v5.x/linux-5.8.8.tar.xz
```

解凍と展開を行います。

```
tar Jxvf linux-5.8.8.tar.xz
```

展開したカーネルソースのディレクトリ配下に移動

```
cd linux-5.8.8
```

###2.カーネルの設定
**①既存設定ファイルをmake oldconfigでアップデート**
現在のカーネルで利用されている設定ファイルを`.config`（カーネルの設定ファイル）にコピーし、ゼロからのカーネル設定ファイル作成を回避します。

```
cp -p /boot/config-4.18.0-193.el8.x86_64 .config
```

カーネルコンフィギュレーションのアップデートを行います。
`make oldconfig`を利用することで、新しいカーネルで付け加えられた機能についてのみ問い合わせを行い、
従来から存在する設定については既存の設定をそのまま流用することが可能です。

本記事では新規項目に関しては全てデフォルト設定（yやnを入力せずただEnterを押す）とし、
設定が必要な「Kernel compression mode」については、今回は「1. Gzip (KERNEL_GZIP)」としました。

```
make oldconfig
```

```bash
# make oldconfigの出力例
[root@ip-172-31-42-117 linux-5.8.8]# make oldconfig
scripts/kconfig/conf  --oldconfig Kconfig
.config:1089:warning: symbol value 'm' invalid for NF_CT_PROTO_GRE
.config:2949:warning: symbol value 'm' invalid for ISDN_CAPI
*
* Restart config...
*
*
* General setup
*

# 従来から存在する項目はそのまま自動で流用
Compile also drivers which will not load (COMPILE_TEST) [N/y/?] n　　　　　　　　　　
Local version - append to kernel release (LOCALVERSION) []
Automatically append version information to the version string (LOCALVERSION_AUTO) [N/y/?] n

# (NEW)と記載されている新規項目のみこちらに問い合わせてくる
Build ID Salt (BUILD_SALT) [] (NEW)
Kernel compression mode
> 1. Gzip (KERNEL_GZIP)
  2. Bzip2 (KERNEL_BZIP2)
  3. LZMA (KERNEL_LZMA)
  4. XZ (KERNEL_XZ)
  5. LZO (KERNEL_LZO)
  6. LZ4 (KERNEL_LZ4)
choice[1-6?]: 1
（省略）
```

**②make menuconfigを利用してカーネル設定を微調整**
更に`make menuconfig`を利用することで、カーネルの各設定項目の選択式で調整することが可能です。
今回は検証段階でコンパイルエラーとなった原因のカーネル設定を事前にmake menuconfigで修正（※）します。

※エラー解決時に参考にさせて頂いたサイト
["No rule to make target 'debian/certs/debian-uefi-certs.pem', needed by 'certs/x509_certificate_list'. Stop."を解決する](https://blog.ishikawa.tech/entry/2019/09/03/174858)

参考サイトによるとエラー原因となっているカーネル設定はCONFIG_SYSTEM_TRUSTED_KEYSという項目（/boot以下の既存カーネル設定ファイルをコピーした場合、この項目は空文字列に修正しないとコンパイルエラーとなってしまうようです）

```
[root@ip-172-31-42-117 linux-5.8.8]# cat .config | grep "CONFIG_SYSTEM_TRUSTED_KEYS"
CONFIG_SYSTEM_TRUSTED_KEYS="certs/rhel.pem"
```

カーネル設定の修正を開始します。

```
make menuconfig
```

以下のようなコンソールが出たら、カーソルを利用してカーネルコンフィギュレーションの設定が可能です。
以下画像の赤枠の部分までカーソルで移動してEnterで選択していきます。
![tempsnip.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/647616/7c2d2af5-9e6b-0e80-0359-81e4b4893731.png)
![tempsnip.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/647616/715c35dd-cedf-15ab-dd1c-374ad91e6f4d.png)
![tempsnip.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/647616/1925d20c-1665-7a5c-13f5-eae6fc6de1d4.png)
デフォルトで記載されている文字列を消去し、空にしたらEnter
![tempsnip.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/647616/2e3b0b3d-0a62-88e4-4b0e-ef8bde0eeccd.png)
最後に.configにSave
![tempsnip.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/647616/6d11fb61-3772-09b5-2a85-0feee6a1fb02.png)
![キャプチャ.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/647616/794b2f02-f8f5-9a41-66e1-141f7bddd763.png)

変更が反映されているか.configの中身確認

```
[root@ip-172-31-42-117 linux-5.8.8]# cat .config | grep "CONFIG_SYSTEM_TRUSTED_KEYS"
CONFIG_SYSTEM_TRUSTED_KEYS=""
```



###3.カーネルとカーネルモジュールのコンパイル
`make`でカーネルとカーネルモジュールのコンパイルをします。
引数なしでも実行可能ですがこのコンパイル作業がかなり時間がかかるため-jオプションを利用して並列処理数を変更し、コンパイル時間の短縮を図ります（※）。
本記事での構成ですと約1時間弱コンパイルに時間かかりました。

※参考にさせて頂いた記事
[コア数に応じた最適なmake実行](https://qiita.com/ymdymd/items/312c9f554d4ffb1f8dc6)

```bash
# CPUコア数に応じた最適なプロセス数を起動する
JOBS=$[$(grep cpu.cores /proc/cpuinfo | sort -u | sed 's/[^0-9]//g') + 1]
make -j${JOBS}
```

※なお、コンパイル中にCONFIG_DEBUG_INFO_BTFという設定項目に関するエラーでたので修正しました。

```bash

# make中以下エラー発生
BTF: .tmp_vmlinux.btf: pahole (pahole) is not available
Failed to generate BTF for vmlinux
Try to disable CONFIG_DEBUG_INFO_BTF

# 言われた通りCONFIG_DEBUG_INFO_BTFを無効化
[root@ip-172-31-42-117 linux-5.8.8]# cat .config | grep CONFIG_DEBUG_INFO_BTF
CONFIG_DEBUG_INFO_BTF=n
```



##4.カーネルモジュールとカーネルのインストール
**①カーネルモジュールのインストール**

```bash
# 特にエラーなく完了すること
make modules_install
```

以下のように`/lib/modules/カーネルバージョン`ディレクトリが構成されていればOKです。

```
[root@ip-172-31-42-117 linux-5.8.8]# ls -l /lib/modules/5.8.8/
total 3440
lrwxrwxrwx.  1 root root     17 Sep 10 09:46 build -> /root/linux-5.8.8
drwxr-xr-x. 13 root root    141 Sep 10 09:47 kernel
-rw-r--r--.  1 root root 873761 Sep 10 09:47 modules.alias
-rw-r--r--.  1 root root 837562 Sep 10 09:47 modules.alias.bin
-rw-r--r--.  1 root root   8171 Sep 10 09:46 modules.builtin
-rw-r--r--.  1 root root  10467 Sep 10 09:47 modules.builtin.bin
-rw-r--r--.  1 root root  62064 Sep 10 09:46 modules.builtin.modinfo
-rw-r--r--.  1 root root 278819 Sep 10 09:47 modules.dep
-rw-r--r--.  1 root root 389096 Sep 10 09:47 modules.dep.bin
-rw-r--r--.  1 root root    405 Sep 10 09:47 modules.devname
-rw-r--r--.  1 root root  99497 Sep 10 09:46 modules.order
-rw-r--r--.  1 root root    521 Sep 10 09:47 modules.softdep
-rw-r--r--.  1 root root 422378 Sep 10 09:47 modules.symbols
-rw-r--r--.  1 root root 510059 Sep 10 09:47 modules.symbols.bin
lrwxrwxrwx.  1 root root     17 Sep 10 09:46 source -> /root/linux-5.8.8
```


**②カーネルのインストール**

```bash

# 特にエラーなく完了すること（エラーが出ずに終了することは必ず確認してください。筆者はエラーがでたまま再起動したらサーバが立ち上がらなくなりました。。）
make install -j${JOBS}
```

以下のようにカーネルイメージ`/boot/vmlinuz-カーネルバージョン`が/boot内に存在していればOKです。

```
[root@ip-172-31-42-117 ~]# ls -l /boot/vmlinuz*
lrwxrwxrwx. 1 root root      19 Sep 10 09:47 /boot/vmlinuz -> /boot/vmlinuz-5.8.8
-rwxr-xr-x. 1 root root 8913760 Apr 23 05:16 /boot/vmlinuz-0-rescue-bb64a14c7512444f9744c3076505b65f
-rwxr-xr-x. 1 root root 8920432 Sep 10 08:05 /boot/vmlinuz-0-rescue-ec211058807a3398326019a9b3f9e8bf
-rwxr-xr-x. 1 root root 8920432 Aug 26 19:47 /boot/vmlinuz-4.18.0-193.19.1.el8_2.x86_64
-rwxr-xr-x. 1 root root 8913760 Mar 27 14:48 /boot/vmlinuz-4.18.0-193.el8.x86_64
-rw-r--r--. 1 root root 8613632 Sep 10 09:47 /boot/vmlinuz-5.8.8
```

##5.完了確認
再起動後、以下のようにカーネルバージョンが変更されていればOKです。

```
[root@ip-172-31-42-117 ~]# uname -r
5.8.8
```