multipassのVM作成時にcloud-initでLXDをセットアップ

はじめに

multipass ではVMの作成時に multipass launch--cloud-init オプションで cloud-init を使って初期化を行えます。

LXD をセットアップする手順を試行錯誤したのでメモです。

参考資料

cloud-initの設定ファイル例その1

#cloud-config
locale: en_US.utf8
timezone: Asia/Tokyo
package_upgrade: true
package_reboot_if_required: true
apt:
  primary:
    - arches:
        - amd64
        - default
      uri: "http://jp.archive.ubuntu.com/ubuntu/"
lxd:
  init:
    storage_backend: zfs
    storage_create_loop: 80
  bridge:
    mode: new
    name: lxdbr0

上記のファイルを lxd-cloud-config.yml などお好みの名前で保存し、以下のコマンドを実行してVMを作成・起動します。ディスクサイズは上記の zfs のプールサイズ80GBにシステム領域で20GBを使う想定で合計100GBとしています。

multipass launch -n primary -c 2 -m 4G -d 100G --cloud-init lxd-cloud-config.yml

cloud-initの設定ファイル例その2

その1の例に加えて以下の設定を追加しています。

#cloud-config
locale: en_US.utf8
timezone: Asia/Tokyo
package_upgrade: true
package_reboot_if_required: true
apt:
  primary:
    - arches:
        - amd64
        - default
      uri: "http://jp.archive.ubuntu.com/ubuntu/"
lxd:
  init:
    storage_backend: zfs
    storage_create_loop: 80
  bridge:
    mode: new
    name: lxdbr0
 ipv4_address: 192.168.255.1
 ipv4_netmask: 24
 ipv4_nat: !!str "true"
 ipv6_address: none
 domain: my-lxd.test
runcmd:
  - 'sudo -u multipass lxc init ubuntu:18.04 u1'
  - 'sudo -u multipass lxc network attach lxdbr0 u1 eth0 eth0'
  - 'sudo -u multipass lxc config device set u1 eth0 ipv4.address 192.168.255.2'
  - 'sudo -u multipass lxc start u1'

ハマりポイントのメモ。

ipv4_nat のデフォルト値は "true" なので省略しても良いです。 ただ、書く場合は文字列の "true" が必要で単に "true" だとうまく行かず上記のように !!str を付けるとうまく行きました。 YAMLパーサが対応しているバージョンの違いっぽいですが、詳しく調べていません。

runcmd のドキュメントを見るとコマンドは [sudo, -u, multipass, lxc, init, ubuntu:18.04, u1] のように文字列ではなく配列形式でも書けるようなのですが、どうもうまく行かなかったので文字列形式にしています。

cloud-init に以下の設定も追加してホスト名のFQDNを設定しようと試みたが

preserve_hostname: false
hostname: hoge.my-lxd.test

以下のエラーが発生した。VMのホスト名は変更しないほうが良さそう。

timed out waiting for initialization to complete
mount failed: The following errors occurred:
error mounting "setup": ssh connection failed: 'Failed to resolve hostname primary.mshome.net (そのようなホストは不明です。 )'

multipassの cloud-init での初期化のタイムアウトは5分間。

https://github.com/CanonicalLtd/multipass/blob/v0.8.0/src/daemon/daemon.cpp#L77

constexpr auto cloud_init_timeout = 5min;

上記の例ではruncmdでLXDのコンテナ作成までやろうとしていますが、実はこのときは package_upgrade: true はまだ入れてませんでした。パッケージノアップデートとLXDのセットアップまでにして、コンテナの作成はcloud-init終わって起動してからにするほうが無難。

おわりに

これで Windows と macOS でも手軽に LXD の環境がセットアップ出来て良い感じです。