← 返回上一頁
CI/CD Kubernetes

使用 ArgoCD + Kargo 打造 GitOps 多環境 CD Pipeline

最後更新:2026-04-06
本頁目錄
69d0cdbc303cd

本文示範如何從零開始,使用 ArgoCD 與 Kargo 建立一套完整的多環境持續交付(CD)Pipeline。
所有 Pipeline 設定都透過 GitOps 版本控管,讓環境還原、稽核追蹤變得簡單可靠。


架構概覽 #

新 Image 推上 Registry
        ↓ 自動偵測
  Kargo Warehouse
        ↓ 自動 promote
      dev  ──────→ sit ──────→ uat ──────→ yb-prod
           (手動 approve)  (手動 approve) (手動 approve)
  • Warehouse:監控 Container Registry,偵測到新 image tag 時自動建立 Freight
  • dev:有新 Freight 時自動 promote(無需人工)
  • sit / uat / yb-prod:需在 Kargo UI 手動 approve,且必須按順序推進

核心元件 #

元件 角色
ArgoCD GitOps 引擎,監控 Git 並將資源同步到 K8s
Kargo CD Pipeline,管理版本在各環境間的推進
Kustomize K8s 資源的 overlay 管理(各環境差異化設定)

前置需求 #

  • kubectl >= 1.28
  • helm >= 3.12
  • 已安裝 ArgoCD(本文假設已有可用的 ArgoCD)
  • 一個 K8s Cluster(範例使用 GKE)
# 設定 kubectl context
gcloud container clusters get-credentials <your-cluster-name> \
  --zone <your-zone> \
  --project <your-project-id>

Step 1:安裝 Kargo #

Kargo 使用 Helm 安裝,支援本地 chart 或遠端 chart。

# 建立 namespace
kubectl create namespace kargo

# 安裝 Kargo(使用本地 chart 或 OCI registry)
helm install kargo ./developers/kargo \
  --namespace kargo \
  --set api.adminAccount.passwordHash='<your-bcrypt-password-hash>' \
  --set api.adminAccount.tokenSigningKey='<your-random-signing-key>'
# 等待 pod 就緒
kubectl wait --for=condition=Ready pods --all -n kargo --timeout=300s

產生 bcrypt hash:htpasswd -bnBC 10 "" yourpassword | tr -d ':\n'

安裝完成後,透過 NodePort 或 LoadBalancer 公開 Kargo API(port 443)。


Step 2:規劃目錄結構 #

本文採用以下 GitOps 目錄結構,所有設定都版控於 Git:

kustomize/
├── bases/                        # 各服務的 base kustomize 定義
├── env/                          # 各環境 overlay
│   ├── dev/tool-api/
│   ├── sit/tool-api/
│   ├── uat/tool-api/
│   └── yb-prod/tool-api/
├── argocd-apps/                  # ArgoCD Application 定義(App of Apps)
│   └── tool-api/
│       ├── kustomization.yaml
│       ├── argocd-app.yaml       # App of Apps 入口
│       ├── dev-tool-api.yaml
│       ├── sit-tool-api.yaml
│       ├── uat-tool-api.yaml
│       └── ybprod-tool-api.yaml
└── kargo/                        # Kargo Pipeline 設定
    ├── argocd-app-kargo-tool-api.yaml   # 管理 Kargo 設定的 ArgoCD app
    └── kargo-tool-api/
        ├── kustomization.yaml
        ├── project.yaml
        ├── projectconfig.yaml
        ├── warehouse.yaml
        ├── stage-dev.yaml
        ├── stage-sit.yaml
        ├── stage-uat.yaml
        ├── stage-yb-prod.yaml
        └── git-credentials.yaml

Step 3:建立 Kargo Pipeline 設定 #

3.1 Project #

kustomize/kargo/kargo-tool-api/project.yaml

apiVersion: kargo.akuity.io/v1alpha1
kind: Project
metadata:
  name: kargo-tool-api
spec: {}

3.2 ProjectConfig(自動 promote 設定) #

kustomize/kargo/kargo-tool-api/projectconfig.yaml

apiVersion: kargo.akuity.io/v1alpha1
kind: ProjectConfig
metadata:
  name: kargo-tool-api
  namespace: kargo-tool-api
spec:
  promotionPolicies:
  - stage: dev
    autoPromotionEnabled: true   # dev 環境自動 promote
  # sit/uat/yb-prod 預設手動

3.3 Warehouse(監控 Container Registry) #

kustomize/kargo/kargo-tool-api/warehouse.yaml

apiVersion: kargo.akuity.io/v1alpha1
kind: Warehouse
metadata:
  name: tool-api
  namespace: kargo-tool-api
spec:
  freightCreationPolicy: Automatic
  interval: 5m0s
  subscriptions:
  - image:
      repoURL: <your-registry>/tool-api
      semverConstraint: ">=0.0.0"
      imageSelectionStrategy: SemVer
      strictSemvers: true
      discoveryLimit: 10

Warehouse 每 5 分鐘掃描 Registry,發現新 tag 後自動建立 Freight。

3.4 Stage 設定(以 dev 為例) #

kustomize/kargo/kargo-tool-api/stage-dev.yaml

apiVersion: kargo.akuity.io/v1alpha1
kind: Stage
metadata:
  name: dev
  namespace: kargo-tool-api
spec:
  requestedFreight:
  - origin:
      kind: Warehouse
      name: tool-api
    sources:
      direct: true    # 直接從 Warehouse 取 Freight
  promotionTemplate:
    spec:
      steps:
      - uses: git-clone
        config:
          repoURL: https://<your-git-repo>
          checkout:
          - branch: main
            path: ./repo
      - uses: kustomize-set-image
        as: update-image
        config:
          path: ./repo/kustomize/env/dev/tool-api
          images:
          - image: <your-registry>/tool-api
            tag: ${{ imageFrom("<your-registry>/tool-api").Tag }}
      - uses: git-commit
        config:
          path: ./repo
          message: "chore(dev): promote tool-api to ${{ imageFrom(\"<your-registry>/tool-api\").Tag }}"
      - uses: git-push
        as: push
        config:
          path: ./repo
      - uses: argocd-update
        config:
          apps:
          - name: dev-tool-api
            namespace: argocd

關鍵說明:

  • kustomize-set-image:修改 kustomize overlay 中的 image tag
  • git-commit + git-push:將修改推回 Git
  • argocd-update:通知 ArgoCD 同步最新 commit

其他環境(sit/uat/yb-prod)的 Stage 設定類似,差別在:

  • sources.direct: false,改為 upstream: [{origin: {kind: Stage, name: dev}}(sit 從 dev 取)
  • promotionTemplate 的 path 和 app name 對應各自環境

3.5 Git Credentials(Kargo push 回 Git 用) #

kustomize/kargo/kargo-tool-api/git-credentials.yaml

apiVersion: v1
kind: Secret
metadata:
  name: git-credentials
  namespace: kargo-tool-api
  labels:
    kargo.akuity.io/cred-type: git
stringData:
  repoURL: https://<your-git-repo>
  username: <your-git-username>
  password: <your-git-password-or-token>   # 建議使用 Project Access Token

安全提醒:正式環境建議使用 External Secrets Operator 或 Vault 管理此 Secret,避免明文入 Git。

3.6 kustomization.yaml #

apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- project.yaml
- projectconfig.yaml
- warehouse.yaml
- git-credentials.yaml
- stage-dev.yaml
- stage-sit.yaml
- stage-uat.yaml
- stage-yb-prod.yaml

Step 4:建立 ArgoCD Applications #

4.1 各環境 Application(含 Kargo 授權 annotation) #

每個環境的 ArgoCD Application 需加上 kargo.akuity.io/authorized-stage annotation,讓 Kargo 有權觸發 ArgoCD sync:

kustomize/argocd-apps/tool-api/dev-tool-api.yaml

apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: dev-tool-api
  namespace: argocd
  annotations:
    kargo.akuity.io/authorized-stage: kargo-tool-api:dev   # 允許 dev stage 觸發 sync
spec:
  project: default
  source:
    repoURL: https://<your-git-repo>
    targetRevision: HEAD
    path: kustomize/env/dev/tool-api
  destination:
    server: https://kubernetes.default.svc
    namespace: dev
  syncPolicy:
    automated:
      prune: true
      selfHeal: true
    syncOptions:
    - ServerSideApply=true

其他環境類推,annotation 改為對應的 stage 名稱(kargo-tool-api:sitkargo-tool-api:uatkargo-tool-api:yb-prod)。

4.2 App of Apps(管理所有 ArgoCD Applications) #

kustomize/argocd-apps/tool-api/argocd-app.yaml

apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: tool-api-argocd-apps
  namespace: argocd
  annotations:
    argocd.argoproj.io/sync-wave: "-1"
spec:
  project: default
  source:
    repoURL: https://<your-git-repo>
    targetRevision: HEAD
    path: kustomize/argocd-apps/tool-api
  destination:
    server: https://kubernetes.default.svc
    namespace: argocd
  syncPolicy:
    automated:
      prune: true
      selfHeal: true
    syncOptions:
    - ServerSideApply=true

4.3 Kargo Pipeline 的 ArgoCD Application #

kustomize/kargo/argocd-app-kargo-tool-api.yaml

apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: kargo-tool-api
  namespace: argocd
spec:
  project: default
  source:
    repoURL: https://<your-git-repo>
    targetRevision: HEAD
    path: kustomize/kargo/kargo-tool-api
  destination:
    server: https://kubernetes.default.svc
    namespace: kargo-tool-api
  syncPolicy:
    automated:
      prune: true
      selfHeal: true
    syncOptions:
    - ServerSideApply=true
  ignoreDifferences:
  - group: kargo.akuity.io
    kind: Warehouse
    managedFieldsManagers:
    - kargo
  - group: kargo.akuity.io
    kind: Stage
    managedFieldsManagers:
    - kargo
  - group: kargo.akuity.io
    kind: Project
    managedFieldsManagers:
    - kargo
  - group: kargo.akuity.io
    kind: ProjectConfig
    managedFieldsManagers:
    - kargo

ignoreDifferences + managedFieldsManagers: [kargo] 是關鍵設定:Kargo controller 會在資源上加入預設值,若不忽略這些差異,ArgoCD 會一直顯示 OutOfSync。


Step 5:Apply 到 Cluster #

# 1. 建立 Kargo pipeline 的 ArgoCD app
#    → ArgoCD 會自動從 Git 同步 Kargo 所有資源
kubectl apply -f kustomize/kargo/argocd-app-kargo-tool-api.yaml

# 2. 建立 App of Apps(管理 tool-api 的 4 個 ArgoCD Application)
kubectl apply -f kustomize/argocd-apps/tool-api/argocd-app.yaml

確認所有資源同步完成:

kubectl get applications -n argocd
kubectl get project,warehouse,stage -n kargo-tool-api

環境畫面說明 #

Kargo Projects 頁面 #

登入 Kargo UI 後,可以看到所有 Project 的概覽:

69d0ceb291f92

每個 Project 顯示 Stages 和 Warehouses 的數量與健康狀態。


Kargo Pipeline 視覺化 #

點進 Project 後,可以看到完整的 Pipeline 流程圖:

69d0cec432430

畫面最上方的 Freight bar 顯示 Warehouse 偵測到的所有 image 版本。
Pipeline 從左到右:Warehouse → dev → sit → uat → yb-prod

每個 Stage 卡片顯示:

  • Ready / Healthy:Stage 的健康狀態
  • 當前版本:目前此環境執行的 image tag
  • Last Promotion:上次 promote 的時間

ArgoCD Applications 列表 #

在 ArgoCD UI 中可以看到所有由 App of Apps 管理的 Application:

69d0ced440c94

共 6 個 Application:

Application 管理內容
dev-tool-api dev 環境部署
sit-tool-api sit 環境部署
uat-tool-api uat 環境部署
ybprod-tool-api yb-prod 環境部署
tool-api-argocd-apps App of Apps(管理上面 4 個 app)
kargo-tool-api Kargo Pipeline 資源(Project/Warehouse/Stage)

手動 Promote 流程 #

當需要將某個版本推進到 sit/uat/yb-prod 時,在 Kargo UI 操作:

Step 1:點擊 Stage 的 Promote 按鈕 #

69d0cb80e031b

有三個選項:

選項 說明
Promote 從 Freight 清單中手動選擇要 promote 的版本
Promote from upstream 選擇上游 Stage(例如 sit→dev)目前的版本來 promote
Instant promote from upstream 直接 promote 上游 Stage 目前的版本,跳過確認

Step 2:選擇要 Promote 的 Freight #

69d0cb9125bce

畫面頂部顯示所有可用的 Freight,每張卡片代表一個 image 版本。
帶有警示圖示(⚠️)的 Freight 表示該版本未經上游 Stage 驗證,需謹慎選擇。
點選對應版本的 Select 按鈕即可觸發 promote。

Step 3:確認 Promote 結果 #

Kargo 會執行以下步驟:

  1. Clone Git repo
  2. 使用 kustomize-set-image 更新對應環境的 image tag
  3. Commit + Push 回 Git
  4. 觸發 ArgoCD sync

ArgoCD sync 完成後,K8s 中的 Pod 會自動滾動更新至新版本。


Freight 的概念 #

Freight 是 Kargo 的核心概念,代表一個不可變的版本快照:

Freight = {
  image: <registry>/tool-api:1.0.5,
  gitCommit: abc1234
}

每個 Freight 有一個友善名稱(如 sad-olmfun-tarsier),方便識別。
一個 Freight 通過 Stage 驗證後,才能繼續往下游 Stage promote(除非使用 Instant promote)。


常見問題 #

Q: Warehouse 一直顯示 OutOfSync #

原因:Kargo controller 會在 Warehouse 上注入預設值(如 freightCreationPolicyintervalimageSelectionStrategy),這些值不在 Git 的 YAML 中,導致 ArgoCD 偵測到差異。

解法一:在 YAML 中明確加入這些預設值:

spec:
  freightCreationPolicy: Automatic
  interval: 5m0s
  subscriptions:
  - image:
      imageSelectionStrategy: SemVer
      strictSemvers: true

解法二:在 ArgoCD Application 中加入 ignoreDifferences(已在 Step 4.3 示範)。


Q: argocd-update 顯示「not authorized」 #

原因:ArgoCD Application 缺少授權 Kargo 的 annotation。

解法:在對應的 ArgoCD Application 加上:

metadata:
  annotations:
    kargo.akuity.io/authorized-stage: kargo-tool-api:dev

Q: git-commit 顯示「message is required」 #

原因:舊版 Kargo 不支援 messageFromSteps,需直接在 message 欄位使用 expression。

解法

- uses: git-commit
  config:
    path: ./repo
    message: "chore(dev): promote tool-api to ${{ imageFrom(\"<your-registry>/tool-api\").Tag }}"

小結 #

透過 ArgoCD + Kargo 的組合:

  1. GitOps 一致性:所有 Pipeline 設定(Warehouse、Stage、ArgoCD Application)都版控於 Git,可追蹤、可還原
  2. 自動化 + 人工控制:dev 環境全自動,sit/uat/prod 需人工 approve,平衡速度與安全
  3. 視覺化 Pipeline:Kargo UI 讓 Pipeline 狀態一目了然,方便 approve 操作
  4. ArgoCD 整合:Kargo promote 後直接觸發 ArgoCD sync,部署過程完全透明

整套架構建置完成後,開發者只需 push image 到 Registry,剩下的事情 Kargo 和 ArgoCD 會自動完成。

 

分享這篇
X LinkedIn Facebook Hacker News Reddit

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *

這個網站採用 Akismet 服務減少垃圾留言。進一步了解 Akismet 如何處理網站訪客的留言資料