LXD 使ってみた
内容
LXDの導入、bridge, macvlanのコンテナを作成するまで
LXDについて
LXD は次世代のシステムコンテナーおよび仮想マシンのマネージャーです。 コンテナーあるいは仮想マシンの内部で稼働する完全な Linux システムに対して統一されたユーザーエクスペリエンスを提供します。
いろいろな Linux ディストリビューション のあらかじめビルドされたイメージを使ったイメージベースのマネージャーであり、非常に強力でありながら、非常にシンプルに、REST API を使って構築されます。
導入は簡単だったが、VM/物理マシンでのネットワークの設定で戸惑った。。
環境
Ubuntu 20.04 LTS (物理マシン)
よさげLink
install
snapでパッケージインストール
# snap install lxd
バイナリからインストールもできるよう。
起動、初期設定
/etc/sysctl.conf
のnet.ipv4.ip_forward=1
のコメントを外しておく。←いらないかも?
lxd
グループに入っていたら、sudo
なしでlxd
やlxc
コマンドを利用できる。
# lxd init
今回は、すべてデフォルト設定にした。(lxd init --auto
)
image
OSimageは配布されているものを使う。それを基にしたオリジナルimageを使うことも可能。
配布imageにはUbuntuやCentOSなどバージョンも多くの種類が用意されている。
Cloud-initが動作する/しないimage、vmバージョンのimageなど様々。
imageの検索
lxc image list [image_server]: [keyword] .. # lxc image list images: amd64 gentoo
インスタンスの実行
lxc launch [image_server]:[image_alias] [name] [flags] # lxc launch ubuntu:f uf1
[flags]
に--vm
とすれば、VMが起動する。
今回使ったものは、ubuntu:f
。
インスタンスを操作
名前を指定してインスタンスにコマンドを実行させる。
名前はlxc list
などで確認する。
lxc exec [name] -- [command] # lxc exec uf1 bash
--
はなくてもいいが、オプションを渡す場合はこれをつけないとうまくいかない。
また、コンテナ側でリダイレクトを利用するときは、bash -c 'echo hoge > /tmp/hoge.txt'
というようにまとめてから実行させないと、ホスト側にリダイレクトされるので注意。
ネットワークについて
ここまではGettingStartedをみればできるが、ネットワークの設定で躓いた。
まず、インスタンスの設定項目にはnetwork
とprofile
がある。
network
ip l
で出てくるデバイスについて詳細を見る
# lxc network show lxdbr0
lxdbr0
は、デフォルト設定でlxd init
すれば作成されるデバイス。
インスタンスを作成するとき、デフォルトではこれがbridge
として使われる。
bridge
というのは、ネットワークタイプの設定で、ほかにはmacvlan
やovn
などがある。
bridge
は、ホストからインスタンスには通信可能だが、外部からインスタンスには通らない。(private)
macvlan
は、ホストの有線nI/Fを使う(ブリッジする)必要がある(複数のMACアドレスを扱うため。無線は複数MACに対応していないらしい)。外部からインスタンスにアクセスできる(public)
macvlan
を使う場合は、ブリッジするホストのデバイスのDHCPをオンにしておく必要がある。今回は、/etc/netplan/
のconfigからdhcp4: true
となっているのを確認。
VM(VBox)では、インスタンスから外部に通信できないなどうまくできなかった。
物理マシンでは、アパート管理のDHCPサーバーを利用しているためか、ipの割り振りが時々されず。。
結局、安定しているbridge
を使うことにした。
外部からホストを中継してsshすればアクセスできる(後述)し、
bridge
なら、ホストマシンのlxd
がdnsmasq
(lxdのdnsmasqなので、マシンに入れていなくておkだしsystemd-resolvedとの競合もなさげ。)を使ってDHCP割り振りを行っているので管理しやすい。
profile
profileは、インスタンスの設定をテンプレにしたもので、何のprofileを適用するかlaunch時に指定できる。
デフォルトではdefault
というのが使われる。オリジナルのprofileを作るときはこれを基に書き換えるなどする。
defaultにはnetwork: lxdbr0
とあるため、デフォルトインスタンスはlxdbr0
のbridge
となる。
# lxc profile show default
例えばmacvlanのインスタンスを作成するprofileを作成する場合
# lxc profile copy default mvlprof # lxc profile edit mvlprof
とすることで、viを使って編集できる。
このように設定した。
config: {} description: MACVLAN profile devices: eth0: name: eth0 nictype: macvlan parent: enp1s0 type: nic root: path: / pool: default type: disk name: mvlprof used_by: []
parent
の値は、ip l
で出てくる有線デバイス。
これを適用してlaunchすると、macvlanのインスタンスが作成される。
# lxc launch -p mvlprof ubuntu:f mvluf1 # lxc list (launchしただけのときにparentの範囲のipが振られていない場合は、インスタンスを再起動する。) # lxc restart mvluf1
外部からpingを通してみる
$ ping [instance_ip] 64 bytes from 192.168.12.16: icmp_seq=1 ttl=63 time=4.67 ms ...
ipの固定
作成 lxc network attach [network] [instance_name] [insatnce_new_I/F] 割り当て lxc config device set [instance_name] [instance_new_I/F] ipv4.address [ip_address] # lxc network attach lxdbr0 uf1 eth1 # lxc config device set uf1 eth1 ipv4.address 10.91.103.50 (反映させるためにインスタンスの再起動または dhclient を実行させる) # lxc restart uf1 または # lxc exec uf1 dhclient eth1
新しくインスタンス内のネットワークデバイスを作成して割り当てている。
だが、既存のデバイスを指定してもおk。
lxc config device set uf1 eth0 ipv4.address 10.91.103.50
のようにすると、eth0に2つのipを割り当てることになる。
個人的に、"network"と"profile"の関係性を整理するのに少し躓いた。
network
はip a
で出るあのデバイス(正しくはlxc network list
で出るやつ)のことで、
profile
には、それらのどれを物理デバイスとして使うか、ソフト的にはbridgeやmacvlanなどどれを使うのか、を記述している。
…という認識。
/sbin/initが動くので、ansibleのテスト環境としてよさそうに思う。 imageの、cloud-init動作版やvm版との違いがまだわからないが、VMより軽快なのでansibleの簡易テスト環境として使ってみる所存。
よく使うコマンドリスト
状態確認
lxc network show lxdbr0 lxc network list lxc profile show default lxc profile list lxc config device show default lxc config device show uf1 lxc config device list uf1 lxc config show uf1 --expanded // dnsmasq leases cat /var/snap/lxd/common/lxd/networks/lxdbr0/dnsmasq.leases lxc network list-leases
ネットワーク関連
networkデバイス新規作成 # lxc network create newbr0 defaultを流用してnetworkを作成 # lxc profile copy default ufnet 書き換え(bridgeなら lxdbr0 を ufnet に書き換えるだけ) # lxc profile edit ufnet profileの変更 # lxc profile assign uf1 ufnet lxdbr0を利用してコンテナ内のeth1としてネットワークデバイスを作成 # lxc network attach lxdbr0 uf1 eth1 固定IPを設定(lxdbr0のsubnet範囲内) # lxc config device set uf1 eth1 ipv4.address 10.91.103.50 コンテナに反映 # lxc exec f2 dhclient eth1
シェルスクリプト
引数に指定したコンテナのipアドレスを取得(CIDR表記)
#!/bin/bash container=$1 echo $container lxc exec $container -- ip a | awk '$1=="inet"{print $2}' | grep -v 127.0.0.1
全コンテナ名を取得
lxc list | awk 'NR>3{print $2}' | grep -v '^$'
全コンテナを削除
lxc delete `lxc list | awk 'NR>3{print $2}' | grep -v '^$'` --force
ブリッジに鍵登録
cat ~/.ssh/id_rsa.pub | xargs -i% lxc exec container -- bash -c 'echo % >> /root/.ssh/authorized_keys'
外部からlxdホストマシンを中継してコンテナに接続
ssh -t [lxd_host] ssh root@[container_ip]