Helm Smart Resource:讓你的 Chart 學會與既有資源和平共處

前言 在 Kubernetes 的世界裡,Helm 無疑是管理應用程式部署的霸主。它標準化了資源的定義,讓我們可以用宣告式的方式管理整套系統。然而,在真實世界的維運場景中,事情往往沒那麼單純。 我們常遇到一種尷尬的情況:某些資源(例如 Database 的 Secret、外部系統的 ConfigMap)可能在 Helm Chart 安裝之前就已經由維運人員手動建立,或是由另一個流程(如 Terraform)預先準備好了。 這時候,如果直接執行 helm install,往往會收到 “resource already exists” 的錯誤;如果使用 helm upgrade --install,又擔心 Helm 會覆蓋掉這些既有設定。 這篇文章將分享一種「Smart Resource」的設計模式,透過 Helm 的 lookup 函數與樣板邏輯,讓你的 Chart 能夠聰明地判斷:「這東西是我管的嗎?如果是,我才動它;如果不是,我就尊重現狀。」 核心難題:Ownership 在 Kubernetes 中,資源的「所有權」觀念至關重要。Helm 預設認為它 release 中的所有資源都應該由它全權管理。但當我們需要與外部資源協作時,我們需要更細緻的控制。 我們的目標很明確: 若資源不存在:建立它,並標記為 Helm 管理。 若資源已存在且由 Helm 管理:更新它(Patch/Merge)。 若資源已存在但由外部管理:保持原狀,不進行覆蓋或刪除。 為了達成這個目標,我們需要一個輔助函數來判斷資源的歸屬權。 實作細節 1. 定義所有權檢查 首先,我們在 _helpers.tpl 中定義一個檢查函數。Helm 會在它建立的資源上打上特定的 Annotations(meta.helm.sh/release-name 和 meta.helm.sh/release-namespace)。我們可以利用這一點來判斷資源是否屬於當前的 Release。 {{/* Check if a resource is owned by this Helm release Returns "true" or "false" as string for stable piping */}} {{- define "visionone-filesecurity.isOwnedByRelease" -}} {{- $resource := .resource -}} {{- $releaseName := .releaseName -}} {{- $releaseNamespace := .releaseNamespace -}} {{- $owned := and $resource (hasKey $resource.metadata "annotations") (eq (get $resource.metadata.annotations "meta.helm.sh/release-name") $releaseName) (eq (get $resource.metadata.annotations "meta.helm.sh/release-namespace") $releaseNamespace) -}} {{ printf "%t" $owned }} {{- end -}} 這段程式碼邏輯很簡單:只有當資源存在,且其 Annotations 中的 Release Name 與 Namespace 都與當前 Release 相符時,才視為「Owned」。 ...

2025-11-22 · 4 min · 715 words