Ubuntu Weekly Recipe

第647回 Ubuntu CoreなRaspberry PiをUbuntuサーバーとして使う

この記事を読むのに必要な時間:およそ 10 分

Ubuntu Coreの上でLXDをセットアップ

ここまで説明したように,Ubuntu Coreそのものは堅牢なシステムです。⁠一般的なサーバー」としてSSHログインしていろいろと操作するには不向きです。しかしながらUbuntu Coreの上でシステムコンテナを活用し,⁠普通のUbuntuサーバー環境」を作ってしまえば話は別です。要するにUbuntu CoreをVMWare ESXiのように使うということです。

LXDはシステムコンテナにもamd64/arm64向けの仮想マシンにも対応しています。よって仮想マシンマネージャーとしてLXDを使えば,実際にESXiのような機能を実現可能です※3⁠。LXD自体はsnapパッケージ化されているため,Ubuntu Coreにも簡単にインストールできます。LXD上のUbuntuは,Ubuntu Coreのような制約がないため自由にサーバーとしてセットアップできます※4⁠。マシンをまたいだマイグレーションにも対応しているので,複数台のRaspberry Piを用意して,問題が起きたら別のRaspberry Piに移行するといった使い方も可能になるのです。

※3
ただしvSphare Clientに相当する公式のGUIツールは存在しません。
※4
もちろんコンテナの中に関しては,前述の「セキュアである」という前提が崩れてしまいます。

注意すべきなのはストレージの設定でしょう。LXDは作成するコンテナをどこに・どのように保存するかを細かく設定できます。しかしながらイメージ・インスタンスのサイズはそれなりに大きくなるため,保存先もそれなりに大きな容量が必要です。ちょっとしたコンテナを複数動かす程度であれば数GiBでも十分ですが,本格的に使うなら最低でも数十GiBはほしいところです。そうなるとSDカードに保存するのは難しくなります。

Raspberry PiならUSBストレージを増設しましょう。今回は単にLXDをインストールするだけでなく,USBストレージ先にイメージやインスタンスを保存することにします。詳細はDockerの項目を参照してください。ここでは/media/data/lxd/以下をストレージプール用のディレクトリとして使うことにします。

まずはsnap版のlxdパッケージをインストールして,次のように初期化しましょう。

$ snap install lxd --channel=4.0/stable
$ sudo lxd init
(中略)
Do you want to configure a new storage pool? (yes/no) [default=yes]:
Name of the new storage pool [default=default]:
Name of the storage backend to use (lvm, ceph, btrfs, dir) [default=btrfs]:
Create a new BTRFS pool? (yes/no) [default=yes]:
Would you like to use an existing empty block device (e.g. a disk or partition)? (yes/no) [default=no]:
Size in GB of the new loop device (1GB minimum) [default=5GB]: 20
(後略)

上記ではストレージプールに関する部分のみを抜き出してみました。ポイントは「empty block device」の行です。もし空のストレージもしくは空のパーティションをまるまるLXDに利用できるのであれば,ここを「yes」に設定することをおすすめします。

上記のように「no」を設定した場合,標準のストレージプールが/var/snap/lxd/common/lxd/disks/default.imgとして作られます。これをより容量の大きいUSBストレージ上に移行する必要があるのです※5⁠。

※5
標準のストレージプールを使わずに新しいストレージプールを作るという選択肢もあります。詳しいことは第571回のLXD 3.0のストレージ設定を参照してください。

方法はいくつかあるのですが,Dockerと同じように/var/snap/lxd/common/lxd/disks/を外部ストレージからのbind mountにしてしまうのが簡単です。

$ sudo lxc stop --all
$ sudo systemctl stop snap.lxd.daemon.unix.socket
$ sudo systemctl stop snap.lxd.daemon.service
$ sudo cp -a /var/snap/lxd/common/lxd/disks/ /media/data/lxd
$ sudo mv /var/snap/lxd/common/lxd/disks/ ~/lxd.old
$ sudo mkdir /var/snap/lxd/common/lxd/disks/

前回と同様に起動時に自動的にマウントするよう,unitファイルを次の手順で作成します。

$ cat <<'EOF' | sudo tee /etc/systemd/system/var-snap-lxd-common-lxd-disks.mount
[Unit]
Description=External Storage for LXD
After=media-data.mount
Before=snap.snap.lxd.daemon.service

[Mount]
What=/media/data/lxd
Where=/var/snap/lxd/common/lxd/disks
Options=bind

[Install]
WantedBy=multi-user.target

[Install]
WantedBy=multi-user.target
RequiredBy=snap.lxd.daemon.service
Requires=media-data.mount
EOF

unitファイルを再読込して,サービスを起動します。

$ sudo systemctl daemon-reload
$ sudo systemctl start var-snap-lxd-common-lxd-disks.mount
$ sudo systemctl enable var-snap-lxd-common-lxd-disks.mount
$ sudo systemctl start snap.lxd.daemon.unix.socket
$ sudo systemctl start snap.lxd.daemon.service

問題なければ次のようにストレージプールの情報が表示されるはずです。

$ sudo lxc storage show default
config:
  size: 20GB
  source: /var/snap/lxd/common/lxd/disks/default.img
description: ""
name: default
driver: btrfs
used_by:
- /1.0/profiles/default
status: Created
locations:
- none

最後に実際にLXDでインスタンスを作ってみます。

$ sudo lxc launch ubuntu:20.04 focal
Creating focal
Starting focal

ストレージプールの情報を表示すると,ダウンロードしたイメージ,作成したインスタンスがこのストレージプールに紐付いていることがわかります。

$ sudo lxc storage show default
config:
  size: 20GB
  source: /var/snap/lxd/common/lxd/disks/default.img
description: ""
name: default
driver: btrfs
used_by:
- /1.0/images/982ae89228891ed6306876ad21d83c7c1b08d93e2f470067a890f65426a0bf9e
- /1.0/instances/focal
- /1.0/profiles/default
status: Created
locations:
- none

$ sudo lxc storage info default
info:
  description: ""
  driver: btrfs
  name: default
  space used: 1.05GB
  total space: 20.00GB
used by:
  images:
  - 982ae89228891ed6306876ad21d83c7c1b08d93e2f470067a890f65426a0bf9e
  instances:
  - focal
  profiles:
  - default

サーバーとして運用することを考えると,Raspberry Piが繋がっているネットワークにコンテナも繋いだほうが便利でしょう。そこでmacvlanの設定も行っておきます。

$ sudo lxc config device add focal eth1 nic nictype=macvlan parent=eth0

$ sudo lxc exec focal ip link
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN mode DEFAULT group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
11: eth0@if12: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP mode DEFAULT group default qlen 1000
    link/ether 00:16:3e:59:35:3f brd ff:ff:ff:ff:ff:ff link-netnsid 0
13: eth1@if2: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN mode DEFAULT group default qlen 1000
    link/ether 00:16:3e:33:c7:2b brd ff:ff:ff:ff:ff:ff link-netnsid 0

ここで最初のコマンドの末尾にあるeth0はRaspberry Piのインターネットに繋がっているネットワークインターフェースです。もしWiFi側を使う場合はwlan0を指定してください。

たとえばDHCPでeth1にIPアドレスを設定したいのであれば,次のように設定ファイルを用意します。

$ cat <<'EOF' | sudo lxc exec focal -- tee -a /etc/netplan/eth1.yaml
network:
    version: 2
    ethernets:
        eth1:
            dhcp4: true
EOF

あとはNetplanで適用するとIPアドレスが割り当てられているはずです。

$ sudo lxc exec focal netplan apply

$ sudo lxc exec focal ip addr show eth1
13: eth1@if2: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000
    link/ether 00:16:3e:33:c7:2b brd ff:ff:ff:ff:ff:ff link-netnsid 0
    inet 10.42.0.218/24 brd 10.42.0.255 scope global dynamic eth1
       valid_lft 3565sec preferred_lft 3565sec
    inet6 fe80::216:3eff:fe33:c72b/64 scope link
       valid_lft forever preferred_lft forever

ここまですればほぼ普通のUbuntuサーバーとして利用可能です。もしLXDのUbuntuインスタンスの上でDockerを動かしたい場合は,次のように名前空間等のネストを許可した上で,再起動しておきます。

$ sudo lxc config set focal security.nesting true
$ sudo lxc restart focal

あとはUbuntuリポジトリの「docker.io」パッケージをインストールしてください。こちらにはLXD上でDockerを動かすために必要なパッチが適用されています。

$ sudo lxc exec focal apt install docker.io
$ sudo lxc exec focal docker run arm64v8/hello-world

その他のLXDそのものの使い方は,第521回の入門システムコンテナマネージャーLXD 3.0にリンクされている各記事を参照してください。

著者プロフィール

柴田充也(しばたみつや)

Ubuntu Japanese Team Member株式会社 創夢所属。数年前にLaunchpad上でStellariumの翻訳をしたことがきっかけで,Ubuntuの翻訳にも関わるようになりました。