定期自動重啟 Docker 容器
| | | 0 | |
前陣子分享利用 Task.Run 逾時機制防止被同步呼叫永久卡死的小技巧,但不幸地,TPLinkSmartDevice 程式庫不只網路查詢會卡住這一個 Bug,還存在 CPU 無故飆高問題。這點其實以前跑 SQLite + 自繪圖表版時就有觀察到,程式運行一陣子後(通常是幾小時到幾天),該 Docker 的 CPU 使用率會衝到 100% 以上不再下降,我是有陣子摸到機身總是溫溫的才察覺有異,用 top 查才確認。
現在有 cAdvisor + Prometheus + Grafana 圖表可看,Docker 行為無所遁形,證實雖然已重寫成 Promethues Exporter 版,仍屢屢發生數小時到幾天後 CPU 衝上 120% 甚至 160% 的狀況。(圖表裡有不同顏色的 hs300-exporter,每條代表一次 docker compose 重啟的新程序)

截然不同的程式架構,相同的異常,兇手除了兩次都在場的 TPLinkSmartDevice .NET 程式庫,我想不到其他嫌犯。而這一次,在我面前一樣有兩條路可走,一條有趣、一條有用。要嘛追進 TPLinkSmartDevice 程式碼找出 Bug,若能修好應該很有成就感;不然也可以鋸箭避免 CPU 衝高就好,例如:定期重新啟動。
重啟雖然可恥但有用,學會之後,未來若再遇到這類不是操之在我,不一定有能力根治的不穩定問題,都能速解決。

我找到一個簡單做法,在原本的 docker-compose.yaml 增加一個名為 cron-restarter 的輔助容器,其使用 docker:cli 這個超輕量容器,其中內建 Docker 命令行工具(CLI),可用來下達 Docker 指令。cron-restarter 的 Volume 對映要設定 /var/run/docker.sock:/var/run/docker.sock 將 Host 的 Docker 通訊接口(Socket)掛載到容器內部,以便在容器執行 docker restart ... 操作 Host 上的 Docker Daemon。而定期重啟的腳本是一個 while true 迴圈,等待 18000 秒(5 小時),執行 docker restart hs300-exporter 重啟 hs300-exporter 容器,周而復始,永不停止。
services:
hs300-exporter:
image: hs300-exporter:latest
container_name: hs300-exporter
restart: unless-stopped
ports:
- "9300:9999"
environment:
- TZ=Asia/Taipei
- HS300_DeviceIP=192.168.50.80
network_mode: bridge
cron-restarter:
image: docker:cli
container_name: cron-restarter
volumes:
- /var/run/docker.sock:/var/run/docker.sock
command: >
/bin/sh -c "while true; do
sleep 18000;
docker restart hs300-exporter;
done"
restart: unless-stopped
depends_on:
- hs300-exporter
下圖的藍線是啟用 cron-restarter 五小時自動重啟後的效能,下方 Memory 可以觀察到每隔五小時重啟時的斷崖式落差,而 CPU 是全程壓在 2% 以下,雖然還沒有經過長期驗證,但應不必再擔心 CPU 會上衝了。(如有意外再更新囉)

Comments
Be the first to post a comment