GitOps理念與Argo CD定位

在雲端原生應用的開發與維運實務中,持續整合與持續佈署已經成為不可或缺的基礎能力。Tekton與GitHub Actions等工具雖然能夠有效處理程式碼建置與測試流程,但在Kubernetes環境中執行應用程式佈署時,傳統的指令式方法面臨著嚴重的可維護性與一致性挑戰。正如產業專家Daniel Bryant所指出的核心觀念,既然我們不會在傳統環境中使用SSH直接登入伺服器進行佈署,那麼在Kubernetes環境中就不應該依賴kubectl執行臨時性的佈署操作。

這個觀點揭示了雲端原生時代基礎設施管理的根本轉變需求。傳統的佈署方式依賴維運人員執行一系列手動指令,這些操作缺乏版本控制、難以追蹤變更歷史、無法有效審計、更談不上自動化回滾。當團隊規模擴大或環境數量增加時,這種方法的局限性會被急劇放大,導致配置漂移、環境不一致、人為錯誤等問題層出不窮。

Argo CD正是為了解決這些挑戰而誕生的專業工具。它採用GitOps理念,將Git儲存庫視為系統期望狀態的唯一真實來源,透過宣告式的方式管理Kubernetes資源。Argo CD持續監控Git儲存庫與Kubernetes叢集的狀態差異,當偵測到不一致時自動執行協調操作,確保實際狀態始終符合Git中定義的期望狀態。這種方法不僅支援原生的Kubernetes YAML清單,還無縫整合Kustomize與Helm等主流配置管理工具,為複雜的多環境佈署提供統一的管理介面。

@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
skinparam minClassWidth 100

package "傳統佈署流程" {
  actor "維運人員" as ops_old
  component "kubectl命令" as kubectl
  cloud "Kubernetes叢集" as k8s_old
  
  ops_old -down-> kubectl : 手動執行
  kubectl -down-> k8s_old : 指令式變更
}

package "GitOps流程" {
  actor "開發人員" as dev
  database "Git儲存庫" as git
  component "Argo CD" as argocd
  cloud "Kubernetes叢集" as k8s_new
  
  dev -down-> git : 提交變更
  argocd -up-> git : 監控期望狀態
  argocd -down-> k8s_new : 自動同步
  argocd -right-> k8s_new : 持續協調
}

note right of ops_old
  缺乏版本控制
  難以審計追蹤
  容易出現人為錯誤
  環境配置漂移
end note

note right of argocd
  Git作為真實來源
  自動化協調機制
  完整審計軌跡
  宣告式管理
end note

@enduml

Application資源核心概念

Argo CD的運作核心圍繞著Application自訂資源展開。這個Kubernetes原生的資源物件封裝了應用程式佈署所需的完整資訊,包含來源儲存庫位置、目標叢集與命名空間、同步策略等關鍵參數。透過宣告式的方式定義Application,團隊可以將佈署邏輯版本化管理,實現基礎設施即程式碼的理念。

在Kubernetes叢集中部署Argo CD需要先建立專屬的命名空間並安裝核心元件。官方提供的安裝清單包含所有必要的控制器、API伺服器、儲存庫伺服器以及相關的服務帳戶與角色綁定。

kubectl create namespace argocd
kubectl apply -n argocd -f https://raw.githubusercontent.com/argoproj/argo-cd/v2.8.4/manifests/install.yaml

安裝過程會在argocd命名空間中建立多個Pod,包含application-controller負責監控應用程式狀態、repo-server處理Git儲存庫操作、server提供API與使用者介面、dex處理身份驗證等核心元件。這些元件協同運作,構成完整的GitOps佈署平台。

雖然可以完全透過kubectl與YAML檔案管理Argo CD,但安裝命令列工具能夠提供更便捷的互動體驗。CLI工具支援應用程式的建立、同步、狀態查詢等常見操作,在除錯與日常維運中特別有用。

# 取得初始管理員密碼
kubectl -n argocd get secret argocd-initial-admin-secret \
  -o jsonpath="{.data.password}" | base64 -d

# 使用port-forward存取API伺服器
kubectl port-forward svc/argocd-server -n argocd 8080:443

# 登入Argo CD
argocd login localhost:8080 \
  --username admin \
  --password $(kubectl -n argocd get secret argocd-initial-admin-secret -o jsonpath="{.data.password}" | base64 -d) \
  --insecure

建立第一個Application資源是理解Argo CD工作原理的最佳途徑。假設我們需要佈署一個簡單的Web應用程式,其Kubernetes清單檔案已經儲存在Git儲存庫中。Application資源的定義明確指定了這些清單的位置以及應該佈署到哪個目標環境。

apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: demo-application
  namespace: argocd
  finalizers:
  - resources-finalizer.argocd.argoproj.io
spec:
  project: default
  source:
    repoURL: https://github.com/company/kubernetes-manifests.git
    targetRevision: main
    path: applications/demo-app
  destination:
    server: https://kubernetes.default.svc
    namespace: production
  syncPolicy:
    syncOptions:
    - CreateNamespace=true

這個Application定義包含幾個關鍵區段。metadata部分設定了應用程式的識別資訊與終結器,終結器確保刪除Application時相關的Kubernetes資源也會被清理。source區段指定Git儲存庫的URL、要追蹤的分支以及清單檔案所在的路徑。destination區段定義目標叢集與命名空間,這裡使用kubernetes.default.svc表示本地叢集。syncPolicy則控制同步行為,CreateNamespace選項允許Argo CD自動建立目標命名空間。

將這個YAML檔案套用到叢集後,Argo CD會註冊該應用程式並開始監控Git儲存庫。初始狀態下應用程式會顯示為OutOfSync,因為Git中定義的資源尚未在叢集中建立。

kubectl apply -f demo-application.yaml

# 檢查應用程式狀態
argocd app get demo-application

Argo CD預設採用手動同步模式,這提供了額外的控制層,讓團隊可以在套用變更前進行審查。觸發同步操作會讓Argo CD讀取Git儲存庫中的清單檔案,比較期望狀態與實際狀態,然後執行必要的建立、更新或刪除操作。

argocd app sync demo-application --prune

同步過程中Argo CD會顯示詳細的進度資訊,包含正在處理的資源類型、操作結果、健康狀態等。prune選項指示Argo CD刪除那些存在於叢集但不在Git定義中的資源,確保完整的狀態一致性。

@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
skinparam minClassWidth 100

participant "維運人員" as ops
participant "kubectl" as kubectl
participant "Argo CD\nAPI伺服器" as api
participant "Application\n控制器" as controller
participant "Git儲存庫" as git
participant "Kubernetes\nAPI伺服器" as k8s

ops -> kubectl : apply Application資源
activate kubectl
kubectl -> api : 建立Application物件
deactivate kubectl

activate api
api -> k8s : 儲存Application CRD
k8s --> api : 確認建立
api --> ops : 註冊成功
deactivate api

activate controller
controller -> k8s : 監聽Application事件
k8s --> controller : 新Application通知

controller -> git : 讀取清單檔案
activate git
git --> controller : 回傳YAML內容
deactivate git

controller -> controller : 解析期望狀態
controller -> k8s : 查詢實際狀態
k8s --> controller : 回傳現有資源

controller -> controller : 比較差異\n(OutOfSync)
controller --> ops : 應用程式未同步
deactivate controller

ops -> kubectl : argocd app sync
activate kubectl
kubectl -> api : 觸發同步請求
deactivate kubectl

activate api
api -> controller : 執行同步操作
deactivate api

activate controller
controller -> git : 重新讀取清單
git --> controller : 最新YAML內容

controller -> k8s : 套用資源變更
activate k8s
k8s -> k8s : 建立Deployment
k8s -> k8s : 建立Service
k8s --> controller : 資源建立成功
deactivate k8s

controller -> k8s : 監控資源健康
k8s --> controller : Pod Running狀態

controller --> ops : 同步完成(Synced)
deactivate controller

note right of controller
  持續監控模式
  自動偵測配置漂移
  維持期望狀態
end note

@enduml

自動同步與協調機制

手動同步模式雖然提供了明確的控制點,但在持續交付的環境中可能成為瓶頸。當團隊需要頻繁佈署變更或管理大量應用程式時,自動同步策略能夠顯著提升效率。Argo CD的自動同步機制會持續監控Git儲存庫,當偵測到提交時自動觸發同步流程,無需人工介入。

啟用自動同步需要在Application資源中增加syncPolicy區段並設定automated參數。這個簡單的配置改變會徹底改變應用程式的管理方式,從被動的手動操作轉變為主動的自動化協調。

apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: auto-sync-application
  namespace: argocd
spec:
  project: default
  source:
    repoURL: https://github.com/company/kubernetes-manifests.git
    targetRevision: main
    path: applications/web-service
  destination:
    server: https://kubernetes.default.svc
    namespace: production
  syncPolicy:
    automated:
      prune: false
      selfHeal: false
    syncOptions:
    - CreateNamespace=true
    retry:
      limit: 5
      backoff:
        duration: 5s
        factor: 2
        maxDuration: 3m

自動同步的行為可以透過prune與selfHeal兩個關鍵參數精細調整。prune控制是否自動刪除多餘資源,當設定為true時,如果某個資源存在於叢集但不在Git定義中,Argo CD會自動將其移除。這確保了叢集狀態完全反映Git的內容,但也需要謹慎使用,因為意外的刪除可能影響服務可用性。

selfHeal參數則處理另一種常見的配置漂移場景。在實際環境中,維運人員可能因為緊急除錯或測試目的,直接使用kubectl修改叢集中的資源。當selfHeal啟用時,Argo CD會偵測這類直接修改並自動將資源恢復到Git定義的狀態。這個機制強制執行GitOps的核心原則,所有變更必須透過Git流程進行。

# 測試selfHeal機制
# 直接修改叢集中的Deployment副本數
kubectl -n production scale deployment web-service --replicas=5

# 觀察Argo CD的反應
argocd app get auto-sync-application --refresh

# 如果selfHeal啟用,副本數會自動恢復到Git定義的值
kubectl -n production get deployment web-service

retry策略為自動同步增加了容錯能力。網路暫時性問題、資源依賴順序、API伺服器負載高峰等因素可能導致同步操作失敗。透過配置重試限制、初始延遲、指數退避因子與最大延遲,Argo CD能夠智慧地重試失敗的操作,提高佈署的可靠性。

自動同步與自我修復機制的組合創造了強大的自動化能力,但也需要相應的監控與警示配置。團隊應該設定通知規則,當同步失敗、健康檢查異常或資源被頻繁修復時發送警報,確保維運人員能夠及時介入處理異常情況。

apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: production-service
  namespace: argocd
  annotations:
    notifications.argoproj.io/subscribe.on-sync-failed.slack: production-alerts
    notifications.argoproj.io/subscribe.on-health-degraded.slack: production-alerts
spec:
  project: default
  source:
    repoURL: https://github.com/company/services.git
    targetRevision: release
    path: production/api-service
  destination:
    server: https://kubernetes.default.svc
    namespace: production
  syncPolicy:
    automated:
      prune: true
      selfHeal: true
    syncOptions:
    - CreateNamespace=true
    - PruneLast=true
    retry:
      limit: 10
      backoff:
        duration: 10s
        factor: 2
        maxDuration: 5m

PruneLast選項是生產環境中的重要安全機制。當啟用時,Argo CD會在套用所有新資源與更新後才執行刪除操作。這確保了新版本的資源在舊版本被移除前已經就緒,降低服務中斷的風險。

Kustomize整合深度應用

Kustomize作為Kubernetes原生的配置管理工具,提供了無須範本語言即可客製化YAML清單的能力。它採用疊加修補的方式,允許團隊維護一套基礎清單並針對不同環境套用特定的覆蓋層。這種方法減少了重複的配置檔案,同時保持了清晰的環境差異可見性。

Argo CD對Kustomize提供原生支援,當偵測到kustomization.yaml檔案時會自動使用Kustomize處理資源。這種整合是透明的,開發人員無需額外配置即可享受Kustomize的所有功能。

典型的Kustomize專案結構採用base與overlays的組織方式。base目錄包含應用程式的核心資源定義,這些定義在所有環境中保持一致。overlays目錄則包含針對特定環境的修補檔案,例如開發環境可能使用較少的副本數與不同的資源限制,生產環境則需要更嚴格的安全策略與監控配置。

kubernetes-manifests/
├── base/
│   ├── kustomization.yaml
│   ├── deployment.yaml
│   ├── service.yaml
│   └── configmap.yaml
└── overlays/
    ├── development/
    │   ├── kustomization.yaml
    │   ├── replica-patch.yaml
    │   └── resource-limits.yaml
    ├── staging/
    │   ├── kustomization.yaml
    │   └── ingress.yaml
    └── production/
        ├── kustomization.yaml
        ├── replica-patch.yaml
        ├── security-context.yaml
        └── monitoring-annotations.yaml

base目錄的kustomization.yaml檔案定義了基礎資源集合。這個檔案扮演清單的角色,列出所有需要包含的YAML檔案,並可設定通用的標籤、命名前綴等。

# base/kustomization.yaml
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization

resources:
- deployment.yaml
- service.yaml
- configmap.yaml

commonLabels:
  app: web-service
  managed-by: argocd

namespace: default

開發環境的覆蓋層可能需要減少副本數以節省資源,同時放寬資源限制以便開發人員除錯。Kustomize的patchesStrategicMerge功能允許選擇性地覆寫基礎定義中的特定欄位。

# overlays/development/kustomization.yaml
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization

bases:
- ../../base

namespace: development

patchesStrategicMerge:
- replica-patch.yaml
- resource-limits.yaml

configMapGenerator:
- name: app-config
  literals:
  - LOG_LEVEL=debug
  - FEATURE_FLAG_NEW_UI=true

對應的修補檔案僅需包含要變更的欄位,Kustomize會智慧地將這些修改合併到基礎定義中。

# overlays/development/replica-patch.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: web-service
spec:
  replicas: 1

生產環境的覆蓋層則會增強安全性與可觀測性配置。除了調整副本數,還可能包含Pod安全策略、資源配額、服務網格註解等生產級別的設定。

# overlays/production/kustomization.yaml
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization

bases:
- ../../base

namespace: production

patchesStrategicMerge:
- replica-patch.yaml
- security-context.yaml

patchesJson6902:
- target:
    group: apps
    version: v1
    kind: Deployment
    name: web-service
  patch: |-
    - op: add
      path: /spec/template/metadata/annotations
      value:
        prometheus.io/scrape: "true"
        prometheus.io/port: "8080"
        prometheus.io/path: "/metrics"

在Argo CD中佈署Kustomize應用時,source區段需要指向overlays中的特定環境目錄。Argo CD會自動執行kustomize build指令,解析所有的基礎資源與修補檔案,生成最終的Kubernetes清單。

apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: web-service-production
  namespace: argocd
spec:
  project: default
  source:
    repoURL: https://github.com/company/kubernetes-manifests.git
    targetRevision: main
    path: overlays/production
  destination:
    server: https://kubernetes.default.svc
    namespace: production
  syncPolicy:
    automated:
      prune: true
      selfHeal: true

Kustomize還支援從命令列或環境變數覆寫特定值,這在需要動態調整配置時特別有用。Argo CD可以透過kustomize區段傳遞這些參數。

apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: web-service-canary
  namespace: argocd
spec:
  project: default
  source:
    repoURL: https://github.com/company/kubernetes-manifests.git
    targetRevision: main
    path: overlays/production
    kustomize:
      namePrefix: canary-
      nameSuffix: -v2
      images:
      - name: web-service
        newTag: v2.1.0
      commonLabels:
        version: canary
  destination:
    server: https://kubernetes.default.svc
    namespace: production

這個功能在實施金絲雀佈署或藍綠佈署策略時特別有價值。透過動態修改映像標籤與資源名稱,可以在相同的命名空間中並行執行多個版本,實現流量漸進式切換。

@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
skinparam minClassWidth 100

package "Git儲存庫結構" {
  folder "base/" as base {
    file "deployment.yaml" as base_deploy
    file "service.yaml" as base_svc
    file "kustomization.yaml" as base_kust
  }
  
  folder "overlays/" as overlays {
    folder "development" as dev {
      file "kustomization.yaml" as dev_kust
      file "patches" as dev_patch
    }
    folder "production" as prod {
      file "kustomization.yaml" as prod_kust
      file "patches" as prod_patch
    }
  }
}

package "Argo CD處理流程" {
  component "Application\n控制器" as controller
  component "Kustomize\n建構引擎" as kustomize
  database "最終清單" as manifests
}

package "Kubernetes叢集" {
  rectangle "development\nNamespace" as dev_ns
  rectangle "production\nNamespace" as prod_ns
}

base -down-> kustomize : 基礎資源
dev -down-> kustomize : 開發環境修補
prod -down-> kustomize : 生產環境修補

kustomize -down-> manifests : 生成最終YAML

controller -up-> kustomize : 觸發建構
controller -down-> dev_ns : 佈署開發環境
controller -down-> prod_ns : 佈署生產環境

note right of kustomize
  自動偵測kustomization.yaml
  執行策略性合併
  套用JSON補丁
  生成ConfigMap與Secret
end note

@enduml

Helm整合與參數化管理

Helm作為Kubernetes的包管理工具,提供了範本化、版本控制、依賴管理等企業級功能。它將應用程式打包成Chart,包含所有必要的資源定義與預設值,使用者可以透過values檔案客製化安裝參數。Argo CD與Helm的深度整合讓團隊能夠在享受Helm生態系統優勢的同時,維持GitOps的宣告式管理方式。

當Argo CD在Git儲存庫中偵測到Chart.yaml檔案時,會自動識別該目錄為Helm Chart並使用Helm範本引擎處理資源。這個自動偵測機制簡化了配置流程,開發人員無需明確指定工具類型。

典型的Helm Chart結構包含Chart.yaml描述檔、values.yaml預設值、templates目錄儲存範本檔案,以及可選的charts目錄管理依賴項。

web-service-chart/
├── Chart.yaml
├── values.yaml
├── templates/
│   ├── deployment.yaml
│   ├── service.yaml
│   ├── ingress.yaml
│   ├── configmap.yaml
│   ├── _helpers.tpl
│   └── NOTES.txt
└── charts/
    └── postgresql-12.1.9.tgz

Chart.yaml檔案定義了Chart的元資料,包含名稱、版本、應用程式版本、描述等資訊。這些資訊不僅用於文件目的,也影響Helm的版本管理行為。

apiVersion: v2
name: web-service
description: Production-ready web service with PostgreSQL backend
type: application
version: 1.2.0
appVersion: "2.1.0"
dependencies:
- name: postgresql
  version: "12.1.9"
  repository: "https://charts.bitnami.com/bitnami"
  condition: postgresql.enabled

values.yaml檔案提供可客製化參數的預設值。這些值在範本中透過.Values物件存取,Helm的範本引擎會在渲染時進行替換。

replicaCount: 3

image:
  repository: registry.company.com/web-service
  tag: "2.1.0"
  pullPolicy: IfNotPresent

service:
  type: ClusterIP
  port: 80
  targetPort: 8080

ingress:
  enabled: true
  className: nginx
  annotations:
    cert-manager.io/cluster-issuer: letsencrypt-prod
  hosts:
  - host: api.company.com
    paths:
    - path: /
      pathType: Prefix

resources:
  limits:
    cpu: 1000m
    memory: 1Gi
  requests:
    cpu: 500m
    memory: 512Mi

postgresql:
  enabled: true
  auth:
    username: appuser
    database: appdb

templates目錄中的檔案使用Go範本語法,允許條件判斷、迴圈、函數呼叫等進階邏輯。這種靈活性讓單一Chart能夠適應多種部署場景。

# templates/deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: {{ include "web-service.fullname" . }}
  labels:
    {{- include "web-service.labels" . | nindent 4 }}
spec:
  replicas: {{ .Values.replicaCount }}
  selector:
    matchLabels:
      {{- include "web-service.selectorLabels" . | nindent 6 }}
  template:
    metadata:
      annotations:
        checksum/config: {{ include (print $.Template.BasePath "/configmap.yaml") . | sha256sum }}
      labels:
        {{- include "web-service.selectorLabels" . | nindent 8 }}
    spec:
      containers:
      - name: {{ .Chart.Name }}
        image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}"
        imagePullPolicy: {{ .Values.image.pullPolicy }}
        ports:
        - name: http
          containerPort: {{ .Values.service.targetPort }}
          protocol: TCP
        resources:
          {{- toYaml .Values.resources | nindent 12 }}
        env:
        - name: DATABASE_HOST
          value: {{ include "web-service.fullname" . }}-postgresql
        - name: DATABASE_PORT
          value: "5432"
        - name: DATABASE_NAME
          value: {{ .Values.postgresql.auth.database }}

在Argo CD中佈署Helm Chart時,Application資源需要指向Chart所在的目錄。Argo CD會執行helm template指令生成最終的Kubernetes清單,然後套用到目標叢集。

apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: web-service-helm
  namespace: argocd
spec:
  project: default
  source:
    repoURL: https://github.com/company/helm-charts.git
    targetRevision: main
    path: web-service-chart
    helm:
      valueFiles:
      - values.yaml
      - values-production.yaml
      parameters:
      - name: replicaCount
        value: "5"
      - name: image.tag
        value: "2.2.0"
  destination:
    server: https://kubernetes.default.svc
    namespace: production
  syncPolicy:
    automated:
      prune: true
      selfHeal: true

valueFiles欄位允許指定多個values檔案,後面的檔案會覆寫前面檔案中的相同鍵值。這種機制支援環境特定配置的管理,基礎values.yaml定義通用預設值,values-production.yaml則覆寫生產環境的特定設定。

parameters欄位提供了命令列級別的覆寫能力,這些參數的優先級最高,會覆寫所有values檔案中的設定。這在需要動態調整特定值時特別有用,例如在CI/CD流程中根據建置版本更新映像標籤。

Argo CD在處理Helm Chart時會自動填充一系列環境變數,這些變數可以在範本中引用,提供執行時的上下文資訊。

# templates/configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
  name: {{ include "web-service.fullname" . }}
data:
  app.properties: |
    app.name={{ .Chart.Name }}
    app.version={{ .Chart.AppVersion }}
    argocd.app.name={{ .Values.argocd.app.name }}
    argocd.app.namespace={{ .Values.argocd.app.namespace }}
    deployment.timestamp={{ now | date "2006-01-02T15:04:05Z07:00" }}

Helm Hooks提供了在資源生命週期特定時間點執行操作的能力。pre-install鉤子在安裝前執行,適合資料庫遷移等準備工作。post-install鉤子在安裝後執行,可用於驗證或通知。Argo CD完整支援Helm Hooks,確保複雜的佈署流程能夠正確執行。

# templates/db-migration-job.yaml
apiVersion: batch/v1
kind: Job
metadata:
  name: {{ include "web-service.fullname" . }}-db-migration
  annotations:
    "helm.sh/hook": pre-install,pre-upgrade
    "helm.sh/hook-weight": "-5"
    "helm.sh/hook-delete-policy": before-hook-creation
spec:
  template:
    spec:
      containers:
      - name: migration
        image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}"
        command: ["python", "manage.py", "migrate"]
        env:
        - name: DATABASE_URL
          valueFrom:
            secretKeyRef:
              name: {{ include "web-service.fullname" . }}-db-secret
              key: url
      restartPolicy: Never

Image Updater自動化流程

在持續交付流程中,容器映像的更新是最頻繁的操作之一。傳統方法需要在新映像建置完成後,手動更新Kubernetes清單或Helm values檔案中的映像標籤,然後提交到Git觸發佈署。這個過程雖然可以透過腳本自動化,但仍然涉及Git操作權限管理、提交訊息規範、衝突處理等複雜問題。

Argo CD Image Updater提供了更優雅的解決方案。這個獨立的控制器持續監控容器倉庫中的新映像,當偵測到符合策略的新版本時,自動更新Application資源或Git儲存庫中的映像標籤,觸發Argo CD的同步流程。整個過程完全自動化,無需人工介入。

安裝Image Updater需要在Argo CD所在的命名空間中部署其控制器與相關資源。官方提供的安裝清單包含所有必要的元件。

kubectl apply -n argocd \
  -f https://raw.githubusercontent.com/argoproj-labs/argocd-image-updater/v0.12.2/manifests/install.yaml

# 驗證安裝
kubectl -n argocd get pods -l app.kubernetes.io/name=argocd-image-updater

Image Updater透過Application資源上的註解進行配置。這種設計將映像更新策略與應用程式定義緊密結合,避免額外的配置檔案。

apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: web-service-auto-update
  namespace: argocd
  annotations:
    argocd-image-updater.argoproj.io/image-list: web=registry.company.com/web-service
    argocd-image-updater.argoproj.io/web.update-strategy: semver
    argocd-image-updater.argoproj.io/web.allow-tags: regexp:^v[0-9]+\.[0-9]+\.[0-9]+$
    argocd-image-updater.argoproj.io/web.ignore-tags: alpha,beta,rc
spec:
  project: default
  source:
    repoURL: https://github.com/company/kubernetes-manifests.git
    targetRevision: main
    path: applications/web-service
  destination:
    server: https://kubernetes.default.svc
    namespace: production
  syncPolicy:
    automated:
      prune: true
      selfHeal: true

image-list註解定義要監控的映像清單,每個條目包含別名與完整的映像路徑。別名用於在後續註解中引用該映像,支援監控多個映像的場景。

update-strategy註解控制版本選擇邏輯。semver策略根據語意化版本規範選擇最新的穩定版本,自動跳過預發布版本。latest策略則總是選擇最新推送的映像,不考慮版本號。digest策略基於映像摘要而非標籤進行更新,提供最高的確定性。

annotations:
  # 語意化版本策略
  argocd-image-updater.argoproj.io/web.update-strategy: semver
  argocd-image-updater.argoproj.io/web.allow-tags: regexp:^v[0-9]+\.[0-9]+\.[0-9]+$
  
  # 或使用latest策略
  argocd-image-updater.argoproj.io/api.update-strategy: latest
  argocd-image-updater.argoproj.io/api.allow-tags: regexp:^(prod|production)-.*$
  
  # 或使用digest策略
  argocd-image-updater.argoproj.io/worker.update-strategy: digest

Image Updater支援兩種寫回模式決定如何傳播映像更新。Git模式會將變更提交到Git儲存庫,觸發Argo CD的標準同步流程。這種方式保持完整的審計軌跡,所有變更都有對應的Git提交記錄。

annotations:
  argocd-image-updater.argoproj.io/write-back-method: git:secret:argocd/git-credentials
  argocd-image-updater.argoproj.io/git-branch: main
  argocd-image-updater.argoproj.io/git-commit-message-template: |
    build: update {{.AppName}} to {{.NewTag}}
    
    Updated by Argo CD Image Updater
    Previous: {{.OldTag}}
    Current: {{.NewTag}}

使用Git寫回模式需要配置Git認證。Image Updater支援從Kubernetes Secret讀取認證資訊,這個Secret需要包含使用者名稱與個人存取權杖或密碼。

kubectl -n argocd create secret generic git-credentials \
  --from-literal=username=argocd-bot \
  --from-literal=password=ghp_xxxxxxxxxxxxxxxxxxxx

ArgoCD模式則直接透過Argo CD API更新Application資源中的映像參數,繞過Git提交流程。這種方式更快速但缺少Git歷史記錄,適合開發或測試環境。

annotations:
  argocd-image-updater.argoproj.io/write-back-method: argocd
  argocd-image-updater.argoproj.io/write-back-target: kustomization

對於Helm Chart,Image Updater需要知道如何更新values中的映像標籤。helm.image-spec註解提供了欄位路徑映射。

annotations:
  argocd-image-updater.argoproj.io/image-list: web=registry.company.com/web-service
  argocd-image-updater.argoproj.io/web.helm.image-name: image.repository
  argocd-image-updater.argoproj.io/web.helm.image-tag: image.tag
  argocd-image-updater.argoproj.io/web.update-strategy: semver

Image Updater的運作流程涉及多個組件的協同工作。控制器定期輪詢容器倉庫檢查新映像,根據更新策略與過濾規則選擇目標版本,透過配置的寫回模式傳播變更,最終由Argo CD執行實際的同步佈署。

@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
skinparam minClassWidth 100

participant "CI/CD流程" as ci
participant "容器倉庫" as registry
participant "Image Updater\n控制器" as updater
participant "Git儲存庫" as git
participant "Argo CD" as argocd
participant "Kubernetes" as k8s

ci -> registry : 推送新映像\nv2.3.0
activate registry
registry --> ci : 推送成功
deactivate registry

activate updater
updater -> registry : 輪詢新映像標籤
registry --> updater : 回傳標籤列表\nv2.2.0, v2.3.0

updater -> updater : 套用semver策略\n過濾alpha/beta標籤

updater -> git : 讀取當前清單\n(v2.2.0)
activate git
git --> updater : 回傳YAML內容

updater -> updater : 比較版本\nv2.3.0 > v2.2.0

updater -> git : 提交映像更新\nbuild: update to v2.3.0
git --> updater : 提交成功
deactivate git
deactivate updater

activate argocd
argocd -> git : 輪詢或Webhook觸發
git --> argocd : 偵測到新提交

argocd -> argocd : 比較期望與實際狀態

argocd -> k8s : 套用新Deployment\n(v2.3.0)
activate k8s
k8s -> k8s : 滾動更新Pod
k8s --> argocd : 佈署成功
deactivate k8s
deactivate argocd

note right of updater
  每2分鐘輪詢一次
  支援semver/latest/digest
  可配置標籤過濾規則
  Git或ArgoCD寫回模式
end note

@enduml

監控Image Updater的運作狀態對於確保自動化流程可靠性至關重要。控制器暴露Prometheus格式的指標,包含映像檢查次數、更新成功失敗次數、Git操作統計等。

apiVersion: v1
kind: Service
metadata:
  name: argocd-image-updater-metrics
  namespace: argocd
spec:
  ports:
  - name: metrics
    port: 8081
    targetPort: 8081
  selector:
    app.kubernetes.io/name: argocd-image-updater
---
apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:
  name: argocd-image-updater
  namespace: argocd
spec:
  selector:
    matchLabels:
      app.kubernetes.io/name: argocd-image-updater
  endpoints:
  - port: metrics
    interval: 30s

整合策略與最佳實踐

Argo CD在實際應用中需要與既有的工具鏈與流程整合,形成完整的持續交付管線。典型的GitOps工作流程始於開發人員提交程式碼變更,觸發CI流程執行測試與建置,生成新的容器映像並推送到倉庫,然後透過Argo CD或Image Updater更新Kubernetes清單,最終自動佈署到目標環境。

多環境管理是企業級應用的基本需求。建議採用單一Git儲存庫的多目錄結構,使用Kustomize overlays或Helm values檔案管理環境差異。這種組織方式保持配置的可見性與可追溯性,同時避免跨儲存庫同步的複雜性。

安全性配置需要貫穿整個流程。Git儲存庫應該啟用分支保護,要求程式碼審查與狀態檢查通過才能合併。Argo CD的RBAC系統應該根據團隊職責劃分權限,開發人員擁有應用程式的讀取與同步權限,平台團隊管理叢集註冊與專案配置。敏感資料如資料庫密碼、API金鑰應該使用Sealed Secrets或External Secrets管理,避免明文儲存在Git中。

監控與可觀測性確保系統的健康運作。Argo CD暴露詳細的指標,包含應用程式同步狀態、健康檢查結果、Git操作延遲等。透過Prometheus收集這些指標並在Grafana中視覺化,團隊可以即時掌握佈署狀況。整合通知系統如Slack或Microsoft Teams,在同步失敗或健康檢查異常時發送警報,確保問題能夠及時處理。

災難復原計畫是生產環境不可或缺的組成部分。定期備份Argo CD的配置,包含Application定義、專案設定、RBAC規則等。測試從備份恢復的流程,確保在主要系統故障時能夠快速重建。利用Git的分散式特性,在多個位置維護儲存庫副本,降低單點故障風險。

效能優化關注大規模部署場景。當管理數百個應用程式時,可以調整Argo CD的資源配額與並發限制,啟用應用程式分片功能將負載分散到多個控制器實例。優化Git輪詢間隔與同步頻率,平衡即時性與資源消耗。對於大型清單儲存庫,考慮使用Git LFS或拆分成多個較小的儲存庫。

GitOps文化的建立是技術實施之外的重要課題。團隊成員需要理解所有基礎設施變更都應該透過Git流程進行,直接使用kubectl修改資源是違反原則的反模式。建立明確的變更審查流程,使用Pull Request討論與驗證配置修改。自動化測試覆蓋Kubernetes清單的有效性檢查,在合併前捕獲配置錯誤。

Argo CD作為GitOps實踐的核心工具,提供了從基礎佈署到進階自動化的完整能力。透過Application資源的宣告式管理、自動同步與自我修復機制、Kustomize與Helm的深度整合,以及Image Updater的映像自動化更新,技術團隊能夠建立可靠、可審計、高效率的持續佈署流程。隨著雲端原生技術的持續演進,Argo CD生態系統也在不斷擴展,為更複雜的部署場景提供解決方案。