EC2(Ubuntu 22.04)のルートボリュームを縮小する
拡大するのは一瞬のくせに縮小はやたら手間がかかりますね。
備忘録として記述します。
対象のインスタンス情報
- Ubuntu 22.04.2 LTS
- インスタンスサイズ
t2.medium
記事内ではこのインスタンスを 🔵instance-original、それに紐付いているルートボリュームを🔵volume-original と呼ぶ事にします
手順
今回は250GBのルートボリュームを50GBまで減らすものとします。
ボリューム自体のサイズ縮小は出来ないので、新しくボリュームを作ってそこに全てのデータを載せ替えて、そのボリュームをルートボリュームとしてアタッチしてあげる事にします
⚠ 記事内で新しく作るインスタンスは全て🔵instance-originalと同じアベイラビリティーゾーンに作成してください。
1. 新しいボリュームを拵える
普通にボリュームを作ると、パーティション云々も自前で設定しないといけなくて面倒なので、🔵instance-originalと同じスペックのインスタンスを立ち上げて、すぐにインスタンスを停止、そのインスタンスのルートボリュームをデタッチする形で用意します。
この時、ボリュームサイズは縮小後の目標である50GBを選択します
これを 🟢volume-new という名前ラベルを付けて取っておきます。
インスタンス自体はもう使わないので、ボリュームを剥ぎ取れたら終了してしまっても大丈夫です。
2. データ同期元ボリュームを作る
🔵volume-original のスナップショットを取り、そのスナップショットから🟣volume-snapshotとして新規ボリュームを作成します。
3. 作業用インスタンスの作成
これからボリューム感のデータ同期などを行っていきますが、稼働中の🔵instance-originalの中でやるのもアレなので、作業用のインスタンスだけ立てておきます
🔵instance-originalと同じアベイラビリティーゾーンであれば、スペックは最小限でも大丈夫です
4. 作業用インスタンスにボリュームをアタッチ
🟢volume-new を作業用インスタンスにデバイス名/dev/sdf
としてアタッチ
🟣volume-snapshot を作業用インスタンスにデバイス名/dev/sdg
としてアタッチ
そして作業用インスタンスを再起動します
インスタンス内で lsbk -f
打つとこんな感じになってるはずです
xvda
├─xvda1 ext4 1.0 cloudimg-rootfs 4f575094-453e-450d-aeed-215d8cbcbf58
├─xvda14
└─xvda15 vfat FAT32 UEFI 60A8-A611
xvdf
├─xvdf1 ext4 1.0 cloudimg-rootfs 4f575094-453e-450d-aeed-215d8cbcbf58
├─xvdf14
└─xvdf15 vfat FAT32 UEFI 60A8-A611
xvdg
├─xvdg1 ext4 1.0 cloudimg-rootfs 4513eb34-58e6-408e-8ed7-3d487fe6b35b
├─xvdg14
└─xvdg15 vfat FAT32 UEFI 6192-5E23
※ AWSの操作では /dev/s*
というデバイス名でアタッチしましたが、それらはここでは /dev/xv*
として扱われます
5. 新ボリュームにデータを同期する
まずは各デバイスをマウントしていきます
$ sudo mkdir /mnt/snapshot
$ sudo mkdir /mnt/new
$ sudo mount -t ext4 /dev/xvdg1 /mnt/snapshot
$ sudo mount -t ext4 /dev/xvdf1 /mnt/new
rsyncで同期します。 (swapfileがなんか重かったので一旦除外してます。入れ替え後作り直せばいいでしょう)
$ sudo rsync -aAXv /mnt/snapshot/ /mnt/new/ --progress --exclude swapfile
6. 起動に必要な設定を書き換える
まず、rsyncの時点でswapfileを除外していた場合 /mnt/new/etc/fstab
のswapfileの行を消しておきます。
次にgrub.cfg
を書き換えます。
Ubuntu22.04のインスタンスではUUIDではなくPARTUUIDでデバイスを指定して起動しているようなので、これらを書き換えます。
# 🟣volume-snapshotのPARTUUIDを確認
$ blkid | grep '/dev/xvdg1'
/dev/xvdg1: LABEL="cloudimg-rootfs" UUID="....." BLOCK_SIZE="4096" TYPE="ext4" PARTUUID="{ここの値}"
# 🟢volume-newのPARTUUIDを確認
$ blkid | grep '/dev/xvdf1'
/dev/xvdg1: LABEL="cloudimg-rootfs" UUID="....." BLOCK_SIZE="4096" TYPE="ext4" PARTUUID="{ここの値}"
$ sudo sed -i -e 's/🟣のPARTUUID/🟢のPARTUUID/g' /mnt/new/boot/grub/grub.cfg
また、上記の出力例ではどちらのデバイスもLABEL
はcloudimg-rootfs
で一致していますが、ここがズレている場合、🟢volume-new側を🟣volume-snapshot側に合わせてください
$ sudo e2label /dev/xvdf1 cloudimg-rootfs
8. アンマウント & デタッチ
データの同期処理などが終わったので、アンマウントします
$ sudo umount /mnt/new
$ sudo umount /mnt/snapshot
そして、作業用インスタンスを停止し、🟢volume-newと🟣volume-snapshotをデタッチします。
9. 新ボリュームをアタッチ
まず 🔵instance-original を停止し、🔵volume-original をデタッチし、代わりに🟢volume-newを /dev/sda1
としてアタッチします。
これでインスタンスが起動できれば完了です
df -H
等で確認すると目標の50GBになっているはずです
備考
- 稼働中のインスタンスのダウンタイムは数分で済みますが、手順の2~9を行っている間に 🔵instance-original内で起こった変更差分は手順9のタイミングで全て消えてしまうので、インスタンス内のファイルが高頻度で更新されるようなアプリケーションが運用されてる場合は一度停止しておくと良さそうです
- 問題なく起動できてデータの破損がないことも確認できたら、🟣volume-snapshotと🔵volume-originalは削除しちゃってOKです
Discussion