Argo CD with Kubernetes
CloudNet@ Gasida님이 진행하는 CI/CD + ArgoCD + Vault Study를 진행하며 학습한 내용을 공유합니다.
이번 포스트에서는 Argo CD를 사용한 CD (Continuous Delivery) 과정에 대해 다루겠습니다.
실습 환경은 Jenkins + ArgoCD 실습 환경 구축의 실습 환경을 사용합니다.
1. Argo CD란?
Argo CD는 Kubernetes 환경에서 GitOps 방식으로 애플리케이션을 지속적으로 배포(Continuous Delivery) 하기 위한 선언적(Declarative) CD 도구입니다.
공식 정의를 한 줄로 정리하면 다음과 같습니다.
Argo CD is a declarative, GitOps continuous delivery tool for Kubernetes.
즉, 애플리케이션의 원하는 상태(Desired State) 를 Git 저장소에 선언적으로 정의해 두고, Argo CD가 Git을 기준으로 Kubernetes 클러스터의 실제 상태를 계속 맞춰 주는 도구입니다.
1.1. GitOps 관점에서 본 Argo CD
Argo CD는 GitOps 패턴에 따라 Git 저장소를 단일 진실 공급원(Single Source of Truth) 으로 사용합니다.
- 애플리케이션 정의, 환경 설정, 인프라 구성은 모두 선언적(Declarative) 으로 작성합니다.
- 이 선언적 구성은 반드시 버전 관리(Version controlled) 되어야 합니다.
- 배포와 라이프사이클 관리는 자동화(Automated), 감사 가능(Auditable), 이해하기 쉬운(Understandable) 형태여야 합니다.
Argo CD는 이 원칙을 따르며, Git에 정의된 상태를 기준으로 클러스터를 자동으로 동기화합니다.
1.2. Kubernetes Manifest 정의 방식
Argo CD에서 사용할 Kubernetes Manifest 는 여러 방식으로 정의할 수 있습니다.
Argo CD는 위와 같은 도구들에 정의 된 내용을 기반으로 결과물(최종 Manifest)을 생성하고, 이를 기반으로 클러스터의 상태를 관리합니다.
2. Argo CD 아키텍처
공식 문서에서 표현하는 전체 구조를 간단히 요약하면 다음과 같이 볼 수 있습니다.
Git -> (DESIRED) Argo CD (LIVE) -> Kubernetes
- Git
원하는 상태(Desired State), 즉 애플리케이션과 인프라 구성이 선언적으로 정의되어 있음 - Argo CD
Git의 상태(Desired)와 클러스터의 실제 상태(Live)를 비교하고, 필요 시 동기화(Sync) 수행 - Kubernetes
실제로 애플리케이션이 실행되는 환경
2.1. 주요 컴포넌트
Argo CD는 여러 컴포넌트가 함께 동작하면서 GitOps CD 파이프라인을 구성합니다.
2.1.1. API Server
Web UI, CLI, CI/CD 시스템과 통신하는 gRPC / REST API 서버
주요 역할
- 애플리케이션 생성, 조회, 상태 확인 등 Application 관리 및 상태 보고
- Sync, Rollback, 사용자 정의 액션 등 애플리케이션 동작(Operation) 수행
- Repository / Cluster 인증 정보 관리 (Kubernetes Secret에 저장)
- 외부 Identity Provider와 연동한 인증(Authentication) / 권한 위임
- RBAC 정책 적용
- Git Webhook 이벤트 리스너 역할
실제로 사용자가 Web UI 혹은 argocd CLI로 수행하는 대부분의 요청은 API Server를 통해 처리됩니다.
2.1.2. Repository Server
Git 저장소와 연결돼 매니페스트를 생성해 주는 내부 서비스
주요 역할
- Git 저장소를 로컬 캐시 형태로 유지
- 다음 입력값을 기반으로 최종 Kubernetes Manifest 생성
- Repository URL
- Revision (commit, tag, branch)
- Application path
- 도구별 설정 (Helm values.yaml, Parameters 등)
- Kustomize/Helm/Jsonnet 등 Config Management Tool을 실행해 최종 YAML 생성
즉, “Git에 정의된 소스 → 실제 적용 가능한 K8s Manifest”로 변환하는 역할을 합니다.
2.1.3. Application Controller
“Git과 클러스터 상태를 비교하고, OutOfSync를 감지 및 조정하는 컨트롤러”
주요 역할
- Kubernetes 클러스터에 배포된 실제 상태(Live State) 를 지속적으로 모니터링
- Git 저장소에 정의된 원하는 상태(Target/Desired State) 와 비교
- 두 상태가 다를 경우
OutOfSync상태로 표시 - 설정에 따라:
- 자동으로 Sync 수행 (자동 동기화)
- 혹은 사용자 승인 후 수동 Sync만 수행
- Sync 라이프사이클에 따라 다음 Hook 호출
PreSync,Sync,PostSync
즉, Application Controller는 GitOps에서 말하는 “폐쇄 루프(Closed Loop) 조정 로직” 을 담당하는 핵심 컴포넌트입니다.
2.1.4. 기타 컴포넌트
- Redis
- K8s API 및 Git 요청을 줄이기 위한 캐시 레이어
- 빈번한 조회에 대한 성능 개선 역할
- Notifications (Argo CD Notifications)
- 특정 이벤트(예: Sync 실패, Health 상태 변경)를 Slack, Email 등으로 알림
- GitOps 파이프라인의 이벤트를 팀에 빠르게 전달
- Dex
- OIDC 등 외부 인증 제공자(IdP)를 추상화하는 인증 프록시
- GitHub, GitLab, OIDC, LDAP, SAML 2.0 등과의 SSO 연동에 사용
- ApplicationSet Controller
- 여러 클러스터 혹은 여러 애플리케이션을 템플릿 기반으로 한 번에 관리
- 예: N개 클러스터에 동일 애플리케이션 배포, 클러스터 목록/ConfigMap/리포지토리 구조 등을 기반으로 Application들을 자동 생성
3. Argo CD 주요 기능
Argo CD가 제공하는 주요 기능을 GitOps 관점에서 정리하면 다음과 같습니다.
- 자동화된 애플리케이션 배포
- 지정된 대상 환경(Target Cluster)으로 애플리케이션을 자동 배포
- 다양한 Config Management 도구 지원
- Kustomize, Helm, Jsonnet, Plain YAML 등 지원
- 멀티 클러스터 관리
- 하나의 Argo CD 인스턴스로 여러 Kubernetes 클러스터에 배포 및 관리 가능
- SSO 통합
- OIDC, OAuth2, LDAP, SAML 2.0, GitHub, GitLab, Microsoft, LinkedIn 등과 연동
- 멀티 테넌시 및 RBAC
- 팀·조직 단위 권한 분리를 위한 RBAC와 멀티 테넌시 지원
- Rollback / Roll-anywhere
- Git에 커밋된 어느 시점으로든 구성 롤백 가능
- Health 상태 분석
- 각 리소스의 Health 상태를 분석해 UI에서 시각화
- Configuration Drift 감지 및 시각화
- Git과 실제 클러스터 간 구성 차이를 자동 감지 및 표시
- 자동 / 수동 Sync 모드 지원
- 자동 동기화(자동 수정) 또는 수동 승인 후 동기화 선택 가능
- Web UI 제공
- 실시간 애플리케이션 상태, 이벤트, 리소스 구조를 시각적으로 확인 가능
- CLI 제공
argocdCLI를 통한 자동화 및 CI 파이프라인 연동
- Webhook 통합
- GitHub, GitLab, Bitbucket 등 Git Webhook을 받아 즉각적인 Sync 트리거
- Access Token 기반 자동화
- Script/CI에서 사용 가능한 토큰 발급
- Lifecycle Hook (PreSync, Sync, PostSync)
- Blue-Green, Canary 등 복잡한 배포 전략 구현 가능
- Audit Trail 제공
- 애플리케이션 이벤트 및 API 호출 기록을 통해 감사(Audit) 가능
- Prometheus Metrics
- Prometheus 연동을 통한 모니터링 및 알림
- Helm Parameter Override
- Git 내 정의된 Helm 파라미터를 상황에 맞게 Override 가능
4. Argo CD 설치 및 기본 설정
4.1. Argo CD 설치
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
##############################################################
# 디렉터리 생성 및 이동
##############################################################
mkdir cicd-labs
cd cicd-labs
##############################################################
# 네임스페이스 생성 및 파라미터 파일 작성
##############################################################
kubectl create ns argocd
cat <<EOF > argocd-values.yaml
dex:
enabled: false
server:
service:
type: NodePort
nodePortHttps: 30002
extraArgs:
- --insecure # HTTPS 대신 HTTP 사용
EOF
##############################################################
# 설치 : Argo CD v3.1.9 , (참고) 책 버전 v2.10.5
##############################################################
helm repo add argo https://argoproj.github.io/argo-helm
helm install argocd argo/argo-cd --version 9.0.5 -f argocd-values.yaml --namespace argocd
##############################################################
# 확인
##############################################################
kubectl get pod,svc,ep,secret,cm -n argocd
kubectl get crd | grep argo
# applications.argoproj.io 2024-04-14T08:12:16Z
# applicationsets.argoproj.io 2024-04-14T08:12:17Z
# appprojects.argoproj.io 2024-04-14T08:12:16Z
kubectl get appproject -n argocd -o yaml
# configmap
kubectl get cm -n argocd argocd-cm -o yaml
kubectl get cm -n argocd argocd-rbac-cm -o yaml
# ...
# data:
# policy.csv: ""
# policy.default: ""
# policy.matchMode: glob
# scopes: '[groups]'
# 최초 접속 암호 확인
kubectl -n argocd get secret argocd-initial-admin-secret -o jsonpath="{.data.password}" | base64 -d ;echo
# vIkG90xaTZ1u2p5I-kk
##############################################################
# Argo CD 웹 접속 주소 확인 : 초기 암호 입력 (admin 계정)
##############################################################
open "http://127.0.0.1:30002" # macOS
## Windows OS경우 직접 웹 브라우저에서 http://<Ubuntu Eth0 IP>:30002 접속
4.2. Argo CD 웹 접속 확인 및 admin 계정 암호 변경 (qwe12345)
4.2.1. 접속 확인
4.2.2. 계정 암호 변경
4.3. ops-deploy Repository 등록
Settings -> Repository -> CONNECT REPO 클릭
- connection method : VIA HTTP/HTTPS
- Type : git
- Name (optional) : gogs
- Project : default
- Repo URL :
http://***<자신의 IP>***:3000/devops/ops-deploy - Username : devops
- Password : ***
***
입력 후 CONNECT 클릭
5. Argo CD를 통해 Repository(ops-deploy)의 nginx helm chart 배포
5.1. Helm Chart 생성
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
##############################################################
# Gogs 터미널 진입 (docker-compose.yaml 파일이 위치한 경로에서 실행)
##############################################################
docker compose exec --privileged -u root gogs bash
---
##############################################################
# 디렉터리 및 git 초기 세팅
##############################################################
cd /data
MyIP=172.28.8.232
TOKEN=48bf0caa1c0eeaf85eea28858c3dd472c16d9103
echo $MyIP $TOKEN
git clone http://devops:$TOKEN@$MyIP:3000/devops/ops-deploy.git
cd ops-deploy
#
git config --local user.name "devops"
git config --local user.email "a@a.com"
git config --local init.defaultBranch main
git config --local credential.helper store
git --no-pager config --local --list
git --no-pager branch
git remote -v
##############################################################
# Nginx Helm Chart 생성
##############################################################
VERSION=1.26.1
mkdir nginx-chart
mkdir nginx-chart/templates
cat > nginx-chart/VERSION <<EOF
$VERSION
EOF
cat > nginx-chart/templates/configmap.yaml <<EOF
apiVersion: v1
kind: ConfigMap
metadata:
name: {{ .Release.Name }}
data:
index.html: |
{{ .Values.indexHtml | indent 4 }}
EOF
cat > nginx-chart/templates/deployment.yaml <<EOF
apiVersion: apps/v1
kind: Deployment
metadata:
name: {{ .Release.Name }}
spec:
replicas: {{ .Values.replicaCount }}
selector:
matchLabels:
app: {{ .Release.Name }}
template:
metadata:
labels:
app: {{ .Release.Name }}
spec:
containers:
- name: nginx
image: {{ .Values.image.repository }}:{{ .Values.image.tag }}
ports:
- containerPort: 80
volumeMounts:
- name: index-html
mountPath: /usr/share/nginx/html/index.html
subPath: index.html
volumes:
- name: index-html
configMap:
name: {{ .Release.Name }}
EOF
cat > nginx-chart/templates/service.yaml <<EOF
apiVersion: v1
kind: Service
metadata:
name: {{ .Release.Name }}
spec:
selector:
app: {{ .Release.Name }}
ports:
- protocol: TCP
port: 80
targetPort: 80
nodePort: 30000
type: NodePort
EOF
cat > nginx-chart/values-dev.yaml <<EOF
indexHtml: |
<!DOCTYPE html>
<html>
<head>
<title>Welcome to Nginx!</title>
</head>
<body>
<h1>Hello, Kubernetes!</h1>
<p>DEV : Nginx version $VERSION</p>
</body>
</html>
image:
repository: nginx
tag: $VERSION
replicaCount: 1
EOF
cat > nginx-chart/values-prd.yaml <<EOF
indexHtml: |
<!DOCTYPE html>
<html>
<head>
<title>Welcome to Nginx!</title>
</head>
<body>
<h1>Hello, Kubernetes!</h1>
<p>PRD : Nginx version $VERSION</p>
</body>
</html>
image:
repository: nginx
tag: $VERSION
replicaCount: 2
EOF
cat > nginx-chart/Chart.yaml <<EOF
apiVersion: v2
name: nginx-chart
description: A Helm chart for deploying Nginx with custom index.html
type: application
version: 1.0.0
appVersion: "$VERSION"
EOF
tree nginx-chart
# nginx-chart
# ├── Chart.yaml
# ├── VERSION
# ├── templates
# │ ├── configmap.yaml
# │ ├── deployment.yaml
# │ └── service.yaml
# ├── values-dev.yaml
# └── values-prd.yaml
# 아래 확인은 skip
helm template dev-nginx nginx-chart -f nginx-chart/values-dev.yaml
helm template prd-nginx nginx-chart -f nginx-chart/values-prd.yaml
DEVNGINX=$(helm template dev-nginx nginx-chart -f nginx-chart/values-dev.yaml | sed 's/---//g')
PRDNGINX=$(helm template prd-nginx nginx-chart -f nginx-chart/values-prd.yaml | sed 's/---//g')
diff <(echo "$DEVNGINX") <(echo "$PRDNGINX")
# git push
git status && git add . && git commit -m "Add nginx helm chart" && git push -u origin main
5.2. Gogs Helm Chart 확인
5.3. Argo CD Application 생성
- GENERAL
App Name: dev-nginxProject Name: defaultSYNC POLICY: ManualAUTO-CREATE NAMESPACE: 클러스터에 네임스페이스가 없을 시 argocd에 입력한 이름으로 자동 생성APPLY OUT OF SYNC ONLY: 현재 동기화 상태가 아닌 리소스만 배포
SYNC OPTIONS: AUTO-CREATE NAMESPACE(Check)PRUNE PROPAGATION POLICYforeground: 부모(소유자, ex. deployment) 자원을 먼저 삭제함background: 자식(종속자, ex. pod) 자원을 먼저 삭제함orphan: 고아(소유자는 삭제됐지만, 종속자가 삭제되지 않은 경우) 자원을 삭제함
- Source
Repo URL: 설정되어 있는 것 선택Revision: HEADPATH: nginx-chart
- DESTINATION
Cluster URL: <기본값> 기본값>NAMESPACE: dev-nginx
- HELM
Values files: values-dev.yaml
⇒ 작성 후 상단 CREATE 클릭
5.4. Argo CD Application 생성 확인
- dev-nginx App 클릭 후 상세 정보 확인 -> DIFF 클릭 확인















