Argo CD 캐퍼빌리티 문제 해결

Argo CD 캐퍼빌리티 문제 해결

Argo CD 캐퍼빌리티에서 발생하는 일반적인 문제를 해결하는 방법을 설명합니다.

출처: 문서

본문

참고

EKS 캐퍼빌리티는 완전 관리형이며 클러스터 밖에서 실행됩니다. 컨트롤러 네임스페이스에 직접 접근할 수 없습니다. 컨트롤러 동작을 관찰하려면 컨트롤러 로그 전달을 구성할 수 있습니다. EKS 캐퍼빌리티 컨트롤러 로그 접근을 참고하세요. 문제 해결은 캐퍼빌리티 상태(health), 애플리케이션 상태, 구성에 초점을 맞춥니다.

캐퍼빌리티는 ACTIVE인데 애플리케이션이 동기화되지 않음

Argo CD 캐퍼빌리티가 ACTIVE 상태인데 애플리케이션이 동기화되지 않으면 캐퍼빌리티 상태(health)와 애플리케이션 상태를 확인하세요.

캐퍼빌리티 상태(health) 확인:

캐퍼빌리티 상태(health)와 상태 문제는 EKS 콘솔 또는 AWS CLI에서 볼 수 있습니다.

콘솔:

  1. https://console.aws.amazon.com/eks/home#/clusters 에서 Amazon EKS 콘솔을 엽니다.
  2. 클러스터 이름을 선택합니다.
  3. Observability 탭을 선택합니다.
  4. Monitor cluster를 선택합니다.
  5. 모든 캐퍼빌리티의 상태(health)와 상태를 보려면 Capabilities 탭을 선택합니다.

AWS CLI:

# View capability status and health
aws eks describe-capability \
  --region region-code \
  --cluster-name my-cluster \
  --capability-name my-argocd

# Look for issues in the health section

일반적인 원인:

  • 리포지토리 미구성 - Git 리포지토리가 Argo CD에 추가되지 않음
  • 인증 실패 - SSH 키, 토큰, CodeCommit 자격 증명이 잘못됨
  • Application 미생성 - 클러스터에 Application 리소스가 없음
  • 동기화 정책 - 수동 동기화 필요(자동 동기화 비활성화)
  • IAM 권한 - CodeCommit이나 Secrets Manager용 권한 누락

애플리케이션 상태 확인:

# List applications
kubectl get application -n argocd

# View sync status
kubectl get application my-app -n argocd -o jsonpath='{.status.sync.status}'

# View application health
kubectl get application my-app -n argocd -o jsonpath='{.status.health}'

애플리케이션 조건 확인:

# Describe application to see detailed status
kubectl describe application my-app -n argocd

# View application health
kubectl get application my-app -n argocd -o jsonpath='{.status.health}'

Application이 "Progressing" 상태에 머무름

Application이 Progressing을 표시하지만 Healthy에 도달하지 않으면 애플리케이션의 리소스 상태와 이벤트를 확인하세요.

리소스 상태(health) 확인:

# View application resources
kubectl get application my-app -n argocd -o jsonpath='{.status.resources}'

# Check for unhealthy resources
kubectl describe application my-app -n argocd | grep -A 10 "Health Status"

일반적인 원인:

  • Deployment 미준비 - 파드가 시작 실패하거나 준비 프로브 실패
  • 리소스 의존성 - 다른 리소스가 준비되기를 기다리는 리소스
  • 이미지 풀 오류 - 컨테이너 이미지에 접근할 수 없음
  • 리소스 부족 - 클러스터에 파드용 CPU나 메모리가 없음

대상 클러스터 구성 확인(멀티 클러스터 설정):

# List registered clusters
kubectl get secret -n argocd -l argocd.argoproj.io/secret-type=cluster

# View cluster secret details
kubectl get secret cluster-secret-name -n argocd -o yaml

리포지토리 인증 실패

Argo CD가 Git 리포지토리에 접근할 수 없으면 인증 구성을 확인하세요.

CodeCommit 리포지토리의 경우:

IAM 캐퍼빌리티 역할에 CodeCommit 권한이 있는지 확인합니다.

# View IAM policies
aws iam list-attached-role-policies --role-name my-argocd-capability-role
aws iam list-role-policies --role-name my-argocd-capability-role

# Get specific policy details
aws iam get-role-policy --role-name my-argocd-capability-role --policy-name policy-name

역할에는 리포지토리에 대한 codecommit:GitPull 권한이 필요합니다.

프라이빗 Git 리포지토리의 경우:

리포지토리 자격 증명이 올바르게 구성되었는지 확인합니다.

# Check repository secret exists
kubectl get secret -n argocd repo-secret-name -o yaml

시크릿에 올바른 인증 자격 증명(SSH 키, 토큰 또는 사용자 이름/비밀번호)이 포함되어 있는지 확인하세요.

Secrets Manager를 사용하는 리포지토리의 경우:

# Verify IAM Capability Role has Secrets Manager permissions
aws iam list-attached-role-policies --role-name my-argocd-capability-role

# Test secret retrieval
aws secretsmanager get-secret-value --secret-id arn:aws:secretsmanager:region-code:111122223333:secret:my-secret

멀티 클러스터 배포 문제

애플리케이션이 원격 클러스터에 배포되지 않으면 클러스터 등록과 접근 구성을 확인하세요.

클러스터 등록 확인:

# List registered clusters
kubectl get secret -n argocd -l argocd.argoproj.io/secret-type=cluster

# Verify cluster secret format
kubectl get secret CLUSTER_SECRET_NAME -n argocd -o yaml

server 필드에 Kubernetes API URL이 아니라 EKS 클러스터 ARN이 포함되어 있는지 확인하세요.

대상 클러스터 접근 항목 확인:

대상 클러스터에서 Argo CD 캐퍼빌리티 역할에 접근 항목이 있는지 확인합니다.

# List access entries (run on target cluster or use AWS CLI)
aws eks list-access-entries --cluster-name target-cluster

# Describe specific access entry
aws eks describe-access-entry \
  --cluster-name target-cluster \
  --principal-arn arn:aws:iam::111122223333:role/my-argocd-capability-role

교차 계정 IAM 권한 확인:

교차 계정 배포의 경우 Argo CD 캐퍼빌리티 역할이 대상 클러스터에 접근 항목이 있는지 확인하세요. 관리형 캐퍼빌리티는 IAM 역할 가정이 아니라 EKS 접근 항목을 사용해 교차 계정 접근을 처리합니다. 멀티 클러스터 구성에 대한 자세한 내용은 대상 클러스터 등록을 참고하세요.

애플리케이션 동기화 시간 증가

애플리케이션이 동기화되지만 예상보다 오래 걸린다면 다음 진단 단계를 사용해 원인을 파악하세요.

마지막 동기화 시간 확인

애플리케이션이 마지막으로 동기화된 시점을 검토해 지연을 확인합니다.

# View last sync time for all applications
kubectl get application -n argocd -o jsonpath='{range .items[*]}{.metadata.name}{"\t"}{.status.operationState.finishedAt}{"\n"}{end}'

# View last sync time for a specific application
kubectl get application my-app -n argocd -o jsonpath='{.status.operationState.finishedAt}'

애플리케이션 조건 확인

리컨실리에이션 큐 지연이 있는지 애플리케이션 조건을 검토합니다.

# Check conditions on an application
kubectl get application my-app -n argocd -o jsonpath='{.status.conditions}'

targetRevision 구성 확인

targetRevision: HEAD를 사용하는 애플리케이션은 리포지토리에 대한 모든 커밋에서 매니페스트 캐시를 무효화하므로 동기화 시간이 느려집니다.

# List applications using HEAD as targetRevision
kubectl get application -n argocd -o jsonpath='{range .items[?(@.spec.source.targetRevision=="HEAD")]}{.metadata.name}{"\n"}{end}'

일반적인 원인:

  • 웹훅 미구성 - 웹훅이 없으면 Argo CD가 기본 간격 6분으로 리포지토리를 폴링합니다. 이로 인해 새 커밋 감지가 지연됩니다.
  • targetRevision이 HEAD로 설정 - 리포지토리에 대한 모든 커밋이 매니페스트 캐시를 무효화합니다. Argo CD는 각 리컨실리에이션에서 매니페스트를 다시 생성합니다.
  • 크거나 복잡한 Git 리포지토리 - 처리할 파일과 템플릿이 많아서 모노레포나 복잡한 Helm 차트가 느린 매니페스트 생성을 유발합니다.
  • 단일 애플리케이션의 많은 Kubernetes 리소스 - 많은 리소스를 관리하는 애플리케이션은 Argo CD가 각 리소스의 상태를 추적해야 하므로 클러스터 캐시 동기화가 느려집니다.

완화 방법:

  • Git 웹훅 구성 - 웹훅이 변경이 푸시될 때 Argo CD에 즉시 알려 기본 폴링 간격을 우회합니다. 구성 단계는 Argo CD 고려 사항을 참고하세요.
  • 특정 브랜치 이름 또는 커밋 SHA 사용 - 동기화 사이에 매니페스트 캐시를 보존하려면 targetRevision을 HEAD 대신 브랜치 이름이나 커밋 SHA로 설정하세요.
  • 큰 모노레포 분할 - 큰 리포지토리를 더 작고 집중된 리포지토리로 나누어 매니페스트 생성 시간을 줄이세요.
  • 애플리케이션당 리소스 감소 - Kubernetes 리소스가 많은 애플리케이션을 여러 개의 더 작은 애플리케이션으로 분할해 클러스터 캐시 동기화 시간을 줄이세요.
  • 컨트롤러 로그 전달 활성화 - 컨트롤러 로그가 리컨실리에이션 동작과 큐 처리를 관찰할 수 있게 해줍니다. 구성 단계는 EKS 캐퍼빌리티 컨트롤러 로그 접근을 참고하세요.

애플리케이션이 반복적으로 동기화되거나 out of sync에 머무름

애플리케이션이 동기화된 후 즉시 OutOfSync가 되거나 동기화 루프에 빠진 경우, 원인은 보통 Git이 정의하는 것과 클러스터에 존재하는 것 사이의 드리프트입니다. 기본 진단부터 시작하세요.

진단 정보 수집:

# View current sync and health status
argocd app get my-app

# Show exact fields that differ between Git and live state
argocd app diff my-app

# Check whether the app has ever reached a stable state
argocd app history my-app

argocd app diff 명령이 가장 유용한 출발점입니다. 애플리케이션이 out of sync로 보이게 만드는 정확한 필드를 보여줍니다.

자체 관리 인증서로 인한 드리프트

cert-manager, OPA Gatekeeper, KEDA 같은 컨트롤러는 런타임에 인증서를 생성합니다. 이 런타임 값은 Git에 없으므로 Argo CD는 모든 리컨실리에이션에서 드리프트를 감지합니다.

증상은 다음과 같습니다.

  • 애플리케이션이 동기화된 후 즉시 OutOfSync 표시
  • diff가 웹훅 caBundle 필드나 TLS Secret data 필드의 변경을 보여줌

이를 해결하려면 영향을 받는 필드에 ignoreDifferences를 추가하고 동기화 옵션에서 RespectIgnoreDifferences를 활성화하세요.

apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: my-app
spec:
  ignoreDifferences:
    - group: admissionregistration.k8s.io
      kind: ValidatingWebhookConfiguration
      jsonPointers:
        - /webhooks/0/clientConfig/caBundle
    - group: ""
      kind: Secret
      jsonPointers:
        - /data/tls.crt
        - /data/tls.key
  syncPolicy:
    syncOptions:
      - RespectIgnoreDifferences=true

자가 치유가 느리게 시작하는 워크로드를 방해함

selfHeal이 활성화되면 Argo CD는 드리프트를 감지할 때 애플리케이션을 다시 동기화합니다. 워크로드가 시작되는 데 30~60초가 걸리면 워크로드가 Healthy가 되기 전에 자가 치유가 트리거됩니다. prune이 활성화되면 부분적으로 시작된 리소스를 철거할 수 있습니다.

이를 해결하려면 먼저 기본 드리프트를 수정하세요(인증서 시나리오 참고). 드리프트가 원인이 아니라면 Git을 통해서만 관리하는 워크로드에 대해 자가 치유를 비활성화하는 것을 고려하세요.

apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: my-app
spec:
  syncPolicy:
    automated:
      selfHeal: false
      prune: false

참고

자가 치유 백오프 타이밍은 인스턴스 수준 컨트롤러 설정입니다. 자가 치유를 비활성화하는 대신 자가 치유 타이밍을 조정해야 한다면 AWS Support 케이스를 여세요.

ApplicationSet 또는 리소스 소유권 충돌

두 개의 Application 또는 ApplicationSet이 같은 Kubernetes 리소스를 관리하면 Argo CD가 SharedResourceWarning을 표시합니다. 리소스는 안정 상태에 도달하지 못합니다. 이는 공유 리소스 이름이 환경이나 클러스터별로 범위를 지정하지 않을 때 흔히 발생합니다.

이를 해결하려면:

  • 경쟁하는 리소스를 소유자별로 고유하게 만드세요. 리소스 이름에 환경 또는 클러스터 접미사를 추가하세요.
  • ApplicationSet 이름을 바꿀 때 기존 리소스의 파괴적 철거를 피하려면 먼저 preserveResourcesOnDeletion: true를 설정하세요.
apiVersion: argoproj.io/v1alpha1
kind: ApplicationSet
metadata:
  name: my-appset
spec:
  syncPolicy:
    preserveResourcesOnDeletion: true

리소스 finalizer로 인한 삭제 중단

애플리케이션이 Terminating 상태에 멈추거나 "N objects remaining for deletion"을 표시하면, resources-finalizer.argocd.argoproj.io finalizer가 모든 관리 리소스가 삭제될 때까지 제거를 차단합니다. 처리할 수 없는 자체 finalizer가 있는 관리 리소스는 삭제를 무기한 차단합니다.

확인하려면 삭제 타임스탬프가 있지만 제거되지 않은 리소스를 나열하세요.

kubectl get all -n my-namespace -o json | \
  jq '.items[] | select(.metadata.deletionTimestamp != null) | {name: .metadata.name, kind: .kind, finalizers: .metadata.finalizers}'

이를 해결하려면:

  • 차단 중인 finalizer를 소유한 컨트롤러가 정상 상태로 실행 중인지 확인하세요.
  • 소유 컨트롤러가 정상이지만 finalizer가 처리되지 않는다면, 멈춘 리소스에서 차단 중인 finalizer를 제거하세요.
  • 이전 명령이 출력한 finalizer 목록을 사용해 유지하려는 finalizers만 목록으로 설정하고 차단 중인 것만 뺍니다. finalizer-a와 finalizer-b를 해당 이름으로 바꾸세요.
kubectl patch resource-kind
            resource-name -n my-namespace \
  --type merge -p '{"metadata":{"finalizers":["finalizer-a","finalizer-b"]}}'

차단 중인 finalizer가 리소스의 유일한 finalizer라면 빈 목록을 전달하세요: --type merge -p '{"metadata":{"finalizers":[]}}'.

경고

finalizer 목록을 위치로 항목을 제거하는 대신 명시적으로 설정하세요. 리소스는 둘 이상의 컨트롤러에서 finalizer를 가질 수 있습니다. finalizer는 보장된 순서가 아닙니다. 첫 항목을 제거하면 잘못된 finalizer가 삭제되어 차단 중인 finalizer가 남아 리소스가 여전히 멈출 수 있습니다.

finalizer 제거는 소유 컨트롤러가 수행했을 정리 작업도 건너뛰므로, 클러스터에 기록 없이 AWS 리소스가 남을 수 있습니다. 소유 컨트롤러가 finalizer를 처리할 수 없다는 것을 확인한 후에만 이 작업을 수행하세요.

실패한 동기화가 같은 리비전을 자동 재시도하지 않음

특정 리비전으로의 동기화가 실패한 후 Argo CD는 같은 리비전을 자동 재시도하지 않습니다. 이는 중복 환경 변수 키로 인한 ComparisonError 같은 매니페스트 결함 때문에 흔히 발생합니다.

애플리케이션 상태를 확인해 확인합니다.

argocd app get my-app
# Look for: Operation: Sync  Phase: Failed  Revision:

이를 해결하려면 Git 리포지토리의 매니페스트 결함을 수정하고 새 커밋을 푸시하세요. 또는 수동 동기화를 트리거하세요.

argocd app sync my-app

모노레포 커밋 변동이 광범위한 재생성을 유발

많은 애플리케이션이 같은 리포지토리의 HEAD를 추적하면, 해당 리포지토리에 대한 어떤 커밋도 모든 애플리케이션의 HEAD를 변경합니다. 이는 파일이 변경되지 않은 애플리케이션까지 포함해 모든 애플리케이션에 매니페스트 재생성을 트리거합니다. targetRevision과 캐싱에 대한 자세한 내용은 이 페이지의 "애플리케이션 동기화 시간 증가" 섹션을 참고하세요.

재생성을 각 애플리케이션이 사용하는 파일로만 한정하려면 manifest-generate-paths 어노테이션을 추가하세요.

apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: my-app
  annotations:
    argocd.argoproj.io/manifest-generate-paths: /apps/my-app
spec:
  source:
    repoURL: https://github.com/my-org/my-monorepo.git
    targetRevision: HEAD
    path: apps/my-app

이 어노테이션을 사용하면 Argo CD는 지정된 경로 아래의 파일이 변경될 때만 매니페스트를 재생성합니다. 애플리케이션 간 공유 라이브러리의 경우 세미콜론(;)으로 구분해 여러 경로를 지정할 수 있습니다. 가능하면 targetRevision을 HEAD 대신 브랜치 이름이나 태그로 고정하세요.

Kubernetes 기본값 지정과 뮤테이팅 웹훅으로 인한 가짜 diff

애플리케이션이 동기화 직후 OutOfSync를 표시하면, 설정하지 않은 필드(예: terminationGracePeriodSeconds, dnsPolicy, /spec/replicas)의 diff를 확인하세요. Kubernetes API 서버나 뮤테이팅 웹훅이 적용 시점에 해당 필드를 추가했습니다.

다른 컨트롤러가 관리하는 필드(HPA가 확장을 관리할 때 /spec/replicas 같은)의 경우 ignoreDifferences를 추가하세요.

apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: my-app
spec:
  ignoreDifferences:
    - group: apps
      kind: Deployment
      jsonPointers:
        - /spec/replicas
  syncPolicy:
    syncOptions:
      - RespectIgnoreDifferences=true

Kubernetes 기본값 지정이나 뮤테이팅 웹훅이 추가한 필드의 경우 애플리케이션에서 서버 측 diff를 활성화할 수 있습니다.

apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: my-app
  annotations:
    argocd.argoproj.io/compare-options: ServerSideDiff=true,IncludeMutationWebhook=true

서버 측 diff는 리소스별로 드라이 런 적용을 수행하므로 Kubernetes API 서버에 대한 부하가 증가합니다. 널리 활성화하기 전에 적은 수의 애플리케이션에서 테스트하세요.

고변동 컨트롤러 소유 리소스

일부 컨트롤러는 대량의 단기 수명 또는 자주 업데이트되는 리소스를 생성합니다. 예로는 Karpenter 노드 객체, Cilium identity 및 endpoint 객체, Kyverno policy reports가 있습니다. 이 리소스들이 많은 양의 watch 이벤트를 생성해 동기화 변동을 유발한다면 해당 리소스 종류를 제외하거나 watch 이벤트를 필터링해 부하를 줄일 수 있습니다. 이러한 변경에는 인스턴스 수준 컨트롤러 구성이 필요합니다.

관리형 캐퍼빌리티에서는 이 리소스 종류에 대한 리소스 제외 또는 watch 이벤트 필터링을 요청하려면 AWS Support 케이스를 여세요.

모범 사례

  • 애플리케이션 diff를 먼저 사용 - 반복되는 동기화 문제에 대한 첫 진단 단계로 argocd app diff를 실행하세요. 드리프트의 정확한 원인을 보여줍니다.
  • 좁은 ignoreDifferences 선호 - 특정 리소스 종류의 특정 필드를 대상으로 삼으세요. 실제 구성 드리프트를 가릴 수 있는 광범위한 무시 규칙을 피하세요.
  • ignoreDifferences와 RespectIgnoreDifferences 짝짓기 - 항상 RespectIgnoreDifferences=true 동기화 옵션을 추가하세요. 이 옵션이 없으면 동기화가 무시된 필드를 여전히 덮어씁니다.
  • 리소스 이름 고유하게 유지 - Application 또는 ApplicationSet 간의 소유권 충돌을 피하기 위해 리소스 이름을 환경과 클러스터별로 범위를 지정하세요.
  • prune과 selfHeal에 주의 - 시작 시간이 오래 걸리는 워크로드에서는 둘 다 활성화하지 마세요. 자가 치유가 리소스가 정상이 되기 전에 철거할 수 있습니다.
  • targetRevision 고정과 매니페스트 경로 범위 지정 - 크고 공유되는 리포지토리의 애플리케이션에는 HEAD 대신 브랜치나 태그를 사용하고 manifest-generate-paths 어노테이션을 추가하세요.

AWS Support에 문의해야 하는 경우

다음 상황에서는 AWS Support 케이스를 여세요.

  • 인스턴스 수준 컨트롤러 튜닝이 필요한 것 같을 때(프로세서 수, 자가 치유 타이밍 또는 리소스 제외)
  • 앱 수에 비해 repo-server나 컨트롤러 용량이 부족해 보일 때
  • 워크로드 구성, 드리프트, 소유권, finalizer가 동작을 설명하지 못할 때

지원 케이스에 영향을 받는 애플리케이션의 argocd app get과 argocd app diff 출력을 포함하세요.

다음 단계

  • Argo CD 고려 사항 - Argo CD 고려 사항과 모범 사례
  • Argo CD 사용하기 - Argo CD Application 생성 및 관리
  • 대상 클러스터 등록 - 멀티 클러스터 배포 구성
  • EKS 캐퍼빌리티 문제 해결 - 일반적인 캐퍼빌리티 문제 해결 안내

더 알아보기 (Learn more)