Fedora 31以降でLXCを使う手順

[Fedora 31以降でCGroup V2がデフォルトになった](https://www.redhat.com/sysadmin/fedora-31-control-group-v2) こともあり LXC (Linux Container) をFedora 31以降（特にサーバー最小インストール）で`dnf install lxc lxc-templates`としてもそのままでは使えない。使えるようにする手順を説明する。

# 足りないパッケージの補充
`dnf install tar wget openvswitch dnsmasq` をrootで実行する(`openvswitch`の代わりに`bridge-utils`でもよい）。必要なパッケージが自動でインストールされるように依存関係を設定してほしい。

# LXCブリッジ

## LXCブリッジ(lxcbr0)のための設定変更

```diff
--- etc/sysconfig/lxc-orig	2019-12-15 20:41:04.000000000 +0900
+++ etc/sysconfig/lxc	2020-01-01 14:00:29.856450559 +0900
@@ -23,6 +23,6 @@
 #	If you want to kill containers fast, use -k
 STOPOPTS="-a -A -s"
 
-USE_LXC_BRIDGE="false"  # overridden in lxc-net
+USE_LXC_BRIDGE="true"  # overridden in lxc-net
 
 [ ! -f /etc/sysconfig/lxc-net ] || . /etc/sysconfig/lxc-net
--- lib/systemd/system/lxc-net.service-orig	2019-12-15 20:41:03.000000000 +0900
+++ lib/systemd/system/lxc-net.service	2020-01-01 14:04:36.796450990 +0900
@@ -3,6 +3,7 @@
 After=network-online.target
 Wants=network-online.target
 Before=lxc.service
+Wants=openvswitch.service # この行はopenvswitch の代わりにbridge-utilsを用いるなら不要
 
 [Service]
 Type=oneshot
```

## LXCブリッジ(lxcbr0)の起動
`systemctl enable --now lxc-net.service` をrootで実行する

## openvswitch.service が起動されていないときのエラーメッセージ
```shell-session
# lxc-start -F -n fedora31
lxc-start: fedora31: network.c: lxc_ovs_attach_bridge: 2500 Failed to attach "lxcbr0" to openvswitch bridge "vethALZ6WE": ovs-vsctl: unix:/var/run/openvswitch/db.sock: database connection failed (No such file or directory)
lxc-start: fedora31: network.c: instantiate_veth: 395 Operation not permitted - Failed to attach "vethALZ6WE" to bridge "lxcbr0"
```

## lxcbr0 をlxc-net.serviceが準備していないときのエラーメッセージ
```shell-session
# lxc-start -F -n fedora31
lxc-start: fedora31: network.c: lxc_ovs_attach_bridge: 2500 Failed to attach "lxcbr0" to openvswitch bridge "vethAXQEHN": ovs-vsctl: no bridge named lxcbr
lxc-start: fedora31: network.c: instantiate_veth: 395 Operation not permitted - Failed to attach "vethAXQEHN" to bridge "lxcbr0"
```

# コンテナ設定ファイルの変更
## V1デバイスコントローラーの禁止
大抵の場合CGroup V1デバイスコントローラーをLXCが使おうとして使えず

```text
ERROR    cgfsng - cgroups/cgfsng.c:cg_legacy_set_data:2415 - Failed to setup limits for the "devices" controller. The controller seems to be unused by "cgfsng" cgroup driver or not enabled on the cgroup hierarchy
ERROR    start - start.c:lxc_spawn:1910 - Failed to setup legacy device cgroup controller limits
```

というエラーメッセージを表示して`lxc-start` がすぐに終了していしまう。これを防ぐためにはコンテナ設定ファイル(`/var/lib/lxc/fedora31/config`など）に

```config:/var/lib/lxc/コンテナ名/configの末尾
lxc.cgroup.devices.allow =
lxc.cgroup.devices.deny =
```

を追加する。

## コンテナ内systemdをCGroup V2専用モードで起動する
systemdを使っている大抵のLinuxディストリビューション（Fedora 31以降ではないものほぼ全て）ではsystemdをCGroup V1&V2混合モードで使っていて、それをFedora 31以降の上のLXCコンテナ内で起動すると

```text
Failed to mount cgroup at /sys/fs/cgroup/systemd: Operation not permitted
[!!!!!!] Failed to mount API filesystems.
Exiting PID 1...
```

というエラーが出て`lxc-start`がすぐに終了していしまう。これを防ぐためにはコンテナ設定ファイル(`/var/lib/lxc/fedora31/config`など）に

```config:/var/lib/lxc/コンテナ名/configの末尾
lxc.init.cmd = /sbin/init systemd.unified_cgroup_hierarchy=1
```

を追加する。

# libvirt lxc
libvirt 5.6 あたりだと `virt-install --memory 2048  --connect lxc:/ --os-variant fedora31 --filesystem /var/lib/lxc/fedora31/rootfs,/ --network none   --transient --import --name fedora31` とすると `内部エラー: 'devices' cgroup コントローラーのマウントを確認できません` というエラーが出て異常終了するので、libvirt を（例えばFedora RawhideからRPMを持ってくるとかして） 5.10 以降に更新するとlibvirt lxcを使えるようになる。

# 関連する Fedora へのバグレポート
* https://bugzilla.redhat.com/show_bug.cgi?id=1765821
* https://bugzilla.redhat.com/show_bug.cgi?id=1787093
* https://bugzilla.redhat.com/show_bug.cgi?id=1787097
* https://bugzilla.redhat.com/show_bug.cgi?id=1787209