1. 每次部署都讓我的伺服器停擺,問題出在哪裡?
在經營個人專案時,常會碰到資源有限的環境(例如 GCP 超小型實例、Raspberry Pi 等)。我同時管理多台伺服器,從高規格的 AI 推理與訓練機器,到僅能跑名稱伺服器的低配 VM,種類相當多元。尤其喜歡 Raspberry Pi 5,因為即使 24 小時運行,電費負擔不大,且性能相當穩定。若把其他伺服器比作需要照料的牲畜,Raspberry Pi 則更像是讓人有感情的寵物。
然而,讓這隻「寵物」負擔過多工作時,部署時 CPU 會瞬間飆到 100%。罪魁禍首是 Celery Worker。為了實現無停機部署,我同時啟動 Blue 與 Green 兩個環境,結果 Worker 數量瞬間翻倍,系統無法負荷。若減少 Worker 數量,處理速度會受影響;若保持原樣,伺服器又會當機,陷入兩難。

為了解決這個問題,我製作了一套 自訂 Blue‑Green 部署腳本,在最小化資源消耗的同時,確保系統穩定性。
2. 解決策略:省資源、提升穩定性
傳統的 Blue‑Green 部署會同時跑兩套環境,我則採取以下方式降低 CPU 壓力:
- 先行停止背景服務(Celery):在新版本的 Web 伺服器上線前,先停止舊版的重型背景工作(Worker、Beat),釋放 CPU 資源。
- 分段啟動:不一次性啟動所有服務,而是先上線
Web + Redis,完成健康檢查後再繼續。 - Human‑in‑the‑loop:所有自動化流程結束後,由管理者親自確認,最後才刪除舊版,確保「最終批准」步驟。
回顧前面的說明,主要問題在於 Celery Worker 在初始化後立刻接收大量任務,導致 CPU 瞬間飆高。雖然降低 Worker 的 concurrency 設定可以緩解,但會讓非同步任務處理變慢,這並非我們想要的。於是,我想到在重新部署時暫時停掉 Celery,先釋放 CPU,再部署新程式碼,從而保持無停機。
3. 核心程式碼一覽
完整程式碼可在我的 GitHub 儲存庫 中取得,以下挑選幾段關鍵邏輯說明。
① 利用 Docker Compose 進行專案隔離
使用 docker compose -p 參數,即使使用相同的 compose 檔,也能建立 blue 與 green 兩個獨立的專案(命名空間)。
dc() {
# 動態指定專案名稱(-p)以實現環境隔離
docker compose -f "$COMPOSE_FILE" "$@"
}
② 徹底的健康檢查(Health Check)
在新版本完全就緒之前,絕不切換流量。
health_check() {
# 嘗試 10 次檢查指定端口是否回傳 200 OK
if curl -fsSIL --max-time "$HEALTH_TIMEOUT" "$url"; then
ok "Health check passed"
return 0
fi
}
③ 失敗時的快速恢復
若新版本出現問題,立即恢復先前停止的服務,避免讓使用者感受到中斷。為此,我沒有使用 rm -f 直接殺掉舊版的 Celery Worker 與 Beat,而是採用 stop 指令快速釋放 CPU,待需要時可即時重新啟動。
4. 運維心得:「確認後刪除」的美學
腳本的最後一步不會自動刪除舊版,而是顯示提示訊息讓管理者自行決定。
「部署已成功,但請自行連線確認。若無異常,請複製下方指令以清理舊版。」
這道安全檢查能防止自動化系統漏掉的 1% 錯誤,提升整體可靠性。
5. 結語
在資源受限的環境中尋求最佳效率的思考,都凝聚於這支腳本。雖然程式碼不算華麗,但我實際使用後感到相當滿意,也相信在這個星球上有許多開發者面臨相似困境。希望我的腳本能對同樣在小規模環境奮鬥的開發者提供幫助。
相關連結:
- GitHub Repository 直接前往
- 使用 GitHub Webhook 的自動部署系統 ⑤ Nginx、HTTPS 設定與最終整合
- 如有疑問,歡迎在留言或 GitHub Issue 中提出!