TenForward

技術ブログ。はてなダイアリーから移転しました

lxc-checkpoint で CRIU を使って LXC コンテナの checkpoint/restore 処理

CRIUを最後に試したのは昨年11月でした。

いつの間にやらバージョンも 1.3 とかで進化しています。でも LXC できちんと動かないよという話だったので動向だけ見守っていました。まあ、前回でもそれなりには動いていましたが。最近、Add support for checkpoint and restore via CRIU · lxc/lxc@735f2c6 · GitHub で LXC が CRIU 対応し lxc-checkpoint というコマンドが新しく実装されました。

早速触ってみました。試したのは以下の環境です。プレーンな環境なのでコンテナに限らず新しいモノを触るのに最適ですよ! > Plamo Linux

  • Plamo 5.2 (x86_64)
  • Kernel 3.16.1 (自前ビルド)
  • LXC, CRIU は master ブランチの最新

カーネルで必要な config があるので、そのあたり不足していればカーネル作りなおしてください。

# criu check --ms
Warn  (tun.c:55): Skipping tun support check
Warn  (timerfd.c:44): timerfd: Skipping timerfd support check
Warn  (cr-check.c:260): Skipping mnt_id support check
Looks good.

コンテナの作成と設定ファイル

  1. ホストで fuse モジュールが読み込まれているとダメなのでロードされないようにしました。
  2. まずは通常通りコンテナを作成します。Ubuntu Trusty (amd64) のコンテナにしました。私の環境は /var/lib/lxc は btrfs なので一応 btrfs を指定しています。
    # lxc-create -n ct01 -t download -B btrfs -- -d ubuntu -r trusty -a amd64
  3. まずはコンテナを起動させて、動作確認のためにコンテナに nginx をインストールしておきました。
  4. 設定ファイルを書き換えます。デフォルトだと ubuntu.common.conf と common.conf を include しているので include をやめて全部直に書きます。
    # cd /var/lib/lxc/ct01
    # mv config config.tmp
    # cp /usr/share/lxc/config/common.conf > config
    # cat /usr/share/lxc/config/ubuntu.common.conf >> config
    # cat config.tmp >> config
    ここでのキモは
    lxc.tty = 0
    lxc.console = none
    lxc.cgroup.devices.deny = c 5:1 rwm
    です。この 3 つは LXC - CRIU で指定されている設定で、lxc-checkpoint でも criu コマンドを実行する前にチェックされます。必要な設定がないと LXC のチェックでひっかかります。
    # lxc-checkpoint -v -n ct01 -s -D /root/criu
    lxc_container: couldn't find devices.deny = c 5:1 rwm
    Checkpointing ct01 failed.
  5. /sys 以下の bind mount があるとダメだったのでコメントアウトしました。

最終的にこんな設定ファイルになってます。

lxc.tty = 0
lxc.console = none
lxc.cgroup.devices.deny = c 5:1 rwm

lxc.pts = 1024

lxc.cap.drop = mac_admin mac_override sys_time sys_module

lxc.pivotdir = lxc_putold

lxc.hook.clone = /usr/share/lxc/hooks/clonehostname

lxc.cgroup.devices.deny = a
lxc.cgroup.devices.allow = c *:* m
lxc.cgroup.devices.allow = b *:* m
lxc.cgroup.devices.allow = c 1:3 rwm
lxc.cgroup.devices.allow = c 1:5 rwm
lxc.cgroup.devices.allow = c 1:7 rwm
lxc.cgroup.devices.allow = c 5:0 rwm
lxc.cgroup.devices.allow = c 5:2 rwm
lxc.cgroup.devices.allow = c 1:8 rwm
lxc.cgroup.devices.allow = c 1:9 rwm
lxc.cgroup.devices.allow = c 136:* rwm

lxc.seccomp = /usr/share/lxc/config/common.seccomp

lxc.mount.entry = proc proc proc nodev,noexec,nosuid 0 0
lxc.mount.entry = sysfs sys sysfs defaults 0 0
lxc.mount.entry = /sys/fs/fuse/connections sys/fs/fuse/connections none bind,optional 0 0
#lxc.mount.entry = /sys/kernel/debug sys/kernel/debug none bind,optional 0 0
#lxc.mount.entry = /sys/kernel/security sys/kernel/security none bind,optional 0 0
lxc.mount.entry = /sys/fs/pstore sys/fs/pstore none bind,optional 0 0

lxc.cgroup.devices.allow = c 254:0 rm
lxc.cgroup.devices.allow = c 10:229 rwm
lxc.cgroup.devices.allow = c 10:200 rwm
lxc.cgroup.devices.allow = c 10:228 rwm
lxc.cgroup.devices.allow = c 10:232 rwm
lxc.arch = x86_64

lxc.rootfs = /var/lib/lxc/ct01/rootfs
lxc.utsname = ct01

lxc.network.type=veth
lxc.network.link=lxcbr0
lxc.network.flags=up

コンテナイメージ内

コンテナの rootfs 以下のファイルも少し調整します。

  1. udev は起動させないように、と CRIU ページにあったので /etc/init/udev.conf を削除
    # rm /var/lib/lxc/ct01/rootfs/etc/init/udev.conf
  2. console, tty は無効にしてますので、その関係も一応 /etc/init 以下から削除しました。まあこれは削除しなくてもエラーで起動しないだけかも。

checkpoint 処理

ではコンテナを起動させます。きちんと動作しています。

# lxc-start -n ct01
# lxc-ls --fancy
NAME  STATE    IPV4          IPV6  GROUPS  AUTOSTART  
----------------------------------------------------
ct01  RUNNING  10.0.100.119  -     -       NO         

nginx を入れたのでその動作確認。

# curl -I http://10.0.100.119/
HTTP/1.1 200 OK
Server: nginx/1.4.6 (Ubuntu)
Date: Fri, 29 Aug 2014 09:00:59 GMT
Content-Type: text/html
Content-Length: 612
Last-Modified: Tue, 04 Mar 2014 11:46:45 GMT
Connection: keep-alive
ETag: "5315bd25-264"
Accept-Ranges: bytes

lxc-checkpoint を実行します。lxc-checkpoint は必要なチェックや準備をしてからインストールされている criu コマンドを実行します。criu をデーモンで動かしておく必要はありません。

  • 指定オプション
    • -v : criu のログの verbose モード指定
    • -s : checkpoint が終わったらコンテナを停止させる
    • -D : dump ファイルの置き場所
# lxc-checkpoint -v -n ct01 -s -D /root/criu 
# lxc-ls --fancy
NAME  STATE    IPV4  IPV6  GROUPS  AUTOSTART  
--------------------------------------------
ct01  STOPPED  -     -     -       NO         

エラーなく終わると黙って lxc-checkpoint は終了します。-s を指定したのでコンテナも停止しています。

# curl -I http://10.0.100.119/
^C

コンテナが止まってるから当然 nginx とか反応しません。

ダンプファイル指定した場所にたくさんの dump ファイルができています。

# ls /root/criu/
bridge0            fs-151.img          pagemap-257.img
cgroup.img         fs-248.img          pagemap-289.img
core-1.img         fs-254.img          pagemap-373.img
core-141.img       fs-257.img          pagemap-374.img
core-151.img       fs-289.img          pagemap-389.img
core-248.img       fs-373.img          pagemap-390.img
core-249.img       fs-374.img          pagemap-391.img
core-250.img       fs-389.img          pagemap-393.img
core-252.img       fs-390.img          pagemap-394.img
core-254.img       fs-391.img          pagemap-566.img
core-257.img       fs-393.img          pagemap-568.img
core-289.img       fs-394.img          pagemap-570.img
core-373.img       fs-566.img          pagemap-572.img
core-374.img       fs-568.img          pagemap-574.img
core-389.img       fs-570.img          pagemap-shmem-60541.img
  : (snip)

たくさんすぎるので省略。

restore 処理

では dump ファイルから restore 処理を行って、コンテナを起動させましょう。

  • 指定したオプション
    • -r : restore 処理を行う
    • -d : restore 後、コンテナをデーモンモードで起動
# lxc-checkpoint -v -n ct01 -r -d -D /root/criu 
# lxc-ls --fancy
NAME  STATE    IPV4          IPV6  GROUPS  AUTOSTART  
----------------------------------------------------
ct01  RUNNING  10.0.100.119  -     -       NO         

起動しました。nginx の起動を確認してみましょう。

# curl -I http://10.0.100.119/
HTTP/1.1 200 OK
Server: nginx/1.4.6 (Ubuntu)
Date: Fri, 29 Aug 2014 09:02:21 GMT
Content-Type: text/html
Content-Length: 612
Last-Modified: Tue, 04 Mar 2014 11:46:45 GMT
Connection: keep-alive
ETag: "5315bd25-264"
Accept-Ranges: bytes

問題なく起動しており、コンテナ内のプロセスも無事復帰しているのがわかります。

チェックポイント機能として働いているかまではチェックしてないけど、とりあえずこんなところで。

(続くかも)