Kubernetes ArgoCD GitOps 持續部署

Kubernetes ArgoCD GitOps Continuous Deployment

GitOps 概念與原則

GitOps 是一種以 Git 作為單一事實來源(Single Source of Truth)的基礎設施與應用程式部署方法論。透過 GitOps,我們將所有的基礎設施配置和應用程式定義存放在 Git Repository 中,並透過自動化工具將 Git 中的狀態同步到目標環境。

GitOps 核心原則

  1. 聲明式配置(Declarative Configuration)

    • 所有系統狀態都以聲明式方式定義
    • 使用 YAML 或 JSON 描述期望狀態
    • 系統自動協調實際狀態與期望狀態
  2. 版本控制與不可變性(Versioned and Immutable)

    • 所有配置變更都透過 Git commit 進行
    • 完整的變更歷史記錄與審計軌跡
    • 可輕鬆回滾到任何歷史版本
  3. 自動拉取(Pull-based Automation)

    • 系統持續監控 Git Repository 的變更
    • 自動將變更同步到目標環境
    • 無需手動觸發部署流程
  4. 持續協調(Continuous Reconciliation)

    • 系統不斷比較實際狀態與期望狀態
    • 自動修復配置漂移(Configuration Drift)
    • 確保環境始終符合 Git 中定義的狀態

GitOps 與傳統 CI/CD 的差異

面向傳統 CI/CDGitOps
部署方式Push-basedPull-based
狀態管理指令式操作聲明式配置
安全性需要叢集存取權限僅需 Git 權限
回滾機制需要重新執行 PipelineGit 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_infoApplication 基本資訊
argocd_app_sync_total同步操作總數
argocd_app_health_status應用程式健康狀態
argocd_app_reconcile_count協調操作次數
argocd_cluster_api_resource_objects叢集資源物件數量
argocd_git_request_totalGit 請求總數

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. 分支策略

  • 使用 mainmaster 作為 production 環境的來源
  • 使用 feature branches 進行開發
  • 透過 Pull Request 進行 code review
  • 使用 Git tags 標記版本

3. 安全建議

  • 最小權限原則:為每個 Application 建立專屬的 Project
  • 使用 RBAC 控制使用者權限
  • 啟用 SSO 和 MFA
  • 定期輪換憑證
  • 使用密鑰管理工具而非直接存放 Secret

參考資料

comments powered by Disqus
Built with Hugo
Theme Stack designed by Jimmy