🔝

【2025年版】EBSのルートボリュームを縮小する方法

に公開

【AWS】Amazon LinuxでEBSボリュームを縮小する手順

Amazon EC2では、EBSボリュームのサイズ拡張は簡単にできますが、縮小は直接行えません。どうしても縮小したい場合は、新しいボリュームを作成し、必要なデータを移行する必要があります。

この記事では、Amazon LinuxでEBSボリュームを縮小するための具体的な手順を紹介します。

🤔 背景

いつの間にか、社内AWS費用が高くなっていた...なんてことはないでしょうか。
調査してみると、ESB(サーバのストレージ)の容量が多く取得されていることが原因の一つに挙がってきました。

$ df -h
Filesystem      Size  Used Avail Use% Mounted on
devtmpfs        4.0M     0  4.0M   0% /dev
tmpfs           475M     0  475M   0% /dev/shm
tmpfs           190M  2.9M  188M   2% /run
/dev/xvda1      256G  9.2G  247G   4% /    ←★256GBあるが、ほどんど使っていない
tmpfs           475M     0  475M   0% /tmp
tmpfs            95M     0   95M   0% /run/user/1000

汎用 SSD (gp3)の料金は「USD 0.096/GB 月」です。
1USD=150円計算だと、16GBなら月額230円、256GBなら月額3,686円です。
ESBの料金はインスタンスが停止していても発生します。スナップショットに掛かる費用も当然増加します。
サーバ構築時にデータ量予測をしっかり立てていきたいですね。

🗺️ 縮小の戦略

データ領域をrsyncなどでコピーしただけでは、OSが起動しません。ブート領域も含めてコピーが必要です。また、データ整合性を保つため、縮小対象のディスクを使用しているインスタンスを停止して作業を行います。(スナップショットを作成しても良し)

  • 縮小対象のインスタンスを停止し、ボリュームをデタッチ
  • 縮小後のボリュームを新規作成
  • 作業用インスタンスを起動
  • 縮小対象ボリュームを/dev/xvdfにアタッチ、縮小後ボリュームを/dev/xvdgにアタッチ
    アタッチ先(/dev/xvdfとか)はどこでもいいですが、固定しておくとコマンドが使いまわせるのでおススメです。

✅ 前提条件

  • 対象はAmazon Linux
  • 作業用インスタンスを起動済み。t2.microで充分です
  • rootで作業を行う
  • 元のボリューム(例:/dev/xvdf)をアタッチ済み
  • 新しいボリューム(例:/dev/xvdg)を作成・アタッチ済み

lsblkすると、こんな感じ

確認
$ lsblk
NAME      MAJ:MIN RM  SIZE RO TYPE MOUNTPOINTS
xvda      202:0    0    8G  0 disk           ...1
├─xvda1   202:1    0    8G  0 part /
├─xvda127 259:0    0    1M  0 part 
└─xvda128 259:1    0   10M  0 part /boot/efi
xvdf      202:80   0  256G  0 disk           ...2
├─xvdf1   202:81   0  256G  0 part 
├─xvdf127 259:2    0    1M  0 part 
└─xvdf128 259:3    0   10M  0 part 
xvdg      202:96   0   16G  0 disk           ...3

1. 作業用インスタンスのボリューム
2. 縮小したい256GBボリューム(コピー元)
3. 縮小後の16GBボリューム(コピー先)

1. パーティションの作成

まず、縮小後に使う新しいボリューム(例:/dev/xvdg)にパーティションを作成します。
fdisk -> p -> qでコピー元ボリュームの状態を確認します。

確認
$ fdisk /dev/xvdf

Welcome to fdisk (util-linux 2.37.4).
Changes will remain in memory only, until you decide to write them.
Be careful before using the write command.


Command (m for help): p
Disk /dev/xvdf: 256 GiB, 274877906944 bytes, 536870912 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disklabel type: gpt                      ←★ディスクラベルタイプ
Disk identifier: 8880764D-1715-4E0B-97CD-61647DB0F4AE

Device       Start       End   Sectors  Size Type
/dev/xvdf1   24576 536870878 536846303  256G Linux filesystem
/dev/xvdf127 22528     24575      2048    1M BIOS boot
/dev/xvdf128  2048     22527     20480   10M EFI System

Partition table entries are not in disk order.

Command (m for help): q

ディスクラベルタイプがGPTであることと、3つのパーティションで構成されていることがわかります。

ディスクラベルタイプ
GPT
パーティション番号 サイズ タイプ
1 256GB ファイルシステム
127 1M BIOS boot
128 10M EFI System

コピー先も、同じ構成でパーティションを切っていきます。
fdisk で以下の操作を行います:

変更コマンド
$ fdisk /dev/xvdg

g         # GPTパーティションテーブルの作成

n         # 1つ目のパーティション作成
128       # パーティション番号
[Enter]   # 開始セクタ(自動)
+10M      # サイズ指定
t         # パーティションタイプ変更
1         # コード(EFI System)

n         # 2つ目のパーティション作成
127       # パーティション番号
[Enter]   # 開始セクタ(自動)
+1M       # サイズ指定
t         # タイプ変更
127       # パーティション選択
4         # コード(BIOS boot)

n         # 3つ目のパーティション(ファイルシステム用)
1         # パーティション番号
[Enter]   # 開始セクタ(自動)
[Enter]   # サイズ指定(残り全部)

w         # 保存して終了
実行結果
$ fdisk /dev/xvdg

Welcome to fdisk (util-linux 2.37.4).
Changes will remain in memory only, until you decide to write them.
Be careful before using the write command.

Device does not contain a recognized partition table.
Created a new DOS disklabel with disk identifier 0xd3a80fd6.

Command (m for help): g
Created a new GPT disklabel (GUID: 997B69CD-CDB3-FC4A-83A2-265F8F1FD10B).

Command (m for help): n
Partition number (1-128, default 1): 128
First sector (2048-33554398, default 2048): 
Last sector, +/-sectors or +/-size{K,M,G,T,P} (2048-33554398, default 33554398): +10M

Created a new partition 128 of type 'Linux filesystem' and of size 10 MiB.

Command (m for help): t
Selected partition 128
Partition type or alias (type L to list all): 1
Changed type of partition 'Linux filesystem' to 'EFI System'.

Command (m for help): n
Partition number (1-127, default 1): 127
First sector (22528-33554398, default 22528): 
Last sector, +/-sectors or +/-size{K,M,G,T,P} (22528-33554398, default 33554398): +1M

Created a new partition 127 of type 'Linux filesystem' and of size 1 MiB.

Command (m for help): t
Partition number (127,128, default 128): 127
Partition type or alias (type L to list all): 4

Changed type of partition 'Linux filesystem' to 'BIOS boot'.

Command (m for help): n
Partition number (1-126, default 1): 1
First sector (24576-33554398, default 24576): 
Last sector, +/-sectors or +/-size{K,M,G,T,P} (24576-33554398, default 33554398): 

Created a new partition 1 of type 'Linux filesystem' and of size 16 GiB.

Command (m for help): w
The partition table has been altered.
Calling ioctl() to re-read partition table.
Syncing disks.

再度ボリュームの構成を確認:

確認
$ lsblk
NAME      MAJ:MIN RM  SIZE RO TYPE MOUNTPOINTS
xvda      202:0    0    8G  0 disk 
├─xvda1   202:1    0    8G  0 part /
├─xvda127 259:0    0    1M  0 part 
└─xvda128 259:1    0   10M  0 part /boot/efi
xvdf      202:80   0  256G  0 disk 
├─xvdf1   202:81   0  256G  0 part 
├─xvdf127 259:2    0    1M  0 part 
└─xvdf128 259:3    0   10M  0 part 
xvdg      202:96   0   16G  0 disk 
├─xvdg1   202:97   0   16G  0 part     ★作成したパーティション
├─xvdg127 259:4    0    1M  0 part     ★作成したパーティション
└─xvdg128 259:5    0   10M  0 part     ★作成したパーティション

xdvg1,xdvg127,xdvg128のパーティションが作成できました。

2. ファイルシステムの作成

ファイルシステム用に作成したパーティション(/dev/xvdg1)をXFSでフォーマットします。

変更コマンド
$ mkfs.xfs -f -L "/" /dev/xvdg1
meta-data=/dev/xvdg1             isize=512    agcount=4, agsize=1047807 blks
         =                       sectsz=512   attr=2, projid32bit=1
         =                       crc=1        finobt=1, sparse=1, rmapbt=0
         =                       reflink=1    bigtime=1 inobtcount=1
data     =                       bsize=4096   blocks=4191227, imaxpct=25
         =                       sunit=0      swidth=0 blks
naming   =version 2              bsize=4096   ascii-ci=0, ftype=1
log      =internal log           bsize=4096   blocks=16384, version=2
         =                       sectsz=512   sunit=0 blks, lazy-count=1
realtime =none                   extsz=4096   blocks=0, rtextents=0

3. UUIDの確認

ここでファイルシステム用に作成したパーティション(/dev/xvdg1)のUUIDをメモしておきます。後ほどfstabに反映させます。

確認
$ blkid | sort
/dev/xvda127: PARTLABEL="BIOS Boot Partition" PARTUUID="e0313941-35e7-4973-ab5d-f0754ec3c4f5"
/dev/xvda128: SEC_TYPE="msdos" UUID="DED7-C018" BLOCK_SIZE="512" TYPE="vfat" PARTLABEL="EFI System Partition" PARTUUID="530085fb-f39d-4060-b126-251f6dde51e7"
/dev/xvda1: LABEL="/" UUID="b1e84820-06b0-4d3b-9b5d-edd836bd5895" BLOCK_SIZE="4096" TYPE="xfs" PARTLABEL="Linux" PARTUUID="efbbf2b4-45cf-491c-ab80-cfcffc2743c4"
/dev/xvdf127: PARTLABEL="BIOS Boot Partition" PARTUUID="f0fb8e58-7ba7-4a72-af46-2f60b7843650"
/dev/xvdf128: SEC_TYPE="msdos" UUID="91D7-D9DA" BLOCK_SIZE="512" TYPE="vfat" PARTLABEL="EFI System Partition" PARTUUID="3b99f0e9-e410-4353-a6a4-56ad71e34467"
/dev/xvdf1: LABEL="/" UUID="260bd470-a0f6-43ff-9f03-fee351c25cb3" BLOCK_SIZE="4096" TYPE="xfs" PARTLABEL="Linux" PARTUUID="d73e5c49-61fd-44a2-97b0-ff176cc70be9"
/dev/xvdg127: PARTUUID="53a1cec1-cf07-b940-a2cc-509f006876cc"
/dev/xvdg128: PARTUUID="9b7bd650-a94b-e84c-9e0d-377690d094cb"
/dev/xvdg1: LABEL="/" UUID="8d351996-caa9-4685-bdf7-9b03ee360c28" BLOCK_SIZE="512" TYPE="xfs" PARTUUID="d1164587-4269-7846-8de0-8f3cb62b0a30"

/dev/xvdg1のUUIDは8d351996-caa9-4685-bdf7-9b03ee360c28です。

4. データコピー

ボリュームの特定領域をコピー

BIOSとEFIのパーティションはサイズが小さいのでddコマンドでコピーします。

変更コマンド
$ dd if=/dev/xvdf127 of=/dev/xvdg127 bs=1M
1+0 records in
1+0 records out
1048576 bytes (1.0 MB, 1.0 MiB) copied, 0.0158905 s, 66.0 MB/s

$ dd if=/dev/xvdf128 of=/dev/xvdg128 bs=1M
10+0 records in
10+0 records out
10485760 bytes (10 MB, 10 MiB) copied, 0.0746474 s, 140 MB/s

マウントしてファイルを移動

次に、ファイルシステム領域をrsyncコマンドでコピーします。

変更コマンド
$ mkdir -p /mnt/new /mnt/old
$ mount /dev/xvdg1 /mnt/new
$ mount /dev/xvdf1 /mnt/old

$ rsync -aAXH --exclude={"/dev/*","/proc/*","/sys/*","/tmp/*","/run/*","/mnt/*","/media/*","/lost+found"} /mnt/old/ /mnt/new/ --log-file=/root/rsync-copy.log

SELinuxのファイルはPermissionがなくコピーできないと言われますが、気にせず大丈夫なようです。筆者の環境では今のところ支障ありません。

5. 起動設定

fstab を編集

/etc/fstabの内容を書き換えます。rsyncでコピーしたので、fstabもコピー元ボリュームの情報で上書きされてしまっています。
先ほどメモしておいたファイルシステム用パーティション(/dev/xvdg1)のUUIDを設定します。

変更コマンド
$ vi /mnt/new/etc/fstab

<変更前>
#
UUID=260bd470-a0f6-43ff-9f03-fee351c25cb3     /           xfs    defaults,noatime  1   1
UUID=91D7-D9DA        /boot/efi       vfat    defaults,noatime,uid=0,gid=0,umask=0077,shortname=winnt,x-systemd.automount 0 2

↓
<変更後>
#
UUID=8d351996-caa9-4685-bdf7-9b03ee360c28     /           xfs    defaults,noatime  1   1
UUID=91D7-D9DA        /boot/efi       vfat    defaults,noatime,uid=0,gid=0,umask=0077,shortname=winnt,x-systemd.automount 0 2

chroot 環境を作成し、GRUBの再構成とインストール

変更コマンド
$ mount --bind /dev /mnt/new/dev
$ mount --bind /proc /mnt/new/proc
$ mount --bind /sys /mnt/new/sys
$ chroot /mnt/new

$ grub2-mkconfig -o /boot/grub2/grub.cfg
Generating grub configuration file ...
done
$ cat /boot/grub2/grub.cfg | grep UUID
  set kernelopts="root=UUID=8d351996-caa9-4685-bdf7-9b03ee360c28 ro  console=tty0 console=ttyS0,115200n8 nvme_core.io_timeout=4294967295 rd.emergency=poweroff rd.shell=0 selinux=1 security=selinux quiet"
$ grub2-install /dev/xvdg
Installing for i386-pc platform.
Installation finished. No error reported.
$ exit

6. 後片付け

$ umount /mnt/new/dev
$ umount /mnt/new/proc 
$ umount /mnt/new/sys 
$ umount /mnt/new
$ umount /mnt/old

🔥 起動確認

  1. 作業用インスタンスから縮小後ボリュームをデタッチし、移行元インスタンスのルートボリューム(/dev/xvda)にアタッチします。
  2. インスタンスを起動します。無事起動すれば完了です!

🎉 まとめ

新しいEBSボリュームに必要なパーティションとデータを再構成することで、間接的にEBSボリュームを縮小できます。縮小したい理由(コスト削減など)がある場合は、この方法を試してみてください!

とはいえ、ボリュームをごっそり入れ替えるという荒業であるため、慎重に検討してください。
使用するコマンドもFromとToを間違えると大変なことになるものばかりです。
このような危険な操作をしなくても済むよう、サーバ構築時にデータ量予測をしっかり立てていきたいですね(2回目)。

🐍 蛇足

パーティション数の違いについて

今回、題材としている元ボリュームはパーティションが3つありましたが、
2年前ぐらいに構築したサーバはファイルシステムとBIOSの2パーティションでした。
その場合、EFIのパーティション作成およびddコマンドによるコピーは不要です。

ボリュームサイズを小さくしすぎた場合に備えて、ボリュームを拡張する手順

  1. AWSコンソールでボリュームのサイズを変更
  2. 次のコマンドを実行
変更コマンド
$ sudo growpart /dev/xvda 1
$ sudo xfs_growfs /
  1. df -hコマンドで確認

あとがき

本記事が多くの人の財布を救うことを祈っております!

YTT LINKS株式会社では一緒に働くメンバーを募集しております。LINKS(人とのつながり)を大切に、エンジニアの可能性を証明し、世界規模で世の中の課題解消ができるエンジニアを育成します。
https://yttlinks.co.jp

Discussion