本文示範如何從零開始,使用 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 taggit-commit+git-push:將修改推回 Gitargocd-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:sit、kargo-tool-api:uat、kargo-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 的概覽:

每個 Project 顯示 Stages 和 Warehouses 的數量與健康狀態。
Kargo Pipeline 視覺化 #
點進 Project 後,可以看到完整的 Pipeline 流程圖:

畫面最上方的 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:

共 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 按鈕 #

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

畫面頂部顯示所有可用的 Freight,每張卡片代表一個 image 版本。
帶有警示圖示(⚠️)的 Freight 表示該版本未經上游 Stage 驗證,需謹慎選擇。
點選對應版本的 Select 按鈕即可觸發 promote。
Step 3:確認 Promote 結果 #
Kargo 會執行以下步驟:
- Clone Git repo
- 使用
kustomize-set-image更新對應環境的 image tag - Commit + Push 回 Git
- 觸發 ArgoCD sync
ArgoCD sync 完成後,K8s 中的 Pod 會自動滾動更新至新版本。
Freight 的概念 #
Freight 是 Kargo 的核心概念,代表一個不可變的版本快照:
Freight = {
image: <registry>/tool-api:1.0.5,
gitCommit: abc1234
}
每個 Freight 有一個友善名稱(如 sad-olm、fun-tarsier),方便識別。
一個 Freight 通過 Stage 驗證後,才能繼續往下游 Stage promote(除非使用 Instant promote)。
常見問題 #
Q: Warehouse 一直顯示 OutOfSync #
原因:Kargo controller 會在 Warehouse 上注入預設值(如 freightCreationPolicy、interval、imageSelectionStrategy),這些值不在 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 的組合:
- GitOps 一致性:所有 Pipeline 設定(Warehouse、Stage、ArgoCD Application)都版控於 Git,可追蹤、可還原
- 自動化 + 人工控制:dev 環境全自動,sit/uat/prod 需人工 approve,平衡速度與安全
- 視覺化 Pipeline:Kargo UI 讓 Pipeline 狀態一目了然,方便 approve 操作
- ArgoCD 整合:Kargo promote 後直接觸發 ArgoCD sync,部署過程完全透明
整套架構建置完成後,開發者只需 push image 到 Registry,剩下的事情 Kargo 和 ArgoCD 會自動完成。


發佈留言