LXDコンテナの上でDockerを動かしたいという気持ちになったのですが,ググって出てくる解決方法がsecurity.nesting
とsecurity.privileged
をtrue
にするものだけでした.
ただ,コンテナ内でCUDAを使いたいときとかにnvidia.runtime
を使うのですが,privilegedなコンテナではこのオプションが使えません (起動でコケます).
これではホストとコンテナのCUDAドライバーのバージョンを手動で一致させてあげる必要があり,非常にだるいです.
そこで,非特権コンテナ上でDockerを動かす方法を探ってみました.
環境等
- Ubuntu 18.04 LTS
- LXD version: 4.4
- Docker version: 19.03.8
- LXD,Dockerのストレージドライバはそれぞれzfs,overlay2 (デフォルト)
- LXDコンテナはゲストユーザーが利用するためprivilegedにしたくない
- LXDコンテナ内でCUDAを使う
- CUDAを使うだけなら
nvidia.runtime=true
にするだけでいい
- CUDAを使うだけなら
- LXDコンテナ内でNVIDIA Dockerを使いたい
解決方法
どうやらLXDのストレージドライバがzfsだと死ぬらしい -> zfs以外にすればよいのでは?
ということで,結果として
- LVMのボリュームグループ(VG)を作る
-
lxc storage create <LXDのストレージプール> lvm source=<作ったVG>
でストレージプールを作る - LXDコンテナのrootデバイスにこのストレージプールを指定してコンテナを作る
ことで,非特権でも中でDockerが動くLXDコンテナが作れました.
1の手順を飛ばしlxc storage createでストレージドライバーをlvmにしてストレージプールを作ることもできるのですが,この場合ブロックデバイスが (たしか) /var/snap/lxd/common/lxd/disks/
配下に作られるだけなので,ホスト上に直にVGを作るよりもパフォーマンスは落ちます.
あとクラスタ構成の場合はこの手は使えない (loopデバイスを参照できず落ちる) ので,ちゃんと各ノード上でVGを作ってあげる必要があります.
他にもDockerのストレージドライバをoverlay2以外にするとか方法は色々ありますが,手軽さとコンテナのパフォーマンスを考慮してこれに落ち着きました.
ちなみに,DockerのストレージドライバにもzfsはあるのでLXDのストレージドライバと一致させたらいけそうですが,LXDコンテナ内から見てみるとlxcfsという別のドライバにラップされているためできません.
また,別の方法としてrootlessバージョンのdockerをインストールする方法もあります.こちらでも動作が確認できました.
ただ,どちらの方法でも以下の問題点があります.
未解決の問題
通常のDockerコンテナはこれで十分なのですが,GPUを使うものだと以下のようなエラーを吐いて死にます.
docker: Error response from daemon: OCI runtime create failed: container_linux.go:349: starting container process caused "process_linux.go:449: container init caused \"process_linux.go:432: running prestart hook 0 caused \\\"error running hook: exit status 1, stdout: , stderr: nvidia-container-cli: mount error: write error: /sys/fs/cgroup/devices/docker/120159eccefb2caae5671cc8b60abe83d11ac8621582406980f63091ab4504fb/devices.allow: operation not permitted\\\\n\\\"\"": unknown.
ちょっとよくわからないので勉強中です...
コメント欄でぜひ教えてください.お願いします.