📉

EC2(Ubuntu 22.04)のルートボリュームを縮小する

2023/10/27に公開

拡大するのは一瞬のくせに縮小はやたら手間がかかりますね。
備忘録として記述します。

対象のインスタンス情報

  • 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

また、上記の出力例ではどちらのデバイスもLABELcloudimg-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