なぜ試す必要が出てきたのか
RHEL(Red Hat Enterprise Linux)9 の EC2 を構築することになり、ファイルシステムを次のように設計しました。
- 1 個の EBS にまとめる
内訳:-
/(ルート)ファイルシステム: 20GB -
/logファイルシステム: 30GB
-
ファイルシステムごとに EBS を分けず、1 本の EBS にまとめる構成です。
AMI は AWS が提供しているパブリック AMI を使用しました。
RHEL9 の AMI はルート EBS が 10GB のため、ローンチ時に 50GB としておけば、40GB の未割り当て領域が残るだろう、と予想していました。
ところがですよ、実際はこうなりました。
$ lsblk
NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINTS
nvme0n1 259:0 0 50G 0 disk
├─nvme0n1p1 259:1 0 1M 0 part
├─nvme0n1p2 259:2 0 200M 0 part /boot/efi
├─nvme0n1p3 259:3 0 1G 0 part /boot
└─nvme0n1p4 259:4 0 48.8G 0 part /
こうなったのです。(そうなる理由も理解できます。)
UEFIのパーティションがいくつかが作成されて、その残りすべてが / ファイルシステムに 48.8GB 丸ごと割り当てられている!
しかも xfs フォーマットのために、縮小もできないのです。
つまり、設計に合わせるには EC2 を作り直すしかないのです...
しかし、nginxのインストールとセットアップ等を進めてしまったために、そのやり直しをしたくない。
この設定を維持して何とか / ファイルシステムを縮小できないかな、と考えました。
OKだった手順
今回、テストして期待通りに動作した方法を紹介します。
公式な手順ではありません。真似する場合は、各自で十分な検証を行ってください。
前提: 元のEC2の稼働状況を確認
$ ps -ef | grep nginx | grep -v grep
root 16613 1 0 08:45 ? 00:00:00 nginx: master process /usr/sbin/nginx
nginx 16614 16613 0 08:45 ? 00:00:00 nginx: worker process
nginx 16615 16613 0 08:45 ? 00:00:00 nginx: worker process
nginx のプロセスが稼働しています。
セットアップを終えているので、これを維持して / の縮小だけを実現したいのです。
セットアップでは、OS起動時にnginxを自動起動させるようにしています。
1. 2つのEC2の作成(ローンチ)
まずは、2つのEC2を作成します。
元のEC2と合わせて、登場人物のEC2は合計3つです。
| 役割 | 名前 | EBSサイズ | AMI |
|---|---|---|---|
| (1) 元のEC2 | svr-main | 50GB | RHEL9 |
| (2) レスキュー用EC2 | resq | 最小限でOK | RHEL9 or RHEL10 |
| (3) 新規EBS用EC2 | svr-smallEBS | 20GB | (1)と同じAMI |
(2)と(3)のどちらも、Availability Zoneは、(1) と合わせることが必須です。
(2)は、今回は RHEL10 で試しました。
(3)の 20GB というのは、/ に必要なサイズを指定しています。
2. EBSの付け替え
レスキュー用 EC2に付けていきます。
デバイスの番号がずれたりするとややこしいので、作業の順番が大事です。
- 「(2)resq」のOSを起動
- 「(1)svr-main」をシャットダウン
- 「(1)svr-main」の EBS 50GB をデタッチ
- EBS 50GB を「(2)resq」にアタッチ(デバイス名は 空きの
/dev/sde等) - 「(3)svr-smallEBS」をシャットダウン
- 「(3)svr-smallEBS」の EBS 20GB をデタッチ
- EBS 20GB を「(2)resq」にアタッチ(デバイス名は 空きの
/dev/sdf等)
結果、resq には次のように 3 本のディスクが接続されます。
$ lsblk
NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINTS
nvme0n1 259:0 0 10G 0 disk
├─nvme0n1p1 259:1 0 1M 0 part
├─nvme0n1p2 259:2 0 200M 0 part /boot/efi
└─nvme0n1p3 259:3 0 9.8G 0 part /
nvme1n1 259:4 0 50G 0 disk
├─nvme1n1p1 259:5 0 1M 0 part
├─nvme1n1p2 259:6 0 200M 0 part
├─nvme1n1p3 259:7 0 1G 0 part
└─nvme1n1p4 259:8 0 48.8G 0 part
nvme2n1 259:9 0 20G 0 disk
├─nvme2n1p1 259:10 0 1M 0 part
├─nvme2n1p2 259:11 0 200M 0 part
├─nvme2n1p3 259:12 0 1G 0 part
└─nvme2n1p4 259:13 0 18.8G 0 part
- nvme0n1: resq自身のEBS
- nvme1n1: 50GBのEBS (
/の nvme1n1p4 は 48.8GB) - nvme2n1: 20GBのEBS (
/の nvme2n1p4 は 18.8GB)
3. UUIDの確認
実はこれが今回の肝です。
同じ AMI からローンチしたため、50GB と 20GB のディスクでファイルシステムの UUID が一致しています。
$ lsblk -f
(中略)
├─nvme1n1p3
│ xfs boot f0409cde-e434-47b6-a960-4dd387b74305
└─nvme1n1p4
xfs root dbeea23e-b90e-4803-9ff6-a4a0b3f6193d
(中略)
├─nvme2n1p3
│ xfs boot f0409cde-e434-47b6-a960-4dd387b74305
└─nvme2n1p4
xfs root dbeea23e-b90e-4803-9ff6-a4a0b3f6193d
UUIDが同じだと、/etc/fstab の修正や、grub2-mkconfig などの追加対応が不要になる点がうれしいのです。
むしろ、ここで UUID を変更するとトラブルの元になります。
4. ファイルの削除とコピー
20GBのEBSには、素のRHEL9のファイルが入っています。
これをそのままで、50GBのEBSのファイルを上書きすると、OSの稼働やセットアップの過程で削除されたファイルが復活 してしまいます。
一旦 rm で削除してから rsync でコピーという手順にします。
もう1つのポイントですが、/dev /proc /sys は仮想ファイルシステムなので除外します。
$ # ディレクトリの作成
$ sudo mkdir /mnt/source /mnt/dest
$ # コピー元をマウント
$ sudo mount /dev/nvme1n1p4 /mnt/source
$ # コピー先をマウント
$ sudo mount /dev/nvme2n1p4 /mnt/dest
mount: /mnt/dest: wrong fs type, bad option, bad superblock on /dev/nvme2n1p4,
missing codepage or helper program, or other error.
dmesg(1) may have more information after failed mount system call.
おっと、引っ掛かりました。これエラーメッセージからはわかりにくいですが、同じUUIDをmountしようとしているためです。
-o nouuid で回避します。
$ # コピー先をマウント リトライ
$ sudo mount -o nouuid /dev/nvme2n1p4 /mnt/dest
$ # ディレクトリ配下のサイズを確認
$ sudo du -ms /mnt/source
1891 /mnt/source
$ sudo du -ms /mnt/dest
1622 /mnt/dest
/mnt/source に 50GBのEBSの/ファイルシステム、/mnt/source に 20GBのEBSの/ファイルシステム をマウントしています。
du -ms で確認されるように、合計サイズが 1891MB と 1622MB で違いがあります。
nginx をセットアップしているためです。
削除と、その後のコピーをしていきます。
$ # /mnt/dest を一旦削除 (/mnt/dest/proc, sys, dev は除外)
$ sudo find /mnt/dest -mindepth 1 -maxdepth 1 ! -name proc ! -name sys ! -name dev -exec rm -rf {} +
$ # /mnt/source から /mnt/dest にコピー (/mnt/dest/proc, sys, dev を操作から除外)
$ sudo rsync -aAHXS --exclude=/dev --exclude=/proc --exclude=/sys /mnt/source/ /mnt/dest/ > /dev/null
$
rsyncでは、標準出力のみ /dev/null として、標準エラーは何も指定していないので、エラーすれば画面に出るはずですが、出ませんでした。
OKです。
$ sudo du -ms /mnt/source/
1891 /mnt/source/
$ sudo du -ms /mnt/dest/
1891 /mnt/dest/
$
du -ms の結果が一致しました。
OKです。
5. UUIDの確認(念のため)
$ cat /mnt/dest/etc/fstab
UUID=dbeea23e-b90e-4803-9ff6-a4a0b3f6193d / xfs defaults 00
UUID=f0409cde-e434-47b6-a960-4dd387b74305 /boot xfs defaults 00
UUID=7B77-95E7 /boot/efi vfat defaults,uid=0,gid=0,umask=077,shortname=winnt 0 2
$ sudo lsblk -f /dev/nvme2n1
NAME FSTYPE FSVER LABEL UUID FSAVAIL FSUSE% MOUNTPOINTS
nvme2n1
│
├─nvme2n1p1
│
├─nvme2n1p2
│ vfat FAT16 ESP 7B77-95E7
├─nvme2n1p3
│ xfs boot f0409cde-e434-47b6-a960-4dd387b74305
└─nvme2n1p4
xfs root dbeea23e-b90e-4803-9ff6-a4a0b3f6193d 16.7G 11% /mnt/dest
長いUUID 2個と、短いUUID 1個。いずれも一致しています。
OKです。
6. ディスクの付け戻し
アンマウントします。
$ sudo umount /mnt/source
$ sudo umount /mnt/dest
次に、20GB の EBS を svr-main に戻します。
- 「(2)resq」の EBS 20GB をデタッチ
- EBS 20GB を「(1)svr-main」にアタッチ(デバイス名は /dev/sda1)
7. いざ!RHELの起動
- 「(1)svr-main」を選択してEC2インスタンスを開始
OSにログインできたら、状況を確認します。
$ lsblk
NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINTS
nvme0n1 259:0 0 20G 0 disk
├─nvme0n1p1 259:1 0 1M 0 part
├─nvme0n1p2 259:2 0 200M 0 part /boot/efi
├─nvme0n1p3 259:3 0 1G 0 part /boot
└─nvme0n1p4 259:4 0 18.8G 0 part /
$ ps -ef | grep nginx | grep -v grep
root 1076 1 0 09:33 ? 00:00:00 nginx: master process /usr/s bin/nginx
nginx 1078 1076 0 09:33 ? 00:00:00 nginx: worker process
nginx 1079 1076 0 09:33 ? 00:00:00 nginx: worker process
$
/ファイルシステムが 18.8GB となってきちんと縮小されています!
nginxのプロセスが自動起動してきています!
OKです。
ログインできなければ、手順を再実施するか、以下のメニューからも、原因を推測できる可能性があります。
- アクション > モニタリングとトラブルシューティング
- システムログを取得
- インスタンスのスクリーンショットを取得
8. 後始末
- resq のシャットダウン
- resq, svr-smallEBS の終了(Terminate)
- 50GB の EBSの削除(念のためsnapshotを残してもよい)
NGとなってしまった手順
当初は「より確実」と思われていた次の手順を試しましたが、失敗しました。
当初の手順
- 2つのEC2の作成(ローンチ) ※OK手順と同じ
- EBSの付け替え ※OK手順と同じ
- UUIDの確認 ※OK手順と同じ
- ファイルの削除とコピー ※ここが異なります
- ファイル削除ではなく
mkfs.xfsコマンドで /dev/nvme2n1p4 を初期化 - マウントして
rsyncでコピー
- ファイル削除ではなく
- /etc/fstab を編集 ※ここが異なる
- lsblk で新しい UUIDを確認
- /etc/fstab を編集して 新しい UUID に変更
- GRUB設定とinitramfsの再作成 ※ここが異なる
- sudo mount /dev/nvme2n1p4 /mnt/dest
- sudo mount /dev/nvme2n1p3 /mnt/dest/boot
- sudo mount /dev/nvme2n1p2 /mnt/dest/boot/efi
- sudo mount --bind /dev /mnt/dest/dev
- sudo mount --bind /proc /mnt/dest/proc
- sudo mount --bind /sys /mnt/dest/sys
- sudo chroot /mnt/dest
- grub2-mkconfig -o /boot/grub2/grub.cfg
- dracut -f
- UUIDの確認(念のため) ※ここが異なる OK手順ではシンプル
- /boot/efi/EFI/redhat/grub.cfg のファイル確認
- /boot/grub2/grub.cfg のファイル確認
- exit (chrootを抜ける)
- lsblk
- blkid /dev/nvme2n1p3
- blkid /dev/nvme2n1p4
- ディスクの付け戻し ※ここが異なる OK手順ではシンプル
- sudo umount /mnt/dest/dev
- sudo umount /mnt/dest/proc
- sudo umount /mnt/dest/sys
- sudo umount /mnt/dest/boot/efi
- sudo umount /mnt/dest/boot
- sudo umount /mnt/dest
- EBSのデタッチとアタッチはOK手順と同じ
当初の手順でRHELの起動
❌ ブートで引っかかってログインできない状態になりました。
具体的には、大きく2つの問題が起こりました。
- GRUB メニューで複数のRHELバージョンの選択画面で引っかかる
- どこかに古い UUID を保持していて、それを参照してしまうためファイルシステムが見つからないというエラーになる
dracut-initqueue[411]: Warning: /lib/dracut/hooks/initqueue/finished/devexists-\x2fdev\x2fdisk\x2fby-uuid\x2【古いUUID】.sh: "if ! grep -q After=remote-fs-pre.target /run/systemd/generator/systemd-cryptsetup@*.service 2>/dev/null; then
dracut-initqueue[411]: [ -e "/dev/disk/by-uuid/【古いUUID】" ]
dracut-initqueue[411]: fi"
エラーの切り分け
複数のAIを利用して、切り分けを進めました。
- dracut のオプション調整
- grub2-mkconfig のオプション調整
- 同じコマンドのリトライ
- エマージェンシーモードでのリトライ
- /etc/default/grub の調査
- 古い UUID が埋め込まれていそうな場所の調査
他にもいろいろ試しましたが、解決に至りませんでした。
よって、UUID が合致している前提で dracut grub2-mkconfig を実施しない方法で進めることとして、最初のOKの手順が確立できました。
単一EBSに複数のファイルシステム
そもそも、/ と /log(/ 以外のユーザー用ファイルシステム) を 1 個の EBS にするという設計はどうなのでしょうか。
技術的には、以下の手順で構成可能です。
将来的に / を拡張したくなるかもしれません。
その場合、/log が続きのセクタに存在するため、EBSを拡張しても、growpart や xfs_growfs では / を拡張できない(はず)です。
OSの稼働に支障をきたすかもしれません。
最初のEBSはシステム領域専用にしておき、追加のファイルシステムはEBSを分ける、が良いでしょう。
あとがき
今回の検証では、UUID を変えた場合にログインプロンプトまで進む方法が見つけられませんでした。
簡単ではないから、「こうすればできる」というガイドが無いのかもしれませんね。
検証の流れは、GCE 永続ディスクの縮小リサイズは本当にできないのか?! の記事を大変参考にさせてもらいました。
ありがとうございました。


