CRIU(チェックポイント・リストア)
動いているプロセスを止めずに丸ごと保存し、別ホストで続きから再開する。コンテナのライブマイグレーションを支える仕組みと、復元できない資源の壁を原理から理解できます。
- 1.CRIUは実行中プロセスのメモリ・ファイルディスクリプタ・ソケット状態などを/procとptraceで収集し、イメージファイル群に保存する。
- 2.復元は新規プロセスをフォークし、mmapでメモリを再構築、システムコール列を再実行してカーネル内部状態を作り直す。
- 3.TCP接続の途中状態やハードウェア依存資源は復元できないため、事前の資源分離やドレインが前提になる。
チェックポイント・リストアとは何をする技術か
CRIU(Checkpoint/Restore In Userspace)は、実行中のプロセス(またはプロセスツリー)の状態を丸ごとディスク上のイメージに固め、任意のタイミング・任意のホストで元通りに再開するためのツールです。プロセスを止めて保存し、後から続きから走らせる。ここで言う「状態」とは、メモリ内容だけではありません。オープン中のファイルディスクリプタ、TCPソケットの接続情報、シグナルハンドラの設定、子プロセスとの親子関係、名前空間の所属など、プロセスを取り巻くカーネル内部の情報すべてが対象です。
名前が示す通り、実装のほとんどはユーザー空間で完結します。カーネルに専用のチェックポイント機構が用意されているわけではなく、/proc以下の各種情報とptraceによるプロセス制御、そしていくつかの補助的なカーネルインタフェースを組み合わせて、外側から状態を読み出し・書き戻します。この設計により、CRIUはカーネル本体に大きな変更を要求せずに実現されています。
CRIUはDocker/PodmanやKubernetesのライブマイグレーション、CI環境でのプロセス状態のスナップショット、HPC分野でのジョブの中断・再開など、多方面で使われます。コンテナの名前空間とcgroupsによる隔離とは独立した技術ですが、コンテナの実体がホスト上の通常プロセスであるからこそCRIUが直接適用できます。
チェックポイント:何をどう集めるか
チェックポイントの手順は、大きく分けて「凍結」「収集」「保存」の3段階です。
まず対象プロセスをptrace(PTRACE_SEIZE)で捕捉し、実行を止めます。SEIZEは古典的なPTRACE_ATTACHと異なり、対象にSIGSTOPを送らずに捕捉できるため、プロセス側のシグナル処理系を乱しません。プロセスツリー全体(親子関係にある複数プロセス)を対象にする場合は、全プロセスを同時に凍結してからでないと、片方だけ状態が進んでしまい整合性が崩れます。
次に状態を収集します。主な情報源は次の通りです。
- メモリ:
/proc/<pid>/mapsでVMA(仮想メモリ領域)の一覧を取得し、/proc/<pid>/memまたはprocess_vm_readvでページ内容を読み出す。匿名メモリはページ単位でダンプし、ファイルバックドなマッピング(実行ファイル・共有ライブラリ)はパスだけを記録してページ内容自体は保存しない。 - ファイルディスクリプタ:
/proc/<pid>/fd/でオープン中のfd一覧とその指す先(通常ファイル・パイプ・ソケット・デバイス)を取得し、ファイルはオフセットやフラグも含めて記録する。 - ソケット:TCPなら
/proc/net/tcp相当の情報やソケットオプションを収集する。特にTCP接続は後述の理由で特別扱いが要る。 - シグナル状態:ペンディング中のシグナル、ハンドラの設定、シグナルマスクを
/proc/<pid>/statusや関連インタフェースから取得する。 - プロセス関係:親子関係、プロセスグループとセッション、スレッド構成をまとめて記録する。
収集した情報はプロセスごとのイメージファイル(pstree.img、mm-<pid>.img、fdinfo-<pid>.imgなど)としてディスクへシリアライズされます。イメージはネットワーク越しに別ホストへ転送でき、この転送こそがライブマイグレーションの実体です。
TCP接続はカーネル内部の輻輳制御状態やシーケンス番号を持つため、ユーザー空間から完全に読み出すのは困難です。CRIUはTCP_REPAIRというソケットオプションを使い、カーネルに接続を「修理モード」にさせて、シーケンス番号などをそのまま読み書きできる状態にします。これにより、TCP接続を維持したままチェックポイント・リストアできます。
リストア:状態をどう作り直すか
リストアは収集の逆順ではなく、新しいプロセスを一から作り、システムコールの実行によってカーネル内部状態を再構築するという形を取ります。CRIUのイメージには「メモリのバイト列」以上に「これを再現するために発行すべきシステムコール列」という性格があります。
典型的な流れは次の通りです。
1. pstree.imgからプロセスツリーを読み、fork/cloneで骨格となる子プロセス群を先に作る
2. 各プロセスは自分自身を「CRIUが用意した復元用の小さなコード(restorer blob)」に
execで置き換える
3. restorer blobがmmapでメモリ領域を再構築し、保存済みページ内容をコピーする
4. open/dup2でファイルディスクリプタを元の番号に復元する
5. TCP_REPAIRモードでソケットを復元し、シーケンス番号等を書き戻す
6. シグナルマスク・ハンドラ・レジスタ値を復元する
7. 最後にrestorer blobから、元のプログラムカウンタ位置へジャンプして実行を再開する
ここで重要なのは、リストア後のプロセスは元のプロセスとPIDが一致するという点です。多くのプログラムは自分のPIDやファイルディスクリプタ番号を前提に動いているため、番号がずれると復元後に破綻します。CRIUは/proc/sys/kernel/ns_last_pidへの書き込みで次に割り当てられるPIDを操作し、clone直後に狙ったPIDを引き当てます。同様にfd番号もdup2で元の番号へ強制的に揃えます。
リストアされたプロセスは、チェックポイント前とは別のカーネルオブジェクト(別のtask_struct、別の物理ページ)の上に成り立っています。外から観測できる状態(PID、fd番号、メモリ内容、接続)が一致するように作り直しているのであり、実行を一時停止したままにしていたわけではありません。この違いは、復元困難な資源を考えるときの土台になります。
復元が困難な資源
チェックポイント・リストアは万能ではありません。ホストのハードウェアや外部エンティティに直接結びついた資源は、別ホストは元よりチェックポイント元のホストに戻す場合でも、再現が原理的に難しい、あるいは前提条件を要します。
| 資源 | 困難な理由 | 対処 |
|---|---|---|
| GPUデバイスコンテキスト | ドライバがハードウェア固有の内部状態を持ち外部から読み出せない | 対応ドライバのプラグイン、またはチェックポイント対象から除外 |
| 外部TCP接続の相手側 | 自分側の状態は復元できても相手ホストの状態は制御できない | TCP_REPAIRで自分側を凍結し、移行後も相手には同じ接続に見せる |
| 共有メモリの外部プロセス | チェックポイント対象外のプロセスと共有している場合、片方だけ復元すると不整合 | 関係するプロセスをまとめてチェックポイント対象に含める |
| PTYやTTYの実体 | 端末デバイスは物理・仮想端末に紐づき単純な複製ができない | 外部ターミナルマネージャ経由で仮想端末を再割り当て |
| カーネルタイマー・epoll内部状態 | カーネル内部でしか完結しない一時状態がある場合がある | CRIU側での個別対応(カーネルバージョン依存) |
これらに共通するのは、状態の一部がCRIUの外側(ハードウェア、相手ホスト、別プロセス)に存在し、チェックポイント対象のプロセスだけでは閉じていないという点です。原理的な限界であり、CRIUのバージョンが上がっても本質的には残り続けます。
コンテナのライブマイグレーションへの応用
コンテナは実体としてはホスト上の通常プロセス群であり、名前空間による隔離を伴うだけなので、CRIUを直接適用できます。ライブマイグレーションの典型的な流れは以下です。
1. 移行元でコンテナ内の全プロセスをチェックポイントし、イメージを生成する
2. イメージを移行先ホストへ転送する
3. 移行先で同じ名前空間構成(PID/ネットワーク/マウント等)のコンテナを用意する
4. イメージからプロセスツリーをリストアする
5. コンテナのネットワーク設定を切り替え、移行元を停止する
ダウンタイムを縮めるための最適化がプレコピー方式です。実行中のうちにメモリページを先行して転送し、その後の差分(ダーティページ)だけを都度追跡して転送します。最終的に凍結する時間はダーティページの再送分だけで済むため、完全に止めてから丸ごと転送するより移行時間を短縮できます。ただしメモリ書き込みが激しいワークロードでは差分が収束しにくく、プレコピーの効果は限定的です。
CRIUは「カーネル拡張」ではなく「/procとptraceを使うユーザー空間ツール」である点、TCP_REPAIRでソケット状態を凍結する点、PIDとfd番号を厳密に再現する点、そしてGPUや相手ホスト状態など外部に依存する資源は原理的に復元できない点。この4点を押さえれば、ライブマイグレーションの制約についての設問にも対応できます。
まとめ
CRIUは、/procとptraceを軸にプロセスのメモリ・fd・ソケット・シグナル状態を収集してイメージ化し、リストア時はシステムコールの再実行によって同じ状態を作り直します。PIDとfd番号を厳密に一致させる工夫、TCP_REPAIRによるソケット凍結が中核です。一方でGPUコンテキストや相手ホスト依存の資源など、プロセスの外側に状態がまたがる資源は原理的に復元できず、事前の分離や個別対応が前提になります。コンテナのライブマイグレーションはこの仕組みの直接的な応用であり、プレコピーによる差分転送でダウンタイムを縮めます。
OS Article
CRIU(チェックポイント・リストア)を実務で読む
TL;DRは入口です。実際に選ぶ・使う段階では、何を解決するか、何と比較するか、導入後にどこで詰まるかまで見る必要があります。
解決すること
CRIU
比較で見る軸
難易度: advanced / カテゴリ: OS / タグ数: 5
導入後に効く点
復元は新規プロセスをフォークし、mmapでメモリを再構築、システムコール列を再実行してカーネル内部状態を作り直す。
先に潰すリスク
用語だけ覚えても、設計・実装・運用でどこに効くかを確認しないと判断を誤る。
- 難易度
- advanced
- カテゴリ
- OS
- タグ数
- 5
判断チェックリスト
- 自社の用途が「CRIU / コンテナ」に近いか確認する。
- 強みである「CRIUは実行中プロセスのメモリ・ファイルディスクリプタ・ソケット状態などを/procとptraceで収集し、イメージファイル群に保存する。」が本当に評価軸になるか確認する。
- 注意点の「用語だけ覚えても、設計・実装・運用でどこに効くかを確認しないと判断を誤る。」を運用で吸収できるか確認する。
- 公開値や仕様値は、対象プラン・対象機種・対象リージョンまで確認する。
- 既存システム、ID、ネットワーク、監視、バックアップとの接続方法を先に洗い出す。
- 小さく試してから、本番移行、権限設計、障害時手順、コスト監視を決める。