ArgoCD GitOps 구성
OpenEG 시스템을 위한 GitOps 기반 Kubernetes 인프라 자동화
📋 프로젝트 개요
OpenEG 교육 기술 시스템(Flask 웹 서버, Node.js 서버, Webhook 등)을 Kubernetes 환경에 GitOps 방식으로 배포 및 관리하는 인프라 자동화 프로젝트입니다.
핵심 개념: GitOps
- Git = Single Source of Truth: 모든 인프라 설정을 Git으로 관리
- 선언적 구성: 원하는 상태를 YAML로 선언
- 자동 동기화: ArgoCD가 Git 상태를 클러스터에 자동 반영
- 불변성: 이미지 태그를 Git Commit Hash로 고정
🎯 해결한 문제
기존 방식의 문제점
- 수동 배포:
kubectl apply로 수동 배포 (오류 발생 가능) - 재현성 부족: “내 컴퓨터에선 되는데요?” 문제
- 시크릿 관리: 민감 정보를 Git에 저장 불가
- 추적 어려움: 누가, 언제, 무엇을 변경했는지 불명확
GitOps 솔루션
- 자동화: Git push만 하면 자동 배포
- 선언적 관리: YAML 파일로 모든 상태 정의
- 버전 관리: Git으로 모든 변경 이력 추적
- 롤백 용이: Git revert로 즉시 이전 상태 복구
- 보안: Vault + Sealed Secrets로 시크릿 안전 관리
🛠 기술 스택
GitOps Core
- ArgoCD: GitOps 배포 도구 (CD)
- Kustomize: 환경별 설정 관리 (base + overlays)
Secret Management
- HashiCorp Vault: 동적 시크릿 주입 (런타임 환경변수)
- Sealed Secrets: 정적 시크릿 암호화 (K8s 리소스)
Monitoring Stack
- Prometheus: 메트릭 수집
- Grafana: 시각화 대시보드
- Loki + Promtail: 로그 중앙화
Infrastructure
- Kubernetes: 컨테이너 오케스트레이션
- Docker: 컨테이너 런타임
- Private Registry: 사설 이미지 저장소 (
registry.oud.kr)
💡 주요 구현 내용
1. App of Apps 패턴
전체 시스템의 진입점: argocd/applications/openeg-system.yaml
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: openeg-system
spec:
source:
path: overlays/production
repoURL: https://github.com/***
destination:
namespace: openeg-system
server: https://kubernetes.default.svc
syncPolicy:
automated:
prune: true
selfHeal: true
syncOptions:
- CreateNamespace=true특징:
- 하나의 ArgoCD Application이 전체 시스템 관리
- 자동 동기화 (prune, selfHeal)
- Slack 알림 통합 (
cicd채널)
2. Kustomize 기반 환경 관리
리포지토리 구조:
├── base/ # 공통 베이스
│ ├── deployments/ # Flask, Node.js 등
│ ├── services/ # ClusterIP, NodePort
│ └── monitoring/ # Prometheus, Grafana
│
└── overlays/
└── production/ # 프로덕션 오버레이
├── kustomization.yaml
├── patches/ # 환경별 패치
└── secrets/ # Sealed Secrets
kustomization.yaml 예시:
bases:
- ../../base
# 이미지 태그 고정 (Git Commit Hash)
images:
- name: openegflask
newName: registry.oud.kr/openegflask
newTag: 19717d45e19b8de5ae7a31217f396506724d57c0
# 환경별 설정 패치
patchesStrategicMerge:
- patches/production-config.yaml
- patches/resources.yaml
# Sealed Secrets
resources:
- secrets/registry-cred.sealed.yaml
- secrets/app-secrets.sealed.yaml3. 이중 시크릿 관리 전략
HashiCorp Vault (동적 주입) ⭐
용도: 애플리케이션 런타임 환경변수 (DB 비밀번호 등)
# Flask Deployment에 Vault Agent Injector 적용
annotations:
vault.hashicorp.com/agent-inject: 'true'
vault.hashicorp.com/role: 'openeg-role'
vault.hashicorp.com/agent-inject-secret-mongodb: 'openeg/data/data/databases/mongodb'
vault.hashicorp.com/agent-inject-template-mongodb: |
{{- with secret "openeg/data/data/databases/mongodb" -}}
export MONGODB_URI="{{ .Data.data.uri }}"
export MONGODB_USER="{{ .Data.data.user }}"
{{- end }}작동 방식:
1. Pod 시작 → vault-agent-init 컨테이너 실행
2. Vault 서버 인증 (Kubernetes Auth)
3. /vault/secrets/ 경로에 파일 생성
4. 애플리케이션 시작 스크립트에서 source로 로드
Sealed Secrets (정적 암호화)
용도: Kubernetes 리소스 자체 시크릿 (레지스트리 자격증명)
# 암호화 과정
kubectl create secret docker-registry registry-cred \
--docker-server=registry.oud.kr \
--docker-username=*** \
--docker-password=*** \
--dry-run=client -o yaml | \
kubeseal -o yaml > registry-cred.sealed.yaml
# Git에 커밋 (암호화되어 안전)
git add overlays/production/secrets/registry-cred.sealed.yaml4. 이미지 불변성 보장
Git Commit Hash로 이미지 태그 고정:
# CI/CD 파이프라인
1. 코드 변경 → Git Push
2. GitHub Actions 트리거
3. Docker 이미지 빌드
- 태그: <git-commit-hash>
4. Private Registry 푸시
5. kustomization.yaml 업데이트
- newTag: <git-commit-hash>
6. GitOps 리포지토리에 커밋
7. ArgoCD 자동 동기화장점:
- 특정 버전으로 즉시 롤백 가능
- 어떤 코드가 배포되었는지 명확
latest태그 사용 금지 (불변성)
5. 모니터링 스택 통합
# base/monitoring/ 구조
├── prometheus/
│ ├── deployment.yaml
│ ├── service.yaml
│ └── configmap.yaml
├── grafana/
│ ├── deployment.yaml
│ ├── service.yaml
│ └── dashboards/
├── loki/
│ └── statefulset.yaml
└── promtail/
└── daemonset.yaml통합 메트릭:
- Node Exporter: 하드웨어 메트릭 (CPU, Memory, Disk)
- Prometheus: 애플리케이션 메트릭 수집
- Grafana: 대시보드 시각화
- Loki + Promtail: 로그 중앙화
🏗 시스템 아키텍처
GitOps 배포 플로우
[개발자]
↓ (코드 변경)
[Git Push]
↓
[GitHub Actions CI]
↓ (빌드 & 푸시)
[Docker Image]
↓ (태그: commit-hash)
[Private Registry]
↓
[GitOps 리포지토리 업데이트]
↓ (kustomization.yaml)
[Git Commit]
↓ (3분마다 폴링)
[ArgoCD 감지]
↓ (자동 Sync)
[Kubernetes 클러스터]
↓
[Running Pods]
↓ (Slack 알림)
[운영팀 확인]
클러스터 아키텍처
Kubernetes Cluster
├── openeg-system (Namespace)
│ ├── Flask App (Deployment)
│ ├── Node.js Server (Deployment)
│ ├── Webhook Service (Deployment)
│ └── Services (ClusterIP/NodePort)
│
├── vault-system (Namespace)
│ └── Vault Server (StatefulSet)
│
└── monitoring (Namespace)
├── Prometheus (Deployment)
├── Grafana (Deployment)
├── Loki (StatefulSet)
└── Promtail (DaemonSet)
📊 주요 설정 파일
Flask App Deployment (Vault 통합)
apiVersion: apps/v1
kind: Deployment
metadata:
name: flask-app
spec:
template:
metadata:
annotations:
# Vault Agent Injector
vault.hashicorp.com/agent-inject: 'true'
vault.hashicorp.com/role: 'openeg-role'
# MongoDB 시크릿
vault.hashicorp.com/agent-inject-secret-mongodb: 'openeg/data/data/databases/mongodb'
# Redis 시크릿
vault.hashicorp.com/agent-inject-secret-redis: 'openeg/data/data/databases/redis'
spec:
# Control Plane 노드 스케줄링
nodeSelector:
node-role.kubernetes.io/control-plane: ""
tolerations:
- key: node-role.kubernetes.io/control-plane
operator: Exists
effect: NoSchedule
containers:
- name: flask
image: registry.oud.kr/openegflask:latest
args:
- /bin/sh
- -c
- |
# Vault 시크릿 로드
source /vault/secrets/mongodb
source /vault/secrets/redis
# Flask 실행
python app.py
livenessProbe:
httpGet:
path: /health
port: 5000
readinessProbe:
httpGet:
path: /health
port: 5000📈 성과
배포 자동화
- 배포 시간: 수동 30분 → 자동 5분
- 오류율: 수동 배포 오류 90% 감소
- 배포 빈도: 주 1회 → 일 3회 (빠른 피드백)
인프라 관리
- 추적성: Git으로 모든 변경 이력 100% 추적
- 롤백 시간: 수동 1시간 → Git revert 30초
- 일관성: 환경별 설정 불일치 0건
보안
- 시크릿 노출: Git에 평문 시크릿 0건
- 권한 관리: Vault Role 기반 세밀한 접근 제어
- 감사 로그: 모든 시크릿 접근 Vault 로그 기록
모니터링
- 가시성: Prometheus + Grafana로 실시간 모니터링
- 로그 중앙화: Loki로 모든 Pod 로그 수집
- 알림: Slack으로 배포 성공/실패 즉시 통지
🔧 운영 가이드
새 버전 배포
# 1. 코드 변경 및 푸시 (자동 CI 트리거)
git commit -m "feat: 새 기능 추가"
git push origin main
# 2. CI에서 빌드된 이미지 태그 확인
# 예: 19717d45e19b8de5ae7a31217f396506724d57c0
# 3. GitOps 리포지토리 업데이트
cd openeg-gitops
vim overlays/production/kustomization.yaml
# images 섹션 수정
images:
- name: openegflask
newTag: 19717d45e19b8de5ae7a31217f396506724d57c0
# 4. 커밋 및 푸시
git commit -m "deploy: Flask v2.1.0"
git push
# 5. ArgoCD 자동 동기화 (3분 이내)
# 6. Slack 알림 확인환경변수 변경
일반 설정 (ConfigMap):
vim overlays/production/patches/production-config.yaml
git commit -m "config: API 엔드포인트 변경"
git push민감 정보 (Vault):
# Vault CLI 사용
vault kv put openeg/data/databases/mongodb \
uri="mongodb://***" \
user="***"
# Pod 재시작 (자동으로 새 시크릿 로드)
kubectl rollout restart deployment/flask-app -n openeg-system롤백
# Git으로 이전 커밋으로 되돌리기
git revert HEAD
git push
# 또는 특정 커밋으로
git reset --hard <commit-hash>
git push --force
# ArgoCD가 자동으로 이전 상태로 복구🚨 문제 해결 (Troubleshooting)
Pod가 시작하지 않을 때
# 1. Pod 상태 확인
kubectl get pods -n openeg-system
# 2. 상세 정보 확인
kubectl describe pod <pod-name> -n openeg-system
# 3. Vault Agent Init 단계 확인
kubectl logs <pod-name> -c vault-agent-init -n openeg-system
# 일반적인 원인:
# - Vault Role 권한 부족
# - Vault 서버 다운
# - 시크릿 경로 오류ArgoCD 동기화 실패
# 1. ArgoCD UI에서 오류 확인
# https://argocd.example.com
# 2. 로컬에서 Kustomize 빌드 테스트
cd overlays/production
kustomize build .
# 3. YAML 문법 오류 확인
yamllint overlays/production/*.yamlSealed Secrets 디코딩 실패
# 1. Sealed Secrets Controller 확인
kubectl get pods -n kube-system | grep sealed-secrets
# 2. 재암호화
kubeseal --fetch-cert > pub-cert.pem
kubectl create secret ... | kubeseal --cert pub-cert.pem -o yaml🔗 관련 프로젝트
배포 대상
- 출석 모니터링 시스템 - OpenEG 전체
인프라 연관
- Kubernetes 배포 - 클러스터 구성
📝 배운 점
GitOps 패턴 마스터
-
선언적 vs 명령형
- 선언적: “이렇게 되어야 한다” (YAML)
- 명령형: “이렇게 해라” (
kubectl apply) - GitOps는 선언적 방식으로 일관성 보장
-
Git as Single Source of Truth
- Git이 모든 진실의 원천
- 클러스터 상태는 Git 상태를 따름
- 수동 변경은 즉시 되돌려짐 (selfHeal)
-
불변 인프라 (Immutable Infrastructure)
- 이미지 태그를 Git Commit Hash로 고정
- 변경은 새 이미지 빌드로만 가능
- 롤백이 단순하고 안전
Kubernetes 운영 노하우
-
시크릿 관리의 이중화
- Vault: 동적 시크릿 (런타임 주입)
- Sealed Secrets: 정적 시크릿 (K8s 리소스)
- 각각의 용도에 맞게 사용
-
Kustomize vs Helm
- Kustomize: 단순, 학습 곡선 낮음, 패치 기반
- Helm: 복잡, 템플릿 기반, 패키지 관리
- 이 프로젝트는 Kustomize 선택 (단순성)
-
모니터링 필수성
- Prometheus + Grafana는 필수
- Liveness/Readiness Probe 설정 중요
- Slack 알림으로 빠른 대응
자동화의 가치
- 신뢰성: 사람 실수 제거
- 재현성: 언제든 같은 결과
- 속도: 배포 시간 대폭 단축
- 협업: Git으로 변경 이력 공유
🔮 향후 계획
단기
- Multi-cluster 지원 (Dev/Staging/Prod 분리)
- Canary 배포 전략 도입
- 자동화된 보안 스캔 (Trivy)
중기
- GitOps로 전체 인프라 관리 (Terraform → GitOps)
- Progressive Delivery (Flagger)
- Disaster Recovery 자동화
장기
- Service Mesh 도입 (Istio)
- Cost Optimization 자동화
- Multi-Cloud 지원
프로젝트 기간: 2024.01 - 2025.12 현재 상태: 완료됨 (운영 중) 네임스페이스: openeg-system 최종 업데이트: 2025-12-21