原本使用 wsl-distrod 來作為 wsl 中 systemd 的實現方式,後來 microsoft 宣布 wsl 支持 systemd 後,distrod 等等 repo 就沒有在更新了呢,是巧合嗎?我不這麼認為。
這篇簡略紀錄 wsl2 中啟用 systemd 作為 process 管理工具以及配合紅帽推出的 podman 來取代(斷捨離)docker desktop。
環境
wsl2 + ubuntu 22.04
❯ neofetch
.-/+oossssoo+/-. raiven@raiven
`:+ssssssssssssssssss+:` -------------
-+ssssssssssssssssssyyssss+- OS: Ubuntu 22.04.1 LTS on Windows 10 x86_64
.ossssssssssssssssssdMMMNysssso. Kernel: 5.10.43.3-microsoft-standard-WSL2
/ssssssssssshdmmNNmmyNMMMMhssssss/ Uptime: 3 hours, 10 mins
+ssssssssshmydMMMMMMMNddddyssssssss+ Packages: 2005 (dpkg), 4 (snap)
/sssssssshNMMMyhhyyyyhmNMMMNhssssssss/ Shell: zsh 5.8.1
.ssssssssdMMMNhsssssssssshNMMMdssssssss. Theme: Adwaita [GTK3]
+sssshhhyNMMNyssssssssssssyNMMMysssssss+ Icons: Adwaita [GTK3]
ossyNMMMNyMMhsssssssssssssshmmmhssssssso Terminal: Windows Terminal
ossyNMMMNyMMhsssssssssssssshmmmhssssssso CPU: AMD Ryzen 9 5900X (24) @ 3.700GHz
+sssshhhyNMMNyssssssssssssyNMMMysssssss+ GPU: dbac:00:00.0 Microsoft Corporation Device 008e
.ssssssssdMMMNhsssssssssshNMMMdssssssss. Memory: 1427MiB / 15966MiB
/sssssssshNMMMyhhyyyyhdNMMMNhssssssss/
+sssssssssdmydMMMMMMMMddddyssssssss+
/ssssssssssshdmNNNNmyNMMMMhssssss/
.ossssssssssssssssssdMMMNysssso.
-+sssssssssssssssssyyyssss+-
`:+ssssssssssssssssss+:`
.-/+oossssoo+/-.
wsl2 中啟用 systemd
-
請確保 wsl2 的版本是 version 2,可以在 cmd/powershell 中查看
C:\Users\omega>wsl --list -v NAME STATE VERSION * Ubuntu-22.04 Running 2
-
在 wsl2 中修改
/etc/wsl.conf
sudo vim /etc/wsl.conf
-
在
/etc/wsl.conf
中添加啟動選項,確保 wsl2 重啟時以 systemd 作為 pid 1[boot] systemd=true
-
在 cmd/powershell 中關閉 wsl 執行個體,會自己重啟
wsl --shutdown
-
重啟完成後在 wsl 中檢查是否已經正確啟用
❯ systemctl list-unit-files --type=service UNIT FILE STATE VENDOR PRESET accounts-daemon.service enabled enabled acpid.service masked enabled alsa-restore.service static - alsa-state.service static - alsa-utils.service masked enabled anacron.service enabled enabled apparmor.service enabled enabled apport-autoreport.service static - ❯ sudo systemctl status | cat [sudo] password for raiven: ● raiven State: degraded Jobs: 0 queued Failed: 5 units Since: Mon 2023-02-13 19:21:06 CST; 3h 22min ago CGroup: / ├─user.slice │ ├─user-0.slice │ │ └─session-c2.scope │ │ ├─ 978 /bin/login -f │ │ └─1029 -bash
-
若啟用後發現無論是
sudo apt update
或是sudo systemctl status
都跑得很慢,甚至跳出Transport Endpoint Is Not Connected
,可以參考這篇 issue 的解決辦法sudo ln -s /dev/null /etc/systemd/system/acpid.service sudo ln -s /dev/null /etc/systemd/system/acpid.path
安裝 podman
-
按照官方文件安裝即可
sudo apt update sudo apt -y install podman
-
可以檢查/修改
/etc/containers/registries.conf
來添加自己慣用的 container registry,好比自己的 harbor 服務vim /etc/containers/registries.conf unqualified-search-registries=[ "quay.io", "gcr.io", "docker.io", "hao123.omegaatt.com" ]
-
可以設定別名,讓一些使用 docker 的腳本無痛銜接
vim ~/.zshrc alias docker='podman'
-
或是在腳本中使用變數
# xxx.sh #!/bin/bash DOCKER=podman $DOCKER ps
-
以及在 Makefile 中使用變數
# Makefile DOCKER=podman ps: $(DOCKER) ps
使用 systemd 管理 podman container
雖然說 podman 可以使用介於 Docker 與 Kubernetes 之間的 Pod,但那並不是此篇文章的重點,詳細可以參考紅帽的教學。
至於為何要用 systemd 來管理 podman? 是由於 podman 不像 docker 有 Docker Engine a.k.a. dockerd,重開機後不會自動重啟(是的,--restart=always
也不會)。
但同時 podman 也帶來了 rootless container(中文翻譯「無根容器」?),不用每個容器都給予 root 權限。
舉例來說我需要在某台機器上部署 drone-runner:
- 建立 podman container
podman create \ -v /run/podman/podman.sock:/var/run/docker.sock \ -e DRONE_RPC_HOST=$DRONE_HOST \ -e DRONE_RPC_PROTO=http \ -e DRONE_RPC_SECRET=$DRONE_SECRET \ -e DRONE_RUNNER_CAPACITY=3 \ --name drone-runner \ --restart on-failure docker.io/drone/drone-runner-docker:1
- 將 container 轉成 systemd service file
podman generate systemd --new --files --name drone-runner
- 複製 systemd service file
- rootless container
如果沒有資料夾的話需要
接著複製
mkdir -p ~/.config/systemd/user
cp -Z container-drone-runner.service ~/.config/systemd/user
- root container
sudo cp -Z container-drone-runner.service /etc/systemd/system
- rootless container
如果沒有資料夾的話需要
- 啟用
- rootless container
systemctl --user enable container-drone-runner.service systemctl --user start container-drone-runner.service systemctl --user status container-drone-runner.service
- root container
sudo systemctl enable container-drone-runner.service sudo systemctl start container-drone-runner.service sudo systemctl status container-drone-runner.service
- rootless container
- 用 podman ps 查看
- rootless container
podman ps
- root container
sudo podman ps
- rootless container
檢查成果
- 透過
pstree
來看 systemd 與 podman 的 container 的互動,可以看到systemd.conmon.drone-runner-do
正是剛剛部署的 drone runner。❯ pstree systemd─┬─ModemManager───2*[{ModemManager}] ├─agetty ├─bash───frpc───8*[{frpc}] ├─conmon─┬─drone-runner-do───12*[{drone-runner-do}] │ └─{conmon} ├─containerd-shim─┬─2*[entry] │ ├─pause │ └─13*[{containerd-shim}] ├─containerd-shim─┬─argocd-applicat───12*[{argocd-applicat}] │ ├─pause │ └─12*[{containerd-shim}] ├─containerd-shim─┬─argocd-server───12*[{argocd-server}] │ ├─pause │ └─12*[{containerd-shim}] ├─containerd-shim─┬─pause │ ├─s6-svscan─┬─s6-supervise───s6-linux-init-s │ │ ├─s6-supervise │ │ ├─s6-supervise───s6-ipcserverd │ │ ├─s6-supervise───php │ │ ├─s6-supervise───php-fpm8───3*[php-fpm8] │ │ ├─s6-supervise───crond │ │ └─s6-supervise───nginx───4*[nginx] │ └─13*[{containerd-shim}]