zram 実践入門 - 圧縮スワップの効果測定と「優先度でティアリング」の落とし穴

zram 実践入門 - 圧縮スワップの効果測定と「優先度でティアリング」の落とし穴

作成日:
読了:30
更新日:
この記事を読む人におすすめPR / Amazonアソシエイト

当サイトは Amazon.co.jp を宣伝しリンクすることで紹介料を得る手段を提供する、Amazonアソシエイト・プログラムの参加者です。価格・在庫はリンク先の最新情報をご確認ください。

メモリが足りないサーバーに対する対策として、スワップを増やすのは素直な発想です。ただしディスクスワップは遅く、増やしたところで「ページを読み戻すたびにディスクI/Oが発生する」という性質は変わりません。

そこで出てくるのがzramです。RAMの一部を圧縮領域として切り出し、そこをスワップデバイスとして使う仕組みで、ディスクI/Oがゼロのまま実効メモリを増やせます。

この記事では、実際にメモリ2GBの本番VPSにzramを導入して測定した結果をもとに、zramの仕組み、mm_stat の読み方、そしてよく紹介される設定手順に含まれる設計上の落とし穴までを整理します。結論を先に言うと、zramは確かに効きましたが、「zramを高優先度、ディスクスワップを低優先度にすれば自動で階層化される」という説明は正しくありません。

NOTE

測定環境はさくらのVPS上のUbuntu、カーネル 5.15.0-181-generic、物理メモリ1,963MB、Next.jsのプロセスが66本常駐している状態です。記事中の mm_stat / zramctl / swapon / zswapのdebugfs統計の出力は、2026年9月2日にこの環境で実際に取得した値です。仕様の記述はカーネル公式ドキュメントで確認しています。なお本記事の執筆後、同じサーバーを実際にzswapへ切り替えました。その手順と実測値は「追記: 実際に zswap へ切り替えた」にまとめてあります。

zram とは何か

zramは、RAM上に確保した領域を圧縮して使う仮想ブロックデバイスです。カーネルのドキュメントでは、圧縮によって「非常に高速なI/O」と「相応のメモリ節約」が得られる仕組みとして説明されています。作られたデバイスは /dev/zram0 のように見え、スワップにもファイルシステムにも使えます。

スワップとして使った場合の流れはこうなります。

  1. カーネルがページを追い出そうとする
  2. 追い出し先がzramなら、そのページを圧縮してRAM内に置く
  3. 読み戻すときは伸長してRAMへ戻す

ディスクは一切触りません。代わりにCPUを使って圧縮・伸長します。「メモリをCPU時間と引き換えに増やす」仕組みだと考えると分かりやすいです。

仮想メモリとページングそのものの仕組みは仮想メモリとページングの仕組みにまとめてあるので、ページフォルトやページ回収の前提が曖昧な場合はそちらを先に読んでください。

ディスクスワップとの違い

ディスクスワップzram
保存先ディスク(SSD/HDD)RAM
容量ディスクの空き次第RAMの一部を消費
速度ディスクI/O律速メモリ速度+圧縮コスト
実効的な増分確保したぶん全部圧縮率に応じた差分のみ
SSD書き込み発生する発生しない

重要なのは最後から2番目の行です。12GBのディスクスワップは12GB使えますが、1GBのzramが増やすメモリは1GBではありません。圧縮データはRAMを消費するので、増えるのは「元のサイズ - 圧縮後のサイズ」の差分だけです。ここは後で実測値を見ます。

導入手順

Ubuntu 24.04での手順です。zramはカーネルモジュールとして提供されており、追加パッケージは不要でした。

# 1. モジュールを読み込む
sudo modprobe zram num_devices=1
 
# 2. 使える圧縮アルゴリズムを確認する
cat /sys/block/zram0/comp_algorithm

この環境での出力です。角括弧が現在の選択を示します。

lzo [lzo-rle] lz4 lz4hc 842 zstd

既定は lzo-rle でした。今回は圧縮率を優先して zstd を選びます。

# 3. アルゴリズムとサイズを設定する(disksize より先に comp_algorithm を書く)
echo zstd | sudo tee /sys/block/zram0/comp_algorithm
echo 1G   | sudo tee /sys/block/zram0/disksize
 
# 4. スワップとして初期化・有効化する
sudo mkswap /dev/zram0
sudo swapon --priority 100 /dev/zram0

comp_algorithm はデバイスの初期化前、つまり disksize を書く前に設定する必要があります。順序を逆にすると変更が効きません。

サイズの決め方

カーネルのドキュメントには次のように書かれています。

there is little point creating a zram of greater than twice the size of memory since we expect a 2:1 compression ratio

(2対1の圧縮率を見込んでいるので、メモリの2倍を超えるzramを作る意味はほとんどない)

一方でFedoraは、systemdのzram-generatorの既定として物理メモリの50%(上限8GB)を採用しています。Fedora 34で、それまでの「25%・上限4GB」から引き上げられました。

今回の環境は物理1,963MBで、しかもすでに1.4GBが使用中という厳しい状況です。zramの圧縮データはRAMを食うため、いきなり大きく取ると本末転倒になります。そこで1GBから始めました。満杯になっても、後述の実測圧縮率なら消費は300MB程度で収まる計算です。

もう1つ、ドキュメントには見落としやすい注記があります。

zram uses about 0.1% of the size of the disk when not in use so a huge zram is wasteful

(未使用時でもディスクサイズの約0.1%を使うので、巨大なzramは無駄になる)

実測: どれだけ効いたか

有効化してから約1時間後の zramctl の出力です。

NAME       ALGORITHM DISKSIZE   DATA COMPR  TOTAL
/dev/zram0 zstd            1G 336.9M 96.9M 101.5M

337MBぶんのページが、97MBまで圧縮されて格納されています。圧縮率は約3.5倍で、実際に取り戻せたメモリは約235MBです。Next.jsのヒープのようなテキスト主体のデータは、zstdでよく縮みます。

導入前後のメモリの余裕はこう変わりました。

指標導入前導入後
MemAvailable185〜224MB283〜425MB

1GBのzramで235MBを取り戻した、というのが正味の効果です。繰り返しになりますが、1GB確保しても1GB増えるわけではありません。

mm_stat の読み方

zramctl は要約なので、詳しく見るには /sys/block/zram0/mm_stat を読みます。空白区切りで9個の値が並びます。

352944128 101482495 106319872 0 264155136 2578 18245 1644 47174

カーネルドキュメントに定義されている並び順は次のとおりです。

#フィールドこの環境の値意味
1orig_data_size336.6 MiB圧縮前のデータ量
2compr_data_size96.8 MiB圧縮後のデータ量
3mem_used_total101.4 MiB実際に確保したメモリ(断片化とメタデータ込み)
4mem_limit0上限設定(0は無制限)
5mem_used_max251.9 MiBこれまでの最大消費量
6same_pages2,578同一要素で埋まったページ。メモリを消費しない
7pages_compacted18,245コンパクションで解放されたページ数
8huge_pages1,644現在の非圧縮ページ数
9huge_pages_since47,174起動以降の累計

実務で見るべき点を3つ挙げます。

1つ目は2番目と3番目の差です。圧縮後96.8 MiBに対して実際の確保は101.4 MiBで、4.6 MiBがアロケータの断片化とメタデータのオーバーヘッドです。節約量を計算するときは compr_data_size ではなく mem_used_total を使わないと、5%前後を見誤ります。

2つ目は huge_pagesです。ドキュメントは「どのアルゴリズムでも圧縮できなかったページ」と定義しています。この環境では1,644ページ、全体の約2%でした。すでに圧縮済みの画像や暗号化データが多いワークロードでは、この比率が上がって圧縮率が落ちます。導入前に効果を見積もりたいなら、ここを見るのが早いです。

3つ目は mem_used_maxです。現在101.4 MiBでも、ピークでは251.9 MiBまで使っていました。サイジングは現在値ではなくピークで考える必要があります。

なお same_pages は、ゼロで埋まったページなど同一要素だけのページで、メモリを一切消費しません。仮想マシンや起動直後のプロセスが多い環境では、ここがかなりの数になります。

落とし穴: 「優先度でティアリング」は成立しない

ここからが本題です。

zramの解説記事でよく見かけるのが、次の構成です。

sudo swapon --priority 100 /dev/zram0    # 速いので先に使う
# ディスクswapは低い優先度のまま残す

説明としては「まず高速なzramに退避し、溢れたぶんだけディスクに落ちる二段構え」となります。私も今回この構成で入れました。実際の swapon --show はこうなっています。

NAME       TYPE       SIZE USED PRIO
/swapfile  file         4G 3.7G   -2
/swapfile2 file         8G   3G   -3
/swapfile3 file        12G   0B   -4
/dev/zram0 partition 1024M 338M  100

ところが、これは階層化として機能しません。カーネルのメモリ管理に詳しいChris Downは、2026年3月の記事でこの構成を明確な誤りとして挙げています。理由はLRU反転です。

何が起きるかというと、こうです。

  1. 優先度が高いzramが先に埋まる。埋まるのは、たいてい起動直後の初期化データのような古くて冷たいページ
  2. zramが満杯になる
  3. その後に追い出される比較的新しくて熱いページは、行き場がディスクスワップしかない
  4. 結果として、冷たいページが高速なRAMを占有し、熱いページが遅いディスクに置かれる

本来LRUが実現したいこと(熱いものを速い層に、冷たいものを遅い層に)の真逆になります。しかもzramには、いったん入れたページを後からディスクへ追い出す仕組みが標準では働きません。優先度はあくまで「どこに書くかの順番」を決めるだけで、格納済みのページを層の間で移動させる機能ではないのです。

上の出力で /dev/zram0 が338M / 1024Mと、まだ余裕がある状態なのは、zramを入れたのが1時間前だからにすぎません。満杯に達した時点で、この問題が始まります。

writeback は解決策になるか

zramには backing_devwriteback という機能があり、指定したブロックデバイスへページを書き出せます。理屈のうえでは階層化できます。

ただし実運用では、専用パーティションの用意、アイドル判定のしきい値決め、定期実行するスクリプトの整備が必要です。しかもカーネルのページ回収機構とは連動しないため、メモリ需要が急に立ち上がる場面で間に合いません。前掲の記事はこれを「メモリ管理のIKEA」(自分で組み立てる必要がある)と表現しています。

zram と zswap の使い分け

同じ「圧縮スワップ」でも、zswapは設計がまったく違います。

zramzswap
位置づけ独立したブロックデバイスディスクswapの前段キャッシュ
非圧縮ページそのまま格納する検出してディスクへ直行させる
階層化手動、または実質なしカーネルが自動で行う
cgroupへの計上されないされる
ディスクswap必須ではない必須(前段キャッシュなので)
限界に達したとき硬直しやすい段階的に劣化する

zswapはディスクスワップの前に置くキャッシュなので、冷たくなったページをカーネルが自分の判断でディスクへ落とせます。LRU反転が起きないのはこのためです。非圧縮ページを検出してディスクへ回す点も、RAMとCPUの両方を節約します。

前掲の記事は、迷ったらzswapを選ぶべきだとしたうえで、zramが適するのは次のような場合だと整理しています。

  • ディスクを持たない組み込み機器(スワップデバイスが1つしかない)
  • 意図的にディスクを持たない設計で、systemd-oomdのようなユーザー空間のOOMデーモンと組み合わせる場合
  • Androidのように、zram前提で徹底的にチューニングされたワークロード
  • プライベートなデータを永続ストレージに一切書きたくない場合

なお、zramとzswapを同時に有効にしてはいけません。どちらも圧縮キャッシュなので、二重に持つと個別に使うより多くのメモリを消費します。

現在の状態は次のコマンドで確認できます。切り替え前のこの環境では、zswapは無効で、既定のまま lzozbud が選択されていました。

cat /sys/module/zswap/parameters/enabled     # N なら無効
cat /sys/module/zswap/parameters/compressor  # lzo
cat /sys/module/zswap/parameters/zpool       # zbud

cgroupへの計上の差は、コンテナを動かす環境では効いてきます。zramの消費はcgroupから見えないため、コンテナごとのメモリ制限が実態と合わなくなります。cgroupによるリソース制限の仕組みはLinuxコンテナの仕組み入門にまとめてあります。

swappiness をどう決めるか

zramを入れたら vm.swappiness も見直す価値があります。カーネルのドキュメントは、この値を次のように定義しています。

This control is used to define the rough relative IO cost of swapping and filesystem paging.

(スワップとファイルシステムのページングの、おおまかな相対I/Oコストを定義するための制御である)

既定値は60、有効範囲は0から200です。100が「スワップとファイルシステムのI/Oコストが等価」を意味する中立点で、それより大きい値は「スワップのほうが安い」ことを示します。

ドキュメントには具体的な計算例まで書かれています。

if the random IO against the swap device is on average 2x faster than IO from the filesystem, swappiness should be 133 (x + 2x = 200, 2x = 133.33)

(スワップデバイスへのランダムI/Oが平均してファイルシステムの2倍速いなら、swappinessは133にすべきである)

zramはRAM上にあるのでディスクより桁違いに速く、この式に素直に当てはめれば200に近い値になります。実際、zram-generatorの swap-priority の既定が100に設定されているのも、「zramを遅いスワップデバイスより優先させる」ためだと説明されています。

ただし注意が必要です。swappinessを上げるとzramへの退避だけでなく、ディスクスワップへの流入も増えます。前節のLRU反転を抱えたままswappinessを上げると、問題を加速させることになります。構成を整理してから触るべきパラメータです。

関連して vm.page-cluster もあります。スワップから一度に読み戻すページ数を2の冪で指定するもので、既定は3(8ページ)です。zramはシークコストがないため先読みの利点が薄く、Arch Wikiなどでは0(1ページ)にする設定が紹介されています。ただしこちらもワークロード依存なので、変更するなら測定とセットにしてください。

再起動後も有効にする

modprobeswapon は再起動で消えます。永続化の方法は2つあります。

systemd-zram-generator を使う(推奨)

systemdプロジェクトが提供する公式のジェネレータで、Fedoraが既定で採用しているものです。設定ファイルを置くだけで済みます。

# /etc/systemd/zram-generator.conf
[zram0]
zram-size = min(ram / 2, 4096)
compression-algorithm = zstd
swap-priority = 100

zram-size は式で書けるので、メモリ搭載量が違うマシンでも同じ設定を使い回せます。

自前の systemd ユニットを書く

パッケージを追加したくない場合はこちらです。今回の環境ではメモリの余裕がなく、パッケージ導入を避けたかったのでこの方法を採りました。

# /etc/systemd/system/zram-swap.service
[Unit]
Description=zram compressed swap (zstd 1G, priority 100)
After=multi-user.target
DefaultDependencies=no
 
[Service]
Type=oneshot
RemainAfterExit=yes
ExecStartPre=/sbin/modprobe zram
ExecStart=/bin/bash -c "echo zstd > /sys/block/zram0/comp_algorithm && echo 1G > /sys/block/zram0/disksize && /sbin/mkswap /dev/zram0 && /sbin/swapon --priority 100 /dev/zram0"
ExecStop=/bin/bash -c "/sbin/swapoff /dev/zram0 && echo 1 > /sys/block/zram0/reset"
 
[Install]
WantedBy=multi-user.target

モジュール自体も起動時に読ませます。

echo zram | sudo tee /etc/modules-load.d/zram.conf
sudo systemctl daemon-reload
sudo systemctl enable zram-swap.service

ユニットを書いたら systemd-analyze verify で構文を確認しておくと安全です。

sudo systemd-analyze verify /etc/systemd/system/zram-swap.service

なお、すでにzramが有効な状態で systemctl start を実行すると、初期化済みのデバイスに対して mkswap が走って失敗します。起動経路の検証は、swapoff してから行うか、次回再起動時に確認することになります。

追記: 実際に zswap へ切り替えた

この記事を書いた数時間後、同じサーバーでzramをやめてzswapに切り替えました。手順と実測値を残しておきます。

切り替えを決めた理由

導入から数時間後のzramはこうなっていました。

NAME       ALGORITHM DISKSIZE   DATA  COMPR  TOTAL
/dev/zram0 zstd            1G 904.1M 246.6M 257.9M

904.1MB / 1024MBで、ほぼ満杯です。圧縮率3.67倍という数字自体は優秀ですが、ここから先に追い出されるページはすべてディスクswapへ直行します。前述のLRU反転が始まる直前でした。数時間で埋まったという事実そのものが、この構成が階層化として機能していないことの実証になっています。

手順1: zram を空にする

一番慎重を要する工程です。swapoff は、zramに載っている916MBのページを読み戻す必要があります。この時点のMemAvailableは125MBしかありませんでした。

先に受け皿を確認します。

free -m | awk '/Swap/{print "ディスクswapの空き:", $4, "MB"}'
sudo dd if=/dev/zero of=/tmp/ddtest bs=1M count=100 oflag=direct

ディスクswapの空きは18,402MB、書き込みは233MB/sでした。余裕があると判断して実行します。SSHが切れても中断しないよう、サーバー側でデタッチして走らせるのが安全です。

sudo nohup bash -c 'swapoff /dev/zram0; echo "rc=$?"' > /tmp/zram-swapoff.log 2>&1 &

推移です。

経過zramのデータ量MemAvailableload average
20秒677.1MB69MB5.84
40秒488.8MB111MB8.74
60秒174.1MB77MB15.41
80秒68KB116MB13.55
160秒68KB182MB3.67

所要2分、rc=0 で完了しました。loadは一時15.41まで上がりましたが、OOMは起きていません。zramが排出されるにつれて確保していた257.9MBのRAMが解放されるため、見た目ほどメモリは苦しくなりません。

排出後、デバイスを解放して自動起動も止めます。

echo 1 | sudo tee /sys/block/zram0/reset
sudo systemctl disable --now zram-swap.service
sudo rm -f /etc/modules-load.d/zram.conf
sudo rmmod zram

手順2: パラメータを選ぶ(既定のままは損)

ここが見落とされがちです。Ubuntu 24.04・カーネル5.15の既定値はこうでした。

パラメータ既定選んだ値理由
compressorlzozstd圧縮率が高い
zpoolzbudzsmalloczbudは1ページに最大2個までしか詰められず密度が低い
max_pool_percent2020(据え置き)RAM 1,963MBに対して最大392MB

既定の lzozbud のままでは、zswapの利点を大きく取りこぼします。特にzpoolの差は効きます。使えるアルゴリズムは /proc/crypto で確認できます。

grep -c '^name         : zstd' /proc/crypto   # 1 なら利用可

この環境では zstd lzo lzo-rle deflate が使え、lz4 はありませんでした。

手順3: 有効化する

順序が重要です。enabled より先に zpoolcompressor を設定します。

sudo modprobe zsmalloc
echo zsmalloc | sudo tee /sys/module/zswap/parameters/zpool
echo zstd     | sudo tee /sys/module/zswap/parameters/compressor
echo 1        | sudo tee /sys/module/zswap/parameters/enabled

永続化はカーネルパラメータで指定するのが正攻法です。

zswap.enabled=1 zswap.compressor=zstd zswap.zpool=zsmalloc

ただしブート設定を触りたくない場合は、systemdユニットでも代替できます。swapが有効になる前に走らせるのがポイントです。

# /etc/systemd/system/zswap.service
[Unit]
Description=Enable zswap (zstd + zsmalloc)
DefaultDependencies=no
After=sysinit.target
Before=swap.target
 
[Service]
Type=oneshot
RemainAfterExit=yes
ExecStartPre=/sbin/modprobe zsmalloc
ExecStart=/bin/bash -c "echo zsmalloc > /sys/module/zswap/parameters/zpool && echo zstd > /sys/module/zswap/parameters/compressor && echo 1 > /sys/module/zswap/parameters/enabled"
ExecStop=/bin/bash -c "echo 0 > /sys/module/zswap/parameters/enabled"
 
[Install]
WantedBy=sysinit.target

効果測定は debugfs で見る

zswapには mm_stat にあたるファイルがありません。統計はdebugfsに置かれています。

sudo mountpoint -q /sys/kernel/debug || sudo mount -t debugfs none /sys/kernel/debug
ls /sys/kernel/debug/zswap/

主なファイルは次のとおりです。

ファイル意味
stored_pages現在格納しているページ数
pool_total_sizeプールが実際に使っているメモリ量(バイト)
same_filled_pages同一要素で埋まったページ数
written_back_pagesプールから追い出してディスクswapへ書き戻したページ数
pool_limit_hitプールが上限に達した回数
reject_compress_poor圧縮率が悪くて拒否したページ数
reject_alloc_fail確保に失敗した回数

圧縮率は stored_pages × 4096 ÷ pool_total_size で求まります。

実測結果

有効化後の推移です。

stored= 16380p(  64.0MB) pool= 17.0MB 圧縮=3.76倍 書戻=0 上限=0 不良=0
stored= 26073p( 101.8MB) pool= 28.4MB 圧縮=3.59倍 書戻=0 上限=0 不良=0
stored= 36911p( 144.2MB) pool= 42.0MB 圧縮=3.43倍 書戻=0 上限=0 不良=0

144.2MBのページが42.0MBに収まり、圧縮率は3.43倍でした。zramのときの3.5倍とほぼ同等です。同じzstdなので当然ではありますが、zpoolに zsmalloc を選ばず既定の zbud のままだと、ここまでの密度は出ません

reject_compress_poor reject_alloc_fail reject_reclaim_fail pool_limit_hit はいずれも0で、健全に動作しています。

見るべき指標

日常的に見るなら written_back_pages です。これが増えていれば、プールが上限に達してカーネルが自動でディスクswapへ落としている状態を意味します。これがzramには無かった機能そのもので、優先度の設定をしなくても階層化が働いている証拠になります。

pool_limit_hitreject_alloc_fail が増え続けるようなら、max_pool_percent が小さすぎるか、そもそもメモリが足りていません。

1行で確認できるようにしておくと便利です。

d=/sys/kernel/debug/zswap
echo "stored=$(cat $d/stored_pages) pool=$(cat $d/pool_total_size) 書戻=$(cat $d/written_back_pages) 上限=$(cat $d/pool_limit_hit)"

切り替えてみての所感

移行コストは、実質的に swapoff の2分間だけでした。逆に言えばzramに載っているページ量が多いほど、この2分が長く重くなります。切り替えるなら、zramが埋まりきる前の早い段階のほうが安全です。

そして設定項目が減ったのが大きい点です。zramでは優先度、サイズ、writebackのしきい値、swappinessの相互作用を考える必要がありましたが、zswapは有効にしてcompressorとzpoolを選べば、あとはカーネルが階層化を判断します。前掲の記事が「迷ったらzswap」と書いている理由が、運用してみるとよく分かります。

結局どう使えばよいか

今回の測定と一次情報を踏まえた整理です。

zramが素直に効くケース
  • スワップデバイスがzramだけ(ディスクスワップを併用しない)
  • ディスクを持たない、または持ちたくない環境
  • 圧縮の効くデータが主体(テキスト、コード、JSONなど)
  • メモリ不足の緊急避難として、短期的に凌ぎたい場合
zswapを検討すべきケース
  • すでにディスクスワップがあり、これからも使う
  • cgroupでメモリを管理している(コンテナ環境)
  • 手動チューニングを増やしたくない
どちらにせよ効果がないケース
  • 圧縮の効かないデータが主体(暗号化済み、圧縮済みメディア)
  • ワーキングセットそのものがRAMを大きく超えている

最後の点は強調しておきます。zramは冷たいページを圧縮して置いておくための仕組みであって、頻繁にアクセスされるページを増やす仕組みではありません。アクティブなワーキングセットがRAMに収まらない状況では、圧縮と伸長のCPUコストが乗るぶん、かえって遅くなることもあります。

今回の環境で235MBを取り戻せたのは、66本のNode.jsプロセスの大半がアイドルで、そのヒープが「めったに触られない、しかしよく圧縮できるデータ」だったからです。条件が違えば結果も変わります。導入したら必ず mm_stat で圧縮率と huge_pages を確認してください。

そしてスワップ全般に言えることですが、これは時間を買う手段であって、メモリ不足そのものの解決ではありません。ディスクスワップの作り方についてはLinux のスワップファイルは fallocate で速く作るにまとめてあります。

まとめ

  • zramはRAMの一部を圧縮領域にして使う仮想ブロックデバイス。ディスクI/Oなしで実効メモリを増やせる
  • 実測では337MBが97MBに圧縮され、圧縮率3.5倍、実効235MBの節約。ただし1GB確保しても1GB増えるわけではない
  • 効果測定は mm_stat を見る。節約量は compr_data_size ではなく mem_used_total で計算し、huge_pages で非圧縮ページの比率を、mem_used_max でピークを確認する
  • 「zramを優先度100、ディスクswapを低優先度」はLRU反転を招く。優先度は書き込み先の順序を決めるだけで、格納済みページを層間で移動させる機能ではない
  • ディスクスワップを併用するなら、zramではなくzswapのほうが設計として素直。ただし両方を同時に有効にしてはいけない
  • vm.swappiness はカーネル文書に計算例がある。ただしLRU反転を抱えたまま上げると問題を加速させる
  • 実際にこのサーバーはzswapへ切り替えた。916MBの swapoff に2分(loadは一時15.41まで上昇、OOMなし)、切り替え後の圧縮率は3.43倍でzramと同等
  • zswapは既定の lzozbud のままでは利点を取りこぼす。zstdzsmalloc を、enabled より先に設定する
  • zswapの統計は mm_stat ではなくdebugfs(/sys/kernel/debug/zswap/)にある。日常的に見るのは written_back_pages で、増えていれば階層化が働いている

参考リンク

Bad Epoll(CVE-2026-46242)とは - Linux カーネル epoll の権限昇格脆弱性と、AI が見逃した競合バグを読み解く

Bad Epoll(CVE-2026-46242)とは - Linux カーネル epoll の権限昇格脆弱性と、AI が見逃した競合バグを読み解く

18

Linux カーネルの epoll サブシステムに見つかった use-after-free 脆弱性 Bad Epoll(CVE-2026-46242)を、NVD などの一次〜準一次情報ベースで整理します。ep_remove() の競合状態からローカルの一般ユーザーが root を奪える仕組み、影響するカーネルバージョンと Android への波及、そして「同じ 2023 年のコミットが混入させた隣の競合バグを Anthropic の Mythos が見つけ、Bad Epoll だけを見逃した」という話題性のある経緯まで解説します。2026 年 7 月時点の続報(実際の悪用は未確認・CISA KEV 未掲載、修正が公開開示に先行、ディストリのバックポートは配布途上)も追記しました。

Linuxコンテナの仕組み入門 - namespaceとcgroupsから理解するDocker

Linuxコンテナの仕組み入門 - namespaceとcgroupsから理解するDocker

47

コンテナは軽量な仮想マシンではありません。Linuxカーネルのnamespace・cgroups・capabilities・seccomp・overlayfsという既存機能を組み合わせた「普通のプロセス」です。man7.orgのmanページ、kernel.orgのcgroup-v2ドキュメント、OCI仕様、Docker公式ドキュメントを一次ソースに、8種類のnamespaceの役割、cgroup v1とv2の違い、unshareやlsnsで手を動かす確認手順、runcとcontainerdの関係、そしてコンテナがセキュリティ境界として弱い理由までを積み上げて整理します。