職業プログラマの休日出勤

職業プログラマによる日曜自宅プログラミングや思考実験の成果たち。リアル休日出勤が発生すると更新が滞りがちになる。記事の内容は個人の意見であり、所属している(いた)組織の意見ではない。

c3シリーズでswap

明けましておめでとうございます。今年もよろしくお願いします。

さて、早速ですが。
AWSで様々なアプリケーションを動かしていると、普段は c3/c4 シリーズに適した使い方なんだけども稀に大量のメモリを一度に使うことがある、というものに出くわすことがあります。
このような状況ではswap(仮想メモリ)の仕組みが動いていると非常に効果的なのですが、デフォルトではオフになっています。c3/c4シリーズを使う上では通常は後継のc4を使うのが筋なのでしょうけれども、swap領域として使用するストレージは、c3シリーズのみに提供されるインスタンスストアを使うのが気持ちイイです。
この記事では、今更ながら、c3でswap領域を確保する手順を確認します。
※この記事は 第67回 紅白歌合戦 を視聴しながら書きました。

環境情報

インスタンスのlaunch

インスタンスをlaunch(作成)する際は必ず、インスタンスストアを使う宣言をするのを忘れないようにします。デフォルトでは使われません。
Management Console で言うと、この画面ですね。「Add New Volume」ボタンがミソです。
f:id:t_motooka:20170101004135p:plain

まずは負荷テスト環境の整備

指定した量のメモリを確保するには、stress コマンドが便利です。
stressコマンドは標準のyumリポジトリからインストールが可能です。

$ sudo yum install stress
メモリを確保する


$ stress --vm 1 --vm-bytes 2G --vm-keep --timeout 60s
ここで指定しているオプションの意味は以下のような感じです。

  • 1つのプロセスで(--vm 1)、
  • 2GBytesのメモリを確保し(--vm-bytes 2G)、
  • メモリの確保&解放を繰り返さずに確保しっぱなしにして(--vm-keep)、
  • 実行開始から60秒経過したら終了(--timeout 60s

詳しいオプションの説明はmanを見るか、 stress(1): impose load on/stress test systems - Linux man page あたりが参考になるでしょう。

初期状態のマシンで 4GB のメモリを確保

次のコマンドを実行すると 4GBytes のメモリの確保を試みます
$ stress --vm 1 --vm-bytes 4G --vm-keep --timeout 60s
しかし、c3.large が搭載しているメモリは 3.75 GBytes ですので、これは次のようなエラーになります。

stress: info: [2823] dispatching hogs: 0 cpu, 0 io, 1 vm, 0 hdd
stress: FAIL: [2824] (494) hogvm malloc failed: Cannot allocate memory
stress: FAIL: [2823] (394) <-- worker 2824 returned error 1
stress: WARN: [2823] (396) now reaping child worker processes
stress: FAIL: [2823] (451) failed run completed in 0s

これからswapの設定をする訳ですが、同じ操作をしてエラーにならなければ、正常に設定できていることの確認になると言えます。

インスタンスストア1基丸々swapにする

通常は、AWSの公式マニュアルに沿った操作をするのが良いでしょう。
Instance Store Swap Volumes - Amazon Elastic Compute Cloud
コマンドだけ挙げると

# 確認用
$ swapon -s
$ lsblk

# インスタンスストアのswap用初期化
# ※c3.large に「普通に」インスタンスストアを付けると /dev/xvdb と /dev/xvdc になる。ここでは xvdb を使っている
$ sudo mkswap /dev/xvdb

# swapとして利用開始する
$ sudo swapon /dev/xvdb
OS再起動に耐える設定にする

reboot(OS再起動)すると、上記の「swapとして利用開始する」のところだけ忘れ去られてしまいますので、fstabの設定を入れておくと起動時に再設定することができます。
fstab設定内容は前述のマニュアルを見るのが良いでしょう。
※後述の設定をする場合はfstabの設定は不要です。

stop / start に耐える設定にする

stop / start すると、インスタンスストアの中身は忘却の彼方へと消え去ってしまいます(当然ですね)ので、上記の「インスタンスストアのswap用初期化」のところからやり直しになります。
start時にこれらの作業を自動で実施させるには、/etc/rc.local を使うのが便利です。
末尾に mkswapswapon を仕込みましょう。
設定後は次のような状態になりました。

$ cat /etc/rc.local
#!/bin/sh
#
# This script will be executed *after* all the other init scripts.
# You can put your own initialization stuff in here if you don't
# want to do the full Sys V style init stuff.

touch /var/lock/subsys/local

mkswap /dev/xvdb
swapon /dev/xvdb

なお、この設定が存在するとき、stop / start ではなくて reboot を実施したときに mkswap がエラーを吐きます。既に設定済みであるからです。神経質な方は他の手法を探しましょう。

Immutable Infrastructure として捉えた設定

一度 launch したインスタンスは stop することなく、利用停止時は terminate される、という前提を持ち込むと、これらの mkswapswapon/etc/rc.local ではなく cloud-init などの仕組みに乗せるのが便利でしょう。

swap確保後のメモリ確保テスト

topコマンドを別端末で動かしながら $ stress --vm 7 --vm-bytes 2G --vm-keep のように 14GBytes のメモリを確保しようとしても、(数十秒かかりますけれども)落ちずに頑張ってくれます。
これなら気持ち良く新年を迎えることができますね!

今年もメモリ負荷なんかに負けない、良い一年でありますように。