CRIU (3)
(ちょっと雑なのであとで書き直すかも?)
前回,CRIU を試してから丁度 1 年.前回はカーネルは 3.7 ベースで専用のもの,CRIU は 0.2 の頃でした.実はこの時も LXC コンテナで dump/restore するのを試したのですが,やり方が悪かったのか,まだ機能的に無理だったのかわかりませんが,うまくいきませんでした.
今や標準カーネルにも Checkpoint/Restore 用の機能の実装もすすみ,CRIU も 0.8 になっています.だいぶ動くようになっているのが以下からもうかがえますね.
というわけで私も少し試してみました.試した! 動いた! ってだけなのであまり役には立たないエントリです.
準備
- カーネルは 3.9 以降のなるべく新しいものを入れましょう
- カーネルの config は Installation - CRIU を参考に,必要に応じて再構築しましょう
- CRIU は 公式ページ からダウンロードしてコンパイルしましょう
- iproute2 はネットワーク名前空間を扱えるものを準備しましょう
準備ができたら
# criu check --ms (00.002480) Warn (tun.c:54): Skipping tun support check Looks good.
とやって Looks good を確認します.
ちなみにこんな環境になっています.
root@enterprise:~# uname -r 3.11.6-plamo64-karma root@enterprise:~# criu --version Version: 0.8 root@enterprise:~# lxc-version lxc version: 1.0.0.alpha2
iproute2 は 3.8.0 でした.
実行
ほぼ LXC - CRIU に書いてある通りです.私は lxc-create -t plamo で作った Plamo コンテナで実行しています.
- まずコンテナを準備しました.しかし /var/lib/lxc/コンテナ名/rootfs 以下のファイルは別の場所に移して,ここは空にします.あとで bind mount します.
# lxc-create -n plamo02 -t plamo
# cd /root ; rsync -a /var/lib/lxc/plamo02 . ; rm -rf /var/lib/lxc/plamo02/rootfs/* - コンテナの設定ファイルを編集します.設定は後で示します.編集のポイントは
- console はなしにする (lxc.console = none)
- あとで実行時に指定するので veth ペアのホスト側のインターフェース名を固定します (lxc.network.veth.pair = plamo02)
- コンテナ内で cgroupfs はマウントしません.これは 1.0alpha 以降でないと普通はしないですね.
- あとは普通に lxc-create で作るテンプレートでいけそうな気がしますが,ここで挙げる例と公式ページの CentOS コンテナの例しか試してませんので他はわかりません
- コンテナ内で実行するデーモンは最低限にしました.Plamo の場合
- コンテナの rootfs を bind mount します.なぜこれが必要なのかはわかりません.
root@enterprise:~# mount --bind /root/plamo02/ /var/lib/lxc/plamo02/rootfs/
- ここでおもむろにコンテナのスタートです.起動してアドレスも割り当たってます.
root@enterprise:~# lxc-start -n plamo02 -d -o log -l DEBUG
root@enterprise:~# lxc-info -n plamo02
state: RUNNING
pid: 7205
ip: 10.0.100.173 - ip コマンドでネットワーク名前空間を操作するために必要なリンクを張ります.これで別の名前空間内の操作が可能になりますね.
root@enterprise:~# ln -sf /proc/7205/ns/net /var/run/netns/plamo02
root@enterprise:~# ip netns exec plamo02 ip a
1: lo:mtu 65536 qdisc noqueue state UNKNOWN
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
inet6 ::1/128 scope host
valid_lft forever preferred_lft forever
9: eth0:mtu 1500 qdisc pfifo_fast state UP qlen 1000
link/ether d2:17:05:04:10:e2 brd ff:ff:ff:ff:ff:ff
inet 10.0.100.173/24 brd 10.0.100.255 scope global eth0
valid_lft forever preferred_lft forever
inet6 fe80::d017:5ff:fe04:10e2/64 scope link
valid_lft forever preferred_lft forever - 確認のために ping
root@enterprise:~# ping 10.0.100.173
PING 10.0.100.173 (10.0.100.173): 56 octets data
64 octets from 10.0.100.173: icmp_seq=0 ttl=64 time=0.0 ms
64 octets from 10.0.100.173: icmp_seq=1 ttl=64 time=0.0 ms
^C
--- 10.0.100.173 ping statistics ---
2 packets transmitted, 2 packets received, 0% packet loss
round-trip min/avg/max = 0.0/0.0/0.0 ms - ここで dump します.指定した /root/dump 以下には *.img というファイルがたくさんできています.
root@enterprise:~# criu dump \
--tcp-established \
--ext-unix-sk \
--file-locks \
-n net -n mnt -n ipc -n pid \
--action-script "/root/network-script.sh dump 7205 plamo02" \
-D /root/dump/ \
-o dump.log \
-vvvv \
-t $1
plamo02<=>eth0
Detach plamo02 to the bridge lxcbr0
root@enterprise:~# ls /root/dump
core-1.img fdinfo-11.img fs-77.img itimers-77.img pages-4.img rlimit-68.img signal-s-111.img
core-104.img fdinfo-2.img ids-1.img mm-1.img pages-5.img rlimit-77.img signal-s-112.img
core-109.img fdinfo-3.img ids-104.img mm-104.img pages-6.img route-7.img signal-s-113.img
core-110.img fdinfo-4.img ids-109.img mm-109.img pages-7.img sigacts-1.img signal-s-142.img
core-111.img fdinfo-5.img ids-110.img mm-110.img pages-8.img sigacts-104.img signal-s-68.img
core-112.img fdinfo-6.img ids-111.img mm-111.img pages-9.img sigacts-109.img signal-s-77.img
core-113.img fdinfo-7.img ids-112.img mm-112.img pipes-data.img sigacts-110.img signalfd.img
core-142.img fdinfo-8.img ids-113.img mm-113.img pipes.img sigacts-111.img sk-queues.img
core-68.img fdinfo-9.img ids-142.img mm-142.img posix-timers-1.img sigacts-112.img stats-dump
core-77.img fifo-data.img ids-68.img mm-68.img posix-timers-104.img sigacts-113.img stats-restore
core-79.img fifo.img ids-77.img mm-77.img posix-timers-109.img sigacts-142.img tmpfs-49.tar.gz.img
core-80.img filelocks-1.img ifaddr-7.img mountpoints-10.img posix-timers-110.img sigacts-68.img tmpfs-50.tar.gz.img
core-81.img filelocks-104.img inetsk.img netdev-7.img posix-timers-111.img sigacts-77.img tty-info.img
creds-1.img filelocks-109.img inotify-wd.img netlinksk.img posix-timers-112.img signal-p-1.img tty.img
creds-104.img filelocks-110.img inotify.img ns-files.img posix-timers-113.img signal-p-104.img tunfile.img
creds-109.img filelocks-111.img inventory.img packetsk.img posix-timers-142.img signal-p-109.img unixsk.img
creds-110.img filelocks-112.img ipcns-msg-8.img pagemap-1.img posix-timers-68.img signal-p-110.img utsns-9.img
creds-111.img filelocks-113.img ipcns-sem-8.img pagemap-104.img posix-timers-77.img signal-p-111.img vmas-1.img
creds-112.img filelocks-142.img ipcns-shm-8.img pagemap-109.img pstree.img signal-p-112.img vmas-104.img
creds-113.img filelocks-68.img ipcns-var-8.img pagemap-110.img reg-files.img signal-p-113.img vmas-109.img
creds-142.img filelocks-77.img iptables-7.img pagemap-111.img remap-fpath.img signal-p-142.img vmas-110.img
creds-68.img fs-1.img itimers-1.img pagemap-112.img restore.log signal-p-68.img vmas-111.img
creds-77.img fs-104.img itimers-104.img pagemap-113.img rlimit-1.img signal-p-77.img vmas-112.img
dump.log fs-109.img itimers-109.img pagemap-142.img rlimit-104.img signal-p-79.img vmas-113.img
eventfd.img fs-110.img itimers-110.img pagemap-68.img rlimit-109.img signal-p-80.img vmas-142.img
eventpoll-tfd.img fs-111.img itimers-111.img pagemap-77.img rlimit-110.img signal-p-81.img vmas-68.img
eventpoll.img fs-112.img itimers-112.img pages-1.img rlimit-111.img signal-s-1.img vmas-77.img
fanotify-mark.img fs-113.img itimers-113.img pages-10.img rlimit-112.img signal-s-104.img
fanotify.img fs-142.img itimers-142.img pages-2.img rlimit-113.img signal-s-109.img
fdinfo-10.img fs-68.img itimers-68.img pages-3.img rlimit-142.img signal-s-110.img- ここで指定している network-script.sh は 公式ページに案内されているスクリプト] を少し変えたものです(手元では veth ペアの親側は br0 ではなく lxcbr0 にアタッチしてるので).
- ここで ping をしても届きません.lxc-info も STOPPED に.
root@enterprise:~# ping 10.0.100.173
PING 10.0.100.173 (10.0.100.173): 56 octets data
^C
--- 10.0.100.173 ping statistics ---
2 packets transmitted, 0 packets received, 100% packet loss
root@enterprise:~# lxc-info -n plamo02
state: STOPPED - restore します.そのまま返ってこないので ^C で終わらせます.
root@enterprise:~# criu restore \
--tcp-established \
--evasive-devices \
-n net -n mnt -n ipc -n pid \
--action-script "/root/network-script.sh restore plamo02" \
--veth-pair eth0=plamo02 \
--root /var/lib/lxc/plamo02/rootfs \
-D /root/dump \
-o restore.log \
-vvvv
Attach plamo02 to the bridge lxcbr0
^Croot@enterprise:~# - 復帰しているか確認です
root@enterprise:~# ping 10.0.100.173
PING 10.0.100.173 (10.0.100.173): 56 octets data
64 octets from 10.0.100.173: icmp_seq=0 ttl=64 time=0.0 ms
64 octets from 10.0.100.173: icmp_seq=1 ttl=64 time=0.0 ms
^C
--- 10.0.100.173 ping statistics ---
2 packets transmitted, 2 packets received, 0% packet loss
round-trip min/avg/max = 0.0/0.0/0.0 ms
root@enterprise:~# pstree -p
init(1)-+-Thunar(4186)
|-agetty(3991)
: (snip)
|-init(7415)-+-dhclient(7438)
| |-rsyslogd(7436)-+-{rsyslogd}(7443)
| | |-{rsyslogd}(7444)
| | `-{rsyslogd}(7445)
| |-saslauthd(7435)-+-saslauthd(7439)
| | |-saslauthd(7440)
| | |-saslauthd(7441)
| | `-saslauthd(7442)
| `-sshd(7434)
ちゃんと期待するコンテナ内のプロセスが上がっているのが確認できるかと思います.
ちなみに復帰後は lxc-start で起動してないから,lxc ツールのモニタリングに必要な処理がされてないためと思われますが,lxc-info は STOPPED のままです.lxc-stop なんかで止めることはできないので,なんらかの手段でシャットダウンするか,強引に init を kill するかになります.
まだコンテナ側に色々工夫が必要で,普通に起動したコンテナを dump/restore するのは無理ですが,確実に進化していますね :-) 詳しい仕組みは賢い人がきっと説明してくれるでしょう ;-D
(もう少し丁寧に例を挙げて説明するかも?)