LXDが仮想マシンに対応したことで、気軽にデスクトップ環境やWindowsマシンを構築できるようになりました。しかしながらその操作にあたってはvirt-viewerをはじめとするSPICEクライアントが必要になります。そこで今回はリモートマシンで動いているLXDのデスクトップインスタンスを、ローカルからSPICEプロトコルを利用して操作する方法を紹介しましょう。これができればLXDだけで、簡易VDI
なぜRDPではだめなのか
本連載ではこれまでにも、LXDで仮想マシンを構築し、その上にデスクトップ版のUbuntuやWindowsをインストールする方法を紹介してきました。
- 第736回
「vTPMに対応したLXDで、Windows 11とWSLの新機能であるWSLgとsystemdを試してみる」 - 第679回
「LXD上にWindowsをインストールする」 - 第683回
「LXDコンテナ上にUbuntuのフルデスクトップ環境を構築する」
これらはいずれも、
つまり
ちなみに
それに対してSPICEはハイパーバイザー側で画面の描画情報を取得します。つまりVMの上で動いているソフトウェアがなんであれ、その情報を取得し他の環境と共有できます。つまりディスプレイが必要な何かシステムをインストールし、その後RDP等をセットアップするまでは、SPICEクライアントによる共有ができると便利なのです。
リモートのLXDを操作する方法
LXDはデーモンとして動作していますがREST APIも提供しています。LXDを操作するlxcコマンドはUnixドメインソケット経由でREST APIを呼び出すことで、インスタンスの作成や操作を行っているのです。
LXDのREST APIはローカルシステムからしか呼び出せないようになっています。しかしながらサーバー側で設定を行うことで、特定のクライアントに対してネットワーク越しにREST APIを呼び出す仕組みも用意しています。この際、通信データのフォーマットとしてJSONを使用し、通信経路を暗号化するためにHTTPS/
ちなみにREST APIを呼び出すクライアント機能だけであれば、WindowsやmacOS上でも動作可能です。HomebrewやChocolateryでmacOSやWindowsにインストールできるLXDは、このクライアント機能に特化したLXDと言えます。
まずはローカルのLXDシステムを、リモートのLXDシステムと連携させる方法を紹介しましょう。
- 方法1:リモート側でパスワードを登録し、ローカルからパスワードを入力して登録する方法
- 方法2:リモート側でワンタイムトークンを発行し、ローカルからトークンを入力して登録する方法
- 方法3:リモート側にローカルのクライアント証明書を登録する方法
本質的に方法1と方法2は方法3を簡単にするための方法です。他にも証明書を生成するためのPKIを独自のものにしたり、Candidを利用して認証したりもできるようですが、今回は除外します。
方法1については第574回の
まずリモート側の設定です。LXDの初期設定だとリモート接続が不許可になっているため、それを許容する必要があります。ポートを指定可能です。未指定の場合は8443番ポートを利用します。
remote$ lxc config set core.https_address "[::]" remote$ lxc info | grep certificate_fingerprint certificate_fingerprint: 7ba2d3fab2f05419323d6f7827e020437b74bfc12c5c477ec7ac3bb7c27a8f96
「core.
」[::]
」:443
」
さらにリモート側でlxc config trust add
」
remote$ lxc config trust add Please provide client name: nuc Client nuc certificate add token: トークン文字列
「Please provide client name」lxc config trust list-tokens
」
次にクライアント側の対応です。先ほど生成したトークンを使い、リモートに接続します。
client$ lxc remote add meet トークン文字列 Generating a client certificate. This may take a minute... client$ lxc remote list -f compact NAME URL PROTOCOL AUTH TYPE PUBLIC STATIC GLOBAL images https://images.linuxcontainers.org simplestreams none YES NO NO local (current) unix:// lxd file access NO YES NO meet https://10.42.0.239:8443 lxd tls NO NO NO ubuntu https://cloud-images.ubuntu.com/releases simplestreams none YES YES NO ubuntu-daily https://cloud-images.ubuntu.com/daily simplestreams none YES YES NO
これでリモートとの接続完了です。ちなみにリモート側でも接続許可済みのクライアントを一覧表示できます。lxc config trust list-tokens
」
remote$ lxc config trust list -f compact TYPE NAME COMMON NAME FINGERPRINT ISSUE DATE EXPIRY DATE client nuc shibata@nuc 4978f1e4cd11 Nov 5, 2022 at 9:16am (UTC) Nov 2, 2032 at 9:16am (UTC)
リモート側ではlxc config trust remove
」
これまでのLXDコマンドに
client$ lxc ls meet: +-------------------------------+---------+------+------+-----------+-----------+ | NAME | STATE | IPV4 | IPV6 | TYPE | SNAPSHOTS | +-------------------------------+---------+------+------+-----------+-----------+ | dotnet | STOPPED | | | CONTAINER | 0 | +-------------------------------+---------+------+------+-----------+-----------+ | review | STOPPED | | | CONTAINER | 0 | +-------------------------------+---------+------+------+-----------+-----------+ | snapcraft-thorium-reader-snap | STOPPED | | | CONTAINER | 0 | +-------------------------------+---------+------+------+-----------+-----------+
ちなみにlxc remote switch
」
client$ lxc remote switch meet client$ lxc remote list -f compact NAME URL PROTOCOL AUTH TYPE PUBLIC STATIC GLOBAL images https://images.linuxcontainers.org simplestreams none YES NO NO local unix:// lxd file access NO YES NO meet (current) https://10.42.0.239:8443 lxd tls NO NO NO ubuntu https://cloud-images.ubuntu.com/releases simplestreams none YES YES NO ubuntu-daily https://cloud-images.ubuntu.com/daily simplestreams none YES YES NO
「current」
リモートのデスクトップVMの作成
ここからはこれまでとデスクトップVMの作成方法は同じです。あらかじめローカル側にSPICEクライアントであるvirt-viewerをインストールして、LXDを再起動しておいてください。これは一度だけ実施すれば大丈夫です。
client$ sudo apt install virt-viewer client$ sudo systemctl reload snap.lxd.daemon.service
次に空のVMインスタンスを作成し、各種リソースを設定して、インストール用のISOファイルを紐付けます。
client$ lxc init kinetic --empty --vm -c limits.cpu=2 -c limits.memory=8GiB client$ lxc config device override kinetic root size=50GiB client$ lxc config device add kinetic iso disk boot.priority=10 source=$HOME/ダウンロード/ubuntu-22.10-desktop-amd64.iso
VMはコンソールのタイプにVGAを指定すると、virt-viewerなどのSPICEクライアントが起動します。
起動と同時にSPICEクライアントを立ち上げたい場合 client$ lxc start kinetic --console=vga 起動済みのVMインスタンスのコンソールを取得したい場合 client$ lxc console kinetic --type=vga
これだけです。lxc remote switch meet
」lxc remote switch local
」meet:kinetic
」
これでディスプレイが繋がっていないマシンでも、気軽にデスクトップインスタンスを作れるようになりました。この先は、上記のようにvirt-viewerとSPICEを用いて操作しても良いですし、VMインスタンス側でRDP等を導入して、RDPクライアントを使う方法もあります。USBやオーディオなどのリソースの共有や、ファイル共有を考えるとRDPのほうがお手軽です。
LXDのプロジェクト機能を利用したクライアントの制限方法
LXDへのリモート接続を許可したクライアントは、接続先のLXDの機能をすべて利用可能です。この場合、特権コンテナを作れたり、各種物理デバイスの操作も可能になってしまい、セキュリティ的な不安要素となります。そもそも信頼できないクライアントを登録しないことが前提ではあるものの、信頼できるクライアントでもある程度の機能制限を行いたいことはあるでしょう。
一番手っ取り早い方法がそのクライアントを制限付きにしてしまうことです。具体的な手順を見ていきましょう。まず制限をかけたいクライアントのフィンガープリント
remote$ lxc config trust list +--------+------+-------------+--------------+-----------------------------+-----------------------------+ | TYPE | NAME | COMMON NAME | FINGERPRINT | ISSUE DATE | EXPIRY DATE | +--------+------+-------------+--------------+-----------------------------+-----------------------------+ | client | nuc | shibata@nuc | 4978f1e4cd11 | Nov 5, 2022 at 9:16am (UTC) | Nov 2, 2032 at 9:16am (UTC) | +--------+------+-------------+--------------+-----------------------------+-----------------------------+
次にそのクライアント
remote$ lxc config trust show 4978f1e4cd11 name: nuc type: client restricted: false projects: [] certificate: | -----BEGIN CERTIFICATE----- MIIB2TCCAV6gAwIBAgIQA0/jNgAolLEPoNhiJg7gTzAKBggqhkjOPQQDAzA0MRww GgYDVQQKExNsaW51eGNvbnRhaW5lcnMub3JnMRQwEgYDVQQDDAtzaGliYXRhQG51 YzAeFw0yMjExMDUwOTE2MDNaFw0zMjExMDIwOTE2MDNaMDQxHDAaBgNVBAoTE2xp bnV4Y29udGFpbmVycy5vcmcxFDASBgNVBAMMC3NoaWJhdGFAbnVjMHYwEAYHKoZI zj0CAQYFK4EEACIDYgAEPBhMYqdJh8VvB/MrwLsJPRQAhASZcC7aMd0AwDUuEg1n wMzHWH67Q2qzCg5SHR/e8lTqg1PmH1NGSnsCdZPmCcU2zZCSqjCwRjKxETVoCTVV glq8coLiD+OeDvzN90UXozUwMzAOBgNVHQ8BAf8EBAMCBaAwEwYDVR0lBAwwCgYI KwYBBQUHAwIwDAYDVR0TAQH/BAIwADAKBggqhkjOPQQDAwNpADBmAjEA5KLJ+12L HwK+d/HkCTwtZ+G/G94cT4fpwsiSi7el+ZcnO5tRS8uYzoWb+DMsj6fnAjEA6LXL vnKrvC+c3XKEIyuNJBG2qSyVHwXVgC3B5F8pEamE7uoTnwLKAkSVWUfRj8zh -----END CERTIFICATE----- fingerprint: 4978f1e4cd118598ed82f50ae4f496946d35352c83152fab4b0accb2e5fb0d01
ここのrestricted: false
」restricted: true
」restricted.
」
編集の方法はlxc config trust edit
」
remote$ export EDITOR=nvim
もしくは~/.profile
」
remote$ lxc config trust edit 4978f1e4cd11 「restricted: true」にして、保存・終了する。
こうするとクライアントからいくつかの機能が制約されます。たとえばsecurity.
」
client$ lxc launch ubuntu:22.04 meet:docker -c security.privileged=true Creating docker Error: Failed instance creation: not authorized
このように許可されていない旨のメッセージが表示されました。これで最低限の制約はできます。
もしリモート側に作られたインスタンスをクライアントに見せたくない場合は、LXDの
まずはプロジェクトを作りましょう。これはリモートからでもローカルからでもかまいません。
$ lxc project create j2 -c restricted=true Project j2 created $ lxc project show j2 config: features.images: "true" features.profiles: "true" features.storage.buckets: "true" features.storage.volumes: "true" restricted: "true" description: "" name: j2 used_by: - /1.0/profiles/default?project=j2
現在のプロジェクトはlxc project switch
」
$ lxc project list -f compact NAME IMAGES PROFILES STORAGE VOLUMES STORAGE BUCKETS NETWORKS DESCRIPTION USED BY default (current) YES YES YES YES YES Default LXD project 6 j2 YES YES YES YES NO 1 $ lxc project switch j2 $ lxc list +------+-------+------+------+------+-----------+ | NAME | STATE | IPV4 | IPV6 | TYPE | SNAPSHOTS | +------+-------+------+------+------+-----------+
そうすると上記のように、インスタンスが何もない状態になるのです。リモート側はプロジェクトj2を参照することはないと思うのでlxc project switch default
」
次にクライアント側をこのプロジェクトj2にのみ所属するようにしてみましょう。
remote$ lxc config trust edit 4978f1e4cd11 (前略) restricted: true projects: - j2 certificate: | (後略)
この状態でクライアントからリモートのインスタンスリストを参照しようとすると、
client$ lxc list meet: Error: not authorized
ここで--project
」
client$ lxc project list meet: +--------------+--------+----------+-----------------+----------+-------------+---------+ | NAME | IMAGES | PROFILES | STORAGE VOLUMES | NETWORKS | DESCRIPTION | USED BY | +--------------+--------+----------+-----------------+----------+-------------+---------+ | j2 (current) | YES | YES | YES | NO | | 1 | +--------------+--------+----------+-----------------+----------+-------------+---------+ client$ lxc list meet: --project j2 +------+-------+------+------+------+-----------+ | NAME | STATE | IPV4 | IPV6 | TYPE | SNAPSHOTS | +------+-------+------+------+------+-----------+
ただし毎回--project
」
client$ lxc project switch meet:j2 client$ lxc list meet: +------+-------+------+------+------+-----------+ | NAME | STATE | IPV4 | IPV6 | TYPE | SNAPSHOTS | +------+-------+------+------+------+-----------+
これでこのクライアントは、リモートの他のインスタンスにはアクセスできなくなりました。
LXDではプロジェクト単位でのリソース制限も可能です。また、リモート接続する際のトークン発行時lxc config trust add
実行時)--project
」
これらの機能を組み合わせれば、リモートにある強いサーバーマシンを複数人で共有しながら、個別にコンテナやVM、さらにはデスクトップ環境を立ち上げて運用することも可能になるのです。