我有一個 Linebot 部署在樹梅派上的 k3s,原先是透過簡單的 kubectl apply -f 方式來部署這服務的 deployment, service, ingress 等資源。
最近想將這個服務改為使用 Helm Chart 來管理,但過程中遇到了一些問題,本文將詳細介紹如何實現零停機遷移

為什麼要從 YAML 遷移到 Helm?

在開始解決問題前,我們先來看看為什麼要進行這樣的遷移:

  • 配置集中管理:將分散的 YAML 檔案整合到一個 Chart 中
  • 版本控制:可以輕鬆回滾到之前的版本
  • 變數模板化:透過 values.yaml 實現不同環境的配置覆蓋
  • 複用性提高:可以在不同的環境或專案中重複使用
  • 依賴管理:處理複雜的服務依賴關係

從 kubectl apply 到 Helm 的衝突問題

當我撰寫好 Helm Chart 並嘗試執行以下指令時:

1
helm install popofinder ./popofinder -n popo --dry-run

遇到了這樣的錯誤:

1
2
3
4
5
Error: INSTALLATION FAILED: Unable to continue with install: 
Deployment "popofinder" in namespace "popo" exists and cannot be imported into the current release: invalid ownership metadata;
label validation error: missing key "app.kubernetes.io/managed-by": must be set to "Helm";
annotation validation error: missing key "meta.helm.sh/release-name": must be set to "popofinder";
annotation validation error: missing key "meta.helm.sh/release-namespace": must be set to "popo"

從錯誤訊息可以看出,對於 popofinder 這個 deployment 來說,在 popo namespace 中已經存在了,並且因為不是透過 Helm 部署的,因此缺少對應的 labelannotation 來讓 Helm 接管。

最直接的解決方案及其挑戰

最簡單直接的做法就是將已有的資源全部刪除,然後使用 Helm 重新部署:

1
2
3
kubectl delete deploy,ingress,service -l app=popofinder -n popo

helm install popofinder ./popofinder -n popo

但我的服務正在線上運行中,這種方法會帶來兩個明顯的問題:

  1. 不可避免的停機時間: 服務會短暫不可用,影響用戶體驗
  2. 部署風險增加: 如果 Helm Chart 定義有問題,可能需要緊急回滾,造成更長的停機時間

需要尋找更好的解決方案

理想的遷移方案應該能做到:

  • 零停機時間: 用戶無感知
  • 可回滾性: 出現問題能快速恢復
  • 資源保留: 不需要重建所有資源

零停機遷移方案詳解

1. 分析錯誤訊息

從錯誤中我們可以看出,主要是缺少三項關鍵資訊:

  • 標籤 app.kubernetes.io/managed-by: Helm - 表明此資源是由 Helm 管理
  • 註釋 meta.helm.sh/release-name: popofinder - 指定此資源屬於哪個 Helm 發行版本
  • 註釋 meta.helm.sh/release-namespace: popo - 指定此資源所屬的命名空間

2. 逐一添加標籤和註釋

我使用 kubectl labelkubectl annotate 命令來新增這些缺少的資訊,讓 Helm “接管”現有資源:

1
2
3
4
5
6
7
8
9
10
11
12
13
# 為 Deployment 添加標籤和註釋
kubectl label deploy popofinder -n popo app.kubernetes.io/managed-by=Helm
kubectl annotate deploy popofinder -n popo meta.helm.sh/release-name=popofinder meta.helm.sh/release-namespace=popo

# 為 Service 添加標籤和註釋
kubectl label svc popofinder -n popo app.kubernetes.io/managed-by=Helm
kubectl annotate svc popofinder -n popo meta.helm.sh/release-name=popofinder meta.helm.sh/release-namespace=popo

# 為 Ingress 添加標籤和註釋
kubectl label ingress popofinder -n popo app.kubernetes.io/managed-by=Helm
kubectl annotate ingress popofinder -n popo meta.helm.sh/release-name=popofinder meta.helm.sh/release-namespace=popo

# 如果有其他資源,也需要類似處理

3. 驗證遷移結果

在為所有資源添加標籤和註釋後,再次執行 Helm 安裝命令:

1
helm install popofinder ./popofinder -n popo

成功了!現在我可以使用 Helm 來管理和更新這個服務了。

helm-install

注意事項

本文提供的解決方案僅適用於 Helm 3。Helm 2 使用了不同的資源標記系統,這個方法在 Helm 2 中不適用。
如果你使用的是 Helm 2,請考慮先升級到 Helm 3 或尋找特定於 Helm 2 的解決方案。

Helm 帶來的好處

既然我們已經成功將資源遷移到了 Helm,我們來簡單總結一下 Helm 能為我們帶來的好處:

  1. 簡化部署流程

    • 使用單一命令 helm install/upgrade 即可完成部署
    • 不需要手動管理多個 YAML 檔案
  2. 提高可維護性

    • 透過 values.yaml 集中管理配置
    • 更容易進行變更和追踪
  3. 版本控制和回滾

    • 每次部署都是一個版本,可以使用 helm history 查看
    • 出現問題可以立即用 helm rollback 回滾
  4. 模板化和重用

    • 使用 Go 模板語言讓配置更靈活
    • 通過 Chart 依賴關係管理複雜應用

PoPoFinder Linebot 推薦

最後順便在這篇文章推廣一下這個用來方便查詢醫生是否是波波的 Linebot,歡迎掃描 QRcode 加入好友:

popofinder

功能亮點

  • 支援模糊搜尋功能
  • 可以根據地區與科別進行搜尋

GitHub Repo: popofinder


相關閱讀