第521回から紹介しているLXD 3.0の基本的な使い方シリーズ。今回はスナップショットとリストア、それにコンテナのマイグレーションについて紹介します。
LXDコンテナのバックアップとリストア
LXDはシステムコンテナです。つまりDockerコンテナのように不変(immutable)で使い捨て(disposable)可能な使い方ではなく、むしろvirt-manager/KVMやVMWareのように、システムを立ち上げたあとにログインして様々な変更を加えることで、最終的なイメージを構築する使い方を想定しています。
今そこにあるLXDコンテナが、もう一度まったく同じ構成で構築可能かどうかは運用次第です。実運用で使っているコンテナであれば、おそらくcloud-initやAnsibleで再構築可能でしょう。ポリシーによっては、ドキュメントでフォローしているかもしれません。
ただし実験目的でちょっと作ったコンテナにそこまで手間をかけていられないかもしれません。また「試しに何かする」際に「前の状態を残しておきたい」ケースもよくあります。
そこでLXDでは、virt-manager/KVMやVMWareのような仮想マシンシステムと同じように、次のようなコンテナイメージのバックアップ・リストア機能を備えています。
- 停止中のコンテナを他のホストへ移動するマイグレーション機能
- 停止中のコンテナを他のホストへ複製するコピー機能
- 稼働中のコンテナをステートレスに保存するスナップショット機能
- 稼働中のコンテナをステートフルに保存するスナップショット機能
- スナップショットされたコンテナをリストアする機能
- スナップショットをベースイメージとしてエクスポートする機能
- ベースイメージをインポートする機能
- クラスタとして構成されたLXDホスト間でイメージを同期する機能
- 稼働中のコンテナを他のホストへ移動するライブマイグレーション機能(実験的な機能)
今回はこのスナップショットを利用したバックアップとリストア、さらには別ホストとのマイグレーションについても紹介しましょう。
今回もUbuntu 18.04 LTSとLXD 3.0.xの環境をベースに紹介します。debパッケージ版とsnap版でほぼ違いはありませんが、もし違いがある場合は都度説明します。
LXDのスナップショット機能
コンテナのスナップショットを取る方法は至極簡単です。まずは適当なコンテナを作っておきます。
lxc info
はスナップショット作成後との比較のために表示しています。
さて、現在の状態のスナップショットを取ってみましょう。スナップショットはコンテナが起動状態でも取得できます。取得方法は「lxc snapshot コンテナ名 スナップショット名
」です。スナップショット名を省略した場合は「snap0」から始まる連番の名前が自動的に付与されます。
コンテナの情報にスナップショットが追記されていることがわかりますね。
さっそく作ったスナップショットをリストアしてみましょう。リストアされたことがわかるよう、あらかじめコンテナに変更を加えておきます。
最後のuptimeは、kasumiコンテナが起動していた時間を確認しています。
実はLXDの普通のリストアは、対象となるコンテナを停止させる必要があります。もし起動中のコンテナに対してリストアを実行した場合、一度コンテナを停止し(シャットダウンし)、リストアを実行した上で、自動的に再起動します。たとえばSSHでログインしているなら、リストアによって一度切断されます。
一時的であれコンテナが停止すると困る場合は、「--stateful
」オプションを利用してステートフルなスナップショット・リストアを使いましょう[1]。
リストアは「lxc restore コンテナ名 スナップショット名
」で実施します。
先ほど作成したsnap0が、リストアによって削除されていることがわかります。さらにリストア対象のコンテナが再起動したために、uptimeが0分に戻っています。
LXDコンテナはシステムコンテナとは言え、カーネルの起動がスキップできるため、ベースコンテナの起動時間は数秒です。よって大抵のケースにおいては、再起動のダウンタイムはそこまで気にするほどの長さではないでしょう。もちろんcloud-initや、他のサービスによっては起動時間は長くなりますので、プロダクション用途の場合はなんらかの対策が必要になります。
スナップショットの削除はコンテナの削除と同様に「lxc delete
」コマンドを利用します。スナップショット単体で削除したい場合は、「コンテナ名/スナップショット名」と指定してください。
ちなみにLXD 3.8からはコンテナの自動スナップショット設定が追加されました。この設定を利用すると、特定のコンテナに対して定期的に任意の名前でスナップショットを作成できます。
コンテナのバックアップ
スナップショット機能はコンテナのバックアップにも利用できます。
具体的にはコンテナのルートファイルシステムをアーカイブしたい場合、コンテナ以外にもスナップショットを指定できるのです。つまり特定のスナップショットをリストアすることなく、他のLXDホストでそのスナップショットを復活する際にこの機能を活用できます。
まずは先ほどと同様にkasumiコンテナベースで、snap1ファイルを作成したrimiコンテナを作成しましょう。
次にスナップショットをコンテナイメージに変換します。コンテナイメージはインスタンスを作る際のベースイメージです。ベースイメージは別のコンテナインスタンスを作る際にも利用できます。たとえばLXDホストで初めてコンテナを作る際は、大抵の場合はUbuntuのベースイメージをインターネット経由でダウンロードしているはずです。
コンテナイメージの作成には「lxc pulbish コンテナ名
」を使用します。コンテナ名の部分にはコンテナ名単体を指定すればそのコンテナを、スナップショット名も追加すればスナップショットをイメージに変換します。
また「--alias
」オプションで別名をつけることが可能です。別名をつけておくと、今後そのコンテナを指定する際に操作が楽になります。別名をつけなかった場合は、フィンガープリントでイメージを指定しなくてはなりません。
実際に作成されたイメージを確認しましょう。
「c234ecee3baa」はkasumiコンテナを作成したときにダウンロードしたUbuntu 18.04 LTSのベースイメージです。rimiスナップショットとサイズが異なるのは、おそらくインスタンス化の際に/var/logなどが生成されたからでしょう。
もちろん新しく作ったコンテナイメージをベースに新しいコンテナを作ることも可能です。
taeコンテナには最初からsnap1ファイルが作られていますね。このようにコンテナ・スナップショットのイメージ化もバックアップとして利用できます。
次は先ほど作ったコンテナをアーカイブにしてしまいましょう。
アーカイブ化のコマンドは「lxc image export イメージ名 アーカイブ名
」です。イメージ名には先ほどつけた別名はもちろんのこと、別名がない場合はフィンガープリントを指定します。アーカイブ名は出力先のファイル名です。実際には「アーカイブ名.tar.gz」の名前がついたファイルが作られます。
内容はルートファイルシステムをただtar.gzでアーカイブしたものです。またトップディレクトリにはmetadata.yamlやtemplatesというコンテナに関する情報が記録されたファイルやディレクトリも含まれています。いずれにせよルートファイルシステムであることには変わりないので、LXDに限らずいろいろな用途に使えます。
systemd-nspawnで使用する
たとえば第491回で紹介しているような、systemd-nspawnを使ってみましょう。
「--network-bridge=lxdbr0
」オプションをつけることで、LXDが作成するブリッジインターフェースであるlxdbr0に接続したネットワークインターフェースを作成します。このオプションか他の方法でネットワーク接続しておかないと、DHCPでコンテナにアドレスが渡されないので注意してください。
さて、Ubuntuのコンテナイメージにはubuntuアカウントは作られているものの、パスワードは無効化されています。またSSHサーバーは動いているものの、公開鍵認証のみとなっています。つまりこのままだとログインできません。
方法はいくつかあるのですが、ここではssh-import-idコマンドを使って、対象となるルートファイルシステムのホームディレクトリにauthorized_keysを作ってしまいましょう。
「gh:m-shibata」を指定することで、GitHub上のm-shibataアカウントの公開鍵を取得し、「-o
」で指定したファイルに保存してくれます。もちろんcatなどで直接authorized_keysを編集しても良いですし、「/etc/passwd
」を編集するという方法もあります。
起動したコンテナのIPアドレスはmachinectlコマンドで確認できます。
あとは「ubuntu@10.164.119.197
」にログインするだけです。ログイン後は普通のコンテナとして操作できます。もし終了したいならコンテナの中から、shutdownコマンド等を実行してください。
もしログインしていない環境からシャットダウンしたいなら、上記と同じようにmachinectlコマンドを利用できます。
他のLXDインスタンスで利用する
アーカイブ化したコンテナイメージは、他のLXDインスタンスにもインポート可能です。
これだけですね。もちろんpublishのときと同じように「--alias
」オプションで別名をつけられます。
ちなみにイメージをアーカイブしたLXDインスタンスでは、フィンガープリントが衝突してしまうため、そのアーカイブをインポートできません。言い方を変えると、一度インスタンスから衝突するイメージを削除してしまえば、アーカイブからのインポートが可能になります。
LXDコンテナのマイグレーション
単純にあるLXDホストで動いているコンテナを、別のLXDコンテナで動かしたいだけなら、LXD API over HTTPSを利用したマイグレーションという方法があります。ただし2台以上のホストの間でマイグレーションを行うには事前設定が必要です。
まず対象のホストのうちいずれか1台のLXDコンテナのリモートアクセスを有効化します。今回のようなマイグレーションの場合は、マイグレーション元・先どちらのリモートアクセスを有効化してもかまいません。本記事ではkasumiコンテナが存在していたほうのホストをリモート側、リモート側にアクセスするホストをクライアント側とし、リモート側のリモートアクセスを有効化することにしましょう。
「core.https_address
」にはリモートホストでbindするIPアドレスを設定します。上記のように「[::]
」と設定しておけば、リモートホスト上のすべてのアドレスにbindします。また末尾に「:443
」と加えることで特定のポートを指定可能です。未指定の場合は8443番ポートを利用します。
「core.trust_passwd
」にはクライアント側からこのリモートLXDホストにアクセスする際のパスワードを指定します。
最後に表示しているのはリモートホストの証明書のフィンガープリントです。クライアント側から接続する際に正しいリモートに接続しようとしているかを確認する際に使用します。
クライアント側は、「lxc remote add
」コマンドでリモート側のアドレスを指定します。ここではホスト名を指定していますが、IPアドレスでもかまいません。
「Certificate fingerprint」にリモート側のフィンガープリントが表示されているので、先ほどリモート側で表示したそれと一致しているか確認してください。問題なければリモート側で設定したパスワードを入力し、登録完了です。
リモートLXDは「リモート名:」で指定します。最後のコロンが重要です。コマンドによっては最後のコロンがないとコンテナ名として認識してしまうので注意してください。
さっそくリモートのコンテナをコピーしてみましょう。今回はコールドマイグレーションなので、リモート側のkasumiコンテナは停止しておいてください。ちなみにリモート側のLXDサービスにアクセス可能なので、クライアント側からもリモートのkasumiコンテナを操作できます。
スナップショットごと移動されていることがわかりますね。copyコマンドはさまざまなオプションを渡すことで、コピー先の状態をコントロールできます。詳しいことは「lxc copy -h
」を確認してください。
copyコマンドはコピー元にコンテナを残します。もしコピー元からコンテナを残したくない場合は、copyの代わりにmoveコマンドを利用します。ちなみにローカルのコンテナ名やスナップショット名を変更したい場合にもmoveコマンドを利用できます。
LXDのライブマイグレーション
第459回の最後でも紹介したように、LXDはコンテナのライブマイグレーションにも実験的に対応しています[2]。これはコンテナをステートフルな状態で保存し、そのままホスト間を移動して、移動先で再稼働させるモードです。また、同様にコンテナのステートフルなスナップショット・リストアにも対応しています。
ライブマイグレーション機能を有効化するには、CRIUパッケージが必要です。Ubuntu 18.04 LTSのサーバー版のように、DebianパッケージとしてLXDをインストールしている場合は、次のようにインストールしてください。
snapパッケージ版のLXDを利用している場合は、CRIUはインストール済みなので、snapコマンドから機能を有効化します。また、有効化後にLXDサービスを再起動する必要があります。
上記はローカルとリモート両方で設定しておいてください。
また、ローカルとリモートの両方でネットワークの設定をあわせておく必要もあります。リモート側で「lxc network show lxdbr0
」を実行した結果を記録しておき、ローカル側で「lxc network edit lxdbr0
」を実行して、ipv4.addressとipv6.addressを揃えておけば良いでしょう。
実際にsayaで動いているtaeコンテナをローカルにマイグレーションしてみましょう。
これで本来はマイグレーション完了なはずです。はずではあるのですが、環境によって成功したり失敗しました。
ライブマイグレーションを実施するには、リモートとホストでLXDの設定を合わせておく必要があるなど、まだまだ事前準備が必要な状況です。あくまで実験的な機能と考え、普段はコールドなマイグレーションを活用してください。
なお、LXD 3.0からはクラスタリング機能が追加されました。今回は特定のホストのLXDサービスだけ公開し、それ以外のホストからアクセスする形態をとりましたが、クラスタリング機能を使うと複数のホストをひとつのLXDサービスのように見せることが可能になります。クラスタリング機能を使うなら、ホスト間のストレージやネットワーク設定も自動的に同期を取ることになるので、コンテナの移動がより便利になることでしょう。