Amazon EC2(Linux)のswap自動作成を行うRPMパッケージ ec2-swap を作ってみた

AWS

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

ども、大瀧です。
前回のブログエントリーで、「EC2のswap領域は起動時にインスタンスストア上に作るといいよ!ただしインスタンスストア既定のファイルシステムはオススメできなくて、その辺ごにょごにょ実装してね☆」という、微妙にイケてないベストプラクティスを提言してみました。「なんだよ、簡単にできるんじゃないのかよっ!」とご立腹の方もいるかもしれません。アンサーブログとまでは言いませんが、簡単にその辺りの機能を実装するRPMパッケージ ec2-swap を作ってみたので、使い方と仕組みをご紹介します。

動作確認環境

  • Amazon Linux AMI 2013.09.2 - ami-0d13700c (64-bit)

ロードマップとしては、CentOSとRHEL AMIを近日中に動作確認、aptリポジトリの作り方がわかればUbuntu(debパッケージ)向けに対応していきたいです。(小声で)

使い方

EC2インスタンスの起動

起動ウィザードの中で、インスタンスストアを追加しましょう *1。(t1.microにはインスタンスストアが付かないので、swapファイルがルートボリュームに作成されます)複数ボリュームを設定する場合は、ephemeral0にswapファイルが作成されます。後述の設定ファイルで変更可能です。

ec2-swap01-2

ec2-swapパッケージのインストールと再起動

最短で実行するべきコマンドを以下にリストします。

sudo rpm -ivh http://repo.classmethod.info/yum/x86_64/cm-repo-release-0.1.0-1.noarch.rpm
sudo yum install -y ec2-swap
sudo reboot

それぞれ解説していきます。ec2-swapパッケージを提供するyumリポジトリを公開しているので、リポジトリファイル(http://repo.classmethod.info/yum/x86_64/cm-repo-release-0.1.0-1.noarch.rpm)をrpmコマンドで追加します。

[ec2-user@ip-XX-XX-XX-XX ~]$ sudo rpm -ivh http://repo.classmethod.info/yum/x86_64/cm-repo-release-0.1.0-1.noarch.rpm
http://repo.classmethod.info/yum/x86_64/cm-repo-release-0.1.0-1.noarch.rpm を取得中
準備しています...              ################################# [100%]
更新中 / インストール中...
   1:cm-repo-release-0.1.0-1          ################################# [100%]
   

これでec2-swapパッケージをyumコマンドサーチできるようになるので、インストールします。

[ec2-user@ip-XX-XX-XX-XX ~]$ sudo yum install ec2-swap
読み込んだプラグイン:priorities, update-motd, upgrade-helper
依存性の解決をしています
--> トランザクションの確認を実行しています。
---> パッケージ ec2-swap.noarch 0:0.1.0-1 を インストール
--> 依存性解決を終了しました。

依存性を解決しました

====================================================================================================================================================================================================================
 Package                                            アーキテクチャー                                 バージョン                                         リポジトリー                                           容量
====================================================================================================================================================================================================================
インストール中:
 ec2-swap                                           noarch                                           0.1.0-1                                            classmethod                                           2.6 k

トランザクションの要約
====================================================================================================================================================================================================================
インストール  1 パッケージ

総ダウンロード容量: 2.6 k
インストール容量: 1.2 k
Is this ok [y/d/N]: y
Downloading packages:
ec2-swap-0.1.0-1.noarch.rpm                                                                                                                                                                  | 2.6 kB     00:00
Running transaction check
Running transaction test
Transaction test succeeded
Running transaction
  インストール中          : ec2-swap-0.1.0-1.noarch                                                                                                                                                             1/1
  検証中                  : ec2-swap-0.1.0-1.noarch                                                                                                                                                             1/1

インストール:
  ec2-swap.noarch 0:0.1.0-1

完了しました!
[ec2-user@ip-XX-XX-XX-XX ~]$ 

ec2-swapサービスが追加されました!sudo rebootなどでLinuxを再起動すると、以降毎回インスタンスのメモリサイズに合わせた/media/ephemeral0/swap.imgファイルが作成、swaponされます。

設定は、/etc/sysconfig/ec2-swapにあります。インスタンスストアやスワップファイル名は、お好みで変更しましょう。

INSTANCEVOL_VIRTNAME=ephemeral0                     # インスタンスストア名
INSTANCEVOL_MOUNTPOINT=/media/$INSTANCEVOL_VIRTNAME # インスタンスストアのマウントポイント
SWAPFILENAME=$INSTANCEVOL_MOUNTPOINT/swap.img       # スワップファイル名

注意点

  • OSのマウント設定(/etc/fstab)に、本swap設定は載りません。
  • インスタンスストアの一部をswapファイルで消費することになるので、それ以外のデータの総容量はインスタンスストア - swapファイルの大きさに制限されます。
  • インスタンスストアをext4にmkfsしたあとマウントするため、インスタンスストア既定のext3に依存するような処理はエラーになるかもしれません。 *2
  • m1.smallもしくはc1.mediumの場合は元々自動で付与されるインスタンスストアスワップボリュームも追加されるため、swapサイズの合計は900MBほど推奨よりも大きくなります。

仕組み

/etc/rc.d/init.d/ec2-swapファイルのstart処理に全部突っ込んでいる、シェルスクリプトのみの極めてシンプルな実装です。cloud-initがマウントする前(起動順20)に、インスタンスストアをext4でmkfsしています。

/etc/rc.d/init.d/ec2-swap

#!/bin/bash
#
# Init file for ec2-swap
#
# chkconfig: 2345 20 20
# description:  ec2-swap is to create swapon swap image on EC2 instance store
#

# source function library
. /etc/rc.d/init.d/functions
. /etc/sysconfig/ec2-swap

RETVAL=0

start() {
	# get ephemeral disk device name by EC2 meta-data server
	INSTANCEVOL_REALNAME=/dev/`curl -s 169.254.169.254/latest/meta-data/block-device-mapping/$INSTANCEVOL_VIRTNAME`
	# get memory capacity
	MEMSIZE=`cat /proc/meminfo | grep MemTotal | awk '{print $2}'`

	# determine swap file size from memory capacity according to below URL
        # https://access.redhat.com/site/documentation/en-US/Red_Hat_Enterprise_Linux/6/html/Installation_Guide/s2-diskpartrecommend-x86.html
	if [ $MEMSIZE -lt 2097152 ]; then
	  SIZE=$((MEMSIZE * 2))k
	elif [ $MEMSIZE -lt 8388608 ]; then
	  SIZE=${MEMSIZE}k
	elif [ $MEMSIZE -lt 67108864 ]; then
	  SIZE=$((MEMSIZE / 2))k
	else
	  SIZE=4194304k
	fi

	# create mount point if it is not exist.
	if [ ! -d $INSTANCEVOL_MOUNTPOINT ]; then
	  mkdir $INSTANCEVOL_MOUNTPOINT
	fi

	# disable ephemeral disk mount entry by cloud-init
	sed -i 's/\(^.*'$INSTANCEVOL_VIRTNAME'.*$\)/#\1/' /etc/fstab

	# unmount, mkfs and mount ephemeral disk to execute fallocate
	if cat /proc/mounts | grep $INSTANCEVOL_MOUNTPOINT; then
		umount $INSTANCEVOL_MOUNTPOINT
	fi
	mkfs  -t ext4 $INSTANCEVOL_REALNAME
	mount -t ext4 $INSTANCEVOL_REALNAME $INSTANCEVOL_MOUNTPOINT

	# create and enable swap file
	fallocate -l $SIZE $SWAPFILENAME && mkswap $SWAPFILENAME && swapon $SWAPFILENAME
}

stop () {
	:
}

case "$1" in
        start)
                start
                ;;
        stop)
                ;;
        *)
                echo $"Usage: $0 {start}"
                RETVAL=1
esac
exit $RETVAL

Pull Request待ってます!

パッケージの元のソースファイルはGitHubで管理していますので、改善要望などはPull RequestやIssueを上げていただけると助かります!

まとめ

パッケージであれば、swap導入の敷居をぐっと下げられるのではないでしょうか。ご活用ください!

参考資料

脚注

  1. デバイス名はサービス実行時に動的に取得するため、/dev/sdb以外でも構いません。
  2. ext4はext3の上位互換のため、問題になることはほとんど無いと思いますが。