GitOps 概念與原則
GitOps 是一種以 Git 作為單一事實來源(Single Source of Truth)的基礎設施與應用程式部署方法論。透過 GitOps,我們將所有的基礎設施配置和應用程式定義存放在 Git Repository 中,並透過自動化工具將 Git 中的狀態同步到目標環境。
GitOps 核心原則
聲明式配置(Declarative Configuration)
- 所有系統狀態都以聲明式方式定義
- 使用 YAML 或 JSON 描述期望狀態
- 系統自動協調實際狀態與期望狀態
版本控制與不可變性(Versioned and Immutable)
- 所有配置變更都透過 Git commit 進行
- 完整的變更歷史記錄與審計軌跡
- 可輕鬆回滾到任何歷史版本
自動拉取(Pull-based Automation)
- 系統持續監控 Git Repository 的變更
- 自動將變更同步到目標環境
- 無需手動觸發部署流程
持續協調(Continuous Reconciliation)
- 系統不斷比較實際狀態與期望狀態
- 自動修復配置漂移(Configuration Drift)
- 確保環境始終符合 Git 中定義的狀態
GitOps 與傳統 CI/CD 的差異
| 面向 | 傳統 CI/CD | GitOps |
|---|
| 部署方式 | Push-based | Pull-based |
| 狀態管理 | 指令式操作 | 聲明式配置 |
| 安全性 | 需要叢集存取權限 | 僅需 Git 權限 |
| 回滾機制 | 需要重新執行 Pipeline | Git revert 即可 |
| 審計追蹤 | 需額外配置 | Git 歷史記錄 |
ArgoCD 架構與元件
ArgoCD 是一個專為 Kubernetes 設計的聲明式 GitOps 持續交付工具。它持續監控 Git Repository 中的應用程式定義,並自動將變更同步到 Kubernetes 叢集。
核心元件
1
2
3
4
5
6
7
8
9
10
11
| ┌─────────────────────────────────────────────────────────────┐
│ ArgoCD │
│ ┌──────────────┐ ┌──────────────┐ ┌──────────────────┐ │
│ │ API Server │ │ Repository │ │ Application │ │
│ │ │ │ Server │ │ Controller │ │
│ └──────────────┘ └──────────────┘ └──────────────────┘ │
│ ┌──────────────┐ ┌──────────────┐ ┌──────────────────┐ │
│ │ Dex │ │ Redis │ │ Notification │ │
│ │ (SSO) │ │ (Cache) │ │ Controller │ │
│ └──────────────┘ └──────────────┘ └──────────────────┘ │
└─────────────────────────────────────────────────────────────┘
|
1. API Server
API Server 是 ArgoCD 的核心元件,提供以下功能:
- 提供 gRPC/REST API 供 Web UI 和 CLI 使用
- 處理應用程式的 CRUD 操作
- 管理 Repository 和叢集憑證
- 執行使用者認證與授權
2. Repository Server
Repository Server 負責管理 Git Repository 的操作:
- 克隆和快取 Git Repository
- 生成 Kubernetes manifests(支援 Helm、Kustomize、Jsonnet)
- 提供 Repository 內容給其他元件
3. Application Controller
Application Controller 是 GitOps 引擎的核心:
- 持續監控應用程式狀態
- 比較實際狀態與期望狀態
- 執行同步操作
- 觸發 PreSync、Sync、PostSync hooks
4. Dex
Dex 是 OpenID Connect (OIDC) 認證提供者:
- 支援多種身份驗證方式
- 整合 LDAP、SAML、GitHub、GitLab 等
- 提供 SSO 單一登入功能
5. Redis
Redis 作為快取層:
- 快取 Git Repository 資料
- 儲存應用程式狀態
- 提高系統效能
6. Notification Controller
Notification Controller 處理事件通知:
- 發送 Slack、Email、Webhook 通知
- 支援自訂觸發條件
- 整合外部監控系統
安裝與初始設定
前置需求
- Kubernetes 叢集(v1.22+)
- kubectl 已配置並可存取叢集
- 足夠的叢集資源(建議至少 2 CPU、4GB RAM)
使用 kubectl 安裝
1
2
3
4
5
6
7
8
| # 建立 argocd namespace
kubectl create namespace argocd
# 安裝 ArgoCD
kubectl apply -n argocd -f https://raw.githubusercontent.com/argoproj/argo-cd/stable/manifests/install.yaml
# 查看安裝狀態
kubectl get pods -n argocd
|
使用 Helm 安裝
1
2
3
4
5
6
7
8
9
| # 新增 ArgoCD Helm Repository
helm repo add argo https://argoproj.github.io/argo-helm
helm repo update
# 安裝 ArgoCD
helm install argocd argo/argo-cd \
--namespace argocd \
--create-namespace \
--set server.service.type=LoadBalancer
|
自訂 Helm values.yaml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
| # argocd-values.yaml
server:
replicas: 2
service:
type: LoadBalancer
ingress:
enabled: true
hosts:
- argocd.example.com
tls:
- secretName: argocd-tls
hosts:
- argocd.example.com
controller:
replicas: 1
resources:
limits:
cpu: 500m
memory: 512Mi
requests:
cpu: 250m
memory: 256Mi
repoServer:
replicas: 2
resources:
limits:
cpu: 500m
memory: 512Mi
redis:
enabled: true
resources:
limits:
cpu: 200m
memory: 128Mi
configs:
params:
server.insecure: false
cm:
timeout.reconciliation: 180s
|
1
2
3
4
5
| # 使用自訂 values 安裝
helm install argocd argo/argo-cd \
--namespace argocd \
--create-namespace \
-f argocd-values.yaml
|
存取 ArgoCD UI
1
2
3
4
5
6
7
8
| # 方法一:Port Forward
kubectl port-forward svc/argocd-server -n argocd 8080:443
# 方法二:取得 LoadBalancer IP
kubectl get svc argocd-server -n argocd
# 取得初始 admin 密碼
kubectl -n argocd get secret argocd-initial-admin-secret -o jsonpath="{.data.password}" | base64 -d
|
安裝 ArgoCD CLI
1
2
3
4
5
6
7
8
9
10
11
12
13
| # Linux
curl -sSL -o argocd-linux-amd64 https://github.com/argoproj/argo-cd/releases/latest/download/argocd-linux-amd64
sudo install -m 555 argocd-linux-amd64 /usr/local/bin/argocd
rm argocd-linux-amd64
# macOS
brew install argocd
# 登入 ArgoCD
argocd login localhost:8080 --username admin --password <your-password>
# 修改密碼
argocd account update-password
|
Application 資源定義
Application 是 ArgoCD 的核心資源,定義了要部署的應用程式及其來源。
基本 Application 結構
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
| apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: my-app
namespace: argocd
finalizers:
- resources-finalizer.argocd.argoproj.io
spec:
project: default
source:
repoURL: https://github.com/your-org/your-repo.git
targetRevision: main
path: manifests/my-app
destination:
server: https://kubernetes.default.svc
namespace: my-app
syncPolicy:
automated:
prune: true
selfHeal: true
syncOptions:
- CreateNamespace=true
|
使用 Helm Chart 作為來源
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
| apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: nginx
namespace: argocd
spec:
project: default
source:
repoURL: https://charts.bitnami.com/bitnami
chart: nginx
targetRevision: 15.0.0
helm:
releaseName: nginx
values: |
replicaCount: 3
service:
type: ClusterIP
resources:
limits:
cpu: 200m
memory: 256Mi
parameters:
- name: image.tag
value: "1.25.0"
destination:
server: https://kubernetes.default.svc
namespace: web
|
使用 Kustomize
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
| apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: my-app-kustomize
namespace: argocd
spec:
project: default
source:
repoURL: https://github.com/your-org/your-repo.git
targetRevision: main
path: kustomize/overlays/production
kustomize:
namePrefix: prod-
images:
- myapp:v1.2.3
commonLabels:
environment: production
destination:
server: https://kubernetes.default.svc
namespace: production
|
多來源 Application
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
| apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: multi-source-app
namespace: argocd
spec:
project: default
sources:
- repoURL: https://charts.bitnami.com/bitnami
chart: redis
targetRevision: 17.0.0
helm:
releaseName: redis
- repoURL: https://github.com/your-org/your-repo.git
targetRevision: main
path: manifests/app
destination:
server: https://kubernetes.default.svc
namespace: my-app
|
使用 CLI 建立 Application
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
| # 建立基本 Application
argocd app create my-app \
--repo https://github.com/your-org/your-repo.git \
--path manifests/my-app \
--dest-server https://kubernetes.default.svc \
--dest-namespace my-app \
--sync-policy automated \
--auto-prune \
--self-heal
# 建立 Helm Application
argocd app create nginx \
--repo https://charts.bitnami.com/bitnami \
--helm-chart nginx \
--revision 15.0.0 \
--dest-server https://kubernetes.default.svc \
--dest-namespace web \
--helm-set replicaCount=3
# 查看 Application 狀態
argocd app get my-app
# 同步 Application
argocd app sync my-app
|
同步策略與自動同步
同步選項
ArgoCD 提供多種同步選項來控制部署行為:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
| spec:
syncPolicy:
automated:
prune: true # 刪除不在 Git 中的資源
selfHeal: true # 自動修復配置漂移
allowEmpty: false # 不允許空的 Application
syncOptions:
- Validate=true # 驗證 manifests
- CreateNamespace=true # 自動建立 namespace
- PrunePropagationPolicy=foreground # 刪除策略
- PruneLast=true # 最後執行刪除
- RespectIgnoreDifferences=true # 尊重忽略差異設定
- ApplyOutOfSyncOnly=true # 只同步不同步的資源
retry:
limit: 5 # 重試次數
backoff:
duration: 5s # 初始等待時間
factor: 2 # 指數增長因子
maxDuration: 3m # 最大等待時間
|
忽略特定差異
有時某些欄位會被 Kubernetes 自動修改,我們可以設定忽略這些差異:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
| spec:
ignoreDifferences:
- group: apps
kind: Deployment
jsonPointers:
- /spec/replicas
- group: ""
kind: Service
jqPathExpressions:
- .spec.clusterIP
- group: admissionregistration.k8s.io
kind: MutatingWebhookConfiguration
jsonPointers:
- /webhooks/0/clientConfig/caBundle
|
Sync Waves 與 Hooks
透過 Sync Waves 可以控制資源的同步順序:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
| apiVersion: v1
kind: Namespace
metadata:
name: my-app
annotations:
argocd.argoproj.io/sync-wave: "-1" # 最先同步
---
apiVersion: v1
kind: ConfigMap
metadata:
name: app-config
annotations:
argocd.argoproj.io/sync-wave: "0" # 其次
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-app
annotations:
argocd.argoproj.io/sync-wave: "1" # 最後同步
|
Sync Hooks
Hooks 可以在同步過程的不同階段執行特定任務:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
| apiVersion: batch/v1
kind: Job
metadata:
name: db-migration
annotations:
argocd.argoproj.io/hook: PreSync
argocd.argoproj.io/hook-delete-policy: HookSucceeded
spec:
template:
spec:
containers:
- name: migrate
image: my-app:latest
command: ["./migrate.sh"]
restartPolicy: Never
backoffLimit: 2
|
Hook 類型:
| Hook | 說明 |
|---|
| PreSync | 在同步開始前執行 |
| Sync | 與其他資源一起同步 |
| PostSync | 在所有資源同步後執行 |
| SyncFail | 同步失敗時執行 |
| Skip | 跳過不部署 |
Hook 刪除策略:
| 策略 | 說明 |
|---|
| HookSucceeded | 成功後刪除 |
| HookFailed | 失敗後刪除 |
| BeforeHookCreation | 建立新 Hook 前刪除舊的 |
ApplicationSet 多環境部署
ApplicationSet 是 ArgoCD 的擴充功能,可以自動化生成多個 Application,適用於多環境、多叢集部署。
Generator 類型
1. List Generator
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
| apiVersion: argoproj.io/v1alpha1
kind: ApplicationSet
metadata:
name: my-app
namespace: argocd
spec:
generators:
- list:
elements:
- env: dev
namespace: dev
replicas: "1"
- env: staging
namespace: staging
replicas: "2"
- env: production
namespace: production
replicas: "3"
template:
metadata:
name: 'my-app-{{env}}'
spec:
project: default
source:
repoURL: https://github.com/your-org/your-repo.git
targetRevision: main
path: 'manifests/{{env}}'
helm:
parameters:
- name: replicaCount
value: '{{replicas}}'
destination:
server: https://kubernetes.default.svc
namespace: '{{namespace}}'
syncPolicy:
automated:
prune: true
selfHeal: true
|
2. Cluster Generator
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
| apiVersion: argoproj.io/v1alpha1
kind: ApplicationSet
metadata:
name: cluster-apps
namespace: argocd
spec:
generators:
- clusters:
selector:
matchLabels:
environment: production
template:
metadata:
name: '{{name}}-monitoring'
spec:
project: default
source:
repoURL: https://github.com/your-org/monitoring.git
targetRevision: main
path: manifests
destination:
server: '{{server}}'
namespace: monitoring
|
3. Git Directory Generator
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
| apiVersion: argoproj.io/v1alpha1
kind: ApplicationSet
metadata:
name: apps-from-dirs
namespace: argocd
spec:
generators:
- git:
repoURL: https://github.com/your-org/apps.git
revision: main
directories:
- path: apps/*
- path: apps/exclude-this
exclude: true
template:
metadata:
name: '{{path.basename}}'
spec:
project: default
source:
repoURL: https://github.com/your-org/apps.git
targetRevision: main
path: '{{path}}'
destination:
server: https://kubernetes.default.svc
namespace: '{{path.basename}}'
|
4. Git File Generator
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
| apiVersion: argoproj.io/v1alpha1
kind: ApplicationSet
metadata:
name: apps-from-files
namespace: argocd
spec:
generators:
- git:
repoURL: https://github.com/your-org/config.git
revision: main
files:
- path: "config/**/config.json"
template:
metadata:
name: '{{app.name}}'
spec:
project: default
source:
repoURL: https://github.com/your-org/apps.git
targetRevision: '{{app.revision}}'
path: '{{app.path}}'
helm:
values: |
image:
tag: {{app.imageTag}}
destination:
server: '{{app.cluster}}'
namespace: '{{app.namespace}}'
|
5. Matrix Generator(組合多個 Generator)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
| apiVersion: argoproj.io/v1alpha1
kind: ApplicationSet
metadata:
name: matrix-apps
namespace: argocd
spec:
generators:
- matrix:
generators:
- clusters:
selector:
matchLabels:
type: production
- list:
elements:
- app: frontend
version: v1.2.0
- app: backend
version: v2.1.0
template:
metadata:
name: '{{name}}-{{app}}'
spec:
project: default
source:
repoURL: https://github.com/your-org/apps.git
targetRevision: '{{version}}'
path: '{{app}}'
destination:
server: '{{server}}'
namespace: '{{app}}'
|
Progressive Rollout
使用 rolloutSteps 實現漸進式部署:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
| apiVersion: argoproj.io/v1alpha1
kind: ApplicationSet
metadata:
name: progressive-rollout
namespace: argocd
spec:
generators:
- list:
elements:
- env: canary
weight: 10
- env: staging
weight: 30
- env: production
weight: 100
strategy:
type: RollingSync
rollingSync:
steps:
- matchExpressions:
- key: env
operator: In
values:
- canary
- matchExpressions:
- key: env
operator: In
values:
- staging
maxUpdate: 50%
- matchExpressions:
- key: env
operator: In
values:
- production
maxUpdate: 25%
template:
metadata:
name: 'app-{{env}}'
labels:
env: '{{env}}'
spec:
project: default
source:
repoURL: https://github.com/your-org/app.git
targetRevision: main
path: overlays/{{env}}
destination:
server: https://kubernetes.default.svc
namespace: 'app-{{env}}'
|
密鑰管理整合
在 GitOps 流程中,敏感資訊不應直接存放在 Git Repository。ArgoCD 支援多種密鑰管理解決方案。
1. Sealed Secrets
Sealed Secrets 使用非對稱加密,允許將加密後的 Secret 存放在 Git 中。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
| # 安裝 kubeseal CLI
brew install kubeseal
# 安裝 Sealed Secrets Controller
kubectl apply -f https://github.com/bitnami-labs/sealed-secrets/releases/download/v0.24.0/controller.yaml
# 建立一般 Secret
kubectl create secret generic my-secret \
--from-literal=username=admin \
--from-literal=password=secret123 \
--dry-run=client -o yaml > secret.yaml
# 加密 Secret
kubeseal --format yaml < secret.yaml > sealed-secret.yaml
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
| # sealed-secret.yaml(可安全存放在 Git)
apiVersion: bitnami.com/v1alpha1
kind: SealedSecret
metadata:
name: my-secret
namespace: default
spec:
encryptedData:
username: AgBy3i4OJSWK+PiT...
password: AgBy3i4OJSWK+PiT...
template:
metadata:
name: my-secret
namespace: default
type: Opaque
|
2. External Secrets Operator
External Secrets Operator 可從外部密鑰管理系統(AWS Secrets Manager、HashiCorp Vault 等)同步 Secret。
1
2
3
4
5
| # 安裝 External Secrets Operator
helm repo add external-secrets https://charts.external-secrets.io
helm install external-secrets external-secrets/external-secrets \
--namespace external-secrets \
--create-namespace
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
| # 設定 AWS Secrets Manager 連線
apiVersion: external-secrets.io/v1beta1
kind: SecretStore
metadata:
name: aws-secrets-manager
namespace: my-app
spec:
provider:
aws:
service: SecretsManager
region: ap-northeast-1
auth:
jwt:
serviceAccountRef:
name: external-secrets-sa
---
# 定義要同步的 Secret
apiVersion: external-secrets.io/v1beta1
kind: ExternalSecret
metadata:
name: my-app-secrets
namespace: my-app
spec:
refreshInterval: 1h
secretStoreRef:
name: aws-secrets-manager
kind: SecretStore
target:
name: my-app-secrets
creationPolicy: Owner
data:
- secretKey: db-password
remoteRef:
key: production/my-app/db
property: password
- secretKey: api-key
remoteRef:
key: production/my-app/api
property: key
|
3. HashiCorp Vault 整合
使用 ArgoCD Vault Plugin 直接在 manifests 中引用 Vault secrets。
1
2
3
4
5
6
7
8
| # 安裝 argocd-vault-plugin
# 需要自訂 ArgoCD repo-server image
# Dockerfile
FROM argoproj/argocd:v2.9.0
RUN curl -L -o /usr/local/bin/argocd-vault-plugin \
https://github.com/argoproj-labs/argocd-vault-plugin/releases/download/v1.17.0/argocd-vault-plugin_1.17.0_linux_amd64
RUN chmod +x /usr/local/bin/argocd-vault-plugin
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
| # 設定 ArgoCD ConfigMap
apiVersion: v1
kind: ConfigMap
metadata:
name: argocd-cm
namespace: argocd
data:
configManagementPlugins: |
- name: argocd-vault-plugin
generate:
command: ["argocd-vault-plugin"]
args: ["generate", "./"]
- name: argocd-vault-plugin-helm
init:
command: ["/bin/sh", "-c"]
args: ["helm dependency build"]
generate:
command: ["sh", "-c"]
args: ["helm template $ARGOCD_APP_NAME . | argocd-vault-plugin generate -"]
|
1
2
3
4
5
6
7
8
9
10
11
| # 使用 Vault Plugin 的 Secret 範本
apiVersion: v1
kind: Secret
metadata:
name: my-secret
annotations:
avp.kubernetes.io/path: "secret/data/my-app"
type: Opaque
stringData:
username: <username>
password: <password>
|
4. SOPS(Secrets OPerationS)
SOPS 使用 age、PGP 或雲端 KMS 加密 YAML/JSON 檔案。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
| # 安裝 SOPS
brew install sops
# 使用 age 建立金鑰
age-keygen -o key.txt
# 建立 .sops.yaml 設定檔
cat > .sops.yaml << EOF
creation_rules:
- path_regex: .*secrets.*\.yaml$
age: age1xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
EOF
# 加密檔案
sops -e secrets.yaml > secrets.enc.yaml
|
1
2
3
4
5
6
7
8
9
10
11
12
| # ArgoCD 設定使用 SOPS
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: my-app
spec:
source:
plugin:
name: argocd-vault-plugin-kustomize
env:
- name: SOPS_AGE_KEY_FILE
value: /sops/key.txt
|
監控與故障排除
監控 ArgoCD
Prometheus Metrics
ArgoCD 原生支援 Prometheus metrics。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
| # 設定 ServiceMonitor(如果使用 Prometheus Operator)
apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:
name: argocd-metrics
namespace: argocd
spec:
selector:
matchLabels:
app.kubernetes.io/name: argocd-server
endpoints:
- port: metrics
interval: 30s
---
apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:
name: argocd-repo-server-metrics
namespace: argocd
spec:
selector:
matchLabels:
app.kubernetes.io/name: argocd-repo-server
endpoints:
- port: metrics
interval: 30s
|
重要 Metrics
| Metric | 說明 |
|---|
argocd_app_info | Application 基本資訊 |
argocd_app_sync_total | 同步操作總數 |
argocd_app_health_status | 應用程式健康狀態 |
argocd_app_reconcile_count | 協調操作次數 |
argocd_cluster_api_resource_objects | 叢集資源物件數量 |
argocd_git_request_total | Git 請求總數 |
Grafana Dashboard
匯入官方 Dashboard:
1
2
| # ArgoCD Dashboard ID: 14584
# 在 Grafana 中 Import Dashboard by ID
|
通知設定
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
| # argocd-notifications-cm ConfigMap
apiVersion: v1
kind: ConfigMap
metadata:
name: argocd-notifications-cm
namespace: argocd
data:
service.slack: |
token: $slack-token
template.app-deployed: |
message: |
Application {{.app.metadata.name}} is now running new version.
slack:
attachments: |
[{
"title": "{{.app.metadata.name}}",
"color": "#18be52",
"fields": [
{"title": "Sync Status", "value": "{{.app.status.sync.status}}", "short": true},
{"title": "Repository", "value": "{{.app.spec.source.repoURL}}", "short": true}
]
}]
trigger.on-deployed: |
- when: app.status.operationState.phase in ['Succeeded'] and app.status.health.status == 'Healthy'
send: [app-deployed]
subscriptions: |
- recipients:
- slack:argocd-notifications
triggers:
- on-deployed
- on-health-degraded
- on-sync-failed
|
故障排除指令
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
| # 查看 Application 詳細狀態
argocd app get my-app
# 查看同步差異
argocd app diff my-app
# 查看 Application 事件
kubectl describe application my-app -n argocd
# 查看 ArgoCD Controller 日誌
kubectl logs -n argocd -l app.kubernetes.io/name=argocd-application-controller
# 查看 Repo Server 日誌
kubectl logs -n argocd -l app.kubernetes.io/name=argocd-repo-server
# 手動觸發同步
argocd app sync my-app
# 強制同步(忽略差異)
argocd app sync my-app --force
# 硬重置 Application
argocd app sync my-app --prune --replace
# 終止進行中的同步
argocd app terminate-op my-app
# 清除 Application 資源快取
argocd app get my-app --hard-refresh
# 驗證 Repository 連線
argocd repo list
argocd repo get https://github.com/your-org/your-repo.git
|
常見問題與解決方案
1. Application 卡在 Progressing 狀態
1
2
3
4
5
6
7
8
9
| # 檢查資源狀態
kubectl get all -n my-app
kubectl describe deployment my-app -n my-app
# 常見原因:
# - Image pull 失敗
# - Resource quota 不足
# - Node 資源不足
# - Health check 失敗
|
2. OutOfSync 但無法同步
1
2
3
4
5
6
7
| # 查看詳細差異
argocd app diff my-app --local /path/to/manifests
# 常見原因:
# - Kubernetes 自動添加的欄位(如 clusterIP)
# - Mutating webhook 修改的內容
# - 使用 ignoreDifferences 忽略這些差異
|
3. Repository 連線失敗
1
2
3
4
5
6
7
8
| # 驗證憑證
argocd repo get https://github.com/your-org/your-repo.git
# 重新添加 Repository
argocd repo rm https://github.com/your-org/your-repo.git
argocd repo add https://github.com/your-org/your-repo.git \
--username git \
--password $GITHUB_TOKEN
|
4. 記憶體不足(OOMKilled)
1
2
3
4
5
6
7
8
9
10
11
| # 增加 repo-server 記憶體
spec:
template:
spec:
containers:
- name: argocd-repo-server
resources:
limits:
memory: 1Gi
requests:
memory: 512Mi
|
健康狀態檢查自訂
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
| # 自訂資源健康檢查
apiVersion: v1
kind: ConfigMap
metadata:
name: argocd-cm
namespace: argocd
data:
resource.customizations.health.certmanager.io_Certificate: |
hs = {}
if obj.status ~= nil then
if obj.status.conditions ~= nil then
for i, condition in ipairs(obj.status.conditions) do
if condition.type == "Ready" and condition.status == "False" then
hs.status = "Degraded"
hs.message = condition.message
return hs
end
if condition.type == "Ready" and condition.status == "True" then
hs.status = "Healthy"
hs.message = condition.message
return hs
end
end
end
end
hs.status = "Progressing"
hs.message = "Waiting for certificate"
return hs
|
最佳實踐
1. Repository 結構
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
| gitops-repo/
├── apps/ # Application 定義
│ ├── dev/
│ │ └── my-app.yaml
│ ├── staging/
│ │ └── my-app.yaml
│ └── production/
│ └── my-app.yaml
├── manifests/ # Kubernetes manifests
│ └── my-app/
│ ├── base/
│ │ ├── deployment.yaml
│ │ ├── service.yaml
│ │ └── kustomization.yaml
│ └── overlays/
│ ├── dev/
│ ├── staging/
│ └── production/
├── charts/ # 自訂 Helm Charts
│ └── my-app/
└── applicationsets/ # ApplicationSet 定義
└── cluster-apps.yaml
|
2. 分支策略
- 使用
main 或 master 作為 production 環境的來源 - 使用 feature branches 進行開發
- 透過 Pull Request 進行 code review
- 使用 Git tags 標記版本
3. 安全建議
- 最小權限原則:為每個 Application 建立專屬的 Project
- 使用 RBAC 控制使用者權限
- 啟用 SSO 和 MFA
- 定期輪換憑證
- 使用密鑰管理工具而非直接存放 Secret
參考資料