Skip to content
Published on

[ArgoCD] Syncエンジン分析:同期メカニズムのすべて

Authors

1. Syncエンジン概要

ArgoCDのSyncエンジンは、Gitリポジトリに定義された望ましい状態(Desired State)をKubernetesクラスタに適用するコアモジュールです。単純なkubectl applyを超え、Hook、Wave、Health Check、Retryなど精緻なメカニズムを提供します。

Sync状態マシン

Pending --> Running --> Succeeded
                |
                +--> Failed --> (Retry or Manual)
状態説明
PendingSyncがキューで待機中
RunningSyncが実行中
Succeededすべてのリソースが正常に同期完了
FailedSync中にエラー発生

2. Sync Phases(同期フェーズ)

ArgoCDはSyncを複数のフェーズ(Phase)に分けて実行します。各フェーズで特定タイプのリソースを処理します。

Phase実行順序

PreSync --> Sync --> PostSync
              |
              +--> SyncFail (Sync失敗時のみ)

PreSync Phase

PreSyncはメイン同期前に実行されるフェーズです:

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: myapp/migration:latest
          command: ['./migrate', 'up']
      restartPolicy: Never

PreSyncの使用事例:

  • データベーススキーママイグレーション
  • 設定の事前検証
  • 外部システム状態の確認
  • バックアップの作成

Sync Phase

メイン同期フェーズでは実際のKubernetesリソースをクラスタに適用します:

1. すべてのSync PhaseリソースをWave順にソート
2. 各Waveグループごとに:
   a. リソースタイプ順に適用
   b. 各リソースにkubectl apply相当の操作を実行
   c. 該当WaveのすべてのリソースがHealthyになるまで待機
3. 次のWaveに進む

PostSync Phase

PostSyncはメイン同期が成功した後にのみ実行されます:

apiVersion: batch/v1
kind: Job
metadata:
  name: notification
  annotations:
    argocd.argoproj.io/hook: PostSync
    argocd.argoproj.io/hook-delete-policy: HookSucceeded
spec:
  template:
    spec:
      containers:
        - name: notify
          image: curlimages/curl:latest
          command:
            - curl
            - -X
            - POST
            - https://hooks.slack.com/services/XXX
            - -d
            - '{"text":"Deployment successful"}'
      restartPolicy: Never

SyncFail Phase

SyncFailはSyncが失敗した時のみ実行されます:

apiVersion: batch/v1
kind: Job
metadata:
  name: failure-notification
  annotations:
    argocd.argoproj.io/hook: SyncFail
    argocd.argoproj.io/hook-delete-policy: HookSucceeded
spec:
  template:
    spec:
      containers:
        - name: notify-failure
          image: curlimages/curl:latest
          command:
            - curl
            - -X
            - POST
            - https://hooks.slack.com/services/XXX
            - -d
            - '{"text":"Deployment FAILED"}'
      restartPolicy: Never

3. Resource Hooks詳細

Hookアノテーション

metadata:
  annotations:
    argocd.argoproj.io/hook: PreSync|Sync|PostSync|SyncFail|Skip
    argocd.argoproj.io/hook-delete-policy: HookSucceeded|HookFailed|BeforeHookCreation

Hook Delete Policy

ポリシー説明
HookSucceededHook成功時にリソースを削除
HookFailedHook失敗時にリソースを削除
BeforeHookCreation次のSyncでHookを作成する前に既存リソースを削除

BeforeHookCreationがデフォルトで最もよく使用されます。次のSync時に以前のHookリソースを先に削除してから新しく作成します。

4. Sync Waveと順序制御

Sync Waveの概念

Sync Waveはリソース適用順序を細かく制御するメカニズムです:

# Wave -1: インフラリソース(先に作成)
apiVersion: v1
kind: Namespace
metadata:
  name: my-app
  annotations:
    argocd.argoproj.io/sync-wave: '-1'

---
# Wave 0: 設定リソース(デフォルト)
apiVersion: v1
kind: ConfigMap
metadata:
  name: app-config
  annotations:
    argocd.argoproj.io/sync-wave: '0'

---
# Wave 1: アプリケーションリソース
apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-app
  annotations:
    argocd.argoproj.io/sync-wave: '1'

---
# Wave 2: 外部アクセスリソース
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: my-app-ingress
  annotations:
    argocd.argoproj.io/sync-wave: '2'

Wave実行ロジック

1. すべてのリソースをWave番号でグループ化
2. 最も小さいWaveから順に実行
3. 各Wave内ではリソースタイプのデフォルト順序を適用
4. 現在のWaveのすべてのリソースがHealthyになるまで待機
5. 次のWaveに進む
6. いずれかのWaveで失敗した場合、Sync全体を中断

5. Resource Tracking(リソース追跡)

Tracking方式

ArgoCDは管理リソースを追跡するために2つの方式を提供します:

Annotation方式(デフォルト、推奨):

metadata:
  annotations:
    argocd.argoproj.io/tracking-id: 'my-app:apps/Deployment:default/nginx'

Label方式(レガシー):

metadata:
  labels:
    app.kubernetes.io/instance: my-app

Tracking ID構造

APP_NAME:GROUP/KIND:NAMESPACE/NAME

例:
  my-app:apps/Deployment:default/nginx
  my-app:/Service:default/nginx-svc
  my-app:networking.k8s.io/Ingress:default/nginx-ingress

6. Diffエンジン詳細分析

3-Way Diff

ArgoCDは3つの状態を比較します:

1. Desired State: Gitから生成されたマニフェスト(目標状態)
2. Live State: クラスタで実行中の実際の状態
3. Last Applied: 最後に適用された設定(annotationに記録)

Structured Merge Diff

ArgoCDはKubernetesのServer-Side Applyで使用されるStructured Merge Diffライブラリを活用します:

// Diff実行ロジック(簡略化)
func diff(desired, live *unstructured.Unstructured) (*DiffResult, error) {
    // 1. 正規化
    normalizedDesired := normalize(desired)
    normalizedLive := normalize(live)

    // 2. 無視フィールドを除去
    removeIgnoredFields(normalizedDesired)
    removeIgnoredFields(normalizedLive)

    // 3. 構造的比較
    result := structuredMergeDiff(normalizedDesired, normalizedLive)

    return result, nil
}

Diffカスタマイズ

特定フィールドをdiffで無視するよう設定できます:

spec:
  ignoreDifferences:
    - group: apps
      kind: Deployment
      jsonPointers:
        - /spec/replicas # HPAが管理するreplica数を無視
    - group: ''
      kind: ConfigMap
      jqPathExpressions:
        - .data.generated-field # 自動生成フィールドを無視

7. Health Assessment(健康状態評価)

Built-in Health Check

ArgoCDは主要Kubernetesリソースに対して内蔵Health Checkを提供します:

Deployment:

Healthy: すべてのreplicaがReadyで更新完了
Progressing: ロールアウトが進行中(新しいReplicaSet作成中)
Degraded: replicaがReady状態に到達できない

Pod:

Healthy: Running状態ですべてのコンテナがReady
Progressing: PendingまたはContainerCreating状態
Degraded: CrashLoopBackOff、ImagePullBackOffなど

Job:

Healthy: 正常に完了(Completed)
Progressing: 実行中(Active)
Degraded: 失敗(Failed)

カスタムLua Health Check

内蔵チェックで不十分な場合、Luaスクリプトでカスタムロジックを作成します:

# argocd-cm ConfigMap
data:
  resource.customizations.health.cert-manager.io_Certificate: |
    hs = {}
    if obj.status ~= nil then
      if obj.status.conditions ~= nil then
        for _, condition in ipairs(obj.status.conditions) do
          if condition.type == "Ready" then
            if condition.status == "True" then
              hs.status = "Healthy"
              hs.message = "Certificate is ready"
            else
              hs.status = "Degraded"
              hs.message = condition.message
            end
            return hs
          end
        end
      end
    end
    hs.status = "Progressing"
    hs.message = "Waiting for certificate"
    return hs

8. Pruning(リソース整理)詳細

Prune動作原理

1. Gitマニフェストからすべてのリソースリストを生成
2. クラスタでArgoCDが管理するリソースを照会(tracking label/annotation)
3. クラスタに存在するがGitにないリソースを識別(= Prune対象)
4. 削除ポリシーに従ってリソースを削除

Prune保護

意図しない削除を防止するための保護メカニズム:

# リソースにPrune防止アノテーションを追加
metadata:
  annotations:
    argocd.argoproj.io/sync-options: Prune=false

# Applicationレベルでpruneを無効化
spec:
  syncPolicy:
    automated:
      prune: false

9. Retry戦略とBackoff

Auto-Sync Retry

Sync失敗時に自動的にリトライできます:

spec:
  syncPolicy:
    automated:
      selfHeal: true
    retry:
      limit: 5
      backoff:
        duration: 5s
        factor: 2
        maxDuration: 3m

Backoff計算例

リトライ1: 5秒後
リトライ2: 10秒後 (5s * 2)
リトライ3: 20秒後 (10s * 2)
リトライ4: 40秒後 (20s * 2)
リトライ5: 80秒後 (40s * 2) -> 最大3分で制限

10. Syncオプション

Applicationレベルのsyncオプション

spec:
  syncPolicy:
    automated:
      prune: true
      selfHeal: true
      allowEmpty: false
    syncOptions:
      - CreateNamespace=true
      - PrunePropagationPolicy=foreground
      - PruneLast=true
      - Replace=false
      - ServerSideApply=true
      - ApplyOutOfSyncOnly=true
      - Validate=true
      - RespectIgnoreDifferences=true

Server-Side Apply

Server-Side ApplyはKubernetes 1.22+で推奨される適用方式です:

利点:
  - フィールド所有権(Field Ownership)の追跡
  - 複数コントローラー間の競合防止
  - より正確な3-way merge
  - 大規模リソースでのパフォーマンス向上

設定:
  syncOptions:
    - ServerSideApply=true

11. Sync Window(同期時間帯)

Sync Windowの概念

AppProjectで同期を許可または禁止する時間帯を設定できます:

spec:
  syncWindows:
    # 平日の業務時間のみSync許可
    - kind: allow
      schedule: '0 9 * * 1-5'
      duration: 9h
      applications:
        - '*'
      namespaces:
        - 'production'
    # 週末はSync禁止
    - kind: deny
      schedule: '0 0 * * 0,6'
      duration: 24h
      applications:
        - '*'
    # 手動Syncのみ許可する時間帯
    - kind: allow
      schedule: '0 18 * * 1-5'
      duration: 15h
      manualSync: true
      applications:
        - 'critical-*'

優先度ルール

1. denyがallowより優先
2. 同一優先度ではより具体的なルールが優先
3. manualSync=trueは手動Syncのみ許可

12. 本番Sync戦略

安全な本番デプロイ戦略

apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: production-app
spec:
  syncPolicy:
    automated:
      prune: true
      selfHeal: true
    syncOptions:
      - CreateNamespace=true
      - PruneLast=true
      - ServerSideApply=true
      - ApplyOutOfSyncOnly=true
    retry:
      limit: 3
      backoff:
        duration: 10s
        factor: 2
        maxDuration: 5m
  ignoreDifferences:
    - group: apps
      kind: Deployment
      jsonPointers:
        - /spec/replicas
    - group: autoscaling
      kind: HorizontalPodAutoscaler
      jqPathExpressions:
        - .status

13. まとめ

ArgoCD Syncエンジンの核心要素をまとめます:

  1. Phase:PreSync、Sync、PostSync、SyncFailでデプロイ段階を構造化
  2. Hook:JobやPodで各Phaseでカスタム作業を実行
  3. Wave:リソース間の適用順序を細かく制御
  4. Diffエンジン:3-Way Merge基盤の正規化された状態比較
  5. Health Check:内蔵 + Luaカスタムでリソース健康状態を評価
  6. Pruning:Gitから削除されたリソースの安全な整理
  7. Retry:指数バックオフによる自動リトライ
  8. Sync Window:時間帯基盤の同期制御

これらのメカニズムを適切に組み合わせることで、安全で予測可能なGitOpsデプロイパイプラインを構築できます。