容器技術的普及改變了應用程式的開發與部署模式,而 Kubernetes 作為容器編排平台的領導者,已經成為雲原生應用的標準選擇。然而,Kubernetes 本身並不提供容器映像檔建置功能,這在實務上造成開發團隊必須在叢集外維護獨立的建置環境,增加了基礎設施的複雜度。
在我協助企業導入 GitOps 實踐的過程中,發現容器映像檔建置與部署的自動化是最關鍵的環節之一。如何在 Kubernetes 環境內安全地建置容器映像檔,如何管理多環境的部署配置,如何確保建置過程的安全性與可重複性,這些都是團隊面臨的實際挑戰。
這篇文章將深入探討現代容器建置工具的實戰應用,從 Buildah 的無根容器建置,到 Shipwright 框架的整合,再到 Kustomize 的資源管理,完整涵蓋 GitOps 工作流程中的關鍵技術。
Buildah:打造更安全的容器映像檔
Buildah 的核心優勢與設計理念
Buildah 是一個專注於建置安全容器映像檔的工具,它解決了傳統 Docker 建置流程中的數個關鍵安全問題。傳統上,在容器內建置映像檔需要特權模式,這在多租戶環境中存在顯著的安全風險。Buildah 透過無根模式運作,讓一般使用者也能安全地建置容器映像檔。
Buildah 的設計理念在於提供更精細的控制權。它不依賴 Docker daemon,完全獨立運作,這使得建置過程更加輕量且安全。在我參與的金融科技專案中,安全性要求特別嚴格,Buildah 的無根模式成為我們的首選方案,它讓建置過程能在受限的安全環境中順利執行。
Buildah 支援兩種建置模式。第一種是互動式建置,透過一系列命令逐步構建容器,這種方式提供了極大的靈活性。第二種是使用 Dockerfile,這為從 Docker 遷移提供了平滑的過渡路徑。這種雙模式設計讓 Buildah 能適應不同的使用場景。
使用 Buildah 建置 Web 服務容器
讓我們從實際案例開始,看如何使用 Buildah 建立一個簡單的 HTTP 服務容器。整個流程展示了 Buildah 的互動式建置能力,相較於 Dockerfile 的宣告式方式,這種方法提供了更直接的操作體驗。
@startuml
!define PLANTUML_FORMAT svg
!theme _none_
skinparam dpi auto
skinparam shadowing false
skinparam linetype ortho
skinparam roundcorner 5
skinparam defaultFontName "Microsoft JhengHei UI"
skinparam defaultFontSize 16
(*) --> "buildah from centos:latest"
"buildah from centos:latest" --> "建立工作容器"
"建立工作容器" --> "buildah run 安裝 httpd"
"buildah run 安裝 httpd" --> "buildah copy 複製檔案"
"buildah copy 複製檔案" --> "buildah config 設定入口點"
"buildah config 設定入口點" --> "buildah commit 提交映像檔"
"buildah commit 提交映像檔" --> (*)
note right of "建立工作容器"
建立可修改的工作容器
而非不可變的映像檔層
end note
note right of "buildah commit 提交映像檔"
將工作容器狀態
儲存為新的映像檔
end note
@enduml首先從基礎映像檔建立工作容器。使用 buildah from 命令從 CentOS 基礎映像檔建立一個可修改的工作容器,這是 Buildah 操作的基本單位。這個命令類似於 Dockerfile 中的 FROM 指令,但它直接返回一個容器實例,而非僅僅定義建置階段。
執行 buildah containers 命令可以列出當前所有的工作容器,協助我們確認容器已正確建立。然後使用 buildah run 命令在容器內執行安裝指令,例如安裝 Apache HTTP Server。這個過程相當於 Dockerfile 中的 RUN 指令,但提供了更直接的操作方式。
接下來準備應用程式的內容檔案。建立一個簡單的 HTML 頁面作為測試內容,這個檔案將作為 Web 服務的首頁。使用 buildah copy 命令將本地檔案複製到容器中的指定位置,這個操作類似於 Dockerfile 中的 COPY 指令。
設定容器的執行配置是關鍵步驟。使用 buildah config 命令設定容器的入口點,指定容器啟動時要執行的程式。這相當於 Dockerfile 中的 ENTRYPOINT 指令,但可以在建置過程中隨時調整。
最後使用 buildah commit 命令將工作容器的當前狀態儲存為新的映像檔。這個命令會指定映像檔的名稱和標籤,完成整個建置流程。與 Docker 的分層建置不同,Buildah 提供了更靈活的控制方式,可以精確決定何時建立新的映像檔層。
使用 Dockerfile 與 Buildah 建置映像檔
Buildah 完全支援標準的 Dockerfile 格式,這為現有的 Docker 工作流程提供了平滑的遷移路徑。使用 Dockerfile 的好處在於建置過程是宣告式的,易於版本控制與重複執行。
撰寫一個標準的 Dockerfile,指定基礎映像檔、安裝必要套件、複製應用程式檔案、暴露連接埠,以及定義啟動命令。這個 Dockerfile 與在 Docker 中使用的完全相同,無需任何修改。
使用 buildah bud 命令從 Dockerfile 建置映像檔。bud 是 build-using-dockerfile 的縮寫,這個命令允許 Buildah 使用標準 Dockerfile 建置映像檔,同時享受 Buildah 的安全優勢。建置過程與 Docker 幾乎相同,但底層實作更注重安全性與隔離性。
這種相容性設計讓團隊可以逐步遷移到 Buildah,而不需要一次性重寫所有建置腳本。在實務專案中,我通常建議先使用 Dockerfile 模式熟悉 Buildah,然後根據需要逐步採用互動式建置來獲得更細緻的控制。
Buildah 的技術優勢深度分析
Buildah 在容器建置領域提供了數個關鍵優勢,這些特性使它在安全性要求高的環境中特別有價值。首先是無需安裝 Docker daemon,Buildah 完全獨立運作,減少了系統相依性與潛在的安全風險。
無根使用者操作是 Buildah 最重要的安全特性。傳統的容器建置需要 root 權限或特權模式,這在多租戶環境中存在權限提升的風險。Buildah 支援完全在使用者命名空間中運作,讓一般使用者也能安全地建置容器映像檔。
@startuml
!define PLANTUML_FORMAT svg
!theme _none_
skinparam dpi auto
skinparam shadowing false
skinparam linetype ortho
skinparam roundcorner 5
skinparam defaultFontName "Microsoft JhengHei UI"
skinparam defaultFontSize 16
package "Docker 建置流程" {
rectangle "需要 Docker Daemon" as DD
rectangle "需要 root 權限" as DR
rectangle "單一建置階段" as DS
DD -down-> DR
DR -down-> DS
}
package "Buildah 建置流程" {
rectangle "無需 Daemon" as BD
rectangle "支援無根模式" as BR
rectangle "精細層控制" as BS
BD -down-> BR
BR -down-> BS
}
note right of BS
可以精確控制每個映像檔層
支援從零開始建置
提供更好的安全隔離
end note
@enduml對映像檔層的精細控制是 Buildah 的另一個優勢。使用 Buildah 時,開發者可以精確決定何時建立新的映像檔層,這對於最佳化映像檔大小與建置效能非常有用。相較於 Dockerfile 每個指令自動建立一層,Buildah 提供了更靈活的控制方式。
從零開始建置能力讓 Buildah 可以建立極小的生產映像檔。在開發過程中可能需要編譯器與開發工具,但在生產環境中,只需要執行時環境與應用程式。Buildah 讓這種映像檔縮減變得簡單直接,類似於 Dockerfile 中的 FROM scratch,但提供了更多控制選項。
Cloud Native Buildpacks:自動化容器建置的革新
Buildpacks 的核心理念與價值主張
Cloud Native Buildpacks 代表了容器建置自動化的重大進展。在大規模微服務環境中,維護數百個 Dockerfile 是個巨大的挑戰。每當基礎映像檔更新或安全性修補發布時,都需要更新所有相關的 Dockerfile,這個維護負擔隨著服務數量成長而急劇增加。
Buildpacks 透過自動檢測應用程式類型並套用適當的建置策略,徹底改變了這個局面。開發者不再需要撰寫 Dockerfile,只需要提供應用程式原始碼,Buildpacks 會自動識別程式語言、框架版本、相依套件,並建立最佳化的容器映像檔。
@startuml
!define PLANTUML_FORMAT svg
!theme _none_
skinparam dpi auto
skinparam shadowing false
skinparam linetype ortho
skinparam roundcorner 5
skinparam defaultFontName "Microsoft JhengHei UI"
skinparam defaultFontSize 16
(*) --> "分析原始碼"
"分析原始碼" --> "檢測階段"
"檢測階段" --> if "識別語言?" then
-->[Node.js] "選擇 Node.js Buildpack"
-->[Python] "選擇 Python Buildpack"
-->[Java] "選擇 Java Buildpack"
else
-->[未知] "錯誤:不支援的語言"
"錯誤:不支援的語言" --> (*)
endif
"選擇 Node.js Buildpack" --> "建置階段"
"選擇 Python Buildpack" --> "建置階段"
"選擇 Java Buildpack" --> "建置階段"
"建置階段" --> "安裝相依套件"
"安裝相依套件" --> "編譯應用程式"
"編譯應用程式" --> "設定執行環境"
"設定執行環境" --> "產生容器映像檔"
"產生容器映像檔" --> (*)
note right of "檢測階段"
自動分析專案結構
識別 package.json
requirements.txt
pom.xml 等檔案
end note
@endumlBuildpacks 的工作流程分為兩個主要階段。檢測階段會分析原始碼目錄,識別程式語言與框架。例如,發現 package.json 表示這是 Node.js 專案,發現 requirements.txt 表示這是 Python 專案,發現 pom.xml 表示這是 Java Maven 專案。這個自動檢測機制消除了手動配置的需要。
建置階段使用選定的 buildpack 編譯原始碼並建立容器映像檔。這個階段會安裝相依套件、編譯程式碼、設定執行環境,並自動決定適當的入口點與啟動指令。整個過程完全自動化,開發者無需介入。
使用 Buildpacks 建置 Node.js 應用程式
讓我們透過實際案例來理解 Buildpacks 的運作方式。首先需要安裝 pack CLI 工具,這是 Cloud Native Buildpacks 的命令列介面。在 macOS 上可以使用 Homebrew 安裝,其他作業系統可以從官方網站下載對應版本。
安裝完成後,可以使用 pack builder suggest 命令查看可用的 builder。這個命令會列出由 Google、Heroku、Paketo 等組織提供的各種 builder,每個 builder 包含不同的語言與框架支援。選擇合適的 builder 是建置成功的關鍵。
對於 Node.js 應用程式,Paketo 的 base builder 是個不錯的選擇。使用 pack build 命令並指定 builder 即可開始建置過程。命令執行時,Buildpacks 會下載 builder 映像檔,分析專案目錄,檢測到這是 Node.js 應用程式,選擇適當的 buildpacks 組合,然後自動完成整個建置流程。
建置完成後產生的容器映像檔可以直接使用 Docker 或 Podman 執行。Buildpacks 會自動設定適當的入口點,通常是從 package.json 中的 start 腳本推導出來。整個過程無需撰寫任何 Dockerfile 或建置腳本,大幅降低了容器化的門檻。
Buildpacks 的企業級應用場景
在我協助企業導入 Buildpacks 的經驗中,發現它在數個場景中特別有價值。首先是大規模標準化部署,當組織需要為數百個結構相似的微服務建立容器時,Buildpacks 可以大幅降低維護成本。統一的建置流程也確保了一致的安全標準與最佳實踐。
簡化開發者體驗是另一個重要價值。不是所有開發者都熟悉容器技術,特別是在傳統企業轉型的過程中。Buildpacks 讓開發者可以專注於應用程式邏輯,而不需要學習複雜的容器建置技術。這降低了採用容器技術的門檻,加速了雲原生轉型。
強制執行最佳實踐是 Buildpacks 在企業環境中的關鍵優勢。透過 builder 可以封裝組織認可的建置策略、安全標準、基礎映像檔選擇等。這確保了所有應用程式都遵循相同的標準,減少了安全漏洞與配置錯誤的風險。
降低維護成本是長期的重要利益。當基礎映像檔需要更新或安全性修補發布時,只需要更新 builder,所有使用該 builder 的應用程式都會自動受益。這比逐一更新數百個 Dockerfile 要高效得多,也更不容易出錯。
Shipwright:Kubernetes 原生的容器建置框架
Kubernetes 容器建置的挑戰
Kubernetes 作為容器編排平台的領導者,在容器部署與管理方面表現出色。然而,它本身並不提供建置容器映像檔的內建功能。根據 Kubernetes 官方文件明確說明,持續整合、交付與部署工作流程取決於組織的文化、偏好與技術需求。
這個設計決策在實務上造成團隊必須在 Kubernetes 叢集外維護獨立的建置環境。傳統上,開發者會在本地機器或專用的建置伺服器上使用 Docker 建置映像檔,然後推送到容器倉儲,最後才部署到 Kubernetes。這種分離的工作流程增加了基礎設施的複雜性,也在開發到部署的過程中引入了額外的環節。
@startuml
!define PLANTUML_FORMAT svg
!theme _none_
skinparam dpi auto
skinparam shadowing false
skinparam linetype ortho
skinparam roundcorner 5
skinparam defaultFontName "Microsoft JhengHei UI"
skinparam defaultFontSize 16
package "傳統建置流程" {
rectangle "本地開發環境\nDocker" as Local
rectangle "CI/CD 伺服器\nJenkins/GitLab" as CI
cloud "容器倉儲\nDocker Hub/Quay" as Registry
rectangle "Kubernetes 叢集" as K8s
Local -right-> CI : 提交程式碼
CI -right-> Registry : 推送映像檔
Registry -right-> K8s : 拉取映像檔
}
package "Shipwright 建置流程" {
rectangle "開發者\n提交程式碼" as Dev
rectangle "Shipwright\n在 K8s 內建置" as Ship
cloud "容器倉儲" as Reg2
rectangle "直接部署\n同叢集內" as Deploy
Dev -right-> Ship : Git Push
Ship -right-> Reg2 : 推送映像檔
Ship -down-> Deploy : 立即部署
}
note bottom of Ship
在 Kubernetes 內完成建置
使用 Tekton 執行工作負載
支援多種建置策略
無需額外基礎設施
end note
@endumlShipwright 的出現改變了這個局面。它是一個可擴展的框架,專為在 Kubernetes 上建置容器映像檔而設計。Shipwright 支援多種建置工具,包括 Buildah、Cloud Native Buildpacks、Kaniko 與 BuildKit,讓團隊可以根據需求選擇最適合的建置策略。
Shipwright 的架構設計
Shipwright 採用 Kubernetes 風格的 API 設計,透過自訂資源定義擴展 Kubernetes 的功能。它定義了三個核心資源,這些資源協同工作提供完整的容器建置能力。
ClusterBuildStrategy 代表可用的建置策略,例如 Kaniko、Buildpacks、Buildah 等。每個策略封裝了特定建置工具的使用方式,包括所需的容器映像檔、執行參數、安全性配置等。這種抽象讓開發者可以專注於建置需求,而不需要理解底層工具的複雜細節。
Build 資源代表建置配置,它參照一個 ClusterBuildStrategy 並指定原始碼位置、目標映像檔名稱、認證憑證等資訊。Build 資源是宣告式的,描述了應該如何建置容器映像檔,但不會立即觸發建置過程。
BuildRun 資源代表實際的建置執行。當 BuildRun 被建立時,Shipwright 控制器會根據參照的 Build 配置建立 Tekton 工作負載來執行建置。這種分離設計讓同一個 Build 配置可以被多次執行,非常適合持續整合流程。
安裝與配置 Shipwright 環境
在 Kubernetes 叢集中部署 Shipwright 需要先安裝其相依套件。Shipwright 依賴 Tekton 作為底層執行引擎,因此首先需要安裝 Tekton Pipelines。使用 kubectl apply 命令從官方發布網址安裝 Tekton,這會建立所有必要的自訂資源定義、控制器與相關元件。
接著安裝 Shipwright 本身。同樣使用 kubectl apply 命令從 GitHub 發布頁面安裝,這會部署 Shipwright 的控制器與相關資源。Shipwright 控制器會監控 Build 與 BuildRun 資源的變化,並協調建置過程的執行。
最後安裝預定義的建置策略。Shipwright 提供了一組範例策略,包括常用的建置工具如 Kaniko、Buildah、Buildpacks 等。這些策略定義了如何使用各種工具建置容器映像檔,可以直接使用或作為自訂策略的基礎。
安裝完成後,可以使用 kubectl get clusterbuildstrategy 命令查看所有可用的建置策略。這個命令會列出已安裝的策略,包括 Buildah、BuildKit、Buildpacks、Kaniko 等,讓開發者可以根據需求選擇合適的建置工具。
Kaniko:在 Kubernetes 中安全建置容器
Kaniko 的技術優勢與應用場景
Kaniko 是專為 Kubernetes 環境設計的容器映像檔建置工具,它解決了在容器內建置容器的特權問題。傳統的 Docker-in-Docker 建置方式需要特權模式,這在共享的 Kubernetes 環境中存在嚴重的安全風險。Kaniko 透過在使用者空間完全執行建置過程,消除了對 Docker daemon 與特權模式的需求。
@startuml
!define PLANTUML_FORMAT svg
!theme _none_
skinparam dpi auto
skinparam shadowing false
skinparam linetype ortho
skinparam roundcorner 5
skinparam defaultFontName "Microsoft JhengHei UI"
skinparam defaultFontSize 16
rectangle "Kaniko 建置流程" {
rectangle "取得原始碼\nGit Clone" as Source
rectangle "解析 Dockerfile\n分析指令" as Parse
rectangle "逐層建置\n使用者空間執行" as Build
rectangle "推送映像檔\n到倉儲" as Push
Source -down-> Parse
Parse -down-> Build
Build -down-> Push
}
note right of Build
無需 Docker Daemon
無需特權模式
在標準 Pod 中執行
完全的映像檔層控制
end note
note right of Push
支援多種倉儲
Docker Hub
Google Container Registry
Amazon ECR
Azure Container Registry
end note
@endumlKaniko 的運作方式是在標準容器中執行,讀取 Dockerfile,逐步執行每個指令,並在檔案系統中建立映像檔層。完成後,它會將建置好的映像檔推送到指定的容器倉儲。整個過程不需要 Docker daemon,也不需要任何特權存取,使其非常適合在多租戶 Kubernetes 環境中安全執行。
在我協助客戶建立 CI/CD 流程的經驗中,Kaniko 特別適合需要在 Kubernetes 叢集內完成完整建置與部署循環的場景。它與 Tekton、Argo Workflows 等雲原生 CI/CD 工具整合良好,可以構建完全 Kubernetes 原生的建置流程。
使用 Shipwright 與 Kaniko 建置應用程式
要使用 Kaniko 建置容器映像檔,首先需要設定容器倉儲的認證憑證。Shipwright 使用 Kubernetes Secret 來管理這些敏感資訊,確保憑證的安全性。建立一個 docker-registry 類型的 Secret,包含倉儲伺服器位址、使用者名稱、密碼與電子郵件地址。
在生產環境中,建議使用更安全的認證方式,例如服務帳戶權杖或 OAuth 權杖,而不是直接使用帳戶密碼。許多容器倉儲服務如 Quay.io、Google Container Registry 都支援這些更安全的認證機制。
接下來建立 Build 資源定義。這個 YAML 檔案指定了原始碼的位置、要使用的建置策略、以及建置結果的目標映像檔名稱。原始碼可以來自 Git 倉儲,並可以指定特定的分支或標籤。contextDir 參數指定了 Dockerfile 所在的目錄,這對於包含多個子專案的倉儲特別有用。
建置策略選擇 Kaniko,並指定為 ClusterBuildStrategy 類型。輸出部分定義了建置完成後映像檔應該推送到哪個倉儲,以及使用哪個 Secret 進行認證。這些資訊都是宣告式的,Shipwright 會根據這些定義自動執行建置過程。
使用 kubectl create 命令建立 Build 資源後,可以使用 kubectl get builds 命令檢查狀態。Build 資源註冊成功後,會顯示為已註冊狀態,但建置過程尚未開始。這種分離設計讓我們可以定義建置配置,然後在需要時觸發實際的建置執行。
執行與監控建置過程
要實際執行建置,需要建立 BuildRun 資源。BuildRun 參照先前建立的 Build 資源,並觸發一次建置執行。使用 generateName 而不是固定的名稱,可以讓每次執行都有唯一的識別,這對於追蹤建置歷史非常有用。
當 BuildRun 被建立時,Shipwright 控制器會建立一個 Tekton TaskRun,然後 Tekton 會建立一個 Pod 來執行建置工作。這個 Pod 包含多個容器,分別負責取得原始碼、執行建置,以及處理結果。
使用 kubectl get pods 命令可以看到建置 Pod 的狀態。初始狀態通常是 PodInitializing,表示正在準備執行環境。Pod 包含三個主要的步驟容器,第一個負責取得原始碼,第二個執行 Kaniko 建置並推送映像檔,第三個處理建置結果與產生報告。
使用 kubectl logs 命令可以即時查看建置過程的日誌輸出。Kaniko 會詳細記錄每個 Dockerfile 指令的執行過程,包括取得基礎映像檔、執行指令、建立檔案系統快照等。這些詳細的日誌對於偵錯建置問題非常有幫助,可以清楚看到建置在哪個步驟失敗,以及失敗的原因。
建置完成後,映像檔會被自動推送到指定的容器倉儲,可以立即用於部署。整個過程完全在 Kubernetes 叢集內完成,不需要任何外部的建置基礎設施,這大幅簡化了 CI/CD 流程的架構。
Kustomize:宣告式 Kubernetes 資源管理
Kustomize 解決的核心問題
在容器映像檔建置完成後,下一步是將應用程式部署到 Kubernetes 叢集。管理 Kubernetes 資源檔案,特別是處理多環境的配置差異,一直是個挑戰。直接修改 YAML 檔案雖然可行,但存在高風險,一個錯誤的修改可能導致嚴重的生產事故。
傳統的範本工具如 Helm 使用範本語言來處理配置差異,但這引入了額外的複雜性。範本語言有其學習曲線,而且範本檔案往往難以直接閱讀與理解。Kustomize 採用了不同的方法,它使用原生的 Kubernetes YAML 檔案,透過疊加與修補機制來處理環境差異。
@startuml
!define PLANTUML_FORMAT svg
!theme _none_
skinparam dpi auto
skinparam shadowing false
skinparam linetype ortho
skinparam roundcorner 5
skinparam defaultFontName "Microsoft JhengHei UI"
skinparam defaultFontSize 16
package "Kustomize 架構" {
folder "base/" {
file "kustomization.yaml" as BaseKust
file "deployment.yaml" as BaseDeploy
file "service.yaml" as BaseServ
}
folder "overlays/staging/" {
file "kustomization.yaml" as StagKust
file "patches.yaml" as StagPatch
}
folder "overlays/production/" {
file "kustomization.yaml" as ProdKust
file "patches.yaml" as ProdPatch
}
}
BaseKust -down-> BaseDeploy
BaseKust -down-> BaseServ
StagKust -up-> BaseKust : 參照 base
StagKust -down-> StagPatch : 套用修補
ProdKust -up-> BaseKust : 參照 base
ProdKust -down-> ProdPatch : 套用修補
note right of BaseKust
定義共同的基礎資源
不含環境特定配置
可以直接套用
end note
note right of StagPatch
環境特定的修改
replica 數量
resource limits
image tags
end note
@endumlKustomize 的核心概念是基底與疊加。基底定義了應用程式的基本資源,這些資源在所有環境中都是相同的。疊加則針對特定環境套用修改,例如調整副本數量、修改資源限制、變更映像檔標籤等。這種方式讓環境之間的差異變得明確且易於管理。
Kustomize 已經整合到 kubectl 中,無需額外安裝工具。使用 kubectl apply -k 命令就可以套用 Kustomize 配置,這降低了採用門檻,也確保了工具的長期支援與相容性。
建立 Kustomize 基底配置
讓我們透過實際案例來理解 Kustomize 的使用方式。假設要部署一個簡單的 Web 應用程式,首先建立基底配置,包含命名空間、部署與服務的定義。
命名空間定義建立了一個隔離的環境,用於部署應用程式。部署定義指定了容器映像檔、副本數量、連接埠配置等資訊。服務定義則提供了穩定的網路端點,讓其他服務可以存取這個應用程式。
這些 YAML 檔案都是標準的 Kubernetes 資源定義,沒有任何範本語法或預留位置。它們可以直接使用 kubectl apply 套用,也可以透過 Kustomize 進行客製化。這種設計讓基底配置保持簡單與可讀性。
建立 kustomization.yaml 檔案來組織這些資源。這個檔案列出了所有要包含的資源檔案,Kustomize 會按照指定的順序處理這些資源,確保相依關係得到正確處理。
使用 Kustomize 管理多環境配置
對於多環境部署,建立疊加目錄來處理環境特定的配置。每個環境有自己的目錄,包含該環境特定的 kustomization.yaml 與修補檔案。
疊加的 kustomization.yaml 會參照基底配置,然後套用環境特定的修改。例如,生產環境可能需要更多副本、更高的資源限制、不同的映像檔標籤等。這些修改以修補檔案的形式提供,Kustomize 會將修補套用到基底資源上。
修補可以使用策略性合併或 JSON 修補格式。策略性合併是比較直覺的方式,只需要指定要變更的欄位,Kustomize 會智慧地合併這些變更。JSON 修補提供了更精確的控制,適合複雜的修改場景。
使用 kubectl apply -k 命令並指定疊加目錄,就可以部署特定環境的配置。Kustomize 會讀取基底配置,套用疊加的修改,然後產生最終的 YAML,kubectl 再將這些資源套用到叢集。整個過程是宣告式的,確保了部署的可重複性與一致性。
Kustomize 進階功能應用
Kustomize 提供了許多進階功能來處理常見的配置管理需求。映像檔標籤更新是最常用的功能之一,在持續部署流程中,每次建置都會產生新的映像檔標籤,需要更新部署配置。
使用 Kustomize 的映像檔轉換功能,可以在 kustomization.yaml 中指定新的映像檔標籤,而不需要修改原始的部署檔案。這讓 CI/CD 流程可以輕鬆注入新的映像檔版本,同時保持基底配置的穩定性。
ConfigMap 產生器是另一個強大功能,它可以從檔案、字面值或環境變數產生 ConfigMap。更重要的是,Kustomize 可以在 ConfigMap 名稱中嵌入內容雜湊值,當配置檔案變更時,ConfigMap 名稱也會變更,這會自動觸發使用該 ConfigMap 的 Pod 重新啟動。
這個機制解決了 Kubernetes 的一個長期痛點。傳統上,更新 ConfigMap 不會自動觸發 Pod 重新啟動,導致應用程式繼續使用舊的配置。使用 Kustomize 的 ConfigMap 產生器,配置變更會自動傳播到執行中的應用程式,無需手動重新啟動。
秘密管理也可以使用類似的機制。雖然在生產環境中建議使用專用的秘密管理工具如 Vault 或 Sealed Secrets,但 Kustomize 的秘密產生器在開發與測試環境中非常有用,可以快速產生與管理敏感配置。
整合 GitOps 工作流程
結合 Shipwright 與 Kustomize,可以建立完整的 GitOps 工作流程。開發者提交程式碼到 Git 倉儲,觸發 Shipwright 建置流程。建置完成後,CI/CD 流程更新 Kustomize 配置中的映像檔標籤,然後提交變更到 Git。
GitOps 工具如 Argo CD 或 Flux 會監控 Git 倉儲的變更,自動將新的配置套用到 Kubernetes 叢集。整個流程是宣告式的,所有變更都有完整的審計軌跡,可以輕鬆回滾到任何歷史版本。
這種工作流程將基礎設施即程式碼的理念發揮到極致,所有的配置都以程式碼形式儲存在 Git 中,經過程式碼審查流程,並自動部署到目標環境。這大幅提升了部署的可靠性與可追蹤性,是現代雲原生應用的最佳實踐。
透過本文探討的工具與技術,從 Buildah 的安全建置,到 Cloud Native Buildpacks 的自動化,再到 Shipwright 的 Kubernetes 原生建置,以及 Kustomize 的資源管理,我們可以建立一個完整、安全、高效的容器化工作流程。這些工具各有所長,組合使用可以滿足不同場景的需求,協助團隊建立強大的 GitOps 實踐。