[분석] ArgoCD 3.0이 선언한 GitOps 새로운 시대: 주요 업데이트 기능 완벽 해부

Tech Story/DevOps & Container

[분석] ArgoCD 3.0이 선언한 GitOps 새로운 시대: 주요 업데이트 기능 완벽 해부

 

 
[ kt cloud Foundation플랫폼팀 이지은 님 ]

📋 요약

GitOps 선도 솔루션 ArgoCD 3.0의 주요 업데이트 기능과 2.x 버전 대비 핵심 변경사항을 상세히 분석합니다.

RBAC 권한 제어, 리소스 추적 방식 개선 등 실무 적용을 위한 마이그레이션 가이드를 제공합니다.

#ArgoCD #GitOps #쿠버네티스 #DevOps #지속적배포


 

[분석] ArgoCD 3.0이 선언한 GitOps 새로운 시대: 주요 업데이트 기능 완벽 해부

최근 GitOps의 선두 주자인 ArgoCD가 드디어 3.0 버전을 출시하며 개발자 커뮤니티의 뜨거운 관심을 받고 있습니다.

ArgoCD는 쿠버네티스 환경에서 가장 널리 사용되는 오픈 소스 지속적 배포(CD) 솔루션으로 자리매김했습니다.

 

이번 메이저 버전 업데이트는 단순한 기능 추가를 넘어, 기존의 2.x 마이너 버전 출시를 중단하고 3.x 버전에 집중하겠다는 전략적 변화를 보여줍니다. 현재 사용 중인 2.14 버전의 패치 릴리즈는 새로운 3.2 버전이 출시될 때까지 계속될 예정입니다.

따라서 이번 글에서는 ArgoCD 3.0에서 달라진 주요 기능과 2.x 버전과의 차이점을 상세히 살펴보도록 하겠습니다.


v2.14 → v3.0


주요 변경 사항

Application 리소스에 대한 정밀 권한 제어(RBAC) 변경

  • 2.x: update 또는 delete 권한을 부여하면 하위 리소스(Deployment) 에도 자동 적용
  • 3.x: update, delete 권한은 Application 자체에만 적용되고, 하위 리소스에는 별도로 update/*, delete/* 권한을 명시적으로 부여해야 함
  • 기존 방식으로 롤백은 argocd-cm ConfigMap에 아래 값을 추가
server.rbac.disableApplicationFineGrainedRBACInheritance: false

 

세분화된 정책의 기본 동작이 변경되어 더 이상 하위 리소스에 적용되지 않습니다. v3 이전에는 애플리케이션에 update 또는 delete 권한을 부여하는 정책이 해당 애플리케이션의 모든 하위 리소스에도 적용되었습니다.

 

v3부터는 update 또는 delete 동작이 애플리케이션 자체에만 적용됩니다. 애플리케이션이 관리하는 리소스에 대한 update/* 또는 delete/* 동작을 허용하려면 새로운 정책을 정의해야 합니다.

 

argocd-cm ConfigMap에서 server.rbac.disableApplicationFineGrainedRBACInheritance 구성 값을 false로 설정하여 v2의 동작을 유지할 수 있습니다.


Logs 리소스가 독립적인 RBAC 항목으로 변경

  • 2.3 이전: application get 권한만 있어도 ArgoCD UI에서 로그 확인 가능
  • 2.4: logs RBAC 기능 추가, 사용을 위해 argocd-cm configmap에서 flag 사용
server.rbac.log.enforce.enable: 'true'
  • 3.x: 위 flag 없이 logs 보기 권한 분리가 default로 적용, pod view의 logs 탭은 users/groups/roles에 명시적인 권한 부여 필요

logs가 Argo CD 2.4에서 새로운 RBAC 리소스로 도입되었습니다. 2.3 이하 버전에서는 applications, get 권한이 있는 사용자에게 자동으로 로그 접근 권한이 부여되었습니다. 2.4 버전에서는 argocd-cm ConfigMap에 server.rbac.log.enforce.enable: 'true' 플래그를 설정하여 로그 RBAC 적용을 활성화할 수 있었습니다.

 

3.0 버전부터는 이 플래그가 제거되었고, 로그 RBAC가 기본적으로 적용됩니다. 따라서 logs, get 권한을 명시적으로 부여하지 않으면 pod 뷰의 logs 탭이 보이지 않습니다.

detection 탐지

  • argocd-cm 에 server.rbac.log.enforce.enable: true 가 설정된 사용자는 영향을 받지 않음
  • argocd-rbac-cm 에 policy.default: role:readonly 또는 policy.default: role:admin 이 설정된 사용자는 영향을 받지 않음
  • argocd-rbac-cm 에 policy.default 가 없고, server.rbac.log.enforce.enable: false 로 설정되어 있거나 argocd-cm 에 이 설정이 없는 사용자는 영향을 받음
  • 업그레이드 전 argocd-cm 에 server.rbac.log.enforce.enable 설정이 있다면 업그레이드 후에는 제거 권고

Remediation 수정

  • Quick Remediation (global change)
    • 기존 기본 정책과 사용자 지정 역할이 있는 사용자는 policy.csv에 다음을 추가: p, role:<YOUR_DEFAULT_ROLE>, logs, get, /, allow
    • 기본 정책이 없는 사용자는 policy.csv에 다음 정책 및 기본 정책을 추가: p, role:global-log-viewer, logs, get, /, allow role: policy.default: role:global-log-viewer
  • Recommended remediation (per-policy change)
    • application에 정책이 있는 모든 역할에 logs get 정책을 명시적으로 추가
    • 최소 권한 원칙을 유지하기 위해 권장되는 방식으로, 현재 application에 접근하는 방식과 유사하게 로그 접근은 프로젝트 리소스 범위 수준이나 argocd-rbac-cm 레벨에서 부여

Default resource.exclusions configurations

  • Argo CD가 특정 Kubernetes 리소스들을 무시하도록 만드는 규칙
  • Argo CD는 Git 저장소의 코드와 Kubernetes 클러스터의 실제 상태를 비교하면서 클러스터를 관리해요. 그런데 클러스터에는 Argo CD가 직접 관리하지 않는, 즉 Git에 정의되지 않은 리소스들이 끊임없이 생성되고 수정됩니다. 이런 리소스들은 Argo CD의 주요 관리 대상이 아닐 뿐만 아니라, 매우 자주 변경(high churn)되고 수가 많아서(high volume) Argo CD가 이 모든 변화를 감시하려고 하면 시스템에 큰 부담을 줘요.
  • 불필요한 부담을 줄이기 위해, 자주 변경되는 리소스들을 기본적으로 무시하도록 설정, 불필요하게 자주 바뀌는 리소스들은 이제 Argo CD가 신경 쓰지 않도록 해서, 더 빠르고 효율적으로 동작하게 만들었다

ArgoCD manifest 에서 컨트롤러에 의해 생성되고 git에서 관리되지 않는 리소스를 제외하기 위해 argocd-cm 안에 resource.exclusions 기본 설정이 포함. 이 제외는 성능상의 이유로, 높은 볼륨과 빈번한 변경이 있는 리소스를 제외해 관리되는 클러스터의 kubernetes API 서버에 대한 연결 및 부하를 줄여줌.

  • Kubernetes 리소스: Endpoints, EndpointSlice, Lease, SelfSubjectReview, TokenReview, LocalSubjectAccessReview, SelfSubjectAccessReview, SelfSubjectRulesReview, SubjectAccessReview, CertificateSigningRequest, PolicyReport, ClusterPolicyReport
  • Cert Manager: CertificateRequest
  • Kyverno: EphemeralReport, ClusterEphemeralReport, AdmissionReport, ClusterAdmissionReport, BackgroundScanReport, ClusterBackgroundScanReport, UpdateRequest
  • Cilium: CiliumIdentity, CiliumEndpoint, CiliumEndpointSlice

기본 resource.exclusions는 v2 동작을 유지하기 위해 ConfigMap에서 재정의하거나 제거할 수 있음


제거된 Metrics

버전 1.5.0부터 사용이 중단되고 기본적으로 비활성화되었던 argocd_app_sync_status, argocd_app_health_status, argocd_app_created_time 메트릭이 제거 되었고, argocd_app_info 메트릭의 레이블로 사용

detection

버전 1.5.0부터 이 메트릭들은 ARGOCD_LEGACY_CONTROLLER_METRICS 환경 변수가 명시적으로 true로 설정된 경우에만 사용할 수 있었습니다. 만약 이 변수가 true로 설정되지 않았다면, 변경 없이 안전하게 업그레이드할 수 있습니다.

migration

만약 이 메트릭들을 사용하고 있다면, 업그레이드하기 전에 모니터링 대시보드와 알림을 새로운 메트릭과 레이블을 사용하도록 업데이트해야 합니다.


Dex SSO 인증시 RBAC 변경 사항

  • Dex는 다양한 인증시스템(github, ldap…)과 kubernetes(또는 다른 apps)를 연결해주는 ‘인증브로커’ 역할을 하는 프로그램으로 사용자가 로그인할 때 직접 kubernetes에 로그인하는 대신 Dex에 로그인하고 신뢰할 수 있는 사용자 인증 정보를 넘겨줌.
  • 이번 변경의 핵심은, 더 신뢰할 수 있고 안정적인 user_id를 사용하기 위해 sub 대신 federated_claims.user_id라는 값을 RBAC 주체로 사용하게 된 것입니다.

Dex SSO 인증을 사용할 때, 과거에는 인증에서 반환되는 sub 클레임이 RBAC의 subject 로 사용되었습니다. 그러나 이 값은 Dex 내부 구현에 따라 달라질 수 있으며, 주체를 나타내는 불변의 값으로 간주되어서는 안 됩니다.

 

새로운 동작 방식은 Dex로부터 federated:id 스코프를 요청하며, RBAC 주체로 사용되는 새로운 값은 sub 클레임 대신 federated_claims.user_id 클레임을 기반으로 하게 됩니다.

$> echo "ChdleGFtcGxlQGFyZ29wcm9qLmlvEgJkZXhfY29ubl9pZA" | base64 -d
example@argoproj.iodex_conn_i%
# Policies based on the Dex sub claim (wrong)
- g, ChdleGFtcGxlQGFyZ29wcm9qLmlvEgJkZXhfY29ubl9pZA, role:example
- p, ChdleGFtcGxlQGFyZ29wcm9qLmlvEgJkZXhfY29ubl9pZA, applications, *, *, allow

# Policies now based on federated_claims.user_id claim (correct)
- g, example@argoproj.io, role:example
- p, example@argoproj.io, applications, *, *, allow

만약 RBAC 정책에서 Dex의 sub 클레임을 사용하고 있었다면, 동일한 접근 권한을 유지하기 위해 해당 정책들을 업데이트해야 합니다.

사용자에게 필요한 조치

  • 만약 기존에 Dex의 sub 클레임을 사용해 RBAC 정책을 만들었다면, 새로운 user_id 값에 맞게 정책을 수정해야 합니다.
  • 정책에 사용해야 할 올바른 user_id를 찾으려면, 기존의 sub 클레임 값을 디코딩(복호화)해볼 수 있습니다.
  • CLI로 Argo CD에 로그인하는 경우, 새로운 클레임을 포함하는 토큰을 얻기 위해 최신 버전의 CLI를 사용해야 합니다.

argocd-cm에서 레거시 저장소 구성 지원 제거

  • repository 를 secret 에서 관리 (2.14도 동일, 변동 없음)
  • repository 를 argocd-cm에서 설정하던 방식은 오랫동안 deprecated 되었는데, 3.0에서는 아예 제거됨

detection

argocd-cm 에 구성된 저장소가 있는지 확인

kubectl get cm argocd-cm -o=jsonpath="[{.data.repositories}, {.data['repository\.credentials']}, {.data['helm\.repositories']}]"

구성되어 있지 않다면 [, , ] 출력되고, 이 변경 사항의 영향을 받지 않음

Migration

secret 으로 repository 사용 가이드


ApplicationSet의 applyNestedSelectors 중첩 선택자 필드 무시

  • 중첩된 선택자란?: 여러 단계에 걸쳐 리소스를 선택하는 복잡한 필터링 방식입니다. 예를 들어, 특정 레이블을 가진
  • Cluster들을 먼저 선택하고, 그 클러스터들 중 특정 조건을 만족하는 리소스를 다시 선택하는 방식이 '중첩된 선택자'입니다.
  • 이전 방식 (복잡하고 비직관적): ApplicationSet에 중첩된 선택자를 사용할 때, spec.applyNestedSelectors라는 필드를 true로 명시적으로 설정해야만 중첩된 선택자의 필터가 제대로 적용됐습니다. 만약 이 설정을 하지 않거나 false로 두면, 의도와 다르게 작동하는 경우가 있었습니다.
    • spec.applyNestedSelectors 필드는 ApplicationSet에서 중첩된 선택자를 어떻게 적용할지 제어하는 설정입니다. 이 필드는 중첩된 선택자의 필터가 적용되게 할지 말지를 결정하는 역할을 했습니다.
  • 새로운 방식 (간단하고 명확함): spec.applyNestedSelectors 필드가 완전히 무시됩니다. 이제는 이 필드 설정 여부와 관계없이, 중첩된 선택자는 항상 적용됩니다. spec.applyNestedSelectors는 이제 필요 없어진 설정이며, 중첩된 선택자는 항상 활성화된 상태로 동작합니다. 이로 인해 ApplicationSet의 동작이 더 예측 가능하고 간단해졌습니다.

detection

이 변경 사항의 영향을 받는지 확인하려면, ApplicationSet 컨트롤러 로그에서 "ignoring nested selector"라는 문자열을 검색해보세요. 이 문자열이 포함된 로그가 없다면 영향을 받지 않습니다.

kubectl get appsets -o=json | jq -r '.items[] | select(
    .spec.applyNestedSelectors != true and
    .spec.generators[][].generators[][].generators[].selector != null
  ) | .metadata.name'

remediation

applyNestedSelectors가 기본적으로 false이므로, applyNestedSelectors가 명시적으로 true로 설정되지 않은 ApplicationSet의 중첩 셀렉터를 안전하게 제거할 수 있습니다. 셀렉터가 제거된 후에는 안전하게 업그레이드할 수 있습니다. 예를 들어, Argo CD 3.0으로 업그레이드하기 전에 이 ApplicationSet에서 셀렉터를 제거해야 합니다.

apiVersion: argoproj.io/v1alpha1
kind: ApplicationSet
metadata:
  name: guestbook
spec:
  goTemplate: true
  goTemplateOptions: ["missingkey=error"]
  generators:
  - matrix:
      mergeKeys: ['test-key']
      generators:
      - list:
          elements:
          - test-key: 'test-value'
            cluster: staging
          - test-key: 'test-value'
            cluster: production
      - merge:
          generators:
          - list:
              elements:
              - another-key: 'another-value'
          - cluster: {}
-           selector:
-             matchLabels:
-               app: guestbook

  template:
    metadata:
      name: '{{.cluster}}-guestbook'
    spec:
      project: my-project
      source:
        repoURL: https://github.com/infra-team/cluster-deployments.git
        targetRevision: HEAD
        path: guestbook/{{.cluster}}
      destination:
        server: '{{.url}}'
        namespace: guestbook

헬름 버전 업그레이드로 인한 호환성 문제

Helm이 3.17.1 버전으로 업그레이드되었습니다. 이로 인해 subchart의 values.yaml 파일에 null 객체가 포함되어 있는 경우 파일 내용을 수정해야 할 수 있습니다.

  • Helm 3.17.1 이전: values.yaml 파일에 null 객체가 있으면 helm template 실행 시 cannot overwrite table with non table이라는 경고가 발생했습니다. 하지만 결과적인 Kubernetes 객체는 이 유효하지 않은 null 값으로 덮어쓰여지지 않았습니다. 즉, 경고는 있었지만 실제로는 문제가 발생하지 않았습니다.
  • Helm 3.17.1 이후: 동작 방식이 변경되었습니다. values.yaml 파일에 null 객체가 있을 때 helm template을 실행하면 이전과 동일한 경고가 여전히 발생합니다. 그러나, 이제 결과적인 Kubernetes 객체는 유효하지 않은 null 값으로 덮어쓰여집니다.
  • 이 문제를 해결하려면 null 객체 값이 포함된 values.yaml 파일을 찾아서 해당 null 값을 제거해야 합니다.
(예시-문제상황)
# values.yaml
subchart:
  service:
    enabled: true
    port: null  # 이제 이 'null' 값으로 인해 subchart의 기본 포트가 덮어쓰여져 배포가 실패할 수 있습니다.
(예시-올바른 수정)
# values.yaml
subchart:
  service:
    enabled: true
    # 'port: null' 행을 완전히 제거합니다.

null 항목을 제거하면 Helm이 subchart 자체의 values.yaml에 정의된 기본값으로 돌아가게 되어, 의도했던 구성을 유지할 수 있습니다. Helm 3.17.1로 업그레이드하기 전이나 후에 이 조치를 취하여 예상치 못한 배포 문제를 방지해야 합니다.


리소스 동기화를 위한 Annotation 기반 추적 방식이 기본값으로 변경

  • 2.x: argocd.argoproj.io.instance 라벨을 사용해 리소스가 어떤 application에 속하는지 추적
  • 3.x: argocd.argoproj.io/tracking-id annotation 사용, 기존 템플릿에서 ArgoCD와 호환성을 위해 label 기반 방식을 사용 중이었다면 수정 필요
  • 기존 방식으로 롤백: application.instanceLabelKey 설정

Argo CD의 리소스 추적 기본 동작이 라벨 기반에서 어노테이션(annotation) 기반으로 변경되었습니다. 어노테이션 기반 추적은 더 안정적이며, 외부 코드가 추적 라벨을 복사하여 발생하는 오류에 덜 취약합니다.

detection

영향을 받는지 확인하려면 argocd-cm ConfigMap에서 application.resourceTrackingMethod 필드를 확인하세요.

  • 만약 이 필드가 설정되어 있지 않거나 label로 설정되어 있다면, 라벨 기반 추적을 사용하고 있어 영향을 받습니다.
  • 만약 이 필드가 annotation으로 설정되어 있다면, 이미 어노테이션 기반 추적을 사용하고 있으므로 이 변경의 영향을 받지 않습니다.

다음 명령어로 현재 설정을 확인할 수 있습니다.

kubectl get cm argocd-cm -n argocd -o jsonpath='{.data.application\.resourceTrackingMethod}'

remediation

대부분의 사용자는 Argo CD 3.0으로 안전하게 업그레이드하여 어노테이션 기반 추적을 사용할 수 있습니다. 업그레이드 후 다음 동기화(sync) 작업 시 라벨은 어노테이션으로 교체됩니다. 리소스에 라벨이 없더라도 애플리케이션이 out-of-sync로 표시되지 않습니다.

 

[ 고아(Orphaned) 리소스가 발생할 수 있는 잠재적 위험 ]

 

라벨 기반 추적에서 어노테이션 기반 추적으로 전환할 때, 리소스가 고아가 되는 알려진 엣지 케이스가 있습니다. 전환 후 첫 번째 동기화 작업에 리소스 삭제가 포함되면 Argo CD가 해당 리소스가 애플리케이션에 의해 관리되고 있음을 인식하지 못해 삭제하지 못할 수 있습니다.

 

이러한 문제를 피하려면, out-of-sync 상태가 아니더라도 애플리케이션에 대해 동기화(sync) 작업을 한 번 수행하는 것이 좋습니다. 이렇게 하면 다음 동기화 시 고아 리소스 감지 기능이 정상적으로 작동합니다.

 

Argo CD가 관리하지 않는 리소스

일부 사용자는 Argo CD가 관리하지 않는 리소스를 추적하기 위해 라벨 기반 추적에 의존하기도 합니다. 이러한 경우, 추적 라벨 대신 추적 어노테이션을 직접 만들어서 관련 리소스에 적용해야 합니다. 추적 어노테이션 형식은 다음과 같습니다.

argocd.argoproj.io/tracking-id: <앱 이름>:<리소스 그룹>/<리소스 종류>:<리소스 네임스페이스>/<리소스 이름>

클러스터 스코프(cluster-scoped) 리소스의 경우, 네임스페이스는 애플리케이션의 spec.destination.namespace 필드 값으로 설정됩니다.

추적 라벨이나 어노테이션을 수동으로 만들고 적용하는 것은 공식적으로 지원되지 않는 기능이며, Argo CD의 동작이 향후 변경될 수 있습니다. GitOps를 통해 Argo CD로 리소스를 관리하는 것이 좋습니다.

옵트아웃(Opting Out) 방법

만약 어노테이션 기반 추적을 사용할 준비가 되지 않았다면, argocd-cm ConfigMap의 application.resourceTrackingMethod 필드를 label로 설정하여 이 변경 사항을 적용하지 않을 수 있습니다. 현재로서는 라벨 기반 추적 기능을 제거할 계획은 없습니다.


기타 변경사항

cluster.inClusterEnabled: "false" 사용 시 변경 사항

cluster.inClusterEnabled: "false"가 명시적으로 설정된 경우, 기존에 인-클러스터(in-cluster) 클러스터에서 동기화되도록 구성된 애플리케이션들은 이제 Unknown 상태가 되며 리소스를 동기화할 수 없게 됩니다.

  • 새로운 애플리케이션을 인-클러스터 클러스터를 사용하여 생성하는 것은 불가능해집니다.
  • 기존 애플리케이션을 삭제하더라도 이전에 관리했던 리소스들은 삭제되지 않습니다.

인-클러스터 기능을 비활성화하기 전에, 기존 인-클러스터 애플리케이션에 대한 정리(cleanup) 또는 마이그레이션 작업을 수행하는 것이 좋습니다. 만약 마이그레이션 후 정리 작업을 해야 한다면, 일시적으로 인-클러스터 기능을 다시 활성화해야 합니다.

모든 상태 업데이트 및 높은 변동성(high churn) 변형 무시

Argo CD 매니페스트는 이제 argocd-cm에 resource.customizations.ignoreResourceUpdates 에 대한 기본 설정을 포함합니다. 이 설정은 Kubernetes에서 자주 변형되는 일반적인 리소스들을 제외하기 위함입니다. 이러한 변형은 Argo CD에 불필요한 부하를 유발하는 것으로 알려져 있습니다. 감시 대상 리소스가 수정되면, Argo CD는 .status 변경 사항을 항상 무시하게 됩니다.

 

기본 resource.customizations.ignoreResourceUpdates 설정은 v2 동작을 유지하기 위해 ConfigMap에서 재정의하거나 제거할 수 있습니다.

Application CR의 상태(Status) 업데이트 변경

Argo CD에서 각 객체의 헬스 상태(health status)는 예전에는 기본적으로 Application CR의 /status 필드에 저장되었습니다. 이 때문에 Application이 배포한 리소스의 헬스 상태가 자주 변경되면 애플리케이션 컨트롤러에 부하가 걸리곤 했습니다.

 

이제 헬스 상태는 외부 저장소에 저장되도록 변경되었습니다. 만약 이전과 같은 동작을 원한다면, Argo CD의 argocd-cmd-params-cm.yaml ConfigMap에서 controller.resource.health.persist 필드를 true로 설정하여 되돌릴 수 있습니다.

상태를 Application CR에 유지할 때의 예시

status:
  health:
    status: Healthy
    lastTransitionTime: '2025-01-01T00:00:00Z'
  resources:
    - group: apps
      health:
        status: Healthy
      kind: Deployment
      name: my-app
      namespace: foo
      status: OutOfSync
      version: v1
  sync:
    status: OutOfSync

controller.resource.health.persist: false로 설정되어 Application CR에 헬스 상태가 저장되지 않을 경우, status 필드는 다음과 같이 나타납니다.

status:
  health:
    status: Healthy
    lastTransitionTime: '2025-01-01T00:00:00Z'
  resourceHealthSource: appTree
  resources:
    - group: apps
      kind: Deployment
      name: my-app
      namespace: foo
      status: OutOfSync
      version: v1
  sync:
    status: OutOfSync

detection

  1. argocd-cmd-params-cm.yaml ConfigMap 확인: controller.resource.health.persist 설정값을 확인하여 헬스 상태가 Application CR에 저장되는지 판단할 수 있습니다.
  • 이 명령어의 결과가 **비어있거나 true**라면, 헬스 상태는 여전히 Application CR에 저장되고 있습니다.
kubectl get cm argocd-cmd-params-cm -n argocd -o jsonpath='{.data.controller\.resource\.health\.persist}'

argocd app list API는 더 이상 개별 리소스의 헬스 상태를 반환하지 않습니다.

argocd app get <my app> -o json

Migration

argocd_app_list API나 .status.resources[].health 필드를 파싱하는 모든 도구 또는 CLI 명령어를 업데이트해야 합니다.

이제 헬스 상태를 얻기 위해서는 Argo CD CLI 또는 API를 사용해야 합니다.

argocd app get <my app> -o json

플러그인 내의 빈 환경 변수 Empty Environment Variables in Plugins

ArgoCD 3.0에서는, 비어있는 환경 변수들이 이제 설정 관리 플러그인으로 전달됩니다.

apiVersion: argoproj.io/v1alpha1
kind: Application
spec:
  source:
    plugin:
      name: example-plugin
      env:
        - name: VERSION
          value: '1.2.3'
        - name: DATA # Even though this is empty, it will be passed to the plugin as ARGOCD_ENV_DATA="".
          value: ''

ignoreDifferences의 기본 동작 변경

기존의 시스템 레벨 ignoreDifferences 설정이 이제 리소스 업데이트를 무시하는 데에도 자동으로 추가됩니다.

이는 논리적으로 일치하는 동작입니다. 만약 특정 필드의 차이점을 무시하도록 설정했다면, 해당 필드가 변경될 때 애플리케이션에 대한 diff를 생성할 필요가 없기 때문입니다.

 

이 동작을 비활성화하고 v2의 기본 설정을 유지하려면, ignoreDifferencesOnResourceUpdates 값을 false로 설정하면 됩니다.

apiVersion: v1
kind: ConfigMap
metadata:
  name: argocd-cm
data:
  resource.compareoptions: |
    ignoreDifferencesOnResourceUpdates: false

기본으로 status 필드 상태 변경 무시

기본적으로 status 필드를 무시하는 비교 옵션이 crd에서 all 리소스로 변경되었습니다.

 

이는 status 필드의 변경 사항이 더 이상 차이(diff)로 감지되지 않는다는 것을 의미합니다. 만약 의도한 상태(desired state)의 일부로서 status 필드를 사용하고 있었다면, ignoreResourceStatusField 설정을 통해 v2의 기본 동작을 유지할 수 있습니다.

apiVersion: v1
kind: ConfigMap
metadata:
  name: argocd-cm
data:
  resource.compareoptions: |
    ignoreResourceStatusField: crd

CRD의 preserveUnknownFields 필드 기본 무시 설정 제거

spec.preserveUnknownFields는 CRD v1에서 x-kubernetes-preserve-unknown-fields: true로 대체되면서 사용이 중단(deprecated)되었습니다.

 

Argo CD를 통해 배포된 CRD에 spec.preserveUnknownFields: false가 포함되어 있으면 "Out of Sync" 상태가 될 수 있습니다. 이 문제를 해결하려면 CRD의 spec에서 preserveUnknownFields 필드를 제거해야 합니다.

 

이 작업이 완료되기 전까지 애플리케이션이 Out of Sync 상태가 되지 않도록 하려면, 애플리케이션 매니페스트에 다음 설정을 추가하면 됩니다.

spec:
  ignoreDifferences:
    - group: apiextensions.k8s.io
      kind: CustomResourceDefinition
      jsonPointers:
        - /spec/preserveUnknownFields

argocd-cm ConfigMap에서 전역적으로 설정할 수도 있습니다.

resource.customizations.ignoreDifferences.apiextensions.k8s.io_CustomResourceDefinition: |
    jsonPointers:
    - /spec/preserveUnknownFields

[분석] ArgoCD 3.0이 선언한 GitOps 새로운 시대: 주요 업데이트 기능 완벽 해부

v3.0 → v3.1

KubeVersions 변수 수정 제거

Argo CD v3.0까지는 Helm, Kustomize, Plugins에서 kubeVersions의 + 식별자를 제거했습니다. 예를 들어, kubeVersions가 vX.Y.Z+로 전달되면 내부적으로 vX.Y.Z로 변환했습니다. v3.1부터는 이 내부 변환이 완전히 제거됩니다.

감지 (Detection)

영향을 받는지 확인하려면, 사용 중인 kubeVersions를 확인하세요. 만약 + 식별자가 포함된 kubeVersions를 사용하고 있다면, v3.0에서 v3.1로 업그레이드할 때 애플리케이션이 실패할 수 있습니다.

해결책 (Remediation)

원래 + 기호가 제거되었던 이유는 헬름이 이를 지원하지 않았기 때문입니다. 하지만 이제 헬름은 이러한 제약을 강제하지 않으므로, kubeVersions에 +가 포함되어도 앱은 정상적으로 작동해야 합니다.

그러나 Argo CD가 이제 수정되지 않은 kubeVersions를 헬름에 전달하므로, 변경된 kubeVersions로 인해 생성된 매니페스트가 다를 수 있습니다. 추가적인 주의가 필요한 앱의 경우, 자동 동기화(auto-sync)를 비활성화하고 업그레이드한 다음, diff를 확인하고 나서 자동 동기화를 다시 활성화하는 것이 좋습니다.

API --staticassets 디렉터리의 심볼릭 링크 보호

API 서버의 --staticassets 디렉터리(기본값: /app/shared)가 이제 범위를 벗어나는 심볼릭 링크(out-of-bounds symlinks)로부터 보호됩니다. 이는 심볼릭 링크 공격을 방지하기 위함입니다. 만약 --staticassets 디렉터리에 해당 디렉터리 외부에 위치한 곳을 가리키는 심볼릭 링크가 있다면, 3.1 버전부터 500 에러가 반환됩니다.

v1 Actions API 사용 중단 (Deprecation)

/api/v1/applications/{name}/resource/actions 엔드포인트가 사용 중단되고, /api/v1/applications/{name}/resource/actions/v2 엔드포인트를 사용하도록 권장됩니다. 이 엔드포인트는 API 사용자가 애플리케이션 내의 특정 리소스에 대해 사용자 정의 리소스 액션(custom resource action)을 실행할 수 있게 해줍니다.

 

변경 사항

  • 기존 엔드포인트 (v1): 다양한 파라미터를 쿼리 파라미터로 받았습니다. POST 본문은 액션 이름이었습니다.
  • 새로운 엔드포인트 (v2): 모든 파라미터를 JSON 객체 형태의 POST 본문으로 받습니다. 또한, 액션 실행을 위한 파라미터화(parameterize)를 지원하는 새로운 resourceActionParameters 필드를 지원합니다.

기존 엔드포인트는 향후 릴리스에서 제거될 예정이므로, 가능한 한 빨리 새로운 엔드포인트로 마이그레이션해야 합니다. API 클라이언트는 엔드포인트 URL을 변경하고, 쿼리 문자열 파라미터를 JSON 본문으로 전환하면 됩니다.

만약 기존 엔드포인트를 사용하면 API 서버 로그에 다음과 같은 경고 메시지가 표시됩니다:

RunResourceAction was called. RunResourceAction is deprecated and will be removed in a future release. Use RunResourceActionV2 instead.

 

CLI는 새로운 엔드포인트가 지원되지 않으면 기존 엔드포인트로 대체 사용하며, 이때 다음과 같은 경고 메시지를 로그에 남깁니다:

RunResourceActionV2 is not supported by the server, falling back to RunResourceAction.

OIDC 인증 코드 흐름 처리 방식 변경

이전에는 PKCE가 활성화되었을 때, OIDC를 사용한 로그인 과정(인증 코드 흐름)을 UI에서 처리했습니다. PKCE가 비활성화된 경우에는 서버에서 이 흐름을 처리했습니다. 이제 PKCE 활성화 여부와 관계없이 서버가 항상 이 인증 흐름을 처리합니다.

감지 (Detection)

PKCE 사용 여부를 확인하려면 다음 명령어를 실행하세요.

kubectl get cm argocd-cm -o=jsonpath="{.data.oidc\.config}" | grep enablePKCEAuthentication

이 명령어의 결과가 "enablePKCEAuthentication": true라면, PKCE가 사용 중인 것입니다.

해결책 (Remediation)

사용 중인 OIDC 클라이언트의 리디렉션 URI(redirect URIs)에 Argo CD URL의 /auth/callback 엔드포인트(예: https://argocd.example.com/auth/callback)가 포함되어 있는지 확인해야 합니다.

헬름(Helm) 버전 3.18.4로 업그레이드

  • Argo CD v3.1은 번들로 포함된 헬름 버전을 3.18.4로 업그레이드합니다. 릴리스 노트에 따르면, 헬름 3.18에는 호환성 문제가 되는 변경 사항(breaking changes)이 없습니다.

커스터마이즈(Kustomize) 버전 5.7.0으로 업그레이드

  • Argo CD v3.1은 번들로 포함된 커스터마이즈 버전을 5.7.0으로 업그레이드합니다. 릴리스 노트에 따르면, 커스터마이즈 5.7에는 호환성 문제가 되는 변경 사항이 없습니다.

이번 글을 통해 ArgoCD 3.0 버전의 주요 변경점과 개선 사항들을 살펴보았습니다. 기존 2.x 버전의 안정성을 바탕으로 더 강력하고 유연한 기능을 제공하는 3.0 버전은 GitOps 환경을 한 단계 더 발전시킬 것으로 기대됩니다. 특히 플러그인 실행 시 환경 변수가 비어 있어도 안전하게 동작하도록 개선된 점은 실무에서 자주 겪던 오류를 줄여주며, 보안성과 신뢰성을 동시에 확보할 수 있게 했습니다. 또한 멀티 클러스터 관리 기능이 강화되면서, 운영자가 단일 ArgoCD 인스턴스에서 여러 환경을 손쉽게 제어할 수 있어 관리 복잡도가 크게 낮아졌습니다.

 

실제로 kt cloud에서도 OpenStack 배포 자동화를 위해 ArgoCD 3.0을 도입했는데, 이전에는 App of Apps 패턴에서 종종 발생하던 배포 순서 꼬임이나 값 충돌 문제로 인해 롤백이 잦았습니다. 그러나 3.0 버전에서는 동기화 로직과 파라미터 관리가 개선되어 운영 안정성이 한층 강화되었습니다. 또한 Argo CD 3.0에서는 하나의 Application에 여러 Git 소스(sources)를 지정할 수 있게 되면서, 외부 Helm 차트와 내부 values 파일을 분리된 repo에서 관리하면서도 단일 애플리케이션으로 통합 배포할 수 있게 되었습니다. 외부 차트를 그대로 가져오되 값만 커스터마이징하는 작업을 훨씬 효율적으로 처리할 수 있게 개선되었습니다. Helm 차트 배포에서도, UI 또는 선언적 방식으로 Helm 차트를 지정하고, 여러 values 파일을 원하는 순서로 병합할 수 있으며, 누락된 파일은 무시하도록 설정도 가능해 실무에서 유연성과 안전성을 동시에 확보할 수 있습니다

 

이로써 단순한 자동화를 넘어, 팀 단위 협업에서 이력 추적이 명확해지고 배포 파이프라인이 표준화되는 효과를 체감하고 있습니다. 앞으로도 진화하는 쿠버네티스 생태계 속에서 ArgoCD 3.0은 효율적이고 안정적인 배포 자동화를 위한 핵심 축으로 자리잡을 것입니다.


❓ 자주 묻는 질문 (FAQ)


Q. Argo CD 3.0에서 리소스 추적 방식이 라벨(label) 기반에서 어노테이션(annotation) 기반으로 변경된 이유는 무엇인가요?

A. Argo CD 3.0에서는 리소스 추적 방식의 기본값이 라벨 기반(label tracking) 에서 어노테이션 기반(annotation tracking) 으로 변경되었습니다.

이 변경은 리소스 추적의 정확성, 안정성, 확장성을 높이기 위한 조치입니다.

🔹 라벨 복사 및 충돌 문제 방지

  • 기존 라벨 방식(argocd.argoproj.io/instance)은 Helm 차트나 외부 컨트롤러가 라벨을 그대로 복사하는 경우, Argo CD가 해당 리소스를 잘못 추적하는 문제가 있었습니다.
  • 어노테이션은 이러한 라벨 복사 동작의 영향을 받지 않기 때문에 충돌과 오탐을 줄이고, 추적의 일관성을 강화합니다.

🔹 라벨 제약(63자 제한) 해소 및 메타데이터 확장성 향상

  • Kubernetes 라벨 값은 최대 63자 제한이 있어, 리소스 그룹·종류·네임스페이스·이름 등 세부 정보를 모두 포함하기 어렵습니다.
  • 반면 어노테이션은 이런 제약이 없고, 더 많은 메타데이터를 담을 수 있어 복잡한 리소스 관계를 표현하기에 적합합니다.

🔹 새로운 추적 필드 argocd.argoproj.io/tracking-id 도입

  • Argo CD 3.0부터 각 리소스에는 다음과 같은 어노테이션이 추가됩니다.
  • argocd.argoproj.io/tracking-id: my-app:apps/Deployment:default/nginx-deployment
  • 이를 통해 리소스가 어떤 애플리케이션에 속하며, 어떤 종류의 오브젝트인지 명확하게 식별할 수 있습니다.

🔹 기본값 변경이지만 라벨 방식도 선택 가능

  • 3.0 버전부터 기본 추적 방식은 어노테이션(annotation)이지만, 기존 방식이 필요한 경우 argocd-cm ConfigMap에서 다음과 같이 설정할 수 있습니다.
  • application.resourceTrackingMethod: label
  • 또는 application.instanceLabelKey 값을 지정해 기존 라벨(argocd.argoproj.io/instance) 기반 추적 방식으로 롤백할 수도 있습니다.

📚 관련/출처

https://argo-cd.readthedocs.io/en/stable/operator-manual/upgrading/2.14-3.0/#empty-environment-variables-in-plugins

https://github.com/argoproj/argo-cd/releases/tag/v3.0.11

https://argo-cd.readthedocs.io/en/stable/operator-manual/declarative-setup/#repositories

https://argo-cd.readthedocs.io/en/latest/operator-manual/upgrading/3.0-3.1/