Azure Ubuntu 24.04でcgroup v1のmemory.limit_in_bytesが無い?Judge0が動かない原因と解決策

Azure 上の Ubuntu 24.04 LTS で Judge0 を Docker 運用しようとすると、isolate が依存する cgroup v1 の memory.limit_in_bytes が見つからず、実行が失敗することがあります。本記事では原因の見極め方と、確実に復旧できる OS 選定・移行手順を具体的に解説します。

目次

Azure Ubuntu 24.04 で発生する Judge0 のエラー症状

Azure VM(例:Standard B2as v2)に Ubuntu 24.04 LTS を入れ、Judge0(オープンソースのコード実行 API)を Docker コンテナで起動したところ、実行時に以下のようなエラーで落ちるケースがあります。

Cannot write /sys/fs/cgroup/memory/box-X/memory.limit_in_bytes: No such file or directory

Judge0 は内部で isolate というサンドボックスを使い、リソース制限(特にメモリ)を cgroup に書き込むことで実現します。このとき isolate は伝統的に cgroup v1 のファイル(memory.limit_in_bytes など)へアクセスする実装・設定になっていることが多く、該当ファイルが存在しないと Judge0 側では内部エラー(例:status_id 13)として扱われます。

項目内容(例)重要ポイント
VMAzure Standard B2as v2VM サイズ起因ではないことが多い
OSUbuntu 24.04 LTScgroup v2 前提の挙動が強い世代
カーネルパラメータsystemd.unified_cgroup_hierarchy=false cgroup_enable=memory swapaccount=1付けても v1 が期待通りにならない場合がある
見えている状態/sys/fs/cgroup/memory/ は存在存在しても「v1 が完全」とは限らない
致命点memory.limit_in_bytes が無いisolate が書けず Judge0 が失敗

原因の核心:cgroup v1 の memory.limit_in_bytes が前提の仕組みと、Ubuntu 24.04 の現実

結論から言うと、今回の事故は「Judge0 / isolate が想定する cgroup のインターフェース」と「Ubuntu 24.04(特に cloud 向け構成)が提供する cgroup の実装・既定値」の ミスマッチで起きます。

cgroup v1 と cgroup v2 は“同じ cgroup”でもファイル名も流儀も違う

memory.limit_in_bytes は cgroup v1 のメモリ制限を表す代表的なファイルです。一方、cgroup v2 では設計が変わり、同等の役割は主に memory.max などが担います。つまり、OS が cgroup v2 前提で動いていると、v1 のファイルが無いのは「故障」ではなく「仕様」です。

用途cgroup v1(レガシー)cgroup v2(統合階層)現場での影響
メモリ上限memory.limit_in_bytesmemory.maxisolate が v1 固定だと v2 環境で失敗
メモリ使用量memory.usage_in_bytesmemory.current監視・ログの取り方が変わる
CPU 制限cpu.cfs_quota_us 等cpu.maxツールが v1 前提だと設定不能
階層構造コントローラ別にマウント統合階層(単一ツリー)パスが変わり、ハードコードが壊れやすい

「/sys/fs/cgroup/memory がある」だけでは安心できない理由

混乱の元はここです。Ubuntu 24.04 で /sys/fs/cgroup/memory/ ディレクトリが存在しても、次のような状態があり得ます。

  • cgroup v2 で動いていて、たまたまディレクトリだけ存在している(中身は v1 互換ファイルではない)
  • v1 のマウント自体は見えても、期待するファイルが揃わない(部分的・非推奨構成・組み合わせ不整合)
  • isolate が想定するパスに対して、実際の制御点が別にある(v2 であれば /sys/fs/cgroup/ 配下)

つまり、Judge0 側から見ると「書き込むべきファイルが無い」ため、No such file or directory で止まります。

まずやるべき切り分け:いま本当に cgroup v1 で動いているのか

同じ「cgroup」という言葉でも、v1 と v2 で確認方法が変わります。以下は現場で効く確認セットです。結果を見れば、どこがズレているかが一気に分かります。

確認したいことコマンド例見え方の目安次の一手
cgroup の大枠(v2 かどうか)stat -fc %T /sys/fs/cgroupcgroup2fs なら v2、tmpfs 等なら要調査v2 なら v1 ファイル前提は基本的に破綻
マウント状況(v1 の memory が本当にマウントされているか)mount | grep cgrouptype cgroup で memory が出るか、type cgroup2 かv2 のみなら isolate 側の前提を変える必要
memory.limit_in_bytes が存在するかls -l /sys/fs/cgroup/memory/memory.limit_in_bytes存在しなければ v1 前提アプリは失敗しやすいOS/構成変更が最短
自分のプロセスが属する cgroup 形式cat /proc/1/cgroup0::/ のような表示が多いと v2 の典型Judge0/isolate が v1 依存なら方針転換
Docker が認識している cgroup バージョンdocker info | grep -i cgroupCgroup Version: 2 等コンテナ基盤が v2 なら、v1 固定ツールは要対策

上記のどこかで「v2 っぽい」結果が出た場合、isolate が v1 の memory.limit_in_bytes を書く設計のままでは、根本的に噛み合いません。ここで小手先のマウントやディレクトリ作成をしても、カーネル側の制御点が違うため、期待通りに動かないことがほとんどです。

Judge0 / isolate が失敗するメカニズムをもう一段具体的に

Judge0 の多くの構成では、実行ごとに isolate が「箱(box)」を作り、プロセスをその箱に入れて制限をかけます。その際に、メモリ上限をファイル書き込みで設定します(概念的には次のような流れ)。

  1. 実行用の cgroup ディレクトリを作る(例:/sys/fs/cgroup/memory/box-0)
  2. 上限を書き込む(例:echo 268435456 > memory.limit_in_bytes)
  3. プロセスを cgroup に所属させる(例:cgroup.procs へ PID を書く)

ここで memory.limit_in_bytes が存在しないと、2 が成立しません。結果として isolate は「制限を設定できない=安全な実行環境を作れない」と判断し、Judge0 は実行をエラー扱いにします。

最短・確実な解決策:Azure の Ubuntu を 22.04 LTS(または 20.04 LTS)へ切り替える

現場で「いますぐ Judge0 を安定稼働させたい」「既存の isolate 前提を変えたくない」場合、最も事故が少ないのは OS を Ubuntu 22.04 LTS にすることです。実際に、Ubuntu 24.04 で詰まった構成が Ubuntu 22.04 に変更して解消した事例は珍しくありません。

どの Azure Ubuntu イメージを選べばいいか

Azure には複数の Ubuntu イメージがありますが、Judge0 + isolate のように「レガシーな cgroup v1 前提」が残っているアプリでは、まずは 22.04 LTS を基準に考えるのが安全です。

Ubuntu バージョンJudge0(isolate v1 前提)との相性選びどころおすすめ度
24.04 LTSそのままだと失敗しやすい(v2 前提のため)新しい OS が必要、かつ cgroup v2 対応へ移行できる場合要検証
22.04 LTS解消しやすい(v1 へ寄せる構成が取りやすい)安定運用と保守性のバランスを取りたい場合推奨
20.04 LTS動く可能性は高いが、運用面の検討が必要既存資産が 20.04 前提、または互換性最優先の場合条件付き

特に 20.04 LTS はリリース年が古いため、社内ルールやセキュリティ要件によっては「サポートの取り扱い(更新ポリシー)」を確認してから選ぶのがおすすめです。迷うなら 22.04 LTS が無難です。

Azure Portal での切り替え方(考え方)

Azure VM は「OS をその場で安全に入れ替える」というより、基本は 新しい VM を作って移行するのがトラブルが少ないです。具体的な進め方は次の通りです。

  1. Ubuntu 22.04 LTS の新規 VM を作成(サイズは現状と同等でOK)
  2. Judge0 の設定・環境変数・永続データ(PostgreSQL/Redis/ボリューム)を移行
  3. DNS / Public IP / リバースプロキシ(Nginx 等)を切り替え
  4. 旧 VM を停止し、問題なければ削除(または保管)

Azure CLI で新規 VM を作る例(22.04 LTS)

自動化したい場合は Azure CLI でイメージを明示して作ると、意図しないバージョン差分を避けられます。

az vm create \
  --resource-group RG-NAME \
  --name judge0-ubuntu2204 \
  --image Canonical:0001-com-ubuntu-server-jammy:22_04-lts-gen2:latest \
  --size Standard_B2as_v2 \
  --admin-username azureuser \
  --generate-ssh-keys

既存 VM がどのイメージ参照になっているかは、次のように確認できます。

az vm show \
  --resource-group RG-NAME \
  --name VM-NAME \
  --query storageProfile.imageReference

イメージ指定の文字列(URN)は環境により変わることがあるため、組織内で「標準イメージ」を固定して運用する場合は、作成時に必ず明示する運用が安全です。

「VM サイズが原因?」への答え:ほとんどの場合は違う

Standard B2as v2 のようなサイズが直接 memory.limit_in_bytes を消すことは基本的にありません。今回の問題は、CPU/RAM の量ではなく OS の cgroup 実装と既定の cgroup モードの問題です。

もちろん、Judge0 の同時実行数やコンパイル負荷によってはサイズ見直しが必要ですが、「ファイルが無い」という現象はサイズではなく cgroup 方式(v1/v2)に強く依存します。

どうしても Ubuntu 24.04 で運用したい場合の選択肢

「24.04 を使いたい理由」がある場合もあります(新しいドライバ、他システムとの統一、長期運用、パッケージ世代など)。その場合は、次のいずれかに舵を切る必要があります。

選択肢やることメリットデメリット / リスク
Judge0 / isolate を cgroup v2 対応へ寄せるisolate のバージョン・ビルド・設定を見直し、v2 の制御点(例:memory.max)を扱える構成へOS 標準の流れに乗れる検証コストが高い。既存手順が崩れる可能性
別のサンドボックス機構へ切り替えるJudge0 の実行バックエンドを変更、もしくは isolate 以外の仕組みを検討cgroup v1 依存を断てる安全性・性能・実装難易度のトレードオフが大きい
OS は 22.04 にしてアプリを安定稼働優先24.04 の採用を一旦見送り、22.04 を標準にする最短で動く。運用が読みやすい「最新 OS 統一」の要件があると妥協が必要

実務的には、Judge0 を「サービスとして安定提供」するのが目的なら、まず 22.04 で確実に稼働させ、並行して cgroup v2 対応を検証する二段構えが最も失敗しにくいです。

cgroup v1 に寄せる設定を試す場合の注意点

すでに次のようなパラメータを付けてもダメだった、という状況はよくあります。

systemd.unified_cgroup_hierarchy=false cgroup_enable=memory swapaccount=1

この状態でも改善しない場合、原因は「パラメータが効いていない」「効いているが、想定どおりの v1 構成が実現できていない」「Docker/systemd/isolate の組み合わせが噛み合っていない」などが考えられます。確認するポイントは次の通りです。

  • /proc/cmdline にパラメータが実際に載っているか(設定したつもりで反映されていない事故が多い)
  • cgroup_no_v1 のような v1 を無効化する設定が混ざっていないか
  • mount の種類が本当に v1(type cgroup)になっているか、それとも v2(type cgroup2)なのか
  • v1 の memory 階層で ルートにも memory.limit_in_bytes が無いのか、特定のディレクトリだけ無いのか

ただし、ここを深追いすると「OS の世代が前提としている設計」と喧嘩しやすく、時間が溶けます。Judge0 を目的にするなら、OS を 22.04 へ変更する方がコスト対効果が高いケースが多いです。

移行を成功させるための実務チェックリスト

OS を切り替えるだけで動くこともありますが、Judge0 は周辺コンポーネント(DB、キュー、永続ボリューム)を含むため、移行時は次の点を押さえると事故が減ります。

チェック項目確認内容よくある落とし穴
Docker / Compose の互換性新 VM で同じ Compose がそのまま上がるかパッケージリポジトリ差分で Docker の入れ方が変わる
永続データの移行DB/Redis/ボリューム/アップロード領域コンテナが起動してもデータが空で「動いたように見える」
ネットワークNSG、UFW、リバースプロキシ、ポート開放旧 VM だけ許可していて新 VM が疎通しない
性能同時実行数・コンパイル負荷・スワップ設定メモリ制限が効くようになり、逆に OOM の見え方が変わる
監視ログ、メトリクス、アラートの引き継ぎホスト名や IP が変わって監視が途切れる

よくある質問

Azure 上の Ubuntu 24.04 だけの既知の制限ですか?

「Azure だから」というより、Ubuntu 24.04 世代の cgroup v2 前提と、Judge0/isolate の cgroup v1 前提が衝突している、と捉えるのが正確です。Azure の Ubuntu イメージはクラウド運用を意識した構成で提供されるため、この衝突が表面化しやすい、という側面はあります。

Ubuntu 20.04 と 22.04 ならどちらがよいですか?

迷ったら Ubuntu 22.04 LTS がおすすめです。運用で重要な「サポート期間」「パッケージの新しさ」「周辺ツールの互換性」のバランスが良く、Judge0 のようなミドルウェアも採用例が多い世代です。20.04 は互換性重視で選ぶ価値がありますが、組織の更新方針(セキュリティ更新の扱い)を確認してからにすると安心です。

Ubuntu 24.04 のまま直したいが、何から着手すべき?

まずは cgroup v2 を前提にした設計へ寄せられるか(isolate の更新・設定変更、Judge0 の実行バックエンドの見直し)を検討してください。もし短期でサービス復旧が必要なら、22.04 へ切り替えて稼働を確保し、並行して 24.04 対応を検証するのが現実的です。

まとめ:Judge0 を確実に動かすなら「OS 選定」が最短ルート

  • memory.limit_in_bytes は cgroup v1 のメモリ制御ファイルで、cgroup v2 前提の環境では存在しない(または期待どおりに出ない)ことがある
  • Ubuntu 24.04 LTS(特にクラウド向け構成)では cgroup v2 前提の挙動が強く、Judge0/isolate の v1 前提と衝突しやすい
  • 最短で安定させるなら Azure の OS イメージを Ubuntu 22.04 LTS(または 20.04 LTS)へ切り替えるのが現実的
  • 将来 24.04 を使うなら、cgroup v2 対応(ツール更新・構成変更)を前提にロードマップを組む

この記事を書いた人

実務の現場で詰まりがちなポイントを地図にするITブログ「IT trip」を運営。Windows/Office(Teams・Excel)からSQL、サーバ運用、ガジェットまで、再現性のある手順と“なぜそうなるか”を丁寧に解説します。読んだらすぐ試せること、そして迷った人の次の一歩が見えることを大切にしています。

コメント

コメントする

目次