AWS EC2 インスタンスに swap 領域を作成する
はじめに
世の中世知辛いのでデータ分析のためにひとつの EC2 インスタンスを複数人で一緒に使ったりするんだけどメモリが枯渇して Jupyter のカーネルがクラッシュする。そんな悲しい出来事があったんだ。
g4dn.xlarge
くらいのインスタンスでもメモリは 16GB で複数人で深層学習用のデータを愚直にロードした日には一発でクラッシュする。Swap 領域があればまぁ遅くはなるけど死にはしないのに[1]。
他のアプリケーション用のサーバーとして立てるときにも安全マージンとして swap 領域を確保しておくと想定外の負荷がかかってもプログラムのクラッシュは防ぐことができる。
というわけで EC2 インスタンスに swap 領域を設定する方法を説明する。
参考文献
- 『第15章 swap 領域』 Red Hat Customer Portal
- 『How to create a Swap partition on your EC2 Instance』 Rahul
- 『スワップ領域の追加方法』
- 『swap ファイルをswapon するとエラーになる。(btrfs)』 takuya (id:takuya_1st)
- 『Swapfile』 BTRFS
- 『ループバック・デバイス』 麻生 二郎 日経Linux
- 『losetupコマンドの使い方』 hana_shin (id:hana_shin)
- 『fstab(5) — Linux manual page』
作業手順概要
ほとんど『How to create a Swap partition on your EC2 Instance』に書いてある手順に従えばよいです。ただし、EC2 で使用しているファイルシステムのフォーマットが ext4
でない場合は愚直にやると swapon
コマンドが失敗するので、ファイルシステムに適したやり方で swap ファイルを作成する必要があります。
1. Swap 領域の確認
既に swap 領域があれば誰かが作っているということなので管理者に聞いたほうがよいでしょう。以下のコマンドを実行して swap ファイルまたは swap パーティションが表示されれば、既に swap 領域が存在します。
$ sudo swapon -s
2. Swap 領域のサイズを決める
Swap 領域のサイズをどれくらいにするかは用途によりますが、一般的に swap 領域は物理メモリと同等以上のサイズで確保するというルールがあるそうです。以下のコマンドを実行するとインスタンスの RAM のサイズが MB 単位で表示されます。
$ free -m
『How to create a Swap partition on your EC2 Instance』では、必要なサイズを計算するには単純に RAM のサイズを2倍すればよい、と述べられています(その前には「最低でも同じだけ用意する」と言っていたのになぜ2倍にするのかは不明です)。
3. ファイルシステムを確認する
Swap 領域を作成するストレージのファイルシステムによって、作成方法が微妙に異なります。以下のコマンドで swap 領域を作成したディスクの Type を確認してください。
$ df -Th
上記コマンドの出力はあまり晒すものではないので載せませんが、私は /
直下に作成することにしたので、そちらをあらためて確認します。
$ df -Th /
Filesystem Type Size Used Avail Use% Mounted on
/dev/nvme0n1p1 xfs 100G 50G 51G 50% /
4. Swap ファイルを作成する
先ほど調べた Type によって swap ファイルの作成方法が微妙に違うので、参照する参考文献を変えてください。「XFS swap」 などで検索すればやり方が出てきますが、調べるのが面倒くさいという方は以下の表を参考にしてください。
ファイルシステム | 参考 |
---|---|
ext4 |
『How to create a Swap partition on your EC2 Instance』 |
btrfs |
『Swapfile』 |
xfs |
『スワップ領域の追加方法』 |
以降はもっとも順当に進む ext4
における方法に則りますが、btrfs
と xfs
における条件分岐も含みます。
ext4 の場合
Swap 領域となるファイルを fallocate
コマンドで作成します。以下のコマンドは 2GB の /swapfile
という名前のファイルを作成します。
$ sudo fallocate -l 2G /swapfile
btrfs の場合
fallocate
の前にコマンドが2つ追加されるようです。今回、btrfs
では検証していないのでこれらのコマンドを追加しなかった場合にどうなるかは知りません。
$ sudo truncate -s 0 /swapfile
$ sudo chattr +C /swapfile
$ sudo fallocate -l 2G /swapfile
xfs の場合
ファイルシステムが XFS の場合、fallocate
で作成したファイルは領域を予約するのみで物理領域に紐づいていないためか、後の swapon
コマンドを実行したときにエラーになります。
エラーを回避する方法は
-
dd
コマンドで実体を伴う/swapfile
を作成する -
/swapfile
をループバックデバイスとして登録する
の2つがあります。
dd
コマンドで実体を伴う /swapfile
を作成する
1. 前者は "Disk Destroyer" として悪名高い dd
コマンドを使う方法で、ブロックサイズ bs
が何個分 count
かを指定してファイルを作成します。以下のコマンドは 2GB の swap ファイルを作成します。タイプミスで簡単にディスクのデータを消し飛ばすので実行する前に5回はチェックしてください[2]。
$ sudo dd if=/dev/zero of=/swapfile bs=1M count=2048
/swapfile
をループバックデバイスとして登録する
2. 後者は『swap ファイルをswapon するとエラーになる。(btrfs)』にて BTRFS が swap ファイルに対応する以前[3]の BTRFS における対処法として紹介されていたもので、XFS でも通用することは確認しましたが、使用していて問題が起こるかどうかは知りません。問題が起こらないという確証があるなら dd
を使うよりも安全だと思います(のであったらご教示いただけると幸いです)。
こちらの方法でやる場合は『7. Swap ファイルを loop デバイスとして登録する』の手順を追加で行う必要があります。
5. 権限設定
ここからの手順は共通です。
Swap ファイルの権限は 644
または 600
が推奨されています。特に理由がなければ root 以外のユーザーにアクセスを許す必要はないので権限は 600
に設定します。
$ sudo chmod 600 /swapfile
Swap ファイルは swap ファイル用にフォーマットされている必要があるので、以下のコマンドで swap ファイルとしての形式にします。
$ sudo mkswap /swapfile
6. Swap 領域を有効化する
運がよければ、あとは以下のコマンドを実行するだけで swap 領域として有効化されます。
$ sudo swapon /swapfile
エラーが出なければおそらく成功しているので、top
コマンドなどで swap 領域が追加されていることを確認します。成功していれば『6. Swap 領域を永続化する』に進んでよいです。
私がやったときはファイルシステムが XFS で fallocate
を使って swap ファイルを作成していたため以下のようなエラーが出ました。
swapon: /swapfile: swapon failed: Invalid argument
情報が少なすぎてよく分かりません。他の原因で同じエラーが出るかもしれませんが、その場合はどうにかしてご自身で調べてもらうしかありません。
XFS で fallocate
を使っている場合は次の『7. Swap ファイルを loop デバイスとして登録する』の手順を追加します。
7. Swap ファイルをループバックデバイスとして登録する
ファイルをループバックデバイスとしてマウントすると、そのファイルをあたかもブロックデバイスであるかのように扱うことができます。要するにファイルを論理ボリュームのように扱うことができます。
まずはループバックデバイスとして登録されているファイルを確認します。実行結果は示しません。
$ sudo losetup -l
確認したら、以下のコマンドで /swapfile
を新規のループバックデバイスとしてマウントします。名前は自動で割り当てられます。
$ sudo losetup -f /swapfile
成功したら以下のコマンドで /swapfile
が追加されていることを確認してください。
$ sudo losetup -l
ここでは /swapfile
が /dev/loop0
という名前でマウントされていたとします。/swapfile
の代わりに /dev/loop0
を swap 領域として有効化してください。
$ sudo swapon /dev/loop0
8. Swap 領域を永続化する
Swap 領域のマウントは再起動する度にリセットされてしまうので、/etc/fstab
にマウント設定を書いておくことで毎回の起動時に自動でマウントすることができます。適当なエディタで /etc/fstab
を開いてください。
$ sudo nano /etc/fstab
そして以下の1行を追加してください(ループバックデバイスの設定をしている場合は /swapfile
を /dev/loop0
などに置き換えてください)。
/swapfile swap swap defaults 0 0
上記のレコードは『How to create a Swap partition on your EC2 Instance』からのコピペなので、それぞれのフィールドが何を意味しているのか気になる人は『fstab(5) — Linux manual page』を確認してください。
Man-page によれば swap 領域のレコードの場合、第2フィールドは none
にすべき、と書いてあるので
/swapfile none swap defaults 0 0
が正しい気がしますが、他の人の設定を見ても第2フィールドを swap
にしている人も多いようなので、まぁ動くのでしょう。気が向いたらあとで実験してみます。
9. Swap 領域を無効化&削除する
インスタンスをアップグレードするなどして swap 領域がいらなくなる場合や作り直したい場合があるでしょうから、swap 領域を削除する方法についても書いておきます。
Swap 領域を無効化したい場合は有効化したときの手順を逆に辿ります。まずは /etc/fstab
から swap 領域について記述したレコードを削除します。
$ sudo nano /etc/fstab
次に swap 領域を無効化します(ループデバイスで設定している場合は /swapfile
を /dev/loop0
などで置き換えてください)。
$ sudo swapoff -v /swapfile
ループデバイスで設定している場合はループデバイスのマウントを解除してください。
$ sudo losetup -d /dev/loop0
最後に swap 領域の実体である /swap
を削除してください。
$ sudo rm -f /swapfile
おしまい
イ ン ス タ ン ス を 立 て る 権 限 を 寄 越 せ。
-
Swap 領域を確保しても GPU 側のメモリは増えないので、GPU を用いた学習や推論を同時にできる人数が増えるわけではないが、その他諸々の CPU を使う作業であれば swap 領域の恩恵を受けることができる。インスタンスをアップグレードするまでの暫定的な措置としては十分に機能するだろう。 ↩︎
-
自らの不注意でディスクの重要なデータを取り返しがつかないほど破壊したことがある人間とそうでない人間では覚悟のキマり方が一線を画しています。まだ消し飛ばしたことがない人はよい経験になると思いますので
$ sudo dd if=/dev/zero of=/ bs=1M count=2048
を実行してみてもよいでしょう。このコマンドを実行して発生したいかなる損害についても私は責任取りません。実行した場合はこの免責事項に同意したものとみなします。それでもいいという人はおいで。「こ ち ら 側」に。 ↩︎ -
BTRFS は Linux kernel 5.0 で swap ファイルに対応。 ↩︎
Discussion