LXDのホストOSをふっとばしたけどコンテナイメージは無事に残ってるよって人のための復旧手順

先週末に自宅鯖(UbuntuServer 18.04)を雑に `do-release-upgrade` してて、アップグレード中にうっかり `Ctrl+C` してOSを破壊してしまった私です。

幸いにも自宅鯖で運用していた各サービスはLXDコンテナに乗せてあり、コンテナ用のzfsストレージプールを別ドライブに置いてあったので最悪の事態は免れました。

ただ、zfsストレージプールのみの状態から新しいホストOSのLXDに組み込むのが一苦労したのでそのメモ。

Oracle Solaris ZFS 管理ガイドはもう見飽きました。

## 0. 想定環境

新しい環境は以下の通りになります。

- ホストOS: Ubuntu Server 20.04.3 LTS  
クリーンインストール。基本構成で追加パッケージはOpenSSHのみ
- zfs-0.8.3-1ubuntu12.13
- LXD 4.0.7 (snap版)  
※`snap refresh` してません。4.0.8以降にしてはいけない

## 1. zfsストレージプールのインポート

普段ファイルシステムはext4/LVMばかり使ってるので、勝手が違うzfsに少々手こずりました。
使い慣れたら便利だと思うけど。

ホストOSクリーンインストール直後はzfsストレージプール(LVMで言うところのVGとかに当たる？)がOSの管理外にあるみたいなので、まずはストレージプールをマウントするところから始めます。

まずはzfsの管理ユーティリティが入ってないのでaptで入れます。

```
$ sudo apt install -y zfsutils-linux
```

最初の状態ではストレージプールが取得できません。

```
$ zpool list
no pools available
```

/dev/sdX として物理ドライブが認識できている場合は、以下のコマンドでインポートできます。

```
$ zpool import
## インポートされていないストレージプールが表示される ##
## プール名もしくはIDを確認する ##

$ zpool import <プール名もしくはID> [新しいプール名をつける際はこちらも書く]
```

これで再度 `zpool list` するとインポートしたストレージプールが表示されます。

```
$ zpool list
NAME       SIZE  ALLOC   FREE  CKPOINT  EXPANDSZ   FRAG    CAP  DEDUP    HEALTH  ALTROOT
pool-ssd   149G  50.3G  98.7G        -         -    50%    33%  1.00x    ONLINE  -
```

## 2. zfsボリュームのマウント

LXDは自身でzfsをよしなにしてくれるため普段はマウントなど意識しなくてもいいのですが、コンテナをインポートするときだけは一旦マウントしてLXDが探せるようにしてやる必要があります。

ここで少しつまづいたとこですが、LXDを入れたのがaptかsnapかでマウントポイントが変わるので注意が必要です。

- aptの場合  
`/var/lib/lxd/storage-pools` 配下
- snapの場合  
`/var/snap/lxd/common/lxd/storage-pools` 配下

参考： [バックアップ - LXDドキュメント翻訳プロジェクト](https://lxd-ja.readthedocs.io/ja/latest/backup/)

Ubuntu18.04ではaptベースだったが、Ubuntu20.04ではsnapになったので、 `do-release-upgrade` 成功してるような人はaptの方に置き換えて読んでください。

また、snap版LXDを使っていても、バージョンによって打つコマンドが変わることに注意してください

- LXD v4.0.7以前、またはv4.16以前  
`lxd import` コマンドを用いてストレージの復旧を行います。  
当記事ではこちらの方法を紹介します。
- LXD v4.0.8以降、またはv4.17以降  
`lxd recover` コマンドを用いてストレージの復旧を行います。(`lxd import` はこちらに置き換えられました)

LXDは安定版を4.0.x、最新版を4.xのバージョンで提供しており、Ubuntu20.04.3では安定版のほうが初期インストールされていました。

参考： [LXD 4.17 リリースのお知らせ 〜 Linux Containers - LXD - ニュース](https://linuxcontainers.org/ja/lxd/news/2021_08_06_00_08.html)

今回は、 `lxd import`　を使って `dev` コンテナを復旧する例で手順を説明します。

まずは、zfsストレージプール内のコンテナが保存されているボリュームを探します。

```
zfs list | grep containers/
NAME                      USED  AVAIL     REFER  MOUNTPOINT
...
pool-ssd/containers/dev  5.73G  49.7G     5.80G  none
...
```

基本的に `<ストレージプール>/containers/<コンテナ名>` の中に保存されています。

LXDで管理されていたため、こちらのコマンドからはマウントポイントが見えず `none` となっているようです。

手動でマウントするため、一時的にマウントポイントを設定してやります。

```
# zfs set mountpoint=<LXD格納ディレクトリ>/<コンテナ格納ボリューム> <コンテナ格納ボリューム>
zfs set mountpoint=/var/snap/lxd/common/lxd/storage-pools/pool-ssd/containers/dev pool-ssd/containers/dev
```

マウント先のディレクトリは掘る必要ありません。これだけでマウントできます。

```
# zfs mount <コンテナ格納ボリューム>
zfs mount pool-ssd/containers/dev
```

## 3. LXDの設定を調整する

あとはコンテナのインポートをすればいいだけなんですが、プロファイルやブリッジインタフェースの設定が不足しているとエラーが出るので、事前に準備します。

`lxd init` で設定することもできるんですが、今回は個別に設定していきたいと思います。

まず、コンテナがどんな設定をしていたかを確認します。

```
# cat <格納ディレクトリ>/<コンテナ格納ボリューム>/backup.yaml
cat /var/snap/lxd/common/lxd/storage-pools/pool-ssd/containers/dev/backup.yaml
```

LXDのコンテナイメージの設定は `backup.yaml` に入っています。ここを確認すればどんな設定をしていたかを確認することが出来ます。

`lxc profile list` 及び `lxc network list` を確認し、違う設定がされている場合はプロファイル、ブリッジをそれぞれ作成していきます。

```
lxc profile create profile-dev
lxc network create lxdbr0
```

## 4. コンテナのインポート、起動

ここまで来てようやくコンテナのインポートをすることができるようになりました。

```
# lxd import <コンテナ名>
lxd import dev
```

特にエラーが無ければ、 `lxc list` でコンテナが追加されていることが確認できるはずです。

コンテナを起動する前に、一時的にマウントしたボリュームをアンマウントしてやる必要があります。

```
# zfs unmount <コンテナ格納ボリューム>
zfs unmount pool-ssd/containers/dev
```

また、コンテナインポート時にブリッジインタフェースがないと起こるくせに、attachはしてくれないみたいなので、こちらも手動で行います。

```
# lxc network attach <ネットワーク名> <コンテナ名>
lxc network attach lxdbr0 dev
```

これでコンテナ起動の準備が出来ました。

```
# lxc start <コンテナ名>
lxc start dev
```

無事に起動できました。お疲れさまでした。

あとはネットワークアドレスやプロファイルなどの設定を調整したりしてやれば、以前のようにコンテナが扱えるはずです。

ホストOSをアップグレード失敗したときは心臓が10回くらい止まりましたが、無事に復旧させることが出来てよかったです。

LXDは最近のUbuntuに標準で入ってるし、今まではDocker同様LinuxディストリビューションのコンテナだけだったのがKVMやQEMUに対応してきてVMの幅も広がってきてるし、もっと広がってほしいですね。