본문 바로가기
DevOps/CI.CD

ArgoCD 아키텍처 이해하기 및 여러가지 옵션

by 비어원 2023. 10. 14.
728x90

ArgoCD는 쿠버네티스 환경에서의 GitOps 기반의 CD(Continuously Delivery) 도구이다. 주요 역할은 Git에 저장된 매니페스트를 쿠버네티스 클러스터로 동기화한다. ArgoCD는 이러한 동기화 기능을 마이크로서비스 형태로 제공하고 있으며 ArgoCD를 구성하는 컴포넌트들이 여러가지가 있다. 이번 장에서는 각각의 컴포넌트가 어떤 기능을 담당하는지, ArgoCD가 전반적으로 어떻게 돌아가는지에 대해 알아보자.

Architecture

 

ArgoCD application

ArgoCD Application은 매니페스트가 저장된 Git 또는 Helm 차트와 동기화시킬 쿠버네티스 클러스터 정보를 저장하는 ArgoCD만의 CR(Custom Resource)이다.

 

Application에는 크게 sourcedestination이 저장되어있는데 source에는 Git 레포지토리 또는 Helm chart 정보가 들어있고, destination에는 동기화시킬 쿠버네티스 클러스터 정보가 들어있다.

 

ArgoCD application-controller

ArgoCD applicatio-controller는 Application CR이 생성되거나 변경되는 것에 반응하여 실질적으로 Application에 선언한 Source로부터 매니페스트를 얻은 후 Destination 클러스터에 매니페스트를 반영하는 역할을 담당한다. 매니페스트를 얻기 위해서 repo-server를 사용하고, 매니페스트를 클러스터에 반영하기 위해서 kubernetes apiserver를 사용한다.

 

동작 방식 및 옵션 / ConfigMap 설정

--status-processors, --operation-processors

각 컨트롤러 레플리카는 애플리케이션 조정과 동기화를 위한 두개의 별개의 큐를 사용한다. 각 큐의 프로세서의 개수는 --status-processors--operation-processors 플래그를 통해 설정할 수 있다. ArgoCD 인스턴스가 너무 많은 애플리케이션을 관리한다면 프로세서의 개수를 늘려야 한다. 1000개의 애플리케이션을 기준으로 --status-processors는 50, --operation-processors 는 25로 사용한다.

 

여기서 ArgoCD 관점에서 애플리케이션 조정이란, ArgoCD에서는 Source (Git or Helm)으로부터 매니페스트를 가지고와서 저장하는데 주기적으로 현재 ArgoCD가 가지고 있는 매니페스트 상태와 Source에 저장되어있는 매니페스트 상태가 일치하는지 확인하고, 변경사항이 있다면 변경된 매니페스트를 ArgoCD에 업데이트하는 것을 말한다.

 

애플리케이션 동기화는 ArgoCD가 저장하고 있는 매니페스트를 실제 쿠버네티스 클러스터에 반영하는 것을 말한다. 애플리케이션 동기화가 발생하는 시점은 애플리케이션 조정 후 ArgoCD에서 관리하고 있는 매니페스트가 변경된 경우 또는 쿠버네티스의 리소스가 변경된 경우이다. 실제로 ArgoCD가 관리하는 쿠버네티스 리소스를 kubectl edit 명령어 등으로 수정해도 Source(Git or Helm)에 저장되어있는 값으로 다시 변경된다. 즉, Source의 상태로 유지되는 것이 보장된다.

 

--repo-server-timeout-seconds

일반적으로 애플리케이션 조정 중에는 매니페스트를 생성하는 시간이 가장 많이 소요된다. 컨트롤러의 represh-queue가 넘치지 않도록 하기 위해 --repo-server-timeout-seconds 옵션을 통해 매니페스트 생성 기간을 제한시킬 수 있다. 해당 타임아웃이 넘어가버리면 애플리케이션 조정에서 Context deadline exceeded 에러와 함께 실패한다. 이 에러가 자주 발생한다면 타임아웃을 늘리거나 repo-server 레플리카를 확장하여 해결할 수 있다.

 

timeout.reconciliation

컨트롤러는 기본적으로 매 3분마다 git을 폴링하여 애플리케이션을 조정한다. argocd-cm 컨피그맵에 있는 timeout.reconciliation 값을 설정하여 주기를 변경할 수 있다.

 

HA 구성 (샤딩)

ArgoCD가 많은 클러스터를 관리하는 경우 너무 많은 CPU와 메모리를 사용하여 동기화가 느려질 수 있다. 이런 경우에 컨트롤러의 레플리카를 늘려서 관리할 수 있는데, 컨트롤러 레플리카 개수만큼 샤딩이 되어 각 레플리카마다 관리하는 클러스터가 나눠지게 된다. 예를 들어, 컨트롤러가 3개이면 각각 0, 1, 2번 샤드로 나눠지고 클러스터가 5개라면 0번 레플리카가 2개의 클러스터를 관리, 1번 레플리카가 2개의 클러스터를 관리, 2번 레플리카가 나머지 1개의 클러스터를 관리하게 된다. 그래서 만약 레플리카를 늘리려면 갯수는 관리하는 클러스터보다 작거나 같아야 효과가 있다.

 

샤딩을 하려면 StatefulSet의 레플리카를 늘리고 컨트롤러의 ARGOCD_CONTROLLER_REPLICAS 환경변수의 값을 레플리카 갯수만큼 맞추면 된다. (Helm으로 배포한 경우라면 controller.replicas 값으로 ARGOCD_CONTROLLER_REPLICAS 환경변수가 자동으로 맞춰진다.)

 

application-controller의 샤드 분산 알고리즘은 --sharding-method 파라미터에서 설정할 수 있다. 지원하는 샤딩 메서드는 legacy와 round-robin이다. legacy 모드는 did 기반의 분산 알고리즘을 사용하며 round-robin으은 모든 샤드에 동일한 분포를 사용한다. --sharding-method 파라미터는 argocd-cmd-params-cm 컨피그맵의 controller.sharding.algorithm를 변경하여 적용할 수도 있다. 또는 클러스터 시크릿의 샤드 번호를 포함하도록 변경하여 클러스터를 특정 샤드에 강제로 할당할 수도 있다. 클러스터 정보를 관리하는 시크릿의 data.shard 값에 특정 샤드 번호를 지정하면 된다.

 

ArgoCD repo-server

repo-server는 Application에 저장된 source 정보를 바탕으로 매니페스트를 생성하는 역할을 담당한다. Application의 타입이 git인 경우에는 /tmp 하위에 레포지토리를 클론한다. application-controller가 매 주기별로 git을 폴링한다고 했는데, 실제로 git의 변경사항을 땡겨오는 주체가 repo-server이다.

 

동작 방식 및 옵션

--parallelismlimit

repo-server는 매니페스트를 생성하기 위해 fork/exec 구성 관리 도구를 사용한다. 메모리 부족 또는 쓰레드 수 제한으로 인해 fork가 실패할 수 있다. --parallelismlimit 플래그는 동시에 실행되는 매니페스트 생성 수를 제어하고 OOM kill을 방지하는 데 도움이 된다.

 

Git repo 주의사항

매니페스트 생성 시 helm이나 kustomize 도구를 사용한다면 (ArgoCD Application source 타입이 Helm인 경우) 레포지토리가 clean state인지 확인한다. 만약 Helm 타입의 여러 Application이 같은 Git repo를 바라본다면 repo-server의 성능에 영향을 끼친다.

 

repo-server는 하나의 레포지토리 클론을 로컬에 유지하여 애플리케이션 매니페스트 생성에 사용하는데, 매니페스트 생성 시 로컬 리포지토리 클론의 파일을 변경해야 하는 경우 서버 인스턴스당 하나의 동시 매니페스트 생성만 허용된다. 그래서 같은 레포를 바라보고 있는 Helm 타입의 애플리케이션들은 병렬처리가 되지 않아서 여러 애플리케이션이 포함된 단일 리포지토리가 있는 경우 ArgoCD 속도가 상당히 느려질 수 있다.

 

그리고 repo-server는 레포지토리를 /tmp 하위에 클론한다. 레포지토리에 파일이 아주 많다면 파드는 디스크 공간이 부족하여 문제가 발생할 수 있다. 이 문제를 피하려면 Persistent volume을 마운트하면 된다. 또는 애플리케이션 코드 레포지토리와 매니페스트 파일을 저장하는 레포지토리를 분리해도 좋다.

ARGOCD_GIT_ATTEMPTS_COUNT 환경 변수

repo-servergit ls-remote를 사용하여 HEAD, 브랜치 태그 또는 태그 이름과 같은 모호한 리버전을 해결한다. 이 연산자는 자주 발생하며 실패할 수도 있다. 동기화 실패를 방지하려면 실패한 요청을 다시 시도하기 위해 ARGOCD_GIT_ATTEMPTS_COUNT 환경변수를 적절히 설정하면 된다.

 

--repo-cache-expiration-duration

repo-server는 매 3분마다 ArgoCD 앱 매니페스트의 변경사항을 확인한다. ArgoCD는 기본적으로 레포가 변경될 떄만 매니페스트가 변경된다고 가정하므로 생성된 매니페스트를 캐시한다. 원격 베이스 kustomize 또는 helm patch release를 사용하면 레포지토리가 변경되지 않았더라도 매니페스트가 변경될 수 있다. 캐싱 시간을 줄이면 24시간을 기다리지 않고도 변경 사항을 확인할 수 있다. --repo-cache-expiration-duration을 사용하자. 그리고 저용량 환경에서는 1h를 사용하는 것이 좋다.

 

ARGOCD_EXEC_TIMEOUT 환경변수

repo-server는 helm과 kustomize와 같은 구성 관리 툴을 실행하고 90초의 시간 제한을 적용한다. 이 타임아웃은 ARGOCD_EXEC_TIMEOUT 환경변수를 조절하여 변경할 수 있다.

 

argocd-server

argocd-server는 웹 앱과 RESTful API 서버로 무상태 애플리케이션이며 문제를 일으킬 가능성이 가장 낮다. 업그레이드 중 다운타임이 발생하지 않도록 하려면 복제본 수를 3개 이상으로 늘리고 ARGOCD_API_SERVER_REPLICAS 환경변수에서 이 숫자를 반복하는 것이 좋다.

  • ARGOCD_API_SERVER_REPLICAS 환경변수는 동시 로그인 요청 제한을 나누기 위해 사용된다.
  • ARGOCD_GRPC_MAX_SIZE_MB 환경변수는 서버 응답 메시지의 최대 크기를 지정할 때 사용한다. 기본값은 200이며 3000개 이상의 애플리케이션을 관리할 때 개수를 늘리는 것이 필요할 수 있다.

argocd-dex-server, redis

dex-server는 인메모리 데이터베이스를 사용하며 두개 이상의 인스턴스를 사용하면 일관되지 않은 데이터가 있을 수 있다. redis는 총 3개의 레디스 서버/센티넬만 이해하도록 사전 구성된다.

 

Redis Cache

컨트롤러는 쿠버네티스 watch api를 사용하여 경량 쿠버네티스 클러스터 캐시를 유지한다. 이렇게 하면 애플리케이션 조정 중에 쿠버네티스를 쿼리하지 않아도 되서 성능이 크게 향상된다. 성능의 이유로 컨트롤러는 선호하는 리소스 버전만 모니터링하고 캐시한다. 조정 중에 컨트롤러는 캐싱된 리소스를 기본 설정 버전에서 깃에 저장된 리소스 버전으로 변환해야 할 수 있다. 만약 변환을 지원하지 않아서 kubectl convert 명령어가 실패한다면 컨트롤러는 쿠버네티스 API 쿼리를 사용해서 조정 속도가 느려진다. 이 경우에는 깃에서 선호하는 리소스 버전을 사용하는 것이 좋다.

 

Redis Cache는 필수인가?

Github discussion에서 maintainer가 레디스는 ArgoCD에서 중요한 역할을 담당하고 있어서 필수라고 한다. 아무래도 캐시가 ArgoCD 성능에 아주 중요한 영향이 있어보인다.

https://github.com/argoproj/argo-cd/discussions/6618

 

Is Redis really necessary? · argoproj/argo-cd · Discussion #6618

Hi, There is very little information within the docs regarding the necessity of using redis for caching. According to https://argo-cd.readthedocs.io/en/stable/operator-manual/architecture/#reposito...

github.com

 

argocd-applicationset-controller

applicationset-controller는 ApplicationSet CRD에 대한 지원을 추가하는 쿠버네티스 컨트롤러이다. 컨트롤러/CRD는 다수의 클러스터와 모노레포 내에서 argocd 애플리케이션을 관리할 때 자동화와 유연성 모두 지원하며 멀티테넌트 쿠버네티스 클러스터에서 셀프 서비스 사용이 가능하다.

 

applicationset-controller는 기존 ArgoCD 설치와 함께 작동한다. ArgoCD는 선언형이며 깃옵스 CD 도구이며 개발자가 git 워크플로 내에서 쿠버네티스 애플리케이션 리소스의 배포를 정의하고 제어할 수 있다.

 

ArgoCD와 함께 설치하는 경우 applicartionset-controller는 클러스터 관리자 중심 시나리오를 지원하는 추가 기능을 제공하여 이를 보완한다. applicationset-controller는 다음을 제공한다.

  • 단일 쿠버네티스 매니페스트를 사용하여 ArgoCD로 여러 쿠버네티스 클러스터를 타겟팅할 수 있는 기능
  • 단일 쿠버네티스 매니페스트를 사용하여 ArgoCD로 하나 이상의 깃 레포지토리로부터 여러 애플리케이션을 배포하는 기능
  • 모노레포에 대한 지원 개선 - ArgoCD의 컨텍스트에서 모노레포는 단일 깃 레포지토리 내에 정의된 여러 개의 ArgoCD 애플리케이션 리소스이다.
  • 멀티테넌시 클러스터에서 개별 클러스터 테넌트가 ArgoCD를 사용하여 애플리케이션을 배포하는 기능을 개선한다.

 

참고 자료

https://argo-cd.readthedocs.io/en/stable/operator-manual/high_availability/

 

High Availability - Argo CD - Declarative GitOps CD for Kubernetes

High Availability Argo CD is largely stateless. All data is persisted as Kubernetes objects, which in turn is stored in Kubernetes' etcd. Redis is only used as a throw-away cache and can be lost. When lost, it will be rebuilt without loss of service. A set

argo-cd.readthedocs.io

 

728x90

'DevOps > CI.CD' 카테고리의 다른 글

Jenkins 소개 및 Kubernetes에 설치  (0) 2023.11.07
CI / CD란 무엇일까?  (0) 2023.11.04
ArgoCD를 사용하여 Helm chart 배포하기  (1) 2023.10.13
ArgoCD 소개와 설치  (0) 2023.09.03
GitOps란 무엇인가?  (0) 2023.09.03

댓글