CRIUを利用することで、DockerでCheckpoint & Restoreが可能だった。試してみたのでメモ。
基本的には以下に書いてあることを実施したのみ。
https://github.com/docker/docker/blob/master/experimental/checkpoint-restore.md
チェックポイント・リストアとは
チェックポイント機能により、コンテナ状態(メモリ情報など)をdumpして、ディスク上に書き出すことができる。
リストア機能では、書き出した情報を読み込んでコンテナを実行することができる。この機能を活用することにより、
- 高速なアプリケーション起動が可能
- 予め起動済のアプリケーションコンテナのチェックポイントを利用
- ライブマイグレーションが実現できる
- VMのライブマイグレーションも同様の仕組み
といったことが可能になる。ライブマイグレーションについては、CRIUの現実装で既に可能らしいが、Dockerとしては優先度は低いらしく、Dockerコマンドのみでの実行は不可能と思われる。
セットアップ
本機能を利用するには、Docker experimentalフラグをtrueにする必要がある。やり方は色々とあるが、例えば以下参照。
https://github.com/docker/docker/tree/master/experimental
チェックポイント・リストア自体は、Dockerではなく、CRIUという別のOSSの機能を利用している。
CRIUのインストール方法は、
https://criu.org/Installation
を参照。
Dockerでチェックポイント・リストア
https://github.com/docker/docker/blob/master/experimental/checkpoint-restore.md
に記載されているコマンドを利用。1秒ごとに数字をインクリメントさせることで、checkpoint & restoreが正常に動作しているか確認できる。
まず、コンテナの実行。注意点として、-tオプションをつけないこと。
$ docker run --name cr_test -d busybox sh -c 'i=0; while true; do echo $i; i=$(expr $i + 1); sleep 1; done'
dd8ddc91cfcbf4059b72291996f647204b06d21790742665e43154eaf61add15
計算状況を確認するために、ログを監視。
$ sudo tail -f /var/lib/docker/containers/dd8ddc91cfcbf4059b72291996f647204b06d21790742665e43154eaf61add15/dd8ddc91cfcbf4059b72291996f647204b06d21790742665e43154eaf61add15-json.log
{"log":"0\n","stream":"stdout","time":"2017-01-04T02:18:53.010675677Z"}
{"log":"1\n","stream":"stdout","time":"2017-01-04T02:18:54.012090836Z"}
{"log":"2\n","stream":"stdout","time":"2017-01-04T02:18:55.021312544Z"}
まず、試しに docker stop & start
を利用してみると、ログは、
{"log":"29\n","stream":"stdout","time":"2017-01-04T02:19:22.114085491Z"}
{"log":"30\n","stream":"stdout","time":"2017-01-04T02:19:23.115126028Z"}
{"log":"0\n","stream":"stdout","time":"2017-01-04T02:19:47.989991578Z"}
{"log":"1\n","stream":"stdout","time":"2017-01-04T02:19:48.992716272Z"}
となっており、計算が0から再開されているのがわかる。詳細はコードを見ないとわからないが、おそらく docker stop & start
では、コンテナ上のプロセスを落とした後に、startで再起動という流れになるため、メモリ情報が失われてしまうだと思われる。
次に、checkpointを取得した後に、restoreを実行。
$ docker checkpoint create cr_test checkpoint1
...
$ docker start --checkpoint checkpoint1 cr_test
すると、ログは、
{"log":"29\n","stream":"stdout","time":"2017-01-04T02:20:17.060391105Z"}
{"log":"30\n","stream":"stdout","time":"2017-01-04T02:20:18.061856991Z"}
{"log":"31\n","stream":"stdout","time":"2017-01-04T02:21:05.921558351Z"}
{"log":"32\n","stream":"stdout","time":"2017-01-04T02:21:06.923784094Z"}
となっており、計算が途中から再開されていることがわかる。
これを活用することで、例えば、計算時間が長いプログラムなどを走らせてるときに、定期的にチェックポイントを取得することで、プロセスが落ちても途中から計算再開といったことが、Dockerのレイヤで可能となる。