【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
🔥 起動確認
- 作業用インスタンスから縮小後ボリュームをデタッチし、移行元インスタンスのルートボリューム(/dev/xvda)にアタッチします。
- インスタンスを起動します。無事起動すれば完了です!
🎉 まとめ
新しいEBSボリュームに必要なパーティションとデータを再構成することで、間接的にEBSボリュームを縮小できます。縮小したい理由(コスト削減など)がある場合は、この方法を試してみてください!
とはいえ、ボリュームをごっそり入れ替えるという荒業であるため、慎重に検討してください。
使用するコマンドもFromとToを間違えると大変なことになるものばかりです。
このような危険な操作をしなくても済むよう、サーバ構築時にデータ量予測をしっかり立てていきたいですね(2回目)。
🐍 蛇足
パーティション数の違いについて
今回、題材としている元ボリュームはパーティションが3つありましたが、
2年前ぐらいに構築したサーバはファイルシステムとBIOSの2パーティションでした。
その場合、EFIのパーティション作成およびdd
コマンドによるコピーは不要です。
ボリュームサイズを小さくしすぎた場合に備えて、ボリュームを拡張する手順
- AWSコンソールでボリュームのサイズを変更
- 次のコマンドを実行
$ sudo growpart /dev/xvda 1
$ sudo xfs_growfs /
-
df -h
コマンドで確認
あとがき
本記事が多くの人の財布を救うことを祈っております!
YTT LINKS株式会社では一緒に働くメンバーを募集しております。LINKS(人とのつながり)を大切に、エンジニアの可能性を証明し、世界規模で世の中の課題解消ができるエンジニアを育成します。
Discussion