この文書について
この文書は、連載記事「LXD 2.0: Blog post series」(日本語版目次)の一つである以下の記事を翻訳したものです。
この文書のライセンスは原文と同じく、Creative Commons BY-NC-SA 2.5のもとに提供されています。
リモートプロトコル
LXD 2.0は次のふたつのプロトコルをサポートしています:
- LXD 1.0 API: クライアントとLXDデーモン間で使われるREST APIです。同様にLXDデーモン同士でもイメージやコンテナのコピーや移動にも使います。
- Simplestreams: Simplestreamsプロトコルは読み込み専用、イメージ専用のプロトコルで、LXDクライアントとデーモンの双方が(Ubuntuイメージのような)パブリックなイメージサーバーからイメージ情報の取得やイメージのインポートを行う際に使用します。
以下の説明はすべて、これらのうち前者に関連します。
セキュリティ
LXD APIによる認証は、最新の暗号化技術を用いたTLS 1.2越しのクライアント証明書の認証によって行われます。二つのLXDデーモンが直接情報をやりとりする際は、最初にソースとなるデーモンが一時的なトークンを生成し、クライアント越しにターゲットのデーモンへ送られます。そのトークンはその場のストリームでのみ使われ、即座に破棄し、再利用はできません。
中間者攻撃を回避するために、クライアントツールはソースサーバーの証明書をターゲットにも送ります。つまり、特定のダウンロード操作においては、ターゲットサーバーに送信側サーバーのURL、そのリソースに必要なワンタイムのアクセストークン、そのサーバーが使うであろう証明書が提供されます。この方法は中間者攻撃を防ぎ、送信者のオブジェクトの一時的なアクセスのみを与えます。
必要なネットワーク
LXD 2.0は操作のターゲット側(データの受信側)が直に送信側に接続し、データを取得するモデルを採用しています。
これはターゲットサーバーが、ファイヤーウォールなどを越えて、直に送信サーバーに接続できなくてはならないことを意味します。
厳しいファイヤウォールによってホスト間の通信ができない時のために、逆方向の接続やプロキシ越しの接続のサポートも計画しています。
リモートホストへの接続
リモートホストを使いたいユーザーが常にホストネームやIPアドレスを把握し、正しいリモートホストに接続しようとしているか検証する手間を省くために、LXDは「リモート」という概念を導入してます。
初期状態ではLXDは「local:
」リモートのみが設定されています。これは常に規定の(名前を省略した時の)リモートとして使われます。このローカルリモートは、LXD REST APIを使ってunixソケット越しにローカルのデーモンと通信します。
リモートの追加
LXDがインストールされた二つのマシンがあるとします。一つはローカルのマシンで、リモートホストの方は「foo
」と呼ぶことにしましょう。
最初に、「foo
」をリッスン状態にし、パスワードを設定する必要があります。リモートのシェルで次のコマンドを実行してください:
lxc config set core.https_address [::]:8443
lxc config set core.trust_password 何かパスワード
次にローカルのLXDでも、そこからコンテナやイメージを送信できるように、ネットワークに対して見えるように設定する必要があります:
lxc config set core.https_address [::]:8443
両方のデーモンの設定が完了しました。これで「foo
」をローカルのクライアントに追加できます:
lxc remote add foo 1.2.3.4
(ここで1.2.3.4は、IPアドレスかFQDNに変更してください)
次のような感じで表示されることでしょう:
stgraber@dakara:~$ lxc remote add foo 2607:f2c0:f00f:2770:216:3eff:fee1:bd67
Certificate fingerprint: fdb06d909b77a5311d7437cabb6c203374462b907f3923cefc91dd5fce8d7b60
ok (y/n)? y
Admin password for foo:
Client certificate stored at server: foo
リモートのリストを表示したら、「foo
」が追加されていることでしょう:
stgraber@dakara:~$ lxc remote list
+-----------------+-------------------------------------------------------+---------------+--------+--------+
| NAME | URL | PROTOCOL | PUBLIC | STATIC |
+-----------------+-------------------------------------------------------+---------------+--------+--------+
| foo | https://[2607:f2c0:f00f:2770:216:3eff:fee1:bd67]:8443 | lxd | NO | NO |
+-----------------+-------------------------------------------------------+---------------+--------+--------+
| images | https://images.linuxcontainers.org:8443 | lxd | YES | NO |
+-----------------+-------------------------------------------------------+---------------+--------+--------+
| local (default) | unix:// | lxd | NO | YES |
+-----------------+-------------------------------------------------------+---------------+--------+--------+
| ubuntu | https://cloud-images.ubuntu.com/releases | simplestreams | YES | YES |
+-----------------+-------------------------------------------------------+---------------+--------+--------+
| ubuntu-daily | https://cloud-images.ubuntu.com/daily | simplestreams | YES | YES |
+-----------------+-------------------------------------------------------+---------------+--------+--------+
リモートとの通信
さて、リモートサーバーを設定しました。これで何ができるようになるのでしょうか?
これまでの投稿で説明したことはすべてできます。唯一異なるのは、LXDに対してどのホストで実行するかを指定することです。
たとえば次のようなコマンドがあるとします:
lxc launch ubuntu:14.04 c1
上記は規定のリモート(lxc remote get-default
)で実行されるので、ローカルのホストに対して適用されることでしょう。
lxc launch ubuntu:14.04 foo:c1
上記は、その代わりfoo
上でコマンドを実行します。
リモートホスト上の実行中のコンテナを確認したい場合は、次のようになります:
stgraber@dakara:~$ lxc list foo:
+------+---------+---------------------+-----------------------------------------------+------------+-----------+
| NAME | STATE | IPV4 | IPV6 | TYPE | SNAPSHOTS |
+------+---------+---------------------+-----------------------------------------------+------------+-----------+
| c1 | RUNNING | 10.245.81.95 (eth0) | 2607:f2c0:f00f:2770:216:3eff:fe43:7994 (eth0) | PERSISTENT | 0 |
+------+---------+---------------------+-----------------------------------------------+------------+-----------+
一つ注意しなくてはならないのは、イメージとコンテナの双方にリモートを指定しなくてはならないということです。「foo
」上に「my-image
」という名前のローカルイメージが存在し、そのイメージから「c2
」という名前のコンテナを作りたいときは、次のように指定しなくてはなりません:
lxc launch foo:my-image foo:c2
最後に、リモートコンテナへのシェルの実行も、期待通り動作します:
lxc exec foo:c1 bash
コンテナのコピー
ホスト間のコンテナのコピーはとても簡単です:
lxc copy foo:c1 c2
これによりリモートの「c1
」コンテナのコピーがローカルの「c2
」コンテナとして作成されます。「c1
」コンテナはまず停止している必要があります。ただしスナップショットをコピーすることで、コピー元のコンテナを停止せず実行中のままコピーできます:
lxc snapshot foo:c1 current
lxc copy foo:c1/current c3
コンテナの移動
ライブマイグレーション(別の投稿で説明する予定です)をするのでなければ、コンテナを移動する前にそれを停止している必要があります。それ以外は、予想通りの動作になるはずです:
lxc stop foo:c1
lxc move foo:c1 local:
上記の例は以下と同じ動作です:
lxc stop foo:c1
lxc move foo:c1 c1
どのように操作しているのか
リモートコンテナの操作は、想像通りの動きをすることでしょう。LXDは、ローカルのunixソケットに対するREST APIを使うのではなく、同じAPIをHTTPS経由のリモートに対して呼び出しています。
コピーや移動など、二つのデーモン間でやり取りを行う場合、もう少し複雑な処理を行っています。
上記の場合は、次のような処理を行います:
-
利用者は「
lxc move foo:c1 c1
」を実行します。 -
クライアントは
local:
リモートに「c1
」コンテナが存在するかどうか確認します。 -
クライアントは「
foo
」の情報を取得します。 -
クライアントは移動元となる「
foo
」デーモンに対してマイグレーショントークンを要求します。 -
クライアントは移動元のURLと「
foo
」の証明書と同じくマイグレーショントークン、コンテナとデバイスの設定一緒にローカルのLXDデーモンに送ります。 -
ローカルのLXDデーモンは与えられたトークンを用いて直接「
foo
」に接続します。 -
最初にコントロールWebSocketに接続します。
-
ファイルシステムの転送プロトコル(zfsのsend/receiveやbtrfsのsend/receive、もしくは単純なrsync)とネゴシエーションします。
-
もしローカルに存在すれば、移動元のコンテナを作るために使われたイメージを展開します。これにより不要なデータ転送を抑制します。
-
コンテナと、その差分のスナップショットなどを転送します。
-
成功したら、クライアントは移動元のコンテナの削除を「
foo
」に伝えます。
オンラインで試してみる
リモートの操作やコンテナの移動・コピーのための複数のマシンを持っていますでしょうか?
持っていないのなら、オンラインのデモサービスで、この機能を試すことができます。ここで説明している内容を手順に沿って説明しています!
その他の情報
- LXDのウェブサイト:https://linuxcontainers.org/ja/lxd/
- 開発はGitHub上で行なっています:https://github.com/lxc/lxd
- メーリングリスト:https://lists.linuxcontainers.org
- IRCチャンネル:#lxcontainers on irc.freenode.net