KVMのリモート管理

ここでは、KVMホストから virsh あるいは virt-manager (仮想マシンマネージャ) で別の KVMホストへ接続できるようにする方法を述べる。ゲストのライブマイグレーションを行うために、事前準備として必要な作業だ。KVMホストどうしの接続とは、つまり、互いの libvirt フレームワークどうしが通信するということなので、双方で libvirtd が起動していることが大前提となる。

libvirt には、リモート接続の方式として主に 3つが装備されている。libvirt オフィシャルサイトの "Remote Support" に説明がある。

sshトンネルを介した接続:
libvirtssh の機能であるトネリングを通してリモートの libvirt と通信する。最も準備が簡単な方法。
TCP接続:
平文での TCP 通信。libvirt の待ち受けポートのデフォルトは 16509。ユーザ認証には SASL が使用される。準備は比較的簡単。
TLS接続:
TCP 暗号化通信。3つのうちでは最も実運用に適した安全な通信方法。libvirt の待ち受けポートのデフォルトは 16514。サーバ証明書やクライアント証明書を生成するなど、準備は最も大変。基本的には非対称鍵認証なのでパスワードの入力は不要だが、SASL を併用してユーザ名/パスワードを求めるようにすることも可能。

以下に、それぞれの構築手順と接続法を述べる。ホストへのログインや libvirt への接続などは root で行うものとして説明する。

sshトンネルを介した接続

環境設定

ssh のパブリックキー認証 (非対称鍵認証) を設定する。この接続方法で必要なのは純粋に ssh の設定であって、libvirt の設定に変更を加える必要はない。詳細な解説は sshd のページに掲載しているので、手順はそちらを見ていただきたい。ここでは構築のポイントを挙げるに留める。

接続手順

接続元マシンが alpha.hoge.com、リモートのKVMホストが beta.hoge.com だとする。DNS または hosts によって互いに名前解決ができるものとする。

virsh での接続
  1. 接続元 alpha に root でログインする。
  2. 接続するには、ターミナルで下記のように URI を指定する;
root# virsh -c qemu+ssh://beta.hoge.com/system 
virt-manager (仮想マシンマネージャ) での接続

1. 接続元 alpha の X Window に root でログインし、仮想マシンマネージャを起動する。

2. 仮想マシンマネージャの ファイル -> 接続を追加 を選択する。

3. ハイパーバイザー欄と接続欄を左図のように選択し、ホスト名にリモートKVMホストのホスト名を入力して 接続 する。

4. ssh-keygen の際に設定したパスフレーズを入力する。パスフレーズをいちいち訊かれたくないという人は、ssh-agent (キー認証エージェント) を使用するといい。

TCP接続

環境設定[1] 接続先libvirtdの設定変更

まず、libvirtd の基本的な起動オプションを定義する /etc/sysconfig/libvirtd ファイルを開き、既定ではコメントアウトされている下記の部分を有効にする。

LIBVIRTD_ARGS="--listen"

次に、libvirtd の動作設定ファイル /etc/libvirt/libvirtd.conf を開き、幾つかのパラメータを変更する。

listen_tcp = 1
TCP接続用待ち受けポートを開く。TCP接続はデフォルトでは無効になっている。
tcp_port = 16509
TCP接続用の待ち受けポート番号。デフォルトの 16509 から変えたい時以外は編集の必要はない。
auth_tcp = "sasl"
これもデフォルト。TCP接続時に、SASL認証ライブラリを利用してユーザ名とパスワードを尋ねる。auth_tcp="none" にすることもできるが、ユーザ認証も暗号化通信も行われない無防備な状態となり危険。

編集が終わったら、反映のため `service libvirtd restart' で libvirtd を再起動する。

環境設定[2] SASLへのユーザ/パスワード登録

接続先ホストの SASLlibvirt 用のユーザとパスワードを登録する。接続専用のユーザであり、Linux アカウントとは関係ない。

root# saslpasswd2 -a libvirt USER_NAME

データはバークレイDBファイル形式のパスワードファイル /etc/libvirt/passwd.db に保存される。パスワードDB ファイルの PATH は /etc/sasl2/libvirt.confsasldb_path パラメータで定義されている。保存されたことを確認するには、

root# sasldblistusers2 -f /etc/libvirt/passwd.db

接続手順

接続元マシンが alpha.hoge.com、リモートのKVMホストが beta.hoge.com だとする。DNS または hosts によって互いに名前解決ができるものとする。

virsh での接続
  1. 接続元 alpha に root でログインする。
  2. 接続するには、ターミナルで下記のように URI を指定する;
root# virsh -c qemu+tcp://beta.hoge.com/system

待ち受けポート番号 (tcp_port) を例えば 16999 に変更した場合は、URI を qemu+tcp://beta.hoge.com:16999/system のように指定する。

virt-manager (仮想マシンマネージャ) での接続

1. 接続元 alpha の X Window に root でログインし、仮想マシンマネージャを起動する。

2. 仮想マシンマネージャの ファイル -> 接続を追加 を選択する。

3. ハイパーバイザー欄と接続欄を左図のように選択し、ホスト名にリモートKVMホストのホスト名を入力。図のホスト名欄は tcp_port を 16999 に変更した場合で、デフォルトのままならポート指定は要らない。

4. SASL に設定したユーザ名とパスワードを入力する。

TLS接続

環境設定[1] 非対称鍵の配備

下記の手順は libvirt.org の "Remote Support" で解説されている。作業には、GNU TLS Certtool が必要。RedHat系では gnutls-utils パッケージとして提供されている。

1. CAの作成

キーに署名を行うための認証局を作成する。ここでは便宜上、接続先KVMホスト (サーバ) 上に作成するが、接続元 (クライアント) でも接続先でもない別の Linux マシン上でも構わない。1ヶ所だけあればいい。

CA用のプライベートキーを生成する。certtool ではなぜかうまくいかないので (※)、ここだけ openssl を直接使う。

root# cd /etc/pki/CA/private
root# openssl genrsa -out cakey.pem 1024
root# chmod 600 cakey.pem

※ certtool のコマンドでは、 `certtool --generate-privkey --outfile cakey.pem' となる。

CAプライベートキーの内容を確認したければ、

root# certtool -k --infile cakey.pem
2. 自己署名済みCA証明書の作成

(1) CA証明書署名用のテンプレートファイル /etc/pki/CA/private/ca.info を作成する。内容は下記の要領。有効期限 (expiration_days) は極端に長くしておけばいいだろう。

cn="Hoge Net CA"
organization="Hoge Net"
unit="Hoge Net Certificate Authority"
country=JP
expiration_days=3650
serial=1001
ca
cert_signing_key
crl_signing_key

(2) 自己署名済みのCA公開証明書を作成。

root# cd /etc/pki/CA/private
root# certtool --generate-self-signed \
      --load-privkey cakey.pem \
      --template ca.info \
      --outfile ../cacert.pem
root# chmod 644 ../cacert.pem

公開証明書の内容を確認したければ、

root# certtool -i --infile ../cacert.pem
3. サーバ秘密鍵の生成

接続先 (ここは必ず接続先) で、サーバのプライベートキーを生成する。要領はCA用プライベートキーの時とほぼ同じ。

root# cd /etc/pki/libvirt/private
root# openssl genrsa -out serverkey.pem 1024
root# chmod 600 serverkey.pem

サーバプライベートキーの内容を確認したければ、

root# certtool -k --infile serverkey.pem
4. 署名用テンプレート (サーバ証明書用) の作成

接続先で、テンプレートテキストファイル /etc/pki/libvirt/private/server.info を作成する。内容は下記の要領。有効期限 (expiration_days) は極端に長くしておけばいいだろう。

organization="Hoge Net"
cn=beta.hoge.com
expiration_days=3650
tls_www_server
encryption_key
signing_key
5. CAによるサーバ証明書への署名

(1) 上記 3 と 4 で作成した serverkey.pemserver.info を、CAマシン (当例では接続先KVMホスト) にコピーする。コピー先は任意だが、当解説では下記の位置とする。work ディレクトリは標準では用意されていないので作成する。

/etc/pki/CA/
          \_ work/  <- root:root 700
                \_  serverkey.pem
                    server.info

(2) サーバのプライベートキーから、CA署名済みパブリックキーを作成する;

root# cd /etc/pki/CA/work
root# certtool --generate-certificate \
      --load-privkey serverkey.pem \
      --load-ca-certificate ../cacert.pem \
      --load-ca-privkey ../private/cakey.pem \
      --template server.info \
      --outfile servercert.pem

カレントディレクトリに CA署名済みのサーバパブリックキー servercert.pem ができたはず。内容を確認したければ、

root# certtool -i --infile servercert.pem

(3) 出来上がった署名済みパブリックキー servercert.pem を、接続先KVMホスト (サーバ) の /etc/pki/libvirt/ 直下にコピーする。また、行程2 で作成した /etc/pki/CA/cacert.pem (公開用CA証明書) を接続先KVMホストの /etc/pki/CA/ 直下にコピーする (当例ではCAとサーバが同一なのでコピー不要だが)。ともに、ファイルパーミションは root:root の 644 に。CAマシンの work ディレクトリの serverkey.pem, cervercert.pem, server.info はセキュリティ上なるべく削除する。

ここまでできたら、先に接続先KVMホストの設定変更と libvirtd の再起動を行って、ゲストを起動してもよい。

6. クライアント秘密鍵の生成

接続元で、クライアント用プライベートキーを生成する。要領はサーバ用プライベートキーの時とほぼ同じ。

root# cd /etc/pki/libvirt/private
root# openssl genrsa -out clientkey.pem 1024
root# chmod 600 clientkey.pem

プライベートキーの内容を確認したければ、

root# certtool -k --infile clientkey.pem
7. 署名用テンプレート (クライアント証明書用) の作成

接続元 (クライアント) で、テンプレートテキストファイル /etc/pki/libvirt/private/client.info を作成する。内容は下記の要領。有効期限 (expiration_days) は極端に長くしておけばいいだろう。

country=JP
state=Aichi
locality=Nagoya
organization="Hoge Net"
cn=alpha.hoge.com      <- DNSやhostsで解決できるクライアントの正式ホスト名
expiration_days=3650
tls_www_client
encryption_key
signing_key
8. CAによるクライアント証明書への署名

(1) 上記 6 と 7 で作成した clientkey.pemclient.info を、CAマシン (当例では接続先KVMホスト) にコピーする。要領はサーバ証明書への署名の時と同様。

/etc/pki/CA/
          \_ work/  <- root:root 700
                \_  clientkey.pem
                    client.info

(2) クライアントのプライベートキーから、CA署名済みパブリックキーを作成する;

root# cd /etc/pki/CA/work
root# certtool --generate-certificate \
      --load-privkey clientkey.pem \
      --load-ca-certificate ../cacert.pem \
      --load-ca-privkey ../private/cakey.pem \
      --template client.info \
      --outfile clientcert.pem

カレントディレクトリに CA署名済みのクライアントパブリックキー clientcert.pem ができたはず。内容を確認したければ、

root# certtool -i --infile clientcert.pem

(3) 出来上がった署名済みパブリックキー clientcert.pem を、接続元KVMホスト (クライアント) の /etc/pki/libvirt/ 直下にコピーする。また、行程2 で作成した /etc/pki/CA/cacert.pem (公開用CA証明書) を接続元KVMホストの /etc/pki/CA/ 直下にコピーする。ともに、ファイルパーミションは root:root の 644 に。CAマシンの work ディレクトリの clientkey.pem, clientcert.pem, client.info はセキュリティ上なるべく削除する。

環境設定[2] 接続先libvirtdの設定変更

libvirtd の基本的な起動オプションを定義する /etc/sysconfig/libvirtd ファイルを開き、既定ではコメントアウトされている下記の部分を有効にする。

LIBVIRTD_ARGS="--listen"

libvirtd の動作設定ファイル /etc/libvirt/libvirtd.conf を開き、幾つかのパラメータを変更する。

listen_tls = 1
TLS接続待ち受け用の TCPポートを開く。この機能はデフォルトで有効になっているので、コメントアウトされた既定の状態のままでも問題ない。
tls_port = 16514
TLS接続用の待ち受けポート番号。これもデフォルトなので、ポート番号を変えたい場合以外敢えて設定をいじる必要はない。
auth_tls = "sasl"
TLS接続時に、パブリックキー認証に加えて SASL によるユーザ名/パスワードの入力も求めるようにしたい場合には、このように設定しておく。デフォルトは `auth_tls = "none"' で、ユーザ名/パスワードは求められない。設定方法など詳しくは 「TCP接続」の項を参照 (ただしこの場合は `listen_tcp = 1' にする必要はない)。
tls_allowed_dn_list = ["C=JP,O=Hoge Net,L=Nagoya,ST=Aichi,CN=alpha.hoge.com"]
TLS接続を許可するクライアントのDN (Distinguish Name) を絞り込んでセキュリティをより高めたい場合は設定。右辺は 行程7 でクライアント公開鍵のテンプレートに書いたものに合わせればいいわけだ。ワイルドカードも使用でき、
"C=JP,O=Hoge Net,L=Nagoya,ST=Aichi,CN=*" はもちろん、
"C=JP,O=Hoge Net,L=Nagoya,ST=Aichi,CN=*.hoge.com"
というった指定法も可能。
複数のクライアントDN を書きたい場合は ["...", "..."] のようにDNをカンマ区切りで書く。

編集が終わったら、反映のため `service libvirtd restart' で libvirtd を再起動する。

接続手順

接続元マシンが alpha.hoge.com、リモートのKVMホストが beta.hoge.com だとする。DNS または hosts によって互いに名前解決ができるものとする。

virsh での接続
  1. 接続元 alpha に root でログインする。
  2. 接続するには、ターミナルで下記のように URI を指定する;
root# virsh -c qemu+tls://beta.hoge.com/system

待ち受けポート番号 (tls_port) を例えば 17000 に変更した場合は、URI を qemu+tls://beta.hoge.com:17000/system のように指定する。

virt-manager (仮想マシンマネージャ) での接続

1. 接続元 alpha の X Window に root でログインし、仮想マシンマネージャを起動する。

2. 仮想マシンマネージャの ファイル -> 接続を追加 を選択する。

3. ハイパーバイザー欄と接続欄を左図のように選択し、ホスト名にリモートKVMホストのホスト名を入力。図のホスト名欄は tls_port を 17000 に変更した場合で、デフォルトのままならポート指定は要らない。libvirtd.confauth_tls="sasl" にした場合は、接続ボタンを押した後に TCP接続の時と同様のユーザ/パスワードプロンプトが出る。