😎

WSL2にDocker代替のNerdCtl(containerd)を入れてみる(2023)

2023/05/29に公開

Rancher Desktop 重くね?

関連記事:
WSL2にDocker代替のNerdCtl(containerd)を入れてみる

ポッドマンが倒せないシリーズ過去記事

ポッドマンが倒せないシリーズでPodmanについてはいろいろやった。
自宅の環境は十分整ったのだが、
どうにも会社の環境に合わない。

会社の環境はDockerで作ったものの、
PCリソースが厳しくて代替策を探しているのだが、
Podmanでは認証周りが解決できなかった。
(時間的に断念)

代わりとなるとRancher Desktopだが、

( ゚Д゚) Rancher Desktop 重くね?

実は以前Rancher Desktopの記事を書いていたが、
あんまり使い物にならなそうだったので公開しなかった。

ならRancher Desktopの標準であるcontainerdを使えばいいか。
ということでWSLにcontainerdを入れてみる。

以前の記事ではとりあえず試した程度だったので、
改めてやり直そう。

ヾ(・ω<)ノ" 三三三● ⅱⅲ コロコロ♪

------------------- ↓ 本題はここから ↓-------------------

準備

クライアント側を用意

以下を参照のこと

https://zenn.dev/dozo/articles/860cb5b64b4a97

containerdをインストール

dockerリポジトリにcontainerdのパッケージ containerd.io があるのでそれを使う。
インストール方法はdockerのマニュアル通り。

bash
sudo dnf remove docker docker-client docker-client-latest docker-common docker-latest docker-latest-logrotate docker-logrotate docker-selinux docker-engine-selinux docker-engine
sudo dnf -y install dnf-plugins-core
sudo dnf config-manager --add-repo https://download.docker.com/linux/fedora/docker-ce.repo
sudo dnf install -y containerd.io
sudo chmod u+s $(which newuidmap)
sudo chmod u+s $(which newgidmap) 
sudo systemctl enable --now containerd
containerd --version
   containerd containerd.io 1.6.21 3dce8eb055cbb6872793272b4f20ed16117344f8
runc --version
   runc version 1.1.7

設定ファイルの初期状態がいまいちなので、
バックアップを取りつつ初期値に変える

bash
sudo mv /etc/containerd/config.toml /etc/containerd/config.toml.origin
containerd config default | sudo tee /etc/containerd/config.toml
sudo systemctl restart containerd

nerdctlのインストール

containerd用docker互換コマンドnerdctlをインストールする。
rootlessモード利用を想定しているので、
rootlessコマンドなどを含むフル版を使用

以下のページより最新のFULL版を取得

https://github.com/containerd/nerdctl/releases

bash
mkdir -p ~/.local/src && cd ~/.local/src
curl -LO https://github.com/containerd/nerdctl/releases/download/v1.3.1/nerdctl-full-1.3.1-linux-amd64.tar.gz
tar xzfz nerdctl-full-1.3.1-linux-amd64.tar.gz -C ~/.local/

~/.local/bin を$PATHに通しておく。

bash
source ~/.bashrc
which runc
  /home/dozo/.local/bin/runc

CNI Pluginインストール

CNIプラグインのパッケージをインストール

bash
sudo dnf install containernetworking-plugins -y

cniプラグイン設定を追加する。
無効化する行があるのでコメントアウトし、
bin_dir にパスを設定

/etc/containerd/config.toml
[plugins."io.containerd.grpc.v1.cri".cni]
+   bin_dir = "/usr/libexec/cni"

contenerdを再起動

bash
sudo systemctl restart containerd
containerd config dump | grep -i bin_dir -B 1
    [plugins."io.containerd.grpc.v1.cri".cni]
      bin_dir = "/usr/libexec/cni"

rootlessモード化

containerdをrootlessで動くようにする。
また、どのみち必要になるbuildkitも使えるようにしておく。

containerd
~/.local/bin/containerd-rootless-setuptool.sh install
systemctl --user status containerd
  ● containerd.service - containerd (Rootless)
     Loaded: loaded (/home/dozo/.config/systemd/user/containerd.service; enabled; preset: disabled)
    Drop-In: /usr/lib/systemd/user/service.d
             └─10-timeout-abort.conf
     Active: active (running) since Sun 2023-05-14 09:52:22 JST; 19min ago
   Main PID: 82 (rootlesskit)
     CGroup: /user.slice/user-1000.slice/user@1000.service/app.slice/containerd.service
buildkit
~/.local/bin/containerd-rootless-setuptool.sh install-buildkit
~/.local/bin/containerd-rootless-setuptool.sh install-buildkit-containerd
systemctl --user status buildkit
  ● buildkit.service - BuildKit (Rootless)
     Loaded: loaded (/home/dozo/.config/systemd/user/buildkit.service; enabled; preset: disabled)
    Drop-In: /usr/lib/systemd/user/service.d
             └─10-timeout-abort.conf
     Active: active (running) since Sun 2023-05-14 10:05:13 JST; 5min ago
   Main PID: 501 (buildkitd)
     CGroup: /user.slice/user-1000.slice/user@1000.service/app.slice/buildkit.service
             └─501 buildkitd

動作確認

mkdir ~/airflow && cd ~/airflow
curl -LO https://raw.githubusercontent.com/bitnami/containers/main/bitnami/airflow/docker-compose.yml
nerdctl compose up -d

起動まで少しかかるのでログをみる

nerdctl compose logs -f
・・・
airflow-scheduler_1 |  ____________       _____________
airflow-scheduler_1 | ____    |__( )_________  __/__  /________      __
airflow-scheduler_1 |____  /| |_  /__  ___/_  /_ __  /_  __ \_ | /| / /
airflow-scheduler_1 |___  ___ |  / _  /   _  __/ _  / / /_/ /_ |/ |/ /
airflow-scheduler_1 | _/_/  |_/_/  /_/    /_/    /_/  \____/____/|__/
・・・
airflow-worker_1    |[2023-05-14 01:35:34,694: INFO/MainProcess] celery@airflow-worker ready.

起動したっぽい

!http://localhost:8080/


airflow login

(^_-)-☆ 動いた!

思ったよりうまくいったか。

参考文献

https://www.itzgeek.com/how-tos/linux/fedora-how-tos/install-containerd-on-fedora.html
https://labs.iximiuz.com/tutorials/containerd-cli
https://cj-bc.github.io/blog/posts/2023-03-02-windows-install-and-setup-containerd-on-wsl2.html

------------------- ↓ 後書きはここから ↓-------------------

cgroupをv2に変更

rootlessだとcgroupをv2にしろと言われた。

nerdctl info
  WARNING: Running in rootless-mode without cgroups. To enable cgroups in rootless-mode, you need to boot the system in cgroup v2 mode.

サポート状態を確認

bash
mount -l | grep cgroup
tmpfs on /sys/fs/cgroup type tmpfs (ro,nosuid,nodev,noexec,size=4096k,nr_inodes=1024,mode=755)
cgroup2 on /sys/fs/cgroup/unified type cgroup2 (rw,nosuid,nodev,noexec,relatime,nsdelegate)
cgroup on /sys/fs/cgroup/systemd type cgroup (rw,nosuid,nodev,noexec,relatime,xattr,name=systemd)

kernelのパラメータを調整するらしい。

まずはwsl事態の設定から

~/.wslconfig
kernelCommandLine=systemd.unified_cgroup_hierarchy=1 cgroup_no_v1=all

fstabを調整

bash
echo 'cgroup2 /sys/fs/cgroup cgroup2 rw,nosuid,nodev,noexec,relatime,nsdelegate 0 0' | sudo tee -a /etc/fstab
sudo mount -a

システム自体を再起動する

bash
exit
wsl --shutdown
wsl -d fedora38

状態を確認

bash
mount -l | grep cgroup
tmpfs on /sys/fs/cgroup type tmpfs (rw,nosuid,nodev,noexec,relatime,mode=755)
cgroup2 on /sys/fs/cgroup/unified type cgroup2 (rw,nosuid,nodev,noexec,relatime,nsdelegate)
cgroup2 on /sys/fs/cgroup type cgroup2 (rw,nosuid,nodev,noexec,relatime,nsdelegate)

fedoraには update-grub コマンドがないので、
grubby で代用

bash
sudo dnf install -y grubby
sudo printf "GRUB_CMDLINE_LINUX=\"systemd.unified_cgroup_hierarchy=1\"\n" | sudo tee /etc/default/grub
sudo grub2-set-default 2
sudo grubby --update-kernel=ALL --args="systemd.unified_cgroup_hierarchy=1"
exit
wsl -t Fedora38
wsl -d Fedora38

https://rootlesscontaine.rs/getting-started/common/cgroup2/
https://www.linuxuprising.com/2019/11/how-to-install-and-use-docker-on-fedora.html
https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/8/html/managing_monitoring_and_updating_the_kernel/using-cgroups-v2-to-control-distribution-of-cpu-time-for-applications_managing-monitoring-and-updating-the-kernel

ランタイムをcrunに変更

bash
sudo dnf install crun
crun --version
  crun version 1.8.4
which crun
  /usr/bin/crun
/etc/containerd/config.toml
 [plugins."io.containerd.grpc.v1.cri".containerd]
-   default_runtime_name = "runc"
+   default_runtime_name = "crun"

+     [plugins."io.containerd.grpc.v1.cri".containerd.runtimes.crun]
+       runtime_type = "io.containerd.runc.v2"
+       [plugins."io.containerd.grpc.v1.cri".containerd.runtimes.crun.options]
+         BinaryName = "/usr/bin/crun"
+         SystemdCgroup = true
bash
systemctl --user restart containerd

最新版インストール

containerdの最新版を使うにはバイナリを直接使う流れっぽい。
なのでバイナリインストール方法も記載しておく。

バイナリ版インストール

最新版のパッケージはなさそうなので、
Githubから直接ダウンロード。
rootで扱うので /usr/local/ 配下に配置する。

以下のページより最新版を取得

https://github.com/containerd/containerd/releases

bash
cd /usr/local/src/
sudo curl -LO https://github.com/containerd/containerd/releases/download/v1.7.1/containerd-1.7.1-linux-amd64.tar.gz
sudo tar xvfz ./containerd-1.7.1-linux-amd64.tar.gz -C /usr/local/
containerd --version
  containerd github.com/containerd/containerd v1.7.1 1677a17964311325ed1c31e2c0a3589ce6d5c30d

サービスを登録

bash
sudo curl -LO https://raw.githubusercontent.com/containerd/containerd/main/containerd.service
sudo cp containerd.service /usr/lib/systemd/system/
sudo systemctl enable --now containerd
systemctl status containerd
  ● containerd.service - containerd container runtime
     Loaded: loaded (/usr/lib/systemd/system/containerd.service; enabled; preset: disabled)
    Drop-In: /usr/lib/systemd/system/service.d
             └─10-timeout-abort.conf
     Active: active (running) since Sat 2023-05-13 08:12:38 JST; 13s ago

コンテナランタイムをインストール

コンテナランタイムのruncをインストール。
以下のページより最新版を取得

https://github.com/opencontainers/runc/releases

bash
sudo curl -LO https://github.com/opencontainers/runc/releases/download/v1.1.7/runc.amd64
sudo install -m 755 runc.amd64 /usr/local/sbin/runc
runc --version
  runc version 1.1.7
  commit: v1.1.7-0-g860f061b
  spec: 1.0.2-dev
  go: go1.20.3
  libseccomp: 2.5.4

CNI pluginsをインストール

以下のページより最新版を取得

https://github.com/containernetworking/plugins/releases

bash
sudo mkdir -p /opt/cni/bin
sudo curl -LO https://github.com/containernetworking/plugins/releases/download/v1.1.1/cni-plugins-linux-amd64-v1.1.1.tgz
sudo tar xzvf cni-plugins-linux-amd64-v1.1.1.tgz -C /opt/cni/bin

初期設定値を配置

bash
sudo mkdir -p /etc/containerd
containerd config default | sudo tee /etc/containerd/config.toml
sudo systemctl restart containerd

トラブルシューティング

listen tcp 0.0.0.0:80: bind: permission denied

1024以下のポートは権限ないとダメよ

FATA[0000] failed to create shim task: OCI runtime create failed: runc create failed: unable to start container process: error during container init: error running hook #0: error running hook: exit status 1, stdout: , stderr: time="2023-05-14T10:17:52+09:00" level=fatal msg="failed to expose ports in rootless mode: cannot expose privileged port 80, you can add 'net.ipv4.ip_unprivileged_port_start=80' to /etc/sysctl.conf (currently 1024), or set CAP_NET_BIND_SERVICE on rootlesskit binary, or choose a larger port number (>= 1024): listen tcp 0.0.0.0:80: bind: permission denied"
Failed to write to log, write /home/dozo/.local/share/nerdctl/1935db59/containers/default/a1ca3b639b61e8ed1c438c627e267de171daf38d6428bcf6b3c07967ee6eff1d/oci-hook.createRuntime.log: file already closed: unknown
FATA[0049] error while creating container discourse_discourse_1: exit status 1

sysctlで設定
(または /etc/sysctl.conf に記述)

bash
sudo sysctl net.ipv4.ip_unprivileged_port_start=80

RootlessKit failed, rootlesskit: command not found

rootlesskitが見つからない問題

bash
~/.local/bin/containerd-rootless-setuptool.sh install
[INFO] Checking RootlessKit functionality
/home/dozo/.local/bin/containerd-rootless-setuptool.sh: line 111: rootlesskit: command not found
[ERROR] RootlessKit failed, see the error messages and https://lesscontaine.rs/getting-started/common/ .

コマンドへのパスが通っていないのが原因

export PATH=~/.local/bin/:$PATH

newuidmap権限問題

例のあれ

bash
[rootlesskit:parent] error: failed to setup UID/GID map: newuidmap 3653 [0 1000 1 1 524288 65536] failed: newuidmap: write to uid_map failed: Operation not permitted
: exit status 1
[ERROR] RootlessKit failed, see the error messages and https://rootlesscontaine.rs/getting-started/common/ .

コマンドの権限不足

bash
sudo chmod u+s $(which newuidmap)
sudo chmod u+s $(which newgidmap) 

コンテナ内のネットワークから外に出られない問題

VPNの時と同じような問題が。

bash
nerdctl compose up -d
・・・
INFO[0010] trying next host                              error="failed to do request: Head \"https://registry-1.docker.io/v2/bitnami/airflow-worker/manifests/2\": dial tcp: lookup registry-1.docker.io on 10.0.2.3:53: read udp 10.0.2.100:45252->10.0.2.3:53: i/o timeout" host=registry-1.docker.io
FATA[0010] failed to resolve reference "docker.io/bitnami/airflow-worker:2": failed to do request: Head "https://registry-1.docker.io/v2/bitnami/airflow-worker/manifests/2": dial tcp: lookup registry-1.docker.io on 10.0.2.3:53: read udp 10.0.2.100:45252->10.0.2.3:53: i/o timeout

コンテナ内のネットワークのから外部に出るときの名前解決ができないのが原因
コンテナ内部の /etc/resolv.conf を調整する

bash
containerd-rootless-setuptool.sh nsenter bash
printf "nameserver 1.1.1.1\n" | tee /etc/resolv.conf

Discussion