概要

筆者が運用しているWebサーバ。興味が向くまま様々なWebアプリを入れているため、メモリが心許ない事態が発生します。
単にスワップを増やすのではなく、Linuxの物理メモリ(RAM)の上に圧縮された専用領域(ブロックデバイス)を作成する、zramを導入します。

  • 通常の構造: RAM <---> Disk (HDD/SSD)
  • zram導入後: RAM [ 通常領域 | zram(圧縮領域) ] <---> Disk

環境

  • Ubuntu 24.04

メモリ環境

free -b | awk '
/Mem:/ {
  mem_total=$2/1024/1024/1024;
  mem_used=$3/1024/1024/1024;
  mem_free=$4/1024/1024/1024;
}
/Swap:/ {
  swap_total=$2/1024/1024/1024;
  swap_used=$3/1024/1024/1024;
  swap_free=$4/1024/1024/1024;
}
END {
  printf "| 項目 | 値 |\n| --- | --- |\n";
  printf "| Mem Total | %.2f GiB |\n", mem_total;
  printf "| Mem Used | %.2f GiB |\n", mem_used;
  printf "| Mem Free | %.2f GiB |\n", mem_free;
  printf "| Swap Total | %.2f GiB |\n", swap_total;
  printf "| Swap Used | %.2f GiB |\n", swap_used;
  printf "| Swap Free | %.2f GiB |\n", swap_free;
}'
項目
Mem Total5.78 GiB
Mem Used2.78 GiB
Mem Free0.42 GiB
Swap Total2.00 GiB
Swap Used0.02 GiB
Swap Free1.98 GiB

Caution! 導入の前に

これは万能薬ではありません。

メモリ上にブロックデバイスを作成しますが、その分、マシンパワーを喰います。

元々のメモリ量が少なければ効果を発揮しません。

例えば1GB未満のWebサーバでの運用は厳に慎むべきです。

破壊的アップデートを伴います。

「スワップをいじることのヤバさ」が知らない方は、この先の文章は読まないでください。(正直、DDoS喰らった時以上に神経を使う作業でした)

フェイズ・ゼロ(政治交渉)の必要性-再掲-

このvpsを個人的に運用しているのならばそのまま行って構いません。しかし、これを組織で運用しているとなると話はまるで違います。

  • メモリが心許ない。
  • ついてはこの計画でサーバ設定を行う
  • そのため、追加で作業時間をいただきたい
  • 作業時間は○時頃、○分程度で終わる。その間、サーバそのものの再起動を伴う

など、利用者への周知という名の政治交渉が必要になります。この運用者の政治的な立ち位置(担当者/担当部門が強権を振るえるか否か)でも言い方や手段が決まってきます。そこは状況に応じていきましょう。

当然、設定の大幅変更に関わるので設計書や運用のドキュメント化も待っています。

※ 検証環境を用意できる程度には時間と予算と環境に余裕がある方は、その環境にいることを感謝しつつ、検証を重ねていきましょう。

さっくりとした手順

以下、フェイズ・ゼロをクリアした(必要ない)方向けです。

  1. カーネルモジュールを追加インストールします。
  2. zramをインストールします。
  3. zramの設定を行います。
  4. zramを有効化します。
  5. zramの内容を確認します。

※筆者の好みでaptitudeを用いています。必要に応じてaptに読み替えてください。

強く推奨:イメージ全体のバックアップ

仮想サーバ、vps等で運用している場合は、イメージ全体をバックアップ(スナップショット)などとしておき、何かあったときにすぐに戻せるようにします。

カーネルモジュールの追加インストール

これが地味にハマりました。

sudo apt install linux-modules-extra-$(uname -r)

これを入れていないと「現在のカーネルにzramモジュールが存在しない、あるいはロードできない」事態が発生します。(発生しました)

zramインストール

sudo aptitude install zram-tools

と、コマンド一発で済む作業です。しかし、コマンド一発で済む作業であるからこそ、チューニングは細心の注意が必要です。

zramの設定

  • 設定ファイルのバックアップ
sudo cp -pi /etc/default/zramswap /path/to/backup/zramswap.$(date +%Y%m%d)
  • 設定ファイルのバックアップ確認
diff -u /path/to/backup/zramswap.$(date +%Y%m%d) /etc/default/zramswap

エラーがなければOKです。diffを逆にしているのは、この後で説明します。

  • ファイルの修正

/etc/default/zramswapを以下のように修正します。自身の環境に合わせます

# 圧縮アルゴリズムの指定
ALGO=zstd
# 物理メモリの半分ほどを指定します
PERCENTAGE=50
# 念のため、ディスクサイズも指定します
SIZE=2048
# 既存スワップ(通常の-2)より高く設定します
PRIORITY=100
  • ファイルの修正確認
diff -u /path/to/backup/zramswap.$(date +%Y%m%d) /etc/default/zramswap
 #ALGO=lz4
+ALGO=zstd

 # Specifies the amount of RAM that should be used for zram
 # based on a percentage the total amount of available memory
 # This takes precedence and overrides SIZE below
 #PERCENT=50
+PERCENTAGE=50

 # Specifies a static amount of RAM that should be used for
 # the ZRAM devices, this is in MiB
 #SIZE=256
+SIZE=2048

 # Specifies the priority for the swap devices, see swapon(2)
 # for more details. Higher number = higher priority
 # This should probably be higher than hdd/ssd swaps.
 #PRIORITY=100
+PRIORITY=100

等と表示されればOKです。そして、ここで、先ほど示したdiffのsrcとdstを逆にした理由です。

  • 逆にする(バックアップからの差分)とすることで
    • 「何を足したか(つまり、現時点での正」が明白になります。
  • 逆にしないと
    • 正しい設定が「引かれている」状態となり、視覚的に危険な状態になります。

zramの有効化

  • zram再起動
sudo systemctl restart zramswap

`

※筆者がハマったのはここです。ここでエラーが発生してカーネルモジュールをインストールする手戻りが発生しました。

  • zramサービス確認
systemctl status zramswap.service 

active(exited)を確認します。(これは、apache/mysqlなどの常駐型サービスと異なり「カーネルにロードしてしまえば後はOK」という状態のためexitedとなっています。

サーバ再起動

sudo reboot

行います。再起動に慎重を要する(クラスタリングなど)はその手順に従ってください。

ここで再起動しない事態が発生したら?

「さぱっと死せい 黄泉路の先陣じゃ 誉れじゃ」

ぐらいの潔さを持ちましょう。(持てなければそもそも筆者はサーバ運用をしていません

潔さがない方のためのイメージ全体のバックアップであり、スナップショットなので。

zramの有効化確認

swapon --show
NAME       TYPE      SIZE USED PRIO
/swapfile  file        2G   0B   -2
/dev/zram0 partition   2G   0B  100

/dev/zram0がリストにあれば、カーネルがスワップとして認識中です。

zramctl
NAME       ALGORITHM DISKSIZE DATA COMPR TOTAL STREAMS MOUNTPOINT
/dev/zram0 zstd            2G   4K   59B   20K       4 [SWAP]

で、数字がカウントされればOKです。