Skip to content

caminobelllo/FISA-gitops

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

3 Commits
 
 

Repository files navigation

GitOps: ArgoCD + ApplicationSet 기반 멀티 클러스터 운영 전략

우리FIS 아카데미 2차 기술세미나 | 클라우드 엔지니어링 과정 | 서가영


📋 목차

  1. 프로젝트 개요
  2. 기술 스택
  3. 전체 아키텍처
  4. 레포지토리 구조
  5. 환경별 설계 전략
  6. 구현 내용
  7. 데모 시나리오
  8. 트러블슈팅

🚀 프로젝트 개요

왜 GitOps인가?

기존 배포 방식에서는 다음과 같은 문제가 반복됩니다.

문제 설명
추적 불가 누가, 언제, 무엇을 배포했는지 알 수 없음
드리프트(Drift) 클러스터 실제 상태와 코드가 달라지는 불일치 발생
롤백 난이도 장애 시 이전 버전을 찾느라 시간 낭비
환경 불일치 dev/staging/prod 배포 방식이 사람마다 다를 수 있음

🛠 기술 스택

분류 기술
Container Orchestration Kubernetes (minikube)
GitOps ArgoCD v3.3.5, ApplicationSet
CI/CD GitHub Actions
Registry AWS ECR
Monitoring Prometheus, Grafana
Notification Slack Webhook
Application Node.js (Express.js)

🏗 전체 아키텍처

개발자
  │ git push (코드 변경)
  ▼
GitHub (tech-seminar-source)
  │ Actions 자동 트리거
  ▼
GitHub Actions CI
  ├── Docker 이미지 빌드
  ├── AWS ECR 이미지 푸시 (sha-xxxx 태그)
  └── GitOps repo image 태그 자동 업데이트 → commit & push
        ↓
GitHub (tech-seminar-gitops)
  │ ArgoCD 변경 감지 (3분 이내)
  ▼
ArgoCD + ApplicationSet
  ├── gitops-monitor-dev     → dev 클러스터      🟡 자동 배포 (replicas: 1)
  ├── gitops-monitor-staging → staging 클러스터  🔵 자동 배포 (replicas: 2)
  └── gitops-monitor-prod    → prod 클러스터     🔴 수동 승인 (replicas: 3)
        ↓
  Slack #배포-알림 채널 알림

📁 레포지토리 구조

tech-seminar-source/               ← 소스 코드 레포 (CI 트리거)
├── src/
│   ├── index.js                   ← Express.js 대시보드 서버
│   └── public/style.css           
├── Dockerfile
└── .github/workflows/ci.yaml      ← GitHub Actions 파이프라인

tech-seminar-gitops/               ← 배포 선언 레포 (ArgoCD가 팔로우)
├── apps/
│   └── applicationset.yaml        ← 멀티 클러스터 배포 전략 
└── manifests/
    ├── dev/deployment.yaml
    ├── staging/deployment.yaml
    └── prod/deployment.yaml

파일별 역할

파일 역할
applicationset.yaml "어디에, 무엇을, 어떻게 배포할지" 전략
manifests/*/deployment.yaml "실제로 어떤 컨테이너를 띄울지" 선언
ci.yaml 코드 변경 시 자동으로 이미지 빌드 + 배포 선언 업데이트

🧩 환경별 설계 전략

환경 replicas 배포 방식 용도
dev 1 자동 배포 (Auto-Prune) 개발자 테스트, 리소스 절약
staging 2 자동 배포 (Auto-Prune) 팀 QA, 약간의 트래픽 대응
prod 3 수동 승인 (Manual) 실사용자, 고가용성 + 안전 게이트

💻 구현 내용

ApplicationSet 설정

  1. 자동 배포용 템플릿
# applicationset-auto.yaml

apiVersion: argoproj.io/v1alpha1
kind: ApplicationSet
metadata:
  name: gitops-monitor-auto
  namespace: argocd
spec:
  generators:
    - list:
        elements:
          - env: dev
            server: https://kubernetes.default.svc
          - env: staging
            server: https://192.168.49.3:8443
  template:
    metadata:
      name: "gitops-monitor-{{env}}"
      annotations:
        notifications.argoproj.io/subscribe.on-deployed.slack: "#배포-알림"
        notifications.argoproj.io/subscribe.on-sync-failed.slack: "#배포-알림"
        notifications.argoproj.io/subscribe.on-degraded.slack: "#배포-알림"
    spec:
      project: default
      source:
        repoURL: [tech-seminar-gitops 레포지토리 URL]
        targetRevision: HEAD
        path: manifests/{{env}}
      destination:
        server: "{{server}}"
        namespace: gitops-monitor
      syncPolicy:
        automated:
          prune: true
          selfHeal: true
        syncOptions:
          - CreateNamespace=true
  1. 수동 검증용 템플릿
# applicationset-manual.yaml

apiVersion: argoproj.io/v1alpha1
kind: ApplicationSet
metadata:
  name: gitops-monitor-manual
  namespace: argocd
spec:
  generators:
    - list:
        elements:
          - env: prod
            server: https://192.168.49.4:8443
  template:
    metadata:
      name: "gitops-monitor-{{env}}"
      annotations:
        notifications.argoproj.io/subscribe.on-deployed.slack: "#배포-알림"
        notifications.argoproj.io/subscribe.on-sync-failed.slack: "#배포-알림"
        notifications.argoproj.io/subscribe.on-degraded.slack: "#배포-알림"
    spec:
      project: default
      source:
        repoURL: [tech-seminar-gitops 레포지토리 URL]
        targetRevision: HEAD
        path: manifests/{{env}}
      destination:
        server: "{{server}}"
        namespace: gitops-monitor
      syncPolicy:
        syncOptions:
          - CreateNamespace=true

ArgoCD Reconciliation Loop

ArgoCD는 3분마다 Git 상태와 클러스터 상태를 비교하고 자동으로 맞춥니다.

① Git에 새 커밋 감지 (3분 폴링 or Webhook)
        ↓
② Repository Server: YAML 파일 렌더링 (Desired State 확보)
        ↓
③ Application Controller: Desired State vs Actual State 비교
        ↓
    일치   → Synced (대기)
    불일치 → OutOfSync → 자동 동기화 실행
        ↓
④ 쿠버네티스 API 서버에 apply 요청
        ↓
⑤ 스케줄러 → 워커 노드에 Pod 생성
        ↓
⑥ Healthy + Synced 상태로 업데이트
        ↓
① 무한 반복

🎬 데모 시나리오

데모 ① — 정상 배포

git push → GitHub Actions (빌드 + ECR 푸시)
        → GitOps repo image 태그 자동 업데이트
        → ArgoCD 감지
        → dev/staging 자동 배포
        → prod 수동 승인 후 배포
        → Slack 알림

데모 ② — 장애 발생 & GitOps 롤백

1. 장애 주입

  • 작업 중인 레포지토리의 코드에 장애 발생 코드 작성 후 git push

2. 장애 확인

kubectl get pods -n gitops-monitor --context dev -w
# → CrashLoopBackOff 발생

3. GitOps 롤백

# 배포 이력 확인 
git log --oneline -5

# 한 줄로 롤백
git revert HEAD --no-edit
git push
# → ArgoCD 감지 → 이전 정상 이미지로 자동 배포

롤백 흐름 요약

① process.exit(1) 추가 → git push
         ↓
② GitHub Actions → ECR 푸시 → GitOps 레포 image 태그 업데이트
         ↓
③ ArgoCD 감지 → CrashLoopBackOff 발생
         ↓
④ git revert HEAD → git push (한 줄!)
         ↓
⑤ ArgoCD 감지 → 이전 정상 이미지로 자동 배포
         ↓
⑥ Running 복구 

🔧 트러블슈팅

1. minikube docker 드라이버 환경에서 클러스터 간 네트워크 격리 문제

상황

staging/prod 클러스터를 ArgoCD에 등록하기 위해 argocd cluster add 실행 시 오류 발생

# 시도 1 - kubeconfig 서버 주소가 127.0.0.1이라 접근 불가
dial tcp 127.0.0.1:65007: connect: connection refused

# 시도 2 - IP를 192.168.58.2로 변경했으나 여전히 실패
dial tcp 192.168.58.2:8443: i/o timeout

# 시도 3 - docker network connect 후에도 CLI 레벨에서 차단
error dial proxy: dial tcp 192.168.49.3:8443: connect: operation timed out

원인 분석

  • kubeconfig의 서버 주소가 127.0.0.1로 설정되어 있어 IP를 192.168.58.2로 변경했으나 i/o timeout 지속
  • minikube docker 드라이버가 각 클러스터를 독립된 bridge 네트워크로 분리하고 있어 서로 통신 불가임을 확인
  • 추가로 argocd cluster add CLI 자체가 내부 프록시를 경유하는 구조라 직접 IP 지정으로도 우회 불가

해결

docker network connect로 staging/prod 컨테이너를 dev 네트워크에 연결해 IP를 할당한 뒤, argocd cluster add 대신 ArgoCD cluster Secret을 kubectl로 직접 생성하여 등록

# staging/prod 컨테이너를 dev 네트워크에 연결
docker network connect dev staging
docker network connect dev prod

# IP 확인
docker network inspect dev | grep -A4 "Containers"
# kubectl로 직접 Secret 생성
apiVersion: v1
kind: Secret
metadata:
  name: staging-cluster
  namespace: argocd
  labels:
    argocd.argoproj.io/secret-type: cluster
type: Opaque
stringData:
  name: staging
  server: "https://192.168.49.3:8443"
  config: |
    {
      "tlsClientConfig": {
        "insecure": true
      }
    }

⚠️ 재시작 시 주의: minikube를 껐다 켜면 docker 네트워크 연결이 초기화되므로 docker network connect 재실행 필요

2. minikube + k8s 버전 호환성 문제

상황

컨테이너를 중지했다가 재실행 시 kubelet 초기화 실패

unable to load bootstrap kubeconfig: stat /etc/kubernetes/bootstrap-kubelet.conf: no such file or directory

원인

minikube v1.38.1이 k8s v1.35.1을 완전히 지원하지 못하는 호환성 문제. kube-scheduler가 RBAC 권한을 줄줄이 거부당하는 증상 발생

해결

안정적으로 동작이 확인된 k8s v1.33.0으로 다운그레이드

minikube start --profile dev \
  --cpus 3 --memory 4096 \
  --driver docker \
  --kubernetes-version v1.33.0

About

우리FIS 아카데미 2차 기술세미나 - GitOps: ArgoCD + ApplicationSet 기반 멀티 클러스터 운영 전략

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors