Youki, runc における CRIU によるチェックポイント・リストアの仕組み
Difference between the checkpoint command in runc and youki を実装する前に、 CRIU の役割と youki や runc での実装方法について調べたことをまとめる。
CRIU, rust-criu とは
CRIU(Checkpoint/Restore In Userspace)とは、Linux上で稼働しているコンテナや単一のアプリケーションのプロセスを一時停止(フリーズ)し、その状態をディスクに保存(チェックポイント)して、後から完全に同じ状態から再開(リストア)できるようにするためのソフトウェアである。アプリケーションのプロセスで使われるメモリやディスクの状態だけでなく、TCPコネクションや cgroup 構成など幅広いリソースをチェックポイント・リストアすることができる。
Rust-criu はこの CRIU を Rust で利用できるようにした実装で、似たようなものとして go-criu という Go 言語のバインディングも存在する。 Rust-criu が誕生したのは youki でチェックポイント・リストアを実装するためであったことが issue (実際の提案 issue)から読み取れる。
ここで登場した Youki は Rust で実装されたコンテナランタイムである。 Youki は OCI runtime-spec というコンテナランタイムの標準仕様に従っており、 runc もまたこの標準に従った実装である(こちらは Go で書かれている)。
Runc における CRIU の使い方
CLIから使うことができる。
runc checkpoint [option ...] container-id
runc restore [option ...] container-id
このコマンドの裏では CRIU が動いている訳だが、CRIU の起動方法にもいくつかあり、 runc では SWRK mode を使っている。 SWRK mode では fork() + exec() コマンドで CRIU を起動し、UNIXドメインソケットを通じて起動した親プロセスと通信する。 つまり、 runc で CRIU を SWRK mode で呼び出すことで、 criu-go を使って runc からチェックポイントすることができるというわけである。 なお、ここでチェックポイントを行うために必要な runc から CRIU への指示は RPC で実行される。 Protobuf で定義されているので、実行の仕組みを踏まえてこれを見れば扱い方が想像しやすい。 Runc からチェックポイントの手続きを RPC で CRIU に指示した後、CRIU で処理が完了するとUNIXドメインソケットを通じて完了通知を受け取る。
Rust-criu でも RPC 定義が散見されるため基本的にはこの SWRK mode で CRIU を起動してランタイムから RPC を叩いて CRIU からの通知を受け取るという実装が一般的なのだろうと推察する。
Youki でのチェックポイントの取得
Youki では checkpointt というサブコマンドでチェックポイントを行うことができる。
適当なコンテナを立てて動かした上でチェックポイントを取ってみる。
# https://youki-dev.github.io/youki/user/basic_usage.html
$ mkdir -p tutorial/rootfs
$ cd tutorial
$ docker export $(docker create busybox) | tar -C rootfs -xvf -
tutorial/config.json の process.args を編集して sleep を適当な長さ入れておき、チェックポイントを手動で取るための猶予を作る。
"process": {
...
"args": [
"sleep", "60"
],
...
}
Youki のルートディレクトリに戻ってからコンテナを作成・チェックポイントを取得する。チェックポイントはデフォルトで checkpoint というディレクトリに保存されるのであらかじめ作っておく。
$ sudo ./youki create -b tutorial tutorial_container
$ sudo ./youki state tutorial_container
$ sudo ./youki start tutorial_container
# checkpoint が保存される場所
$ mkdir -p checkpoint
# checkpoint を取得する
$ sudo ./youki checkpointt --shell-job tutorial_container
$ ls checkpoint/
cgroup.img files.img ip6tables-10.img netdev-10.img pstree.img stats-dump tmpfs-dev-79.tar.gz.img
core-1.img fs-1.img ipcns-var-11.img netns-10.img route-10.img timens-0.img tmpfs-dev-80.tar.gz.img
descriptors.json ids-1.img iptables-10.img nftables-10.img route6-10.img tmpfs-dev-71.tar.gz.img tmpfs-dev-81.tar.gz.img
dump.log ifaddr-10.img mm-1.img pagemap-1.img rule-10.img tmpfs-dev-76.tar.gz.img tty-info.img
fdinfo-2.img inventory.img mountpoints-13.img pages-1.img seccomp.img tmpfs-dev-78.tar.gz.img utsns-12.img
checkpoint を見ると様々なファイルが確認できる。これを CRIU image file という。フォーマット等の仕様については公式ページ を参照のこと。
$ file checkpoint/cgroup.img
checkpoint/cgroup.img: CRIU image file v1.1