LXDでコンテナのライブマイグレーションやってみた

最近自分の周りでDockerの話しか聞かなくて、寂しくなってきたので書いてみました(笑)

以前LXCの非特権コンテナをマイグレーションする記事は書いたのですが、コンテナを止めてtarで固めて移行先で展開するという原始的なものでした。

LXCの非特権コンテナを別ホストに移行する - くろの雑記帳

LXDの登場により、マイグレーション自体コマンド一発でできるようになりましたし、さらに条件付きでライブマイグレーションもできるようになったのでその紹介です。

LXDって?

一言でいうと、

LXD はコンテナの『ハイパーバイザ』であり、LXC の新しいユーザ体験です。

Linux Containers - LXD - イントロダクション

ということですが、もう少し詳しく言うと、 LXDがLinuxコンテナ(LXC)を管理するシステム全体のデーモンとして動いてくれて、REST APIを提供してくれます。

また、コマンドラインインターフェイスとしてlxcというコマンドが用意されています。

環境構築

今回はサーバを2台使います。同じ構成で、

  • Ubuntu Server 15.04
  • CPU 1コア
  • Mem 1GB
  • Disk 8GB

です。

ホスト名はそれぞれ、ip-172-31-29-89ip-172-31-29-90です。ユーザ名はubuntuにしました。

インストール

2台とも同じように構築してください。

LXDのインストール

# 開発が活発なので、最新版を使います
$ sudo apt-add-repository -y ppa:ubuntu-lxc/daily
$ sudo apt-add-repository -y ppa:ubuntu-lxc/lxd-git-master
$ sudo aptitude update
# lxdをインストール
$ sudo aptitude install lxd

liblxcがlxcfsを使ってのライブマイグレーションをまだサポートしていないらしいので、lxcfsをアンインストールします。

Live Migration in LXD | Ubuntu Insights

$ sudo aptitude remove lxcfs

ここまで行ったあと、一旦ログアウトしてログインしなおします。ubuntuユーザがlxdグループに追加されるはずです。

criuをインストール

動いているコンテナを状態を保存して止めるためには、checkpoint/restart機能を提供してくれるcriuが必要です。 プロセスの状態をファイルに保存して、それを展開する事でプロセスを再開することができます。

$ sudo aptitude install criu

extraカーネルをインストール

netlink_diagというモジュールがないとライブマイグレーションできないようなのですが、入っていなかったので、extraカーネルイメージをインストールしました。

以下のコマンドで、netlink_diag.koが存在していれば、この手順は必要ありません。

$ ls -l /lib/modules/{今使用しているカーネルバージョン}-generic/kernel/net/netlink

なければインストールします。バージョンは使用しているカーネルに合わせてください。

$ sudo aptitude install linux-image-extra-3.19.0-25-generic

設定

パスワード

ホスト同士がrest apiで通信するのでパスワードを設定します。それぞれ、hogehogefugafugaにしました。

以前はset passwordだったような気がするのですが、set core.trust_passwordになっていました。

# ip-172-31-29-89
ubuntu@ip-172-31-29-89:~$ lxc config set core.trust_password hogehoge
# ip-172-31-29-90
ubuntu@ip-172-31-29-90:~$ lxc config set core.trust_password fugafuga

リモートの追加

それぞれのサーバで、自身ともう一方をリモートとして登録します。パスワードは先ほど設定したものです。

# ip-172-31-29-89
ubuntu@ip-172-31-29-89:~$ lxc remote add ip-172-31-29-90 ip-172-31-29-90
Certificate fingerprint: 06 f0 4d fe f1 60 6a 45 d9 6f bb 4a 65 c7 7f 15 6b 97 21 28 73 6d 86 b7 e2 e8 33 df 65 d1 0b c0
ok (y/n)? y
Admin password for ip-172-31-29-90: fugafuga
Client certificate stored at server:  ip-172-31-29-90
ubuntu@ip-172-31-29-89:~$ lxc remote add ip-172-31-29-89 ip-172-31-29-89
Certificate fingerprint: 56 df 86 39 94 89 fd fe 9a b5 e3 7f 5b 94 4a cb ba 80 f0 94 f9 e9 f2 6c a7 cd 2c 78 b3 9c 35 fc
ok (y/n)? y
Admin password for ip-172-31-29-89: hogehoge
Client certificate stored at server:  ip-172-31-29-89
# ip-172-31-29-90
ubuntu@ip-172-31-29-90:~$ lxc remote add ip-172-31-29-90 ip-172-31-29-90
Admin password for ip-172-31-29-90: fugafuga
Certificate fingerprint: 06 f0 4d fe f1 60 6a 45 d9 6f bb 4a 65 c7 7f 15 6b 97 21 28 73 6d 86 b7 e2 e8 33 df 65 d1 0b c0
ok (y/n)? y
Client certificate stored at server:  ip-172-31-29-90
ubuntu@ip-172-31-29-90:~$ lxc remote add ip-172-31-29-89 ip-172-31-29-89
Certificate fingerprint: 56 df 86 39 94 89 fd fe 9a b5 e3 7f 5b 94 4a cb ba 80 f0 94 f9 e9 f2 6c a7 cd 2c 78 b3 9c 35 fc
ok (y/n)? y
Admin password for ip-172-31-29-89: hogehoge
Client certificate stored at server:  ip-172-31-29-89

リモートが追加されたか確認してみます。

ubuntu@ip-172-31-29-90:~$ lxc remote list
ip-172-31-29-89 <https://ip-172-31-29-89:8443>
ip-172-31-29-90 <https://ip-172-31-29-90:8443>
local <unix:///var/lib/lxd/unix.socket>

ライブマイグレーション用profile作成

プロファイルを作ります。以下のコマンドを入れると、エディタが立ち上がるので編集します。copyできるので片側のサーバで設定すればOKです。

デフォルトは非特権コンテナなのですが、ライブマイグレーションがまだサポートされていないので、特権コンテナで起動するように設定します。

$ ubuntu@ip-172-31-29-89:~$ lxc profile copy default criu
$ ubuntu@ip-172-31-29-89:~$ lxc profile edit criu
name: criu
config:
  raw.lxc: |
    lxc.console = none
    lxc.cgroup.devices.deny = c 5:1 rwm
    lxc.start.auto =
    lxc.start.auto = proc:mixed sys:mixed
  security.privileged: "true"
devices: {}

作ったプロファイルをもう一方のホストにもコピーする必要があるため、以下のコマンドを打ちます。

ubuntu@ip-172-31-29-89:~$ lxc profile copy ip-172-31-29-89:criu ip-172-31-29-90:criu

コンテナを作る

ip-172-31-29-89からip-172-31-29-90マイグレーションしようと思うので、ip-172-31-29-89にだけコンテナを作ります。

イメージ取得

ubuntuのコンテナイメージを取得します。(最初の一回だけ必要です)

ubuntu@ip-172-31-29-89:~$ lxd-images import lxc ubuntu trusty amd64 --alias ubuntu

コンテナ生成

container01という名前のコンテナを作ります。

ubuntu@ip-172-31-29-89:~$ lxc init ubuntu container01

コンテナにプロファイルを設定します。

ubuntu@ip-172-31-29-89:~$ lxc profile apply container01 default,criu
Profile default,criu applied to container01

コンテナを起動する

ubuntu@ip-172-31-29-89:~$ lxc start container01
ubuntu@ip-172-31-29-89:~$ lxc list
+-------------+---------+------+------+-----------+-----------+
|    NAME     |  STATE  | IPV4 | IPV6 | EPHEMERAL | SNAPSHOTS |
+-------------+---------+------+------+-----------+-----------+
| container01 | RUNNING |      |      | NO        | 0         |
+-------------+---------+------+------+-----------+-----------+

IPV4の項目が空だった場合は、ホスト側でdnsmasqが動いているので、DHCPでアドレスを取得します。

ubuntu@ip-172-31-29-89:~$ lxc exec container01 dhclient

コンテナをライブマイグレーションする!

ようやくという感じがしますが、ここまで準備したらあとはコマンド一発打つだけでライブマイグレーションできちゃいます。

移行前のホストで確認

ubuntu@ip-172-31-29-89:~$ lxc list
+-------------+---------+------------+------+-----------+-----------+
|    NAME     |  STATE  |    IPV4    | IPV6 | EPHEMERAL | SNAPSHOTS |
+-------------+---------+------------+------+-----------+-----------+
| container01 | RUNNING | 10.0.3.187 |      | NO        | 0         |
+-------------+---------+------------+------+-----------+-----------+

ip-172-31-29-89からip-172-31-29-90マイグレーションを実行!

ubuntu@ip-172-31-29-89:~$ lxc move ip-172-31-29-89:container01 ip-172-31-29-90:container01
# コマンドが終わるまで(15秒くらい)待つ
ubuntu@ip-172-31-29-89:~$ lxc list
+------+-------+------+------+-----------+-----------+
| NAME | STATE | IPV4 | IPV6 | EPHEMERAL | SNAPSHOTS |
+------+-------+------+------+-----------+-----------+
+------+-------+------+------+-----------+-----------+

ip-172-31-29-89からは先ほどのコンテナは消えてしまいました。では、ip-172-31-29-90の方はというと…?

ubuntu@ip-172-31-29-90:~$ lxc list
+-------------+---------+------------+------+-----------+-----------+
|    NAME     |  STATE  |    IPV4    | IPV6 | EPHEMERAL | SNAPSHOTS |
+-------------+---------+------------+------+-----------+-----------+
| container01 | RUNNING | 10.0.3.187 |      | NO        | 0         |
+-------------+---------+------------+------+-----------+-----------+

無事マイグレーションされています!

その他

LXDでコンテナのライブマイグレーションに成功したのですが、実際のダウンタイムはどれくらいなんだろう?と思って、コンテナのnicをNATのネットワークではなく、ブリッジに接続し、外部からpingを打ち続けてみたのですが、pingの応答がなかったのは3秒くらいでした。

ただし、コンテナと通信を頻繁に行ったり、ディスクに書き込みをしている状態でマイグレーションをしようとすると、リソースのロックに失敗して、マイグレーションが失敗してしまいました。

失敗の仕方も、マイグレーションせず元の状態で動き続けたり、コンテナが停止してしまったりと不安定で、色々制約もありますので、実用レベルとは言えません。

コンテナを停止してからのマイグレーションは特別なプロファイルの設定も要りませんし、特に問題ありませんでした。LXDの開発は活発なようなので、今後も期待です!