Skip to content

필사 모드: ArgoCD Sync 엔진 분석: 동기화 메커니즘의 모든 것

한국어
0%
정확도 0%
💡 왼쪽 원문을 읽으면서 오른쪽에 따라 써보세요. Tab 키로 힌트를 받을 수 있습니다.
원문 렌더가 준비되기 전까지 텍스트 가이드로 표시합니다.

1. Sync 엔진 개요

ArgoCD의 Sync 엔진은 Git 저장소에 정의된 원하는 상태(Desired State)를 Kubernetes 클러스터에 적용하는 핵심 모듈입니다. 단순한 `kubectl apply`를 넘어 Hook, Wave, Health Check, Retry 등 정교한 메커니즘을 제공합니다.

Sync 상태 머신

Pending --> Running --> Succeeded

|

+--> Failed --> (Retry or Manual)

Sync 작업은 다음 상태를 가집니다:

| 상태 | 설명 |

| --------- | --------------------------------- |

| Pending | Sync가 대기열에 있음 |

| Running | Sync가 실행 중 |

| Succeeded | 모든 리소스가 성공적으로 동기화됨 |

| Failed | Sync 중 오류 발생 |

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

**PostSync 사용 사례:**

- 배포 완료 알림 전송

- 스모크 테스트 실행

- CDN 캐시 무효화

- 외부 시스템 동기화 트리거

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:

Hook 유형 지정

argocd.argoproj.io/hook: PreSync|Sync|PostSync|SyncFail|Skip

Hook 리소스 삭제 정책

argocd.argoproj.io/hook-delete-policy: HookSucceeded|HookFailed|BeforeHookCreation

Hook Delete Policy

| 정책 | 설명 |

| ------------------ | ----------------------------------------------------- |

| HookSucceeded | Hook이 성공하면 리소스를 삭제 |

| HookFailed | Hook이 실패하면 리소스를 삭제 |

| BeforeHookCreation | 다음 Sync에서 Hook을 생성하기 전에 기존 리소스를 삭제 |

**BeforeHookCreation**이 기본값이며, 가장 많이 사용됩니다. 이 정책은 다음 Sync 시 이전 Hook 리소스를 먼저 삭제한 후 새로 생성합니다.

Hook 실행 메커니즘

1. Application Controller가 Sync 시작

2. 현재 Phase에 해당하는 Hook 리소스 식별

3. Hook 리소스를 Wave 순서로 정렬

4. 각 Hook 리소스를 클러스터에 적용 (Job, Pod 등)

5. Hook이 완료(성공/실패)될 때까지 대기

6. 성공 시 다음 단계 진행, 실패 시 Sync 중단 또는 SyncFail Phase로 전환

7. Delete Policy에 따라 Hook 리소스 정리

4. Sync Waves와 순서 제어

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 중단

리소스 타입 기본 순서

동일 Wave 내에서 리소스는 다음 순서로 적용됩니다:

Phase 1: 네임스페이스와 기본 설정

1. Namespace

2. NetworkPolicy

3. ResourceQuota

4. LimitRange

5. PodSecurityPolicy

6. ServiceAccount

7. Secret

8. SecretList

9. ConfigMap

Phase 2: RBAC

10. ClusterRole

11. ClusterRoleBinding

12. Role

13. RoleBinding

Phase 3: CRD

14. CustomResourceDefinition

Phase 4: 스토리지와 볼륨

15. PersistentVolume

16. PersistentVolumeClaim

17. StorageClass

Phase 5: 서비스

18. Service

19. Endpoints

Phase 6: 워크로드

20. DaemonSet

21. Deployment

22. ReplicaSet

23. StatefulSet

24. Job

25. CronJob

Phase 7: 라우팅

26. Ingress

27. IngressClass

28. APIService

5. Resource Tracking (리소스 추적)

Tracking 방식

ArgoCD는 자신이 관리하는 리소스를 추적하기 위해 두 가지 방식을 제공합니다:

**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

Tracking 방식 설정

`argocd-cm` ConfigMap에서 설정합니다:

apiVersion: v1

kind: ConfigMap

metadata:

name: argocd-cm

namespace: argocd

data:

application.resourceTrackingMethod: annotation # annotation | label | annotation+label

6. Diff 엔진 상세 분석

3-Way Diff

ArgoCD는 세 가지 상태를 비교합니다:

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

}

Normalization (정규화) 상세

정규화는 불필요한 diff를 제거하기 위한 핵심 과정입니다:

**제거 대상 필드:**

- `metadata.resourceVersion`

- `metadata.uid`

- `metadata.generation`

- `metadata.creationTimestamp`

- `metadata.managedFields`

- `status` (대부분의 리소스)

**정규화 규칙 예시:**

- Container의 `imagePullPolicy`가 생략되었지만 이미지 태그가 `latest`면 Kubernetes가 `Always`를 자동 설정 -> diff에서 무시

- Service의 `clusterIP`가 생략되면 Kubernetes가 자동 할당 -> diff에서 무시

- 빈 필드(`""`, `[]`, `null`)와 미설정 필드의 동등 처리

Diff 결과 해석

| 결과 | 의미 |

| -------- | --------------------------------------- |

| NoDiff | 원하는 상태와 실제 상태가 동일 (Synced) |

| Diff | 차이 존재 (OutOfSync) |

| Modified | 필드 값이 변경됨 |

| Added | 새 필드가 추가됨 |

| Removed | 필드가 제거됨 |

Diff Customization

특정 필드를 diff에서 무시하도록 설정할 수 있습니다:

Application 리소스에서 설정

spec:

ignoreDifferences:

- group: apps

kind: Deployment

jsonPointers:

- /spec/replicas # HPA가 관리하는 replica 수 무시

- group: ''

kind: ConfigMap

jqPathExpressions:

- .data.generated-field # 자동 생성 필드 무시

글로벌 설정은 `argocd-cm` ConfigMap에서 가능합니다:

data:

resource.customizations.ignoreDifferences.all: |

managedFieldsManagers:

- kube-controller-manager

- kube-scheduler

7. Health Assessment (건강 상태 평가)

Built-in Health Check

ArgoCD는 주요 Kubernetes 리소스에 대해 내장 Health Check를 제공합니다:

**Deployment:**

Healthy: 모든 replica가 Ready이고 업데이트 완료

Progressing: 롤아웃이 진행 중 (새 ReplicaSet 생성 중)

Degraded: replica가 Ready 상태에 도달하지 못함

**StatefulSet:**

Healthy: 모든 replica가 Ready이고 currentRevision == updateRevision

Progressing: 업데이트가 진행 중

Degraded: replica가 Ready가 아님

**Pod:**

Healthy: Running 상태이고 모든 컨테이너가 Ready

Progressing: Pending 또는 ContainerCreating 상태

Degraded: CrashLoopBackOff, ImagePullBackOff 등

**Service:**

Healthy: Endpoints가 존재하고 하나 이상의 Ready 주소가 있음

Progressing: LoadBalancer 타입에서 외부 IP 할당 대기 중

**Ingress:**

Healthy: LoadBalancer 주소가 할당됨

Progressing: 주소 할당 대기 중

**Job:**

Healthy: 성공적으로 완료됨 (Completed)

Progressing: 실행 중 (Active)

Degraded: 실패 (Failed)

Custom Lua Health Check

기본 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

Health Check 대상 CRD 예시

| CRD | 프로젝트 | Health Check 기준 |

| -------------- | ------------- | ------------------------ |

| Certificate | cert-manager | Ready condition |

| VirtualService | Istio | 항상 Healthy (상태 없음) |

| Rollout | Argo Rollouts | phase 필드 기반 |

| HelmRelease | Flux | Ready condition |

| Kustomization | Flux | Ready condition |

8. Pruning (리소스 정리) 상세

Prune 동작 원리

1. Git 매니페스트에서 모든 리소스 목록 생성

2. 클러스터에서 ArgoCD가 관리하는 리소스 조회 (tracking label/annotation)

3. 클러스터에 존재하지만 Git에 없는 리소스 식별 (= Prune 대상)

4. 삭제 정책에 따라 리소스 삭제

삭제 전략

**Cascade 삭제 (기본값):**

- 소유 리소스를 재귀적으로 삭제

- Deployment를 삭제하면 ReplicaSet과 Pod도 함께 삭제

- Kubernetes의 garbage collection 메커니즘 사용

**Foreground 삭제:**

- 소유 리소스가 먼저 삭제된 후 부모 리소스 삭제

- 순서가 보장되어야 하는 경우 사용

- finalizer를 통한 순서 제어

Prune 보호

의도하지 않은 삭제를 방지하기 위한 보호 메커니즘:

리소스에 Prune 방지 어노테이션 추가

metadata:

annotations:

argocd.argoproj.io/sync-options: Prune=false

Application 수준에서 Prune 비활성화

spec:

syncPolicy:

automated:

prune: false # 자동 Prune 비활성화

Orphan 리소스 모니터링

ArgoCD는 관리 대상이 아닌 "고아(Orphan)" 리소스도 감지할 수 있습니다:

AppProject에서 Orphan 리소스 모니터링 활성화

spec:

orphanedResources:

warn: true # 경고만 표시

ignore: # 무시할 리소스 패턴

- group: ""

kind: ConfigMap

name: "auto-*"

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분으로 제한

Retry 트리거 조건

다음 상황에서 Retry가 트리거됩니다:

- 리소스 적용 실패 (API 서버 오류, 유효성 검사 실패 등)

- Health Check 타임아웃 (리소스가 시간 내에 Healthy가 되지 않음)

- Hook 실행 실패 (PreSync/PostSync Job 실패)

- 네트워크 일시적 오류

10. Sync 옵션

Application 수준 Sync 옵션

spec:

syncPolicy:

automated:

prune: true # Git에서 삭제된 리소스 자동 정리

selfHeal: true # 수동 변경 자동 교정

allowEmpty: false # 빈 매니페스트 허용 여부

syncOptions:

- CreateNamespace=true # 네임스페이스 자동 생성

- PrunePropagationPolicy=foreground # 삭제 전파 정책

- PruneLast=true # 다른 리소스 동기화 후 Prune

- Replace=false # apply 대신 replace 사용 여부

- ServerSideApply=true # Server-Side Apply 사용

- ApplyOutOfSyncOnly=true # OutOfSync 리소스만 적용

- Validate=true # 매니페스트 유효성 검사

- RespectIgnoreDifferences=true # ignoreDifferences 설정 존중

리소스 수준 Sync 옵션

개별 리소스에 어노테이션으로 설정할 수 있습니다:

metadata:

annotations:

argocd.argoproj.io/sync-options: Prune=false,Replace=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' # 월-금 09:00

duration: 9h # 9시간 동안

applications:

- '*'

namespaces:

- 'production'

주말에는 Sync 금지

- kind: deny

schedule: '0 0 * * 0,6' # 토,일 00:00

duration: 24h

applications:

- '*'

수동 Sync만 허용하는 시간대

- kind: allow

schedule: '0 18 * * 1-5' # 월-금 18:00

duration: 15h

manualSync: true

applications:

- 'critical-*'

Window 유형

| 유형 | 설명 |

| ----- | --------------------------- |

| allow | 지정된 시간에만 Sync를 허용 |

| deny | 지정된 시간에는 Sync를 금지 |

우선순위 규칙

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 # HPA 관리

- group: autoscaling

kind: HorizontalPodAutoscaler

jqPathExpressions:

- .status

Hook을 활용한 완전한 배포 파이프라인

Wave -2: PreSync - DB 백업

apiVersion: batch/v1

kind: Job

metadata:

name: db-backup

annotations:

argocd.argoproj.io/hook: PreSync

argocd.argoproj.io/hook-delete-policy: BeforeHookCreation

argocd.argoproj.io/sync-wave: '-2'

spec:

template:

spec:

containers:

- name: backup

image: backup-tool:latest

command: ['./backup.sh']

restartPolicy: Never

Wave -1: PreSync - DB 마이그레이션

apiVersion: batch/v1

kind: Job

metadata:

name: db-migrate

annotations:

argocd.argoproj.io/hook: PreSync

argocd.argoproj.io/hook-delete-policy: BeforeHookCreation

argocd.argoproj.io/sync-wave: '-1'

spec:

template:

spec:

containers:

- name: migrate

image: myapp/migration:v2

command: ['./migrate', 'up']

restartPolicy: Never

Wave 0: Sync - 메인 애플리케이션

apiVersion: apps/v1

kind: Deployment

metadata:

name: myapp

annotations:

argocd.argoproj.io/sync-wave: '0'

spec:

replicas: 3

selector:

matchLabels:

app: myapp

template:

metadata:

labels:

app: myapp

spec:

containers:

- name: app

image: myapp:v2

Wave 1: PostSync - 스모크 테스트

apiVersion: batch/v1

kind: Job

metadata:

name: smoke-test

annotations:

argocd.argoproj.io/hook: PostSync

argocd.argoproj.io/hook-delete-policy: BeforeHookCreation

argocd.argoproj.io/sync-wave: '1'

spec:

template:

spec:

containers:

- name: test

image: curlimages/curl:latest

command: ['curl', '-f', 'http://myapp:8080/health']

restartPolicy: Never

13. 정리

ArgoCD Sync 엔진의 핵심 요소를 정리합니다:

1. **Phase**: PreSync, Sync, PostSync, SyncFail로 배포 단계를 구조화

2. **Hook**: Job이나 Pod로 각 Phase에서 커스텀 작업 실행

3. **Wave**: 리소스 간 적용 순서를 세밀하게 제어

4. **Diff Engine**: 3-Way Merge 기반의 정규화된 상태 비교

5. **Health Check**: 내장 + Lua 커스텀으로 리소스 건강 상태 평가

6. **Pruning**: Git에서 제거된 리소스의 안전한 정리

7. **Retry**: 지수 백오프를 통한 자동 재시도

8. **Sync Window**: 시간대 기반 동기화 제어

이러한 메커니즘을 적절히 조합하면 안전하고 예측 가능한 GitOps 배포 파이프라인을 구축할 수 있습니다.

현재 단락 (1/511)

ArgoCD의 Sync 엔진은 Git 저장소에 정의된 원하는 상태(Desired State)를 Kubernetes 클러스터에 적용하는 핵심 모듈입니다. 단순한 `kubectl ap...

작성 글자: 0원문 글자: 11,997작성 단락: 0/511