본문 바로가기
삵
Cloud Computing & MSA

Argo CD 3.x로 깨지지 않게 올리기

oopennova·2026년 11월 15일·조회 0

사내 GitOps를 Argo CD로 돌리는 팀이면 올해 한 번쯤 3.x 업그레이드를 미뤄봤을 것이다. 2.14가 2.x 마지막 마이너라 더는 패치가 안 나오고, 보안 공지가 뜰 때마다 3.x로 넘어오라는 안내가 붙는다. 그런데 막상 스테이징에서 올려보면 동기화는 멀쩡해 보이는데 권한이 조용히 막히거나, 리소스가 OutOfSync로 뜨는 지점에서 한 번씩 걸린다. 그 걸리는 자리들을 미리 정리해둔다.

결론부터 말하자면, Argo CD 3.0의 호환성 깨짐은 대부분 기본값 변경에서 온다. RBAC 하위 리소스 권한이 상속되지 않고, 리소스 트래킹이 애노테이션으로 바뀌고, argocd-cm에 넣던 리포지토리 설정이 제거됐다. 각 변경은 argocd-cm의 한 줄로 2.x 동작을 되살릴 수 있으니, 되살릴 것은 되살리고 넘어갈 것만 고쳐서 단계적으로 올리면 된다.

1. 업그레이드 전에 현재 버전과 설정을 떠둔다

3.0은 2.14에서 바로 올리는 것을 전제로 한다. 2.10 같은 구버전을 쓰고 있다면 2.14를 거쳐 올라와야 중간 마이그레이션 로직이 정상 동작한다. 먼저 현재 버전을 확인한다.

$ argocd version --short
argocd: v2.14.5
argocd-server: v2.14.5

되돌릴 거리를 남겨두기 위해 핵심 ConfigMap 세 개를 먼저 백업한다. 3.x에서 기본값이 바뀌는 항목이 전부 이 안에 있다.

$ kubectl -n argocd get cm argocd-cm argocd-rbac-cm argocd-cmd-params-cm -o yaml > argocd-cm-backup.yaml

리포지토리가 Secret이 아니라 argocd-cm에 들어 있는지도 지금 확인해둔다. 아래 4번에서 이 값을 옮겨야 한다.

$ kubectl -n argocd get cm argocd-cm -o jsonpath='{.data.repositories}'
- url: https://github.com/example/manifests
  passwordSecret:
    name: repo-secret
    key: password

2. RBAC 하위 리소스 권한이 더 이상 상속되지 않는다

2.x에서는 Application에 update 권한을 주면, 그 Application이 관리하는 Pod나 Deployment 같은 하위 리소스에 대한 동작(파드 삭제, 롤아웃 재시작 등)까지 자동으로 허용됐다. 3.0에서는 이 상속이 끊겼다. 부모 Application 권한과 하위 리소스 권한을 따로 선언해야 한다.

기준이 되는 설정은 argocd-cm의 server.rbac.disableApplicationFineGrainedRBACInheritance다. 3.0 기본값은 true, 즉 상속을 끈 상태다. 2.x처럼 상속을 유지하려면 false로 명시한다.

apiVersion: v1
kind: ConfigMap
metadata:
  name: argocd-cm
  namespace: argocd
data:
  # 2.x 동작 유지: 하위 리소스 권한 자동 상속
  server.rbac.disableApplicationFineGrainedRBACInheritance: "false"

권장은 상속을 유지한 채로 먼저 3.0에 올라가는 것이다. 업그레이드와 권한 모델 재설계를 한 번에 하면 뭐가 원인인지 구분이 안 된다. 올라간 뒤에 역할별로 하위 리소스 권한을 명시적으로 쪼개는 쪽이 사고 범위가 좁다.

쪼갤 때는 argocd-rbac-cm에서 update/*, delete/* 액션을 따로 추가한다. 예를 들어 dev 역할에 Application 수정과 하위 리소스 수정을 모두 허용하려면 두 줄이 필요하다.

p, role:dev, applications, update, default/*, allow
p, role:dev, applications, update/*, default/*, allow
p, role:dev, applications, delete/*, default/*, allow

같은 맥락에서 로그 조회도 바뀌었다. 2.x에서 선택 사항이던 로그 RBAC가 3.0에서는 항상 켜진다. 기존 server.rbac.log.enforce.enable 설정은 제거됐다. 그래서 UI나 CLI에서 파드 로그가 안 보이면 권한 부족이다. 다음처럼 logs, get 정책을 명시해야 한다.

p, role:dev, logs, get, default/*, allow

policy.default: role:readonly처럼 기본 역할을 깔아둔 환경이라면 readonly에 이미 로그 권한이 들어 있어 영향이 덜하다. 역할을 잘게 나눠 쓰는 곳일수록 로그 정책 누락으로 문의가 들어온다.

3. 리소스 트래킹이 라벨에서 애노테이션으로 바뀐다

리소스 트래킹은 Argo CD가 "이 Pod는 어느 Application이 만든 것인가"를 표시해 두는 방식이다. 2.x 기본값은 라벨(app.kubernetes.io/instance)이었다. 문제는 외부 도구가 이 라벨을 다른 리소스로 복사하면 소유권이 잘못 엮인다는 점이다. 3.0은 기본값을 애노테이션으로 바꿨다. 애노테이션에는 더 많은 정보가 들어가 오인식이 줄어든다.

애노테이션 형식은 이렇다.

argocd.argoproj.io/tracking-id: my-app:apps/Deployment:default/web

여기서 한 가지 함정이 있다. 라벨에서 애노테이션으로 전환한 직후 첫 동기화에서 리소스를 삭제하는 작업이 섞여 있으면, Argo CD가 그 리소스를 자기가 관리하는 것으로 인식하지 못해 삭제하지 않고 남겨둘 수 있다. 애노테이션이 아직 안 붙은 상태에서 삭제 판단이 돌기 때문이다. 그래서 전환 직후에는 리소스를 지우는 변경과 트래킹 방식 전환을 같은 커밋에 넣지 않는 편을 권한다.

트래킹 방식을 그대로 라벨로 두고 올라가려면 argocd-cm에 명시한다.

data:
  application.resourceTrackingMethod: label

라벨로 두면 전환 함정을 피할 수 있지만, 애노테이션의 장점을 못 쓴다. 현장에서는 업그레이드 시점에는 label로 고정해 깨짐 없이 올린 뒤, 운영이 안정되면 별도 변경으로 애노테이션 전환을 잡는 순서가 다루기 쉽다. 전환하는 날에는 전체 Application을 한 번 새로고침해 애노테이션을 다 붙인 다음, 삭제가 포함된 변경을 적용한다.

4. argocd-cm의 리포지토리 설정이 제거된다

2.x에서는 argocd-cm의 repositories, repository.credentials 키에 깃 리포지토리를 선언할 수 있었다. 3.0은 이 방식을 더 지원하지 않는다. 리포지토리는 전부 라벨이 붙은 Secret으로 옮겨야 한다. 1번에서 argocd-cm에 repositories 값이 남아 있었다면 지금 옮긴다.

Secret에는 argocd.argoproj.io/secret-type: repository 라벨을 붙여야 Argo CD가 리포지토리 설정으로 읽는다.

apiVersion: v1
kind: Secret
metadata:
  name: repo-manifests
  namespace: argocd
  labels:
    argocd.argoproj.io/secret-type: repository
stringData:
  url: https://github.com/example/manifests
  password: ghp_xxxxxxxxxxxx
  username: git

적용한 뒤 CLI로 연결 상태를 확인한다. Successful이면 정상이다.

$ argocd repo list
TYPE  NAME  REPO                                      INSECURE  CONNECTION
git         https://github.com/example/manifests      false     Successful

옮기지 않고 3.0으로 올리면 리포지토리 설정이 통째로 무시되면서 Application이 소스에 접근하지 못해 ComparisonError로 떨어진다. 그래서 이 작업은 업그레이드 전에 끝내두는 것이 안전하다. 2.14에서 미리 Secret으로 옮겨도 동작은 동일하므로, 구버전에서 선행 처리하고 올라가면 리포지토리 때문에 멈출 일이 없다.

5. Helm 엔진 교체와 null 값 처리

Helm 쪽은 두 단계로 나뉜다. 3.0에서 번들 Helm이 3.17 계열로 올라갔고, 3.5부터는 차트 렌더링에 쓰는 유일한 Helm 바이너리가 Helm 4로 교체됐다. Application 스펙의 helm.version 필드는 Helm 2 시절 호환용으로만 남아 있어 지금은 지정할 필요가 없다.

엔진이 올라가면서 바뀐 동작 중 실무에서 걸리는 건 null 값 처리다. 예전에는 서브차트의 values.yaml에 null을 넣어도 경고만 났지만, 이제 null이 부모 값을 실제로 덮어써서 지운다. 의도치 않게 리소스 블록이 비어버릴 수 있다.

resources:
  limits:
    cpu: null   # 3.x에서는 상위 값을 제거한다

업그레이드 후 특정 Application만 렌더 결과가 달라졌다면 서브차트 values.yaml의 null부터 의심한다. 값을 지우려던 게 아니라면 해당 키를 통째로 빼는 쪽으로 고친다.

Helm 4로 넘어가는 3.5 이상에서는 차트가 Helm 4 렌더링과 호환되는지도 봐야 한다. 올리기 전에 로컬에서 같은 차트를 helm template으로 돌려 출력이 깨지지 않는지 확인하고 가면 범위를 좁힐 수 있다.

6. 올리는 순서와 되돌릴 자리

정리하면 2.14에서 먼저 리포지토리를 Secret으로 옮기고, argocd-cm에 disableApplicationFineGrainedRBACInheritance: "false"와 resourceTrackingMethod: label을 박아 2.x 동작을 고정한다. 그 상태로 3.0 이미지로 올린다. manifests 설치라면 다음과 같다.

$ kubectl apply -n argocd \
  -f https://raw.githubusercontent.com/argoproj/argo-cd/v3.0.0/manifests/install.yaml
$ kubectl -n argocd rollout status deploy/argocd-server

올라간 뒤 몇 개 Application을 골라 동기화 상태와 로그 접근, 리포지토리 연결을 확인한다.

$ argocd version --short
argocd: v3.0.0
$ argocd app get my-app --refresh
Name:    argocd/my-app
Health:  Healthy
Sync:    Synced

이상이 없으면 그다음 변경으로 RBAC 상속을 끄고 하위 리소스 권한을 역할별로 쪼개고, 또 그다음에 트래킹 애노테이션 전환을 잡는다. 기본값 변경을 한꺼번에 받지 말고 한 축씩 풀면, 문제가 생겨도 되돌릴 자리가 argocd-cm 한 줄로 분명하다. 아직 3.5의 Helm 4 렌더링까지 올릴 계획이라면 보유 차트를 미리 helm template로 한 번 돌려 호환성부터 걸러두는 일이 남는다.

자주 묻는 질문

Argo CD 2.10에서 3.0으로 바로 올려도 되나

권장하지 않는다. 3.0 업그레이드 문서는 2.14에서 올라오는 것을 전제로 한다. 구버전을 쓰고 있다면 먼저 2.14로 올린 뒤 3.0으로 넘어가야 중간 마이그레이션 로직이 정상 동작한다.

3.0으로 올린 뒤 UI에서 파드 로그가 안 보인다

로그 RBAC가 3.0에서 항상 켜지기 때문이다. 2.x에서 선택 사항이던 로그 권한 설정(server.rbac.log.enforce.enable)이 제거됐다. argocd-rbac-cm에 'p, role:역할명, logs, get, 프로젝트/*, allow' 같은 정책을 명시하면 다시 보인다.

리소스 트래킹을 애노테이션으로 바꿨더니 지워야 할 리소스가 안 지워진다

전환 직후 첫 동기화에 삭제 작업이 섞여 있으면 Argo CD가 아직 애노테이션이 없는 리소스를 자기 관리 대상으로 인식하지 못해 남겨둘 수 있다. 전환하는 날에는 전체 Application을 먼저 새로고침해 애노테이션을 붙인 다음, 삭제가 포함된 변경을 따로 적용한다.

argocd-cm에 넣어둔 리포지토리 설정은 어떻게 해야 하나

3.0은 argocd-cm의 리포지토리 설정을 더 지원하지 않는다. argocd.argoproj.io/secret-type: repository 라벨을 붙인 Secret으로 옮겨야 한다. 2.14에서 미리 옮겨두면 업그레이드 시점에 리포지토리 접근 오류가 나지 않는다.

Argo CD에서 Helm 4는 언제부터 쓰나

3.0에서는 번들 Helm이 3.17 계열이고, 차트 렌더링에 쓰는 유일한 Helm 바이너리가 Helm 4로 교체된 것은 3.5부터다. 3.5 이상으로 올릴 때는 보유 차트가 Helm 4 렌더링과 호환되는지 helm template으로 먼저 확인하는 것이 좋다.

관련 글

댓글 0

로그인 후 댓글을 남길 수 있습니다.

아직 댓글이 없습니다.