🫡

AWS EC2 インスタンスに swap 領域を作成する

2023/09/20に公開

はじめに

世の中世知辛いのでデータ分析のためにひとつの EC2 インスタンスを複数人で一緒に使ったりするんだけどメモリが枯渇して Jupyter のカーネルがクラッシュする。そんな悲しい出来事があったんだ。

g4dn.xlarge くらいのインスタンスでもメモリは 16GB で複数人で深層学習用のデータを愚直にロードした日には一発でクラッシュする。Swap 領域があればまぁ遅くはなるけど死にはしないのに[1]

他のアプリケーション用のサーバーとして立てるときにも安全マージンとして swap 領域を確保しておくと想定外の負荷がかかってもプログラムのクラッシュは防ぐことができる。

というわけで EC2 インスタンスに swap 領域を設定する方法を説明する。

参考文献

作業手順概要

ほとんど『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 /
output
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 における方法に則りますが、btrfsxfs における条件分岐も含みます

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 コマンドを実行したときにエラーになります。

エラーを回避する方法は

  1. dd コマンドで実体を伴う /swapfile を作成する
  2. /swapfile をループバックデバイスとして登録する

の2つがあります。

1. dd コマンドで実体を伴う /swapfile を作成する

前者は "Disk Destroyer" として悪名高い dd コマンドを使う方法で、ブロックサイズ bs が何個分 count かを指定してファイルを作成します。以下のコマンドは 2GB の swap ファイルを作成します。タイプミスで簡単にディスクのデータを消し飛ばすので実行する前に5回はチェックしてください[2]

$ sudo dd if=/dev/zero of=/swapfile bs=1M count=2048

2. /swapfile をループバックデバイスとして登録する

後者は『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

おしまい

イ ン ス タ ン ス を 立 て る 権 限 を 寄 越 せ。

脚注
  1. Swap 領域を確保しても GPU 側のメモリは増えないので、GPU を用いた学習や推論を同時にできる人数が増えるわけではないが、その他諸々の CPU を使う作業であれば swap 領域の恩恵を受けることができる。インスタンスをアップグレードするまでの暫定的な措置としては十分に機能するだろう。 ↩︎

  2. 自らの不注意でディスクの重要なデータを取り返しがつかないほど破壊したことがある人間とそうでない人間では覚悟のキマり方が一線を画しています。まだ消し飛ばしたことがない人はよい経験になると思いますので $ sudo dd if=/dev/zero of=/ bs=1M count=2048 を実行してみてもよいでしょう。このコマンドを実行して発生したいかなる損害についても私は責任取りません。実行した場合はこの免責事項に同意したものとみなします。それでもいいという人はおいで。「こ ち ら 側」に。 ↩︎

  3. BTRFS は Linux kernel 5.0 で swap ファイルに対応。 ↩︎

Discussion