在容器中建立一個簡單的Web服務

首先,讓我們看如何使用Buildah建立一個包含HTTP服務的容器映像。以下是完整的步驟:

# 建立根據CentOS的工作容器
buildah from centos:latest

# 檢視建立的容器名稱
buildah containers

# 在容器中安裝HTTPD
buildah run centos-working-container yum -y install httpd

上述命令首先從CentOS基礎映像建立了一個工作容器,這是Buildah操作的基本單位。buildah from命令類別似於Dockerfile中的FROM指令,但它直接回傳一個容器例項而非僅定義一個構建階段。buildah containers命令列出當前所有的工作容器,幫助我們確認容器已正確建立。最後,buildah run命令在容器內執行yum安裝命令,這相當於Dockerfile中的RUN指令,但提供了更直接的操作方式。

現在讓我們增加一個簡單的HTML頁面到容器中:

<html>
<head>
<title>GitOps CookBook example</title>
</head>
<body>
<h1>Hello, World!</h1>
</body>
</html>

將此檔案複製到容器中:

buildah copy centos-working-container index.xhtml /var/www/html/index.xhtml

設定容器的啟動入口點:

buildah config --entrypoint "/usr/sbin/httpd -DFOREGROUND" centos-working-container

最後,提交變更並建立映像:

buildah commit centos-working-container quay.io/gitops-cookbook/gitops-website

這部分操作展示了Buildah的核心功能。buildah copy命令將本地檔案複製到容器內,類別似於Dockerfile中的COPY指令。buildah config則用於設定容器的中繼資料,這裡我們設定了入口點,相當於Dockerfile中的ENTRYPOINT指令。最後,buildah commit將工作容器的狀態儲存為一個新的映像,並指定了映像名稱和標籤。

使用Dockerfile與Buildah構建相同映像

Buildah也支援從Dockerfile構建映像,這提供了良好的相容性:

FROM centos:latest
RUN yum -y install httpd
COPY index.xhtml /var/www/html/index.xhtml
EXPOSE 80
CMD ["/usr/sbin/httpd", "-DFOREGROUND"]

使用Buildah從Dockerfile構建:

buildah bud -f Dockerfile -t quay.io/gitops-cookbook/gitops-website

buildah bud(build-using-dockerfile的縮寫)命令允許Buildah使用標準Dockerfile構建映像。這為現有的Docker工作流程提供了平滑的遷移路徑,同時享受Buildah的安全優勢。這裡的構建過程與Docker幾乎相同,但底層實作更注重安全性和隔離性。

執行構建好的容器

如果你安裝了Podman(Buildah的姊妹工具,專注於容器執行而非構建),可以這樣執行容器:

podman run -p 8080:80 -ti quay.io/gitops-cookbook/gitops-website

然後可以透過瀏覽器存取 http://localhost:8080 來測試服務。

Podman是Buildah生態系統的一部分,專注於容器執行。它提供了與Docker CLI相似的介面,但採用了無守護程式設計。-p 8080:80引數將容器內的80連線埠對映到主機的8080連線埠,-ti引數則請求一個互動式終端。

Buildah的技術優勢

使用Buildah構建容器映像有幾個關鍵優勢:

  1. 無需安裝Docker:Buildah完全獨立執行,不依賴Docker守護程式
  2. 安全設計:支援無根使用者(rootless)操作,減少許可權提升風險
  3. 精細控制:對映像層的建立有更精確的控制
  4. 從零開始構建:可以建立完全空白的映像,類別似於Dockerfile中的FROM scratch

Buildah的一個特別強大的使用案例是建立極小的生產映像。在開發過程中,我們可能需要編譯器和開發工具,但在生產環境中,只需要執行時和應用程式包。Buildah讓這種映像縮減變得簡單明瞭。

Cloud Native Buildpacks:無Dockerfile自動構建

自動檢測與構建的革新

在大規模環境中,維護大量Dockerfile可能變得極具挑戰性。Cloud Native Buildpacks提供了一個優雅的解決方案,透過檢查應用程式原始碼自動建立容器映像,無需手寫Dockerfile。

Buildpacks的工作流程分為兩個主要階段:

  1. 檢測階段:工具分析原始碼,識別程式設計語言或框架(如POM檔案、NPM設定、Python依賴等),並分配適當的buildpack
  2. 構建階段:使用選定的buildpack編譯原始碼,建立容器映像,並設定適當的入口點和啟動指令碼

安裝Buildpacks CLI工具

要使用Buildpacks,首先需要安裝pack CLI工具:

# 在macOS上安裝
brew install buildpacks/tap/pack

對於其他作業系統,可以從Buildpacks官方網站下載對應版本。

使用Buildpacks構建Node.js應用

讓我們嘗試使用Buildpacks為一個簡單的Node.js應用建立容器映像:

首先,我們可以讓pack工具為我們推薦合適的builder:

pack builder suggest

這將顯示可用的builder列表,包括Google、Heroku和Paketo Buildpacks提供的各種選項。每個builder都包含不同的語言和框架支援。

選擇一個合適的builder,例如Paketo的base builder:

pack build nodejs-app --builder paketobuildpacks/builder:base

在這個命令中,pack build指示工具開始構建過程,nodejs-app是我們為新映像指定的名稱,--builder引數指定使用哪個builder。Paketo的base builder包含多種語言支援,包括Node.js、Java、.NET Core等。

執行此命令後,Buildpacks會:

  1. 下載指定的builder映像
  2. 分析專案錄
  3. 檢測到這是一個Node.js應用(透過package.json檔案)
  4. 選擇適當的buildpacks組合
  5. 構建應用並建立容器映像

構建完成後,我們可以用Docker執行它:

docker run --rm -p 3000:3000 nodejs-app

使用curl測試執行中的應用:

curl http://localhost:3000/

Buildpacks自動檢測到應用的入口點(在這個例子中是node server.js)並設定容器執行環境。它還處理了所有依賴安裝,無需我們手動編寫這些步驟。這大簡化了容器化過程,特別是對於標準應用架構。

Buildpacks的技術優勢

在實際工作中,我發現Buildpacks在以下場景特別有價值:

  1. 大規模標準化:當組織需要為數百個相似結構的應用建立容器時
  2. 簡化開發者體驗:讓不熟悉容器技術的開發者也能輕鬆容器化應用
  3. 強制執行最佳實踐:透過builder封裝組織認可的構建策略與安全標準
  4. 降低維護成本:無需維護大量Dockerfile,減少因基礎映像或構建步驟變更帶來的工作量

選擇合適的容器構建工具

在多個容器專案的實踐中,我總結出一些選擇合適工具的準則:

何時選擇Buildah

  1. 當需要極高的安全標準,特別是在需要無根使用者操作的環境
  2. 需要對映像層有精細控制,最佳化映像大小和層結構
  3. 需要從頭建立極小的生產映像
  4. 在無法執行Docker守護程式的環境中

何時選擇Buildpacks

  1. 大規模標準化應用佈署,特別是在微服務架構中
  2. 開發團隊不熟悉容器技術或不希望維護Dockerfile
  3. 需要強制執行組織層面的構建標準和最佳實踐
  4. 使用標準框架和語言,不需要特殊的構建步驟

何時繼續使用Docker

  1. 團隊已經熟悉Docker生態系統並有大量現有工作流程
  2. 需要廣泛的社群支援和豐富的檔案
  3. 與現有CI/CD管道有深度整合
  4. 容器安全性不是首要考慮因素

實際應用案例分析

在一個金融科技專案中,我們面臨著嚴格的安全要求和大量微服務。我們採用了混合策略:

  1. 使用Buildpacks自動化標準微服務的容器化過程,減少開發團隊的負擔
  2. 對於需要特殊設定或極致效能最佳化的核心服務,使用Buildah手動構建
  3. 為所有映像實施嚴格的安全掃描和簽名策略

這種方法顯著提高了團隊效率,同時確保了關鍵服務的效能和安全性。

容器構建技術的未來趨勢

隨著容器技術的成熟,我觀察到幾個明確的發展趨勢:

  1. 更強調安全性:無根容器和精細許可權控制將成為標準
  2. 自動化程度提高:像Buildpacks這樣的工具將進一步簡化容器化流程
  3. 與CI/CD深度整合:容器構建工具將與持續整合和佈署管道無縫銜接
  4. 映像最佳化自動化:自動分析和最佳化容器映像大小和安全性的工具將更加普及

在容器技術快速發展的今天,掌握多種容器構建工具和策略,能夠為不同場景選擇最佳方案,將是DevOps工程師和平台團隊的核心競爭力。

現代容器構建已經遠超出了簡單編寫Dockerfile的範疇。透過Buildah和Buildpacks等工具,我們可以構建更安全、更高效的容器映像,同時簡化開發流程,提高團隊生產力。無論是追求極致安全性的Buildah,還是注重自動化和標準化的Buildpacks,都為容器技術帶來了新的可能性。

Kubernetes 容器構建的挑戰與解決方案

Kubernetes 作為容器協調平台的霸主,在容器佈署和管理方面表現出色,然而它本身卻不提供構建容器映像的內建功能。根據 Kubernetes 官方檔案說明:「Kubernetes 不負責佈署原始碼,也不會構建應用程式。持續整合、交付和佈署 (CI/CD) 工作流程取決於組織文化、偏好以及技術需求。」

在實際開發流程中,這種限制經常迫使開發團隊在 Kubernetes 環境外維護獨立的 CI/CD 系統或 Docker 環境。這不僅增加了基礎設施的複雜性,還在開發到佈署的流程中引入了額外的環節。

雲原生構建工具的崛起

近年來,隨著雲原生技術的發展,一系列針對 Kubernetes 環境的容器構建工具應運而生,其中 Shipwright 框架脫穎而出。

Shipwright 是一個擴充套件性極強的框架,專為在 Kubernetes 上構建容器映像而設計。它支援多種流行的構建工具:

  • Buildah
  • Cloud Native Buildpacks
  • kaniko
  • BuildKit

Shipwright 採用 Kubernetes 風格的 API,並使用 Tekton 執行工作負載,為開發人員提供了一種簡化的容器映像構建方法。開發者只需定義一個最小化的 YAML 檔案,無需事先了解容器或容器引擎的知識,就能完成映像構建。這種設計使 Shipwright 成為一個與具體技術無關與高度整合 Kubernetes API 生態系統的解決方案。

Shipwright:Kubernetes 原生的構建框架

在深入 kaniko 之前,我們需要先了解 Shipwright 的基本架構。Shipwright 透過擴充套件 Kubernetes API,增加了一系列自定義資源定義 (CRD),這些資源協同工作,提供了完整的容器構建能力。

Shipwright 核心元件

Shipwright 定義了三個關鍵的自定義資源:

  1. ClusterBuildStrategy:代表要執行的構建類別,例如 kaniko、Buildpacks 等
  2. Build:代表構建設定,包含一個 ClusterBuildStrategy 物件的規格
  3. BuildRun:代表正在執行的構建,當此物件被建立時,構建過程就會開始

這種設計遵循了 Kubernetes 的宣告式 API 模式,使得構建過程可以像管理其他 Kubernetes 資源一樣被管理和監控。

在 Kubernetes 中安裝 Shipwright

在使用 Shipwright 之前,我們需要將其安裝到 Kubernetes 叢集中。我們可以使用 kind 或 Minikube 這樣的本地叢集進行實驗。

安裝 Tekton 依賴

Shipwright 依賴 Tekton 執行管道,所以首先要安裝 Tekton:

kubectl apply -f \
https://storage.googleapis.com/tekton-releases/pipeline/previous/v0.30.0/release.yaml

安裝 Shipwright 核心元件

接著安裝 Shipwright 本身:

kubectl apply -f \
https://github.com/shipwright-io/build/releases/download/v0.7.0/release.yaml

安裝構建策略

最後,安裝 Shipwright 的構建策略:

kubectl apply -f \
https://github.com/shipwright-io/build/releases/download/v0.7.0/sample-strategies.yaml

這三個安裝步驟建立了完整的 Shipwright 環境。首先安裝 Tekton 作為底層執行引擎,然後安裝 Shipwright 核心 API 和控制器,最後安裝預定義的構建策略,讓你可以立即使用不同的構建工具。值得注意的是,這些 YAML 檔案包含了所有必要的 CRD、服務帳號、角色和其他 Kubernetes 資源,Shipwright 控制器會監控這些資源並協調構建過程。

kaniko:無 Docker 的容器映像構建工具

kaniko 是一個在容器或 Kubernetes 叢集內部直接從 Dockerfile 構建容器映像的工具,無需依賴 Docker daemon。這解決了在安全環境中執行 Docker 的特權問題,特別適合在 Kubernetes 等分享環境中使用。

當我們在研究 Kubernetes 中的容器構建方案時,我發現 kaniko 提供了一種不需要特權模式就能構建容器的方法,這在多租戶環境中特別有價值。

檢查可用的構建策略

安裝完成後,我們可以檢視所有可用的 ClusterBuildStrategy (CBS) 物件:

kubectl get cbs

應該會看到一系列可用的構建策略:

NAME                    AGE
buildah                 26s
buildkit                26s
buildpacks-v3           26s
buildpacks-v3-heroku    26s
kaniko                  26s
kaniko-trivy            26s
ko                      26s
source-to-image         26s
source-to-image-redhat  26s

這個命令展示了 Shipwright 支援的所有構建策略。這些策略代表不同的容器構建工具和方法,每一個都有其特點和適用場景。例如,buildpacks-v3 適合無 Dockerfile 的應用程式構建,而 kaniko 則專注於從 Dockerfile 構建映像。kaniko-trivy 是 kaniko 的變體,整合了 Trivy 安全掃描功能。這種多樣性讓開發團隊可以根據專案需求選擇最合適的構建方法。

設定映像推播憑證

Shipwright 構建完容器映像後,需要將其推播到容器登入檔。為此,我們需要提供登入檔的認證憑證,這透過 Kubernetes Secret 實作:

REGISTRY_SERVER=quay.io
REGISTRY_USER=<your_registry_user>
REGISTRY_PASSWORD=<your_registry_password>
EMAIL=<your_email>

kubectl create secret docker-registry push-secret \
--docker-server=$REGISTRY_SERVER \
--docker-username=$REGISTRY_USER \
--docker-password=$REGISTRY_PASSWORD \
--docker-email=$EMAIL

這個命令建立了一個類別為 docker-registry 的 Kubernetes Secret,包含了推播映像到容器登入檔所需的認證資訊。Shipwright 會在構建過程中使用這個 Secret 來認證並推播映像。在生產環境中,我建議使用更安全的認證方式,比如 Quay 的加密碼或 OAuth token,而不是直接使用帳戶密碼。

使用 kaniko 構建 Node.js 應用

現在,我們可以建立一個使用 kaniko 策略的 Build 物件,來構建一個 Node.js 範例應用。

定義 Build 物件

建立一個 build-kaniko.yaml 檔案:

apiVersion: shipwright.io/v1alpha1
kind: Build
metadata:
  name: kaniko-nodejs-build
spec:
  source:
    url: https://github.com/shipwright-io/sample-nodejs
    contextDir: docker-build
  strategy:
    name: kaniko
    kind: ClusterBuildStrategy
  output:
    image: quay.io/gitops-cookbook/sample-nodejs:latest
    credentials:
      name: push-secret

這個 YAML 定義了一個 Shipwright Build 資源,指定了以下關鍵訊息:

  • source 部分指定了原始碼的來源(GitHub 倉函式庫上下文目錄
  • strategy 選擇了 kaniko 作為構建策略
  • output 定義了構建結果的映像目標地址和推播所需的憑證

這種宣告式設定是 Kubernetes 原生的,讓構建過程變得可版本控制、可稽核與可重複執行。

建立 Build 資源

讓我們應用這個設定:

kubectl create -f build-kaniko.yaml

確認 Build 資源已註冊:

kubectl get builds

應該能看到類別似的輸出:

NAME                 REGISTERED   REASON      BUILDSTRATEGYKIND     BUILDSTRATEGYNAME   CREATIONTIME
kaniko-nodejs-build  True         Succeeded   ClusterBuildStrategy  kaniko              13s

這個輸出顯示 Build 已成功註冊,但尚未開始執行。在 Shipwright 的設計中,Build 資源只是定義了構建的設定,而實際執行則需要建立 BuildRun 資源。這種分離設計讓你可以定義一次 Build 設定,然後多次執行它,非常適合 CI/CD 流程。

執行構建過程

雖然 Build 資源已建立,但構建過程尚未開始。我們需要建立一個 BuildRun 資源來觸發構建:

定義 BuildRun 資源

建立一個 buildrun.yaml 檔案:

apiVersion: shipwright.io/v1alpha1
kind: BuildRun
metadata:
  generateName: kaniko-nodejs-buildrun-
spec:
  buildRef:
    name: kaniko-nodejs-build

這個 YAML 定義了一個 BuildRun 資源,它參照了之前建立的 Build 資源。注意 generateName 欄位 - 這會為每次執行生成一個唯一名稱,這是 Kubernetes 命名的一種模式,特別適合需要多次執行的資源。

開始構建

應用 BuildRun 設定:

kubectl create -f buildrun.yaml

檢查執行中的 Pod:

kubectl get pods

應該能看到一個新的 Pod 正在初始化:

NAME                                            READY   STATUS           RESTARTS   AGE
kaniko-nodejs-buildrun-b9mmb-qbrgl-pod-dk7xt   0/3     PodInitializing  0          19s

當 BuildRun 被建立時,Shipwright 控制器會建立一個包含多個容器的 Pod 來執行構建過程。這個 Pod 包含三個關鍵容器,分別負責取得原始碼、執行構建和處理結果。STATUS 顯示為 “PodInitializing” 表示 Pod 正在準備初始容器,這些容器會設定構建環境。

監視構建過程

每個構建 Pod 包含三個關鍵步驟容器:

  1. step-source-default:負責取得原始碼
  2. step-build-and-push:使用 kaniko 從 Dockerfile 構建並推播映像
  3. step-results:處理構建結果

我們可以檢視構建階段的日誌:

kubectl logs -f kaniko-nodejs-buildrun-b9mmb-qbrgl-pod-dk7xt -c step-build-and-push

輸出將顯示 kaniko 的構建過程:

INFO[0001] Retrieving image manifest ghcr.io/shipwright-io/shipwright-samples/node:12
INFO[0001] Retrieving image ghcr.io/shipwright-io/shipwright-samples/node:12 from registry ghcr.io
INFO[0002] Built cross stage deps: map[]
INFO[0002] Retrieving image manifest ghcr.io/shipwright-io/shipwright-samples/node:12
INFO[0002] Returning cached image manifest
INFO[0002] Executing 0 build triggers
INFO[0002] Unpacking rootfs as cmd COPY . /app requires it.
INFO[0042] COPY . /app
INFO[0042] Taking snapshot of files...
INFO[0042] WORKDIR /app
INFO[0042] cmd: workdir
INFO[0042] Changed working directory to /app
INFO[0042] No files changed in this command, skipping snapshotting.
INFO[0042] RUN pwd && ls -l && npm install && npm run print-http-server-version

這些日誌展示了 kaniko 的構建過程。首先它取得基礎映像 (node:12),然後執行 Dockerfile 中的指令 - 複製應用程式檔案、設定工作目錄、執行 npm 安裝依賴並執行指令碼。kaniko 的一個優點是它詳細記錄了每個步驟,這對於除錯構建問題非常有幫助。這種容器內構建過程不需要特權存取,使其非常適合在多租戶 Kubernetes 環境中安全執行。

理解 Shipwright 的工作流程

使用 Shipwright 構建容器映像的整個流程可以概括為:

  1. 安裝:佈署 Shipwright、Tekton 和相關構建策略到叢集
  2. 設定:建立容器登入檔憑證和 Build

Kubernetes上的容器建置與佈署策略

在現代雲原生架構中,容器技術已成為應用佈署的標準方式。然而,如何有效率地建置容器映像檔並在Kubernetes中管理佈署資源,始終是開發團隊面臨的關鍵挑戰。我在多年的容器化工作中發現,選擇合適的工具鏈可以大幅提升開發效率並確保一致性。

本文將探討兩個核心工具:用於在Kubernetes中建置容器映像檔的Shipwright,以及用於管理Kubernetes資源的Kustomize。這些工具如何協同工作,為開發團隊提供流暢的工作流程?讓我們一起來看。

Shipwright:Kubernetes原生的容器建置平台

Shipwright的核心優勢

Shipwright提供了一種在Kubernetes內部建置容器映像檔的優雅方式。它的最大特點在於策略無關性,這使得它在不同場景下都能保持穩健性和互操作性。在我設計大規模微服務架構時,這種靈活性非常寶貴,因為它允許不同團隊使用他們熟悉的建置工具,同時保持整體工作流程的一致性。

Shipwright的目標是成為Kubernetes的「建置API」,為開發者提供自動化的簡便途徑。由於底層使用Tekton執行建置,它也使從微管道(micropipeline)到更複雜的工作流程的過渡變得更加平滑。

建置過程分析

從上述的建置日誌中,我們可以看到一個完整的Shipwright建置過程:

  1. 首先執行一系列shell命令,檢查環境並安裝依賴項
  2. 安裝npm套件並驗證http-server版本
  3. 然後對檔案系統進行快照
  4. 設定暴露的連線埠(8080)和啟動命令
  5. 最後將映像檔推播到指定的容器倉函式庫這個過程顯示了Shipwright如何將整個建置過程封裝在Kubernetes API中,使開發者可以專注於應用邏輯。

從Kaniko轉向Buildah

在實際工作中,我經常需要根據專案需求切換不同的建置策略。使用Shipwright時,從Kaniko轉向Buildah只需要修改Build物件中的ClusterBuildStrategy即可:

apiVersion: shipwright.io/v1alpha1
kind: Build
metadata:
  name: buildpack-nodejs-build
spec:
  source:
    url: https://github.com/shipwright-io/sample-nodejs
    contextDir: source-build
  strategy:
    name: buildah
    kind: ClusterBuildStrategy
  output:
    image: quay.io/gitops-cookbook/sample-nodejs:latest
    credentials:
      name: push-secret

這個YAML檔案定義了一個Shipwright建置工作,與前面看到的kaniko建置不同,這裡使用了Buildah作為建置策略。Buildah的一個重要優勢是它不需要Dockerfile就能建立容器映像檔,這在某些專案中可能更加靈活。source區段指定了原始碼的位置及上下文目錄,output定義了建置結果的目標映像檔及推播所需的憑證。

Kustomize:無範本的Kubernetes資源管理

從容器映像檔建置完成後,下一步就是將應用程式佈署到Kubernetes叢集。這裡面臨的挑戰是如何管理多個Kubernetes資源檔案,以及如何處理不同環境的設定差異。

Kustomize解決什麼問題?

在我的開發實踐中,直接修改YAML檔案進行佈署雖然可行,但存在高風險。一個錯誤的修改、一個誤刪的行、錯誤的空格,都可能導致災難性後果。特別是當應用規模擴大,環境數量增加時,這種風險指數級上升。

Kustomize採用無範本的方式解決這個問題。它允許我們定義基礎資源檔案(很少變更的部分),然後為每個環境指定特定的變更引數。這種方法避免了範本語言的複雜性,同時提供了強大的客製化能力。

Kustomize的基本佈局

Kustomize的核心是一個kustomization.yaml檔案,它定義了要佈署的資源和如何客製化這些資源。一個典型的Kustomize專案結構如下:

pacman/
├── deployment.yaml    # 基本Kubernetes佈署檔案
├── namespace.yaml     # 名稱空間定義
├── service.yaml       # 服務定義
└── kustomization.yaml # 定義資源列表和客製化

這種結構使得資源管理變得清晰與可維護。基礎YAML檔案是標準的Kubernetes資源定義,無需任何特殊標記或預留位置。

實作Pacman應用佈署

讓我們實際建立一個簡單的網頁應用佈署。首先,建立以下三個資源檔案:

名稱空間定義 (namespace.yaml):

apiVersion: v1
kind: Namespace
metadata:
  name: pacman

佈署定義 (deployment.yaml):

apiVersion: apps/v1
kind: Deployment
metadata:
  name: pacman-kikd
  namespace: pacman
  labels:
    app.kubernetes.io/name: pacman-kikd
spec:
  replicas: 1
  selector:
    matchLabels:
      app.kubernetes.io/name: pacman-kikd
  template:
    metadata:
      labels:
        app.kubernetes.io/name: pacman-kikd
    spec:
      containers:
      - image: lordofthejars/pacman-kikd:1.0.0
        imagePullPolicy: Always
        name: pacman-kikd
        ports:
        - containerPort: 8080
          name: http
          protocol: TCP

服務定義 (service.yaml):

apiVersion: v1
kind: Service
metadata:
  labels:
    app.kubernetes.io/name: pacman-kikd
  name: pacman-kikd
  namespace: pacman
spec:
  ports:
  - name: http
    port: 8080
    targetPort: 8080
  selector:
    app.kubernetes.io/name: pacman-kikd

這三個YAML檔案定義了一個完整的應用佈署:

  1. namespace.yaml - 建立一個名為"pacman"的隔離名稱空間
  2. deployment.yaml - 定義一個具有單一複本的佈署,使用lordofthejars/pacman-kikd:1.0.0映像檔
  3. service.yaml - 建立一個服務,將內部8080連線埠暴露出來,並使用標籤選擇器連線到佈署的Pod

然後,建立kustomization.yaml檔案,將這些資源組合在一起:

apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- ./namespace.yaml
- ./deployment.yaml
- ./service.yaml

這個kustomization.yaml檔案是Kustomize的核心,它告訴Kustomize要處理哪些資源檔案。這些資源會按照深度優先的順序處理,確保依賴關係得到正確處理(例如,名稱空間會在佈署之前建立)。

應用Kustomize設定

使用以下命令可以預覽Kustomize將產生的完整YAML:

kubectl apply --dry-run=client -o yaml -k ./

這個命令使用了-k選項指示kubectl使用kustomization.yaml檔案,而--dry-run=client則表示只生成YAML而不實際應用到叢集。

從我的經驗來看,這種預覽功能非常有用,特別是在進行重大變更時,它能幫助我們在實際佈署前發現潛在問題。

Kustomize進階使用技巧

雖然基本的Kustomize用法已經很強大,但真正的價值在於它的進階功能。在我的專案中,我經常使用以下技巧來增強佈署的靈活性和可維護性。

映像檔更新

在持續佈署流程中,映像檔版本的更新是最常見的操作之一。Kustomize提供了一種簡單的方式來更新映像檔版本,而無需修改基礎YAML檔案:

apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- ./namespace.yaml
- ./deployment.yaml
- ./service.yaml
images:
- name: lordofthejars/pacman-kikd
  newTag: 2.0.0

這種方式使得CI/CD管道能夠輕鬆地注入新的映像檔版本,而不必擔心修改原始檔案。

環境特定設定

在多環境佈署中,管理環境特定的設定是一個常見挑戰。Kustomize透過基底和覆寫的概念優雅地解決了這個問題。我通常會設定一個基礎目錄和多個覆寫目錄:

base/
  kustomization.yaml
  deployment.yaml
  service.yaml
overlays/
  staging/
    kustomization.yaml
  production/
    kustomization.yaml

在覆寫的kustomization.yaml中,可以參照基礎資源並應用特定的修改:

apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- ../../base
patchesStrategicMerge:
- deployment-patch.yaml

這種方法使得環境之間的差異明確與易於管理,大減少了維護的工作量。

ConfigMap自動滾動更新

Kubernetes的一個常見痛點是ConfigMap更新不會自動觸發Pod的重新啟動。在我的實踐中,我發現Kustomize提供了一個優雅的解決方案:透過在ConfigMap名稱中嵌入內容雜湊值,強制Pod在設定變更時進行滾動更新:

apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
configMapGenerator:
- name: app-config
  files:
  - config.properties
generatorOptions:
  disableNameSuffixHash: false

當config.properties檔案變更時,生成的ConfigMap名稱也會變更,這將觸發依賴該ConfigMap的Pod重新啟動。