ArgoCD 아키텍처 구성을 먼저 보여드리면…
[출처] https://inf.run/ZuQ8b
아래의 내용은 대규모 환경에서도 빠르게 안정적으로 작동하는 ArgoCD 에 대한 경험 기고글에 대한 정보를 정리한 것입니다. [출처] https://saikiranpikili.medium.com/make-your-argocd-super-fast-9c75fa94b840
스케일 문제 이해하기
ArgoCD는 작은 환경에서는 뛰어난 성능을 발휘하지만, 수천 개의 애플리케이션을 다루려면 세심한 튜닝이 필요합니다. 일반적으로는 중요한 환경과 그렇지 않은 환경을 나누어 여러 ArgoCD 인스턴스로 분산하는 것이 최선의 방법이지만, 시간 제약으로 인해 우리는 모든 것을 하나의 인스턴스로 통합해야 했습니다.
이 때문에 저장소 서버 성능부터 컨트롤러 동시성까지 ArgoCD의 모든 계층을 최적화해야 했습니다.
ArgoCD 구성 최적화
각 최적화를 나누어 그 역할, 기본값, 그리고 부작용까지 살펴보겠습니다.
Reposerver:
- name: ARGOCD_EXEC_TIMEOUT
value: "180"
- name: ARGOCD_GIT_ATTEMPTS_COUNT
value: "3"
- name: ARGOCD_HELM_ALLOW_CONCURRENCY
value: "true"
Controller:
- name: ARGOCD_CONTROLLER_REPLICAS
value: "3"
- name: ARGOCD_K8S_CLIENT_QPS
value: "150"
- name: ARGOCD_K8S_CLIENT_BURST
value: "300"
Argocd-cm:
timeout.reconciliation: 6m
timeout.hard.reconciliation: 0s
params-cm:
server.repo.server.timeout.seconds: "180"
controller.status.processors: "600"
controller.operation.processors: "300"
controller.repo.server.timeout.seconds: "180"
controller.kubectl.parallelism.limit: "100"
controller.sharding.algorithm: "round-robin"
reposerver.parallelism.limit: "100"
1. 저장소 서버(Repository Server) 설정
매니페스트 생성 타임아웃과 Git 재시도 횟수 최적화
-
ARGOCD_EXEC_TIMEOUT
Repo 서버는 helm, kustomize 등을 실행하기 위해 “exec”를 사용합니다. 큰 규모의 helm 차트 매니페스트를 생성할 때 시간이 오래 걸릴 수 있습니다. 이 때문에 기본값을 늘려주었습니다.- 설명: 명령어가 타임아웃되기 전까지 실행할 수 있는 최대 시간(초 단위)
- 기본값: 90초
- 설정값: 180초
-
ARGOCD_GIT_ATTEMPTS_COUNT
Repo 서버는 commit SHA 해시를 확인하기 위해 “git ls-remote”를 사용합니다. 기본값은 1이며, 첫 시도가 실패하면 재시도를 하지 않습니다. 그래서 시도 횟수를 3으로 늘렸습니다.- 설명: Git 작업에 대한 재시도 횟수를 지정
- 기본값: 1
- 설정값: 3
-
ARGOCD_HELM_ALLOW_CONCURRENCY
차트가 많고 매니페스트 생성이 느릴 경우, 차트 폴더에.argocd-allow-concurrency파일을 추가할 수 있습니다.
단, 템플릿 간 종속성이 없는지 반드시 확인해야 합니다.- 설명: Helm 작업의 동시 실행을 허용
- 기본값: false
- 설정값: true
이를 활성화하면 여러 Helm 기반 애플리케이션을 동시에 동기화할 때 성능이 개선됩니다. 다만, 과도한 동시 실행은 클러스터 내 자원 경쟁, Helm 차트 잠금(lock) 문제, Git 프로세스 문제를 일으킬 수 있습니다.
2. 컨트롤러(Controller) 설정
-
ARGOCD_CONTROLLER_REPLICAS
이 값을 변경하기 전에 Controller StatefulSet의 replicas 수도 함께 변경해야 합니다.- 설명: 컨트롤러 컴포넌트의 replica 수를 설정합니다.
- 기본값: 1
- 설정값: 3
Replica 수를 늘리면 부하 분산과 중복성이 향상됩니다. 단, 추가 Pod을 지원할 수 있는 충분한 클러스터 자원이 필요합니다.
-
ARGOCD_K8S_CLIENT_QPS
초당 Kubernetes API 요청 수를 제한합니다.- 기본값: 50
- 설정값: 150
값을 높이면 대규모 애플리케이션 동기화 시 병목 현상을 줄일 수 있지만, Kubernetes API 서버에 부담을 줄 수 있습니다. 서버가 증가한 부하를 처리할 수 있는지 모니터링이 필요합니다.
-
ARGOCD_K8S_CLIENT_BURST
Kubernetes API에 보낼 수 있는 최대 버스트 요청 수를 정의합니다.- 기본값: 100
- 설정값: 300
버스트 한도를 늘리면 스파이크 상황에서 동기화 속도가 빨라집니다. 하지만 서버 용량을 초과하면 API 서버에서 throttling이 발생할 수 있습니다.
3. 설정 맵(argocd-cm) 업데이트
-
timeout.reconciliation
자동 동기화 시도 간격을 설정합니다.- 기본값: 3분
- 설정값: 6분
값을 약간 늘리면 동기화 빈도가 줄어들어 애플리케이션 변경이 잦은 시기에 컨트롤러 부하를 완화할 수 있습니다.
자동 동기화가 활성화된 애플리케이션의 경우, 재조정(reconciliation) 대기열이 이 시간 간격마다 초기화됩니다. 애플리케이션 수가 많아 타임아웃 내에 동기화를 완료하지 못하면 재조정이 반복적으로 리셋되며 진행되지 않는 문제가 발생할 수 있습니다. 이를 피하기 위해 timeout.reconciliation 값을 늘렸습니다. 이 값을 변경할 때는 자동 동기화 주기 자체가 늘어난다는 점을 감안해야 합니다.
-
timeout.hard.reconciliation
재조정 작업에 대해 강제 타임아웃을 설정합니다.- 기본값: 0초 (비활성화)
- 설정값: 0초 (변경 없음)
비활성 상태를 유지하면 재조정 작업이 중간에 강제로 종료되지 않습니다.
4. 파라미터 설정 맵(params-cm) 업데이트
매니페스트 생성 시간을 최적화하기 위해 타임아웃을 늘려야 합니다.
-
controller.repo.server.timeout.seconds
Application Controller에서 “Context deadline exceeded” 에러가 발생하는 경우(대규모 매니페스트에서 흔히 발생), 지정된 시간 안에 repo 서버로부터 매니페스트를 가져오지 못했음을 의미합니다.- 기본값: 60초
- 설정값: 180초
타임아웃을 늘리면 컨트롤러의 refresh 대기열이 넘칠 수 있습니다.
-
server.repo.server.timeout.seconds
- 설명: 저장소 서버 작업의 타임아웃을 지정합니다.
- 기본값: 60초
- 설정값: 180초
타임아웃을 늘리면 대규모 저장소 동기화에는 도움이 되지만, 실제 장애를 감지하는 데는 지연이 발생할 수 있습니다.
애플리케이션 재조정이나 동기화 속도가 느릴 경우, 상태(status)와 작업(operation) 큐 프로세서를 늘려야 합니다. 이름에서 알 수 있듯, 상태 프로세서는 애플리케이션의 상태(Synced, Health, OutOfSync, Degraded, Unknown, Suspended, Missing, Error 등)를 가져오는 역할을 담당합니다.
-
controller.status.processors
상태 재조정 작업에 사용할 프로세서 수를 설정합니다.- 기본값: 20
- 설정값: 600
프로세서 수를 늘리면 병렬 처리가 향상되지만 CPU와 메모리 자원을 더 많이 소모하게 됩니다.
-
controller.operation.processors
동기화 작업을 관리하는 프로세서 수를 설정합니다.- 기본값: 10
- 설정값: 300
상태 프로세서와 마찬가지로 병렬성을 높이지만, 추가적인 리소스 사용이 발생합니다.
-
controller.kubectl.parallelism.limit
ArgoCD 아키텍처 블로그에서 언급했듯이, ArgoCD는 생성된 매니페스트를 동기화하기 위해 “kubectl apply”를 실행합니다. 때로는 애플리케이션을 동기화한 후에도 속도가 느리게 느껴지거나 로딩만 계속되고 클러스터에 변경 사항이 반영되지 않는 경우가 있습니다. 이런 상황에서는 컨트롤러 리소스와 kubectl 병렬 처리 한도를 늘려야 합니다.
동시에 실행할 수 있는 kubectl 작업 수를 제한합니다.- 기본값: 20
- 설정값: 100
이 값을 늘리면 대규모 배포 관리에 유리하지만 클러스터 리소스를 과부하시킬 수 있습니다.
-
controller.sharding.algorithm
컨트롤러 replica 간에 작업을 분배할 때 사용하는 샤딩 알고리즘을 지정합니다.- 기본값: legacy
- 설정값: round-robin
라운드로빈 알고리즘은 replica 간 작업 분배를 더 균형 있게 해줍니다. 이를 통해 하나의 컨트롤러가 모든 클러스터를 처리하는 대신, 여러 컨트롤러에 클러스터가 분산됩니다.
-
reposerver.parallelism.limit
기본적으로 매니페스트 생성에는 제한이 없습니다. Repo 서버는 모든 매니페스트를 한 번에 생성하려고 하며, 이로 인해 OOMKilled 문제가 발생하거나 매니페스트 생성 속도가 매우 느려질 수 있습니다.
저장소 서버 작업의 동시 실행 수를 제한합니다.- 기본값: 0 (무제한)
- 설정값: 100
마지막 팁으로, 저장소 내 단일 차트만 변경되었을 때 전체 차트에 대한 매니페스트가 다시 생성되는 것을 피할 수 있습니다.
ArgoCD는 기본적으로 매니페스트 캐시를 commit SHA와 함께 Redis에 저장합니다. 동일한 commit SHA가 저장소의 모든 매니페스트와 연결되기 때문에, 파일 하나만 수정해 커밋해도 SHA가 전체에 업데이트되며 ArgoCD는 모든 매니페스트를 다시 생성하려 시도합니다. 이를 피하려면 Application kind에 annotation을 추가할 수 있습니다.
argocd.argoproj.io/manifest-generation-paths: <path-of-the-chart-folder>
이렇게 하면 ArgoCD는 제공된 경로 내 파일이 변경되었을 때만 해당 매니페스트를 생성하도록 인식합니다.
이제 제 ArgoCD는 엄청나게 빨라집니다.
