Skip to content
Published on

ArgoCD 아키텍처 내부 분석: 소스코드 레벨 딥다이브

Authors

1. ArgoCD 전체 아키텍처 개요

ArgoCD는 Kubernetes 환경에서 GitOps를 구현하기 위한 선언적 지속 배포(Continuous Delivery) 도구입니다. CNCF Graduated 프로젝트로, Pull 기반 배포 모델을 통해 Git 저장소에 정의된 원하는 상태와 클러스터의 실제 상태를 지속적으로 동기화합니다.

핵심 컴포넌트

ArgoCD는 다음 5개의 핵심 컴포넌트로 구성됩니다:

  • argocd-server (API Server): 웹 UI, CLI, CI/CD 통합을 위한 gRPC/REST API 제공
  • argocd-repo-server (Repository Server): Git 클론, 매니페스트 생성 담당
  • argocd-application-controller (Application Controller): 애플리케이션 상태 모니터링 및 동기화
  • Redis: 매니페스트 캐시, 세션 데이터 저장
  • Dex: SSO(Single Sign-On) 인증 제공

컴포넌트 간 통신

모든 내부 컴포넌트는 gRPC로 통신합니다:

사용자 (Web UI / CLI / CI)
       |
       v
  API Server (gRPC/REST)
       |
       +-------> Repository Server (gRPC)
       |                |
       +-------> Application Controller
       |                |
       +-------> Redis (TCP)
       |
       +-------> Dex (OIDC)

2. API Server 내부 분석

역할과 책임

API Server는 ArgoCD의 프론트 엔드 역할을 합니다. 외부 요청을 수신하고 내부 컴포넌트에 위임합니다.

gRPC와 REST 이중 인터페이스

API Server는 gRPC를 기본 프로토콜로 사용하며, grpc-gateway를 통해 REST API를 자동 생성합니다:

// API Server의 gRPC 서비스 등록
func (s *ArgoCDServer) Run(ctx context.Context, listeners ...net.Listener) {
    grpcServer := grpc.NewServer(grpcOpts...)
    application.RegisterApplicationServiceServer(grpcServer, s.appService)
    repository.RegisterRepositoryServiceServer(grpcServer, s.repoService)
    project.RegisterProjectServiceServer(grpcServer, s.projectService)
    session.RegisterSessionServiceServer(grpcServer, s.sessionService)
}

주요 gRPC 서비스

서비스설명
ApplicationServiceApplication CRUD, Sync, Rollback
RepositoryServiceGit 저장소 등록/관리
ClusterService대상 클러스터 등록/관리
ProjectServiceAppProject CRUD
SessionService로그인/로그아웃, 토큰 관리
AccountService로컬 사용자 계정 관리

인증 흐름

1. 사용자가 로그인 요청
2. API Server가 Dex에 OIDC 인증 위임 (SSO의 경우)
3. Dex가 외부 IdP (GitHub, LDAP)에 인증 요청
4. 인증 성공 시 JWT 토큰 발급
5. 이후 요청에 JWT 토큰을 Bearer 헤더로 전송
6. API Server가 JWT를 검증하고 RBAC 정책으로 인가 수행

RBAC 모델

ArgoCD의 RBAC은 Casbin 라이브러리를 기반으로 구현되어 있습니다:

# 기본 정책 포맷
p, ROLE, RESOURCE, ACTION, OBJECT, EFFECT

# 예시: proj-admin 역할에 my-project의 모든 application 권한 부여
p, role:proj-admin, applications, *, my-project/*, allow

# 그룹 매핑
g, my-github-team, role:proj-admin

정책은 argocd-rbac-cm ConfigMap에 저장됩니다. 주요 리소스와 액션:

리소스액션
applicationsget, create, update, delete, sync, override, action
repositoriesget, create, update, delete
clustersget, create, update, delete
projectsget, create, update, delete
logsget
execcreate

3. Repository Server 내부 분석

역할과 책임

Repository Server는 Git 저장소에서 소스를 가져오고, 최종 Kubernetes 매니페스트를 생성하는 핵심 컴포넌트입니다.

Git 클론 메커니즘

1. Application Controller가 repo-server에 매니페스트 생성 요청
2. repo-server가 Git 저장소 클론 (shallow clone 기본)
3. 지정된 리비전(branch, tag, commit)으로 checkout
4. 경로 내 매니페스트를 감지하고 적절한 도구로 렌더링
5. 결과를 Application Controller에 반환하고 Redis에 캐시

매니페스트 생성 파이프라인

Repository Server는 다양한 도구를 지원합니다:

// 매니페스트 생성 도구 감지 로직 (간소화)
func detectTool(path string) string {
    if fileExists(path, "Chart.yaml") {
        return "helm"
    }
    if fileExists(path, "kustomization.yaml") ||
       fileExists(path, "kustomization.yml") ||
       fileExists(path, "Kustomization") {
        return "kustomize"
    }
    return "directory" // plain YAML
}

지원 도구별 렌더링 방식:

도구감지 조건렌더링 방식
HelmChart.yaml 존재helm template 실행
Kustomizekustomization.yaml 존재kustomize build 실행
Directory기본YAML 파일 직접 로드
Pluginplugin.yaml 존재CMP sidecar로 위임

Helm 렌더링 프로세스

1. Chart.yaml 파싱으로 차트 메타데이터 확인
2. dependencies가 있으면 helm dependency build 실행
3. values 파일 로드 (기본 values.yaml + 사용자 오버라이드)
4. helm template 명령으로 최종 매니페스트 생성
5. 생성된 YAML을 파싱하고 유효성 검사

Kustomize 렌더링 프로세스

1. kustomization.yaml 파싱
2. bases/resources 참조 해석
3. patches, overlays 적용
4. namePrefix, nameSuffix, labels, annotations 변환
5. 최종 YAML 출력

Config Management Plugin (CMP)

CMP는 사이드카 패턴으로 구현됩니다:

# CMP 설정 예시 - plugin.yaml
apiVersion: argoproj.io/v1alpha1
kind: ConfigManagementPlugin
metadata:
  name: custom-jsonnet
spec:
  version: v1.0
  generate:
    command: [jsonnet]
    args: [main.jsonnet]
  discover:
    fileName: main.jsonnet

CMP 사이드카는 repo-server Pod에 추가되며, Unix 소켓을 통해 통신합니다.

Redis 캐싱 전략

캐시 키: HASH(git-url + revision + path + tool + params)
캐시 TTL: 기본 24시간 (ARGOCD_REPO_SERVER_CACHE_EXPIRATION)
캐시 무효화: Git revision 변경 시

캐시를 통해 동일 리비전에 대한 반복적인 매니페스트 생성을 방지하고, Repository Server의 CPU/메모리 사용량을 크게 줄입니다.

4. Application Controller 내부 분석

역할과 책임

Application Controller는 ArgoCD의 핵심 엔진으로, Kubernetes 리소스를 모니터링하고 동기화를 수행합니다.

Informer 기반 Watch 메커니즘

Application Controller는 Kubernetes의 Informer 패턴을 사용하여 리소스 상태를 효율적으로 추적합니다:

// Informer 기반 리소스 감시 (간소화)
func (c *ApplicationController) watchResources() {
    factory := informers.NewSharedInformerFactory(clientset, resyncPeriod)

    factory.Apps().V1().Deployments().Informer().AddEventHandler(
        cache.ResourceEventHandlerFuncs{
            AddFunc:    c.onResourceAdd,
            UpdateFunc: c.onResourceUpdate,
            DeleteFunc: c.onResourceDelete,
        },
    )
}

Reconciliation Loop

Application Controller의 핵심은 Reconciliation Loop입니다:

반복:
  1. 모든 Application 리소스 조회
  2.Application에 대해:
     a. Repository Server에 원하는 상태(매니페스트) 요청
     b. 대상 클러스터에서 실제 상태 조회
     c. 원하는 상태와 실제 상태 비교 (Diff)
     d. Sync Status 업데이트 (Synced / OutOfSync)
     e. Health Status 업데이트 (Healthy / Degraded / Progressing)
     f. Auto-Sync가 활성화되어 있으면 자동 동기화 실행
  3. 다음 주기까지 대기 (기본 180)

Diff 엔진

ArgoCD의 Diff 엔진은 Kubernetes의 3-way merge를 기반으로 합니다:

비교 대상:
  - Last Applied Configuration (annotation에 저장)
  - Live State (클러스터 실제 상태)
  - Desired State (Git에서 생성된 매니페스트)

Diff 과정:
  1. Live State와 Desired State를 정규화 (normalization)
  2. 기본값 제거 (Kubernetes가 자동 추가하는 필드)
  3. 무시 필드 제외 (resourceVersion, generation 등)
  4. 남은 필드 간 구조적 비교 수행

Normalization (정규화)

Kubernetes는 리소스를 저장할 때 다양한 기본값을 자동 추가합니다. ArgoCD는 이를 정규화하여 불필요한 diff를 방지합니다:

// 정규화 예시
func normalizeResource(resource *unstructured.Unstructured) {
    // metadata에서 관리 필드 제거
    removeFields(resource, "metadata.managedFields")
    removeFields(resource, "metadata.resourceVersion")
    removeFields(resource, "metadata.uid")
    removeFields(resource, "metadata.generation")
    removeFields(resource, "metadata.creationTimestamp")

    // status 필드 제거 (선언적 상태가 아님)
    removeFields(resource, "status")
}

Health Assessment

Application Controller는 각 리소스의 건강 상태를 평가합니다:

상태설명
Healthy리소스가 정상 동작 중
Progressing리소스가 아직 원하는 상태에 도달하지 못함 (롤아웃 진행 중)
Degraded리소스가 비정상 상태 (CrashLoopBackOff 등)
Suspended리소스가 일시 중지됨
Missing리소스가 클러스터에 존재하지 않음
Unknown상태를 판단할 수 없음

Custom Health Check (Lua)

ArgoCD는 Lua 스크립트로 커스텀 Health Check를 정의할 수 있습니다:

-- argocd-cm ConfigMap에 정의하는 커스텀 health check
hs = {}
if obj.status ~= nil then
    if obj.status.conditions ~= nil then
        for _, condition in ipairs(obj.status.conditions) do
            if condition.type == "Ready" and condition.status == "True" then
                hs.status = "Healthy"
                hs.message = condition.message
                return hs
            end
        end
    end
end
hs.status = "Progressing"
hs.message = "Waiting for resource to become ready"
return hs

5. Sync Operation 상세 분석

Sync 실행 흐름

1. 사용자 또는 Auto-Sync가 Sync 트리거
2. Application Controller가 Repository Server에 최신 매니페스트 요청
3. 매니페스트 생성 완료 후 Sync 작업 시작
4. PreSync Hook 실행 (있는 경우)
5. 메인 리소스 동기화 (kubectl apply 동등 작업)
6. PostSync Hook 실행 (있는 경우)
7. Health Check로 리소스 상태 확인
8. Sync Status 업데이트

Resource Ordering

ArgoCD는 Sync Wave와 Phase를 통해 리소스 적용 순서를 제어합니다:

# Sync Wave 예시
metadata:
  annotations:
    argocd.argoproj.io/sync-wave: '-1' # 낮은 번호가 먼저 실행

기본 적용 순서:

  1. Namespace
  2. NetworkPolicy
  3. ResourceQuota
  4. LimitRange
  5. ServiceAccount
  6. Role, ClusterRole
  7. RoleBinding, ClusterRoleBinding
  8. ConfigMap, Secret
  9. Service
  10. Deployment, StatefulSet, DaemonSet
  11. Ingress

Pruning (정리)

Prune은 Git에서 제거된 리소스를 클러스터에서 삭제하는 기능입니다:

Prune 대상 판별:
  1. 클러스터에 존재하는 리소스 목록 조회
  2. ArgoCD tracking label/annotation이 있는 리소스 필터
  3. 현재 Git 매니페스트에 존재하지 않는 리소스 식별
  4. cascade 또는 foreground 삭제 정책에 따라 삭제

6. Redis 내부 분석

역할

Redis는 ArgoCD에서 두 가지 주요 역할을 수행합니다:

캐시 저장소:

  • Repository Server가 생성한 매니페스트 캐시
  • 클러스터 상태 캐시
  • 앱 상태 정보 캐시

세션 스토어:

  • 사용자 로그인 세션
  • JWT 토큰 관련 데이터

캐시 키 구조

app|resources|CLUSTER_URL|NAMESPACE: 리소스 트리 캐시
git|manifest|REPO_URL|REVISION|PATH: 매니페스트 캐시
repo|connection|REPO_URL: 연결 상태 캐시

7. Dex 내부 분석

역할

Dex는 OIDC(OpenID Connect) Identity Provider로, ArgoCD에 SSO 기능을 제공합니다.

지원 커넥터

커넥터설명
LDAPActive Directory 등 LDAP 서버 연동
SAMLSAML 2.0 프로토콜 지원
GitHubGitHub OAuth 인증
GitLabGitLab OAuth 인증
GoogleGoogle OIDC 인증
OIDC범용 OIDC 프로바이더 연동

인증 흐름 상세

1. 사용자가 ArgoCD UI에서 SSO 로그인 클릭
2. API Server가 Dex의 authorization endpoint로 리다이렉트
3. Dex가 설정된 커넥터(GitHub)로 인증 위임
4. 사용자가 외부 IdP에서 인증 수행
5. 외부 IdP가 Dex callback URL로 리다이렉트
6. Dex가 ID Token 생성 (사용자 정보, 그룹 포함)
7. API Server가 ID Token 검증 후 ArgoCD JWT 발급
8. JWT에 사용자 그룹 정보 포함 (RBAC에 활용)

8. AppProject와 접근 제어

AppProject 리소스 구조

AppProject는 ArgoCD의 논리적 격리 단위입니다:

apiVersion: argoproj.io/v1alpha1
kind: AppProject
metadata:
  name: team-alpha
  namespace: argocd
spec:
  description: 'Team Alpha의 프로젝트'
  # 허용 소스 저장소
  sourceRepos:
    - 'https://github.com/org/team-alpha-*'
  # 허용 대상 클러스터/네임스페이스
  destinations:
    - server: 'https://kubernetes.default.svc'
      namespace: 'team-alpha-*'
  # 생성 가능한 클러스터 리소스 (제한)
  clusterResourceWhitelist:
    - group: ''
      kind: Namespace
  # 네임스페이스 리소스 거부 목록
  namespaceResourceBlacklist:
    - group: ''
      kind: ResourceQuota
    - group: ''
      kind: LimitRange
  # 역할 정의
  roles:
    - name: developer
      description: '개발팀 역할'
      policies:
        - p, proj:team-alpha:developer, applications, get, team-alpha/*, allow
        - p, proj:team-alpha:developer, applications, sync, team-alpha/*, allow
      groups:
        - team-alpha-devs

제한 항목

제한설명
sourceRepos사용 가능한 Git 저장소 URL 패턴
destinations배포 가능한 클러스터와 네임스페이스
clusterResourceWhitelist생성 가능한 클러스터 스코프 리소스
namespaceResourceBlacklist생성 불가한 네임스페이스 스코프 리소스
signatureKeys필수 GPG 서명 키
syncWindows동기화 허용/금지 시간대

9. gRPC 통신 아키텍처

내부 통신 흐름

Application Controller
  --gRPC--> Repository Server (매니페스트 생성 요청)
  --gRPC--> API Server (상태 업데이트)

API Server
  --gRPC--> Repository Server (저장소 검증)
  --HTTP--> Dex (인증)
  --TCP---> Redis (캐시/세션)

Repository Server
  --TCP---> Redis (매니페스트 캐시)
  --HTTPS--> Git Server (저장소 클론)

TLS 설정

컴포넌트 간 gRPC 통신은 기본적으로 TLS로 보호됩니다:

- API Server가 TLS 인증서를 생성하고 관리
- 각 컴포넌트는 argocd-server-tls Secret에서 인증서 로드
- mTLS(상호 TLS)는 선택적으로 활성화 가능

10. 정리

ArgoCD의 아키텍처를 요약하면 다음과 같습니다:

  1. API Server: 외부 인터페이스 + 인증/인가 게이트웨이
  2. Repository Server: 매니페스트 생성의 단일 책임 (Helm, Kustomize, Plain YAML, CMP)
  3. Application Controller: 상태 감시 + 동기화 실행의 핵심 엔진
  4. Redis: 성능 최적화를 위한 캐시 계층
  5. Dex: SSO 통합을 위한 인증 브로커

이 컴포넌트들이 gRPC를 통해 긴밀하게 연동되면서 안정적이고 확장 가능한 GitOps 플랫폼을 구성합니다. 다음 포스트에서는 Sync 엔진의 내부 동작을 더 깊이 분석하겠습니다.