Raspberry Pi 4でCentOS7を外付けSSDで動かす

今回はrootパーティションとswapを外付けのSSDで動作させてみたいと思います。

タイトルでは、CentOS7と書いてますが応用すればRaspbianでも動かせます。

class10(UHS-I)のmicroSDだと読み書きの速度が、最大90MB/秒に対して、自分の使っている安いSSDでも最大530MB/秒、書込み速度：最大310MB/秒、そしてラズパイ4からUSB3.0が搭載されたことで最大5Gbpsということから、SSDの速度がしっかりと活かしていけます！！

# 参考にさせて頂いたサイト

[Raspberry Pi 3 に繋いだ USB 接続の SSD に CentOS 7 を入れてみる](https://bucci.bp7.org/archives/40931/)
[『Rasberry Pi に CentOS7 をインストールし SSD化』](https://ameblo.jp/tony1124/entry-12149357121.html)

# 大まかな動かすイメージ

やる前に全体のイメージ像を掴まないと、一つ一つのやる意味が理解できないと思うので、超絶ざっくりと全体を俯瞰してみたいと思います。

自分はインフラのお仕事をしている訳ではないので詳しくないのですが、ラズパイの電源オンからログインまでは

## /boot/cmdline.txtが読み込まれる

中身は、以下のようになっています。

```
console=ttyAMA0,115200 console=tty1 root=/dev/mmcblk0p3 rootfstype=ext4 elevator=deadline rootwait
```
この中の、root=/dev/mmcblk0p3がポイントで、起動した時のrootパーティションが書かれています。(この場合は、/dev/mmcblk0p3がrootパーティションとして扱われる)
初期状態は、microSDのrootパーティションが設定されているので、ここをSSDにしていてあげると良さそうです。

## rootパーティションの中の/etc/fstabファイルが読み込まれる

中身は、以下のようになっています。

```:/etcfstab
UUID=f28e182b-76a9-4f22-9a79-d49691313906  / ext4    defaults,noatime 0 0
UUID=AF94-12D3  /boot vfat    defaults,noatime 0 0
UUID=d61648c4-62a4-4ad7-84ca-4913ae013c7b  swap swap    defaults,noatime 0 0
```
これは、
ルートパーティション(/)が、f28e182b-76a9-4f22-9a79-d49691313906というUUIDのパーティション
bootパーティションが、AF94-12D3というUUDのパーティション
swapがd61648c4-62a4-4ad7-84ca-4913ae013c7bというUUIDのパーティション
としてマウントされるようになっています。

そして、blkidコマンド打ってみます。

```shell
/dev/mmcblk0p1: SEC_TYPE="msdos" UUID="AF94-12D3" TYPE="vfat"
/dev/mmcblk0p2: LABEL="_swap" UUID="d61648c4-62a4-4ad7-84ca-4913ae013c7b" TYPE="swap"
/dev/mmcblk0p3: LABEL="_/" UUID="f28e182b-76a9-4f22-9a79-d49691313906" TYPE="ext4"
/dev/mmcblk0: PTTYPE="dos"
/dev/sda: PTTYPE="dos"
```
するとこのようになっており、/dev/mmcblk~~~はmicroSDとなっており、/dev/sdaは外付けのSSDとして認識されていることが分かります。

しかしながら、SSDは何もパーティションが区切られていないので、こちらも自分でパーティションを切って作成してあげる必要がありそうです。

つまり、初期設定では起動時に全てのパーティションをmicroSDに設定されており、ここのルートパーティションとswapをSSDに指定してあげると良さそうです。

なので、今回は

1. SSDのパーティション作成
2. /boot/cmdline.txt
3. SSDの中の/etc/fstab

を設定してあげると、うまく起動できそうです！！

(間違っているところがあれば、ご指摘ください…😭😭😭)

# SELinuxをオフにする

今回、いろいろ頑張ってみたのですが、SELinuxをオフにしないと起動してもbashコマンドが実行できないので、ここでオフにしておきましょう。

以下のコマンドで、SELinuxの設定を開きます。

```
vim /etc/sysconfig/selinux
```
この中のSELINUX=enforcingをSELINUX=disabledにして無効化させます。

```
# This file controls the state of SELinux on the system.
# SELINUX= can take one of these three values:
#     enforcing - SELinux security policy is enforced.
#     permissive - SELinux prints warnings instead of enforcing.
#     disabled - No SELinux policy is loaded.
# SELINUX=enforcing ←コメントアウトする
SELINUX=disabled
```

# SSDにパーティションを作成する
次は、SSDをswapとルートパーティションとして使えるようにするために、パーティションを作成します。

## SSDの場所を探す
fdisk -lと打ち、自分のSSDが接続されている場所を探します。

```
(中略)
 
Disk /dev/mmcblk0: 31.3 GB, 31312576512 bytes, 61157376 sectors
Units = sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O サイズ (最小 / 推奨): 512 バイト / 512 バイト
Disk label type: dos
ディスク識別子: 0x00060b0d
 
  デバイス ブート      始点        終点     ブロック   Id  システム
/dev/mmcblk0p1   *        8192      593919      292864    c  W95 FAT32 (LBA)
/dev/mmcblk0p2          593920     1593343      499712   82  Linux swap / Solaris
/dev/mmcblk0p3         1593344     4524031     1465344   83  Linux
 
Disk /dev/sda: 120.0 GB, 120040980480 bytes, 234455040 sectors
Units = sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 4096 bytes
I/O サイズ (最小 / 推奨): 4096 バイト / 4096 バイト
Disk label type: dos
ディスク識別子: 0x000f4106
 
デバイス ブート      始点        終点     ブロック   Id  システム
```
最後のところに、自分のSSDの場所が書かれています。(今回は、/dev/sda)

## パーティションの作成
次に以下のコマンドで、パーティション作成を行う(/dev/sdaは各自のSSDの場所に置換)

```shell
parted /dev/sda
```
そうすると、パーティションを編集することが出来るので、最初にSSDのフォーマットを行ます。
その後、自分のラズパイ4はメモリが4GBなので先頭から6GBをswap領域、6GBから最後までをルートパーティションに割り当てたいと思います。

```
(parted) mktable msdos
警告: いま存在している /dev/sda のディスクラベルは破壊され、このディスクの全データが失われます。続行しますか？
はい(Y)/Yes/いいえ(N)/No? y
(parted) mkpart primary ext4 0% 6G
(parted) mkpart primary ext4 6G 100%
(parted) print
モデル: JMicron Tech (scsi)
ディスク /dev/sda: 120GB
セクタサイズ (論理/物理): 512B/4096B
パーティションテーブル: msdos
ディスクフラグ:
 
番号  開始    終了    サイズ  タイプ   ファイルシステム  フラグ
 1    1049kB  6000MB  5999MB  primary  linux-swap(v1)
 2    6000MB  120GB   114GB   primary  ext4
 
(parted) quit
通知: 必要であれば /etc/fstab を更新するのを忘れないようにしてください。
```
このようにすることで、/dev/sdaが、/dev/sda1と/dev/sda2と論理的に分割されます。

ただこれだけだと、パーティションを作成しただけなので、2つをファイルシステム用とswap用で初期化して利用できるようにします！

## ルートパーティションのフォーマット
まずは、ルートパーティション用の/dev/sda2から

```
[root@localhost ~]# mkfs.ext4 /dev/sda2
mke2fs 1.42.9 (28-Dec-2013)
Filesystem label=
OS type: Linux
Block size=4096 (log=2)
Fragment size=4096 (log=2)
Stride=0 blocks, Stripe width=0 blocks
6963200 inodes, 27842048 blocks
1392102 blocks (5.00%) reserved for the super user
First data block=0
Maximum filesystem blocks=2176843776
850 block groups
32768 blocks per group, 32768 fragments per group
8192 inodes per group
Superblock backups stored on blocks:
    32768, 98304, 163840, 229376, 294912, 819200, 884736, 1605632, 2654208,
    4096000, 7962624, 11239424, 20480000, 23887872
 
Allocating group tables: done
Writing inode tables: done
Creating journal (32768 blocks): done
Writing superblocks and filesystem accounting information: done
```

## swapのフォーマット
続いて、swap用の/dev/sda1
(このコマンドは少し時間がかかるかも…)

```
[root@localhost ~]# mkswap -c /dev/sda1
0 bad pages
mkswap: /dev/sda1: warning: wiping old swap signature.
スワップ空間バージョン1を設定します、サイズ = 5858300 KiB
ラベルはありません, UUID=5e92b785-dca9-4281-9201-f611d4eb80ee
```

# microSDのルートパーティションをSSDのルートパーティションへコピー

## ddコマンドでmicroSDからSSDへコピー

まず、何も触っていない/boot/cmdline.txtのroot=/dev/*******の部分を見ると、現在のルートパーティションが分かります。

```:/boot/cmdline.txt
[root@localhost ~]# cat /boot/cmdline.txt
console=ttyAMA0,115200 console=tty1 root=/dev/mmcblk0p3 rootfstype=ext4 elevator=deadline rootwait
```
私の場合だと、/dev/mmcblk0p3がルートパーティションと分かります。

そして、以下のコマンドを入力して、現在のルートパーティション(私の場合は/dev/mmcblk0p3)を、先ほど作成したSSDのルートパーティション(/dev/sda2)へコピーします。

```
[root@localhost ~]# dd if=/dev/mmcblk0p3 of=/dev/sda2 bs=32M status=progress
1500512256 バイト (1.5 GB) コピーされました, 43.498312 s, 34.5 MB/s
44+1 レコード入力
44+1 レコード出力
1500512256 バイト (1.5 GB) コピーされました、 43.4987 秒、 34.5 MB/秒
```

if と ofの場所を間違えたら全部のデータが消えるので慎重に行ってください。
しばらく待ち、コピーが終わった後、以下のコマンド入力してファイルのチェックを行い、途中で修復する場所が出たらyを押して修復しましょう。

```
[root@localhost ~]# e2fsck -f /dev/sda2
e2fsck 1.42.9 (28-Dec-2013)
Warning!  /dev/sda2 is mounted.
_/: recovering journal
Pass 1: Checking inodes, blocks, and sizes
Inode 7 has illegal block(s).  Clear<y>? yes
Illegal block #11731 (1217396736) in inode 7.  CLEARED.
Illegal block #11747 (2629894144) in inode 7.  CLEARED.
Illegal block #11763 (2687565824) in inode 7.  CLEARED.
Illegal block #11779 (1952448512) in inode 7.  CLEARED.
Inode 7, i_blocks is 8552, should be 8584.  Fix<y>? yes
Pass 2: Checking directory structure
Pass 3: Checking directory connectivity
Pass 4: Checking reference counts
Pass 5: Checking group summary information
Free blocks count wrong (36162, counted=36130).
Fix<y>? yes
Free inodes count wrong (62829, counted=62824).
Fix<y>? yes
 
_/: ***** FILE SYSTEM WAS MODIFIED *****
_/: 28760/91584 files (0.5% non-contiguous), 330206/366336 blocks
```
そして、df -hと入力すると104GBもあるのに使用率が100％になっていることが分かります。

```
[root@localhost ~]# df -h
ファイルシス   サイズ  使用  残り 使用% マウント位置
/dev/root        1.4G  1.3G  111M   92% /
devtmpfs         1.9G     0  1.9G    0% /dev
tmpfs            2.0G     0  2.0G    0% /dev/shm
tmpfs            2.0G   17M  1.9G    1% /run
tmpfs            2.0G     0  2.0G    0% /sys/fs/cgroup
/dev/mmcblk0p1   286M   54M  233M   19% /boot
tmpfs            391M     0  391M    0% /run/user/0
/dev/sda2         64Z   64Z  104G  100% /mnt
```
なので、ディスクの容量を拡張したいのですが、マウント状態だと拡張できないので、以下のコマンドを入力してマウントを解除します。

```
[root@localhost ~]# umount /dev/sda2
```
マウント解除後、以下のコマンドを入力してディスクの容量を拡張します。

```
[root@localhost ~]# resize2fs /dev/sda2
resize2fs 1.42.9 (28-Dec-2013)
Resizing the filesystem on /dev/sda2 to 27734016 (4k) blocks.
The filesystem on /dev/sda2 is now 27734016 blocks long.
```
その後、マウントしてもう一度df -hを入力するとしっかりと拡張されていることが分かります。

```
[root@localhost ~]# mount /dev/sda2 /mnt/
[root@localhost ~]# df -h
ファイルシス   サイズ  使用  残り 使用% マウント位置
/dev/root        1.4G  1.3G  111M   92% /
devtmpfs         1.9G     0  1.9G    0% /dev
tmpfs            2.0G     0  2.0G    0% /dev/shm
tmpfs            2.0G   17M  1.9G    1% /run
tmpfs            2.0G     0  2.0G    0% /sys/fs/cgroup
/dev/mmcblk0p1   286M   54M  233M   19% /boot
tmpfs            391M     0  391M    0% /run/user/0
/dev/sda2        105G  1.3G  102G    2% /mnt
```
そして、blkidと入力するとコピー元の/dev/mmcblk0p3とコピー先の/dev/sda2のUUIDが同じになっていると思います。

```
[root@localhost ~]# blkid
/dev/mmcblk0p1: SEC_TYPE="msdos" UUID="AF94-12D3" TYPE="vfat"
/dev/mmcblk0p2: LABEL="_swap" UUID="d61648c4-62a4-4ad7-84ca-4913ae013c7b" TYPE="swap"
/dev/mmcblk0p3: LABEL="_/" UUID="f28e182b-76a9-4f22-9a79-d49691313906" TYPE="ext4"
/dev/sda1: UUID="194fecdc-6d06-4534-ae14-84903398843d" TYPE="swap"
/dev/sda2: LABEL="_/" UUID="f28e182b-76a9-4f22-9a79-d49691313906" TYPE="ext4"
/dev/mmcblk0: PTTYPE="dos"
```
ddコマンドは、ファイルだけでなくUUIDもそのまま全てコピーする操作らしいので、下記のコマンドで、マウント解除後もう一度UUIDを割り振りたいと思います。

```
[root@localhost ~]# umount /dev/sda2
[root@localhost ~]# tune2fs -U random /dev/sda2
tune2fs 1.42.9 (28-Dec-2013)
```
そして、再度マウント後blkidをすると、/dev/sda2に別のUUIDが割り当てられていることが分かります。

```
[root@localhost ~]# mount /dev/sda2 /mnt/
[root@localhost ~]# blkid
/dev/mmcblk0p1: SEC_TYPE="msdos" UUID="AF94-12D3" TYPE="vfat"
/dev/mmcblk0p2: LABEL="_swap" UUID="d61648c4-62a4-4ad7-84ca-4913ae013c7b" TYPE="swap"
/dev/mmcblk0p3: LABEL="_/" UUID="f28e182b-76a9-4f22-9a79-d49691313906" TYPE="ext4"
/dev/sda1: UUID="194fecdc-6d06-4534-ae14-84903398843d" TYPE="swap"
/dev/sda2: LABEL="_/" UUID="987316ca-4ec9-4e9b-a131-85322f0a6afb" TYPE="ext4"
/dev/mmcblk0: PTTYPE="dos"
```
これで、必要な準備が全て終わったので、次からは上手く起動できるような設定を行ます。


# /boot/cmdline.txtの編集

ここでは、起動した時に読み込まれるルートパーティションの設定を行ます。

デフォルトでは、以下のようにmicroSDのルートパーティション(/dev/mmcblk0p3)が呼ばれます。

```
[root@localhost ~]# cat /boot/cmdline.txt
console=ttyAMA0,115200 console=tty1 root=/dev/mmcblk0p3 rootfstype=ext4 elevator=deadline rootwait
```

## SATA/USB変換アダプタの情報を調べる

何も知らないと、2回目以降に起動したときにずっと以下の文が出てきて起動しなくなり、今回1番のつまづきポイントになります...

```
kernel: [36208.700136] scsi host0: uas_eh_device_reset_handler success
```

変換アダプタのベンダIDとデバイスIDを調べる為に、lsusbというコマンドが必要なのですがデフォルトではインストールされていません。
なので、下記のコマンドでインストールしましょう。

```shell
yum install -y usbutils
```
そうすると、lsusbコマンドが使えるので入力します。

```
[root@localhost ~]# lsusb
Bus 003 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
Bus 002 Device 002: ID 152d:0578 JMicron Technology Corp. / JMicron USA Technology Corp. JMS567 SATA 6Gb/s bridge
Bus 002 Device 001: ID 1d6b:0003 Linux Foundation 3.0 root hub
Bus 001 Device 003: ID 1c4f:0002 SiGma Micro Keyboard TRACER Gamma Ivory
Bus 001 Device 002: ID 2109:3431 VIA Labs, Inc. Hub
Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
```
このIDの後ろにある：で繋がれたものがベンダID：デバイスIDとなっているようです。
私のものはJMicronなので152d:0578をメモしておきます。

その後、/boot/cmdline.txtの先頭にusb-storage.quirks=ベンダID:デバイスID:uを追記します。
私の場合だと、usb-storage.quirks=152d:0578:uとなります。

```
usb-storage.quirks=152d:0578:u console=ttyAMA0,115200 console=tty1 root=/dev/mmcblk0p3 rootfstype=ext4 elevator=deadline rootwait
```

## ルートパーティションのパスを書き換える

root=/dev/mmcblk0p3という部分を、先ほど作成したroot=/dev/sda2に書き換えます。

```
usb-storage.quirks=152d:0578:u console=ttyAMA0,115200 console=tty1 root=/dev/sda2 rootfstype=ext4 elevator=deadline rootwait
```

# /mnt/etc/fstabの編集

ここでは、マウントされるルートパーティションとswapの設定を、microSDからSSDへ変更していきます。

大事なのは、マウントする情報が呼ばれるのは、cmdline.txtのrootで設定したパーティションの/etc/fstabなので、今回はSSDのルートパーティション(/dev/sda2)がマウントされている「/mnt」の中の「/etc/fstab」つまり「/mnt/etc/fstab」を編集する必要があり、「/etc/fstab」ではないことに注意しましょう！！

デフォルトでは、以下のように「/」「/boot」「swap」が全てmicroSDとなっています。

```shell
[root@localhost ~]# cat /mnt/etc/fstab
UUID=f28e182b-76a9-4f22-9a79-d49691313906  / ext4    defaults,noatime 0 0
UUID=AF94-12D3  /boot vfat    defaults,noatime 0 0
UUID=d61648c4-62a4-4ad7-84ca-4913ae013c7b  swap swap    defaults,noatime 0 0
```
なので、blkidコマンドを入力して、/dev/sda1と/dev/sda2のUUIDを調べます。

```shell
[root@localhost ~]# blkid
/dev/mmcblk0p1: SEC_TYPE="msdos" UUID="AF94-12D3" TYPE="vfat"
/dev/mmcblk0p2: LABEL="_swap" UUID="d61648c4-62a4-4ad7-84ca-4913ae013c7b" TYPE="swap"
/dev/mmcblk0p3: LABEL="_/" UUID="f28e182b-76a9-4f22-9a79-d49691313906" TYPE="ext4"
/dev/sda1: UUID="194fecdc-6d06-4534-ae14-84903398843d" TYPE="swap"
/dev/sda2: LABEL="_/" UUID="987316ca-4ec9-4e9b-a131-85322f0a6afb" TYPE="ext4"
/dev/mmcblk0: PTTYPE="dos"
```
/dev/sda1のUUIDは「194fecdc-6d06-4534-ae14-84903398843d」
/dev/sda2のUUIDは「987316ca-4ec9-4e9b-a131-85322f0a6afb」
ということが分かりました。

なので、/mnt/etc/fstabのルートを/dev/sda2のUUID、swapを/dev/sda1のUUIDに変更します。

```shell
UUID=987316ca-4ec9-4e9b-a131-85322f0a6afb  / ext4    defaults,noatime 0 0
UUID=AF94-12D3  /boot vfat    defaults,noatime 0 0
UUID= 194fecdc-6d06-4534-ae14-84903398843d  swap swap    defaults,noatime 0 0
```
念のため、以下のコマンドで/dev/sda2のマウントを解除してから、再起動をかけてSSDで動いているか確認しましょう！！

```shell
[root@localhost ~]# umount /dev/sda2
[root@localhost ~]# reboot
```

# 読み込まれているか確認

まずは、 df -hと入力してルートパーティションがSSDの/dev/sda2として設定したサイズになっていることを確認しましょう！

```shell
[root@localhost ~]# df -h
ファイルシス   サイズ  使用  残り 使用% マウント位置
/dev/root        105G  1.3G   98G    2% /
devtmpfs         1.9G     0  1.9G    0% /dev
tmpfs            2.0G     0  2.0G    0% /dev/shm
tmpfs            2.0G  8.5M  1.9G    1% /run
tmpfs            2.0G     0  2.0G    0% /sys/fs/cgroup
/dev/mmcblk0p1   286M   53M  234M   19% /boot
tmpfs            391M     0  391M    0% /run/user/0
```
そして、free -mと入力してswapがSSDの/dev/sda1として設定したサイズになっていることを確認します。

```shell
[root@localhost ~]# free -m
              total        used        free      shared  buff/cache   available
Mem:           3906          98        3705          16         102        3752
Swap:          5720           0        5720
```

ラズパイ4にCentOSを導入している方はちらほらいたのですが、まだCentOSをSSDで起動している方はいなかったので、出来るか不安でしたが何とか成功できてよかったです！