diff --git a/docs/k8s-architecture-overview.docx b/docs/k8s-architecture-overview.docx new file mode 100644 index 0000000000..eaaf75dda1 Binary files /dev/null and b/docs/k8s-architecture-overview.docx differ diff --git a/docs/k8s-architecture-overview.md b/docs/k8s-architecture-overview.md new file mode 100644 index 0000000000..daa2832b88 --- /dev/null +++ b/docs/k8s-architecture-overview.md @@ -0,0 +1,863 @@ +# Kubernetes 전체 서비스 아키텍처 이해하기 + +> 이 문서는 example-voting-app 프로젝트를 기반으로 Kubernetes의 전체 구성 요소들이 어떻게 하나의 서비스를 이루는지 설명합니다. + +## 목차 + +1. [전체 그림: 모든 것이 연결되는 방식](#1-전체-그림-모든-것이-연결되는-방식) +2. [사용자 요청부터 응답까지: 트래픽 흐름](#2-사용자-요청부터-응답까지-트래픽-흐름) +3. [Deployment → ReplicaSet → Pod 계층 구조](#3-deployment--replicaset--pod-계층-구조) +4. [Service 타입별 트래픽 노출 방식](#4-service-타입별-트래픽-노출-방식) +5. [ConfigMap / Secret → Pod 환경변수](#5-configmap--secret--pod-환경변수) +6. [PersistentVolume → PVC → Pod 볼륨](#6-persistentvolume--pvc--pod-볼륨) +7. [Horizontal Pod Autoscaler (HPA)](#7-horizontal-pod-autoscaler-hpa) +8. [Ingress Controller & Service Mesh](#8-ingress-controller--service-mesh) +9. [모니터링 스택 (Prometheus + Grafana)](#9-모니터링-스택-prometheus--grafana) +10. [로깅 스택](#10-로깅-스택) +11. [CI/CD 파이프라인](#11-cicd-파이프라인) +12. [모든 것이 연결된 전체 그림](#12-모든-것이-연결된-전체-그림) + +--- + +## 1. 전체 그림: 모든 것이 연결되는 방식 + +``` +┌─────────────────────────────────────────────────────────────────────────────────────┐ +│ 사용자 요청 흐름 │ +└─────────────────────────────────────────────────────────────────────────────────────┘ + │ + ▼ +┌──────────────────────────────────────────────────────────────────────────────────────┐ +│ ① 외부 트래픽 진입점 │ +│ ┌─────────────┐ ┌─────────────────┐ ┌──────────────────────────────────┐ │ +│ │ 사용자 │ ──▶ │ Load Balancer │ ──▶ │ Ingress Controller │ │ +│ │ (브라우저) │ │ (클라우드 LB) │ │ (nginx-ingress / istio-gateway) │ │ +│ └─────────────┘ └─────────────────┘ └──────────────────────────────────┘ │ +└──────────────────────────────────────────────────────────────────────────────────────┘ + │ + ▼ +┌──────────────────────────────────────────────────────────────────────────────────────┐ +│ ② 서비스 라우팅 계층 │ +│ ┌─────────────────────────────────────────────────────────────────────────────┐ │ +│ │ Ingress Rules │ │ +│ │ vote.example.com ──▶ vote-service:8080 │ │ +│ │ result.example.com ──▶ result-service:8080 │ │ +│ └─────────────────────────────────────────────────────────────────────────────┘ │ +│ │ │ +│ ┌────────────┴────────────┐ │ +│ ▼ ▼ │ +│ ┌────────────────────────────┐ ┌────────────────────────────┐ │ +│ │ Service: vote │ │ Service: result │ │ +│ │ type: NodePort/ClusterIP │ │ type: NodePort/ClusterIP │ │ +│ │ port: 8080 → 80 │ │ port: 8080 → 80 │ │ +│ └────────────────────────────┘ └────────────────────────────┘ │ +└──────────────────────────────────────────────────────────────────────────────────────┘ + │ + ▼ +┌──────────────────────────────────────────────────────────────────────────────────────┐ +│ ③ 워크로드 계층 (Deployment → ReplicaSet → Pod) │ +│ │ +│ Deployment (vote) Deployment (result) │ +│ │ │ │ +│ ▼ ▼ │ +│ ReplicaSet ReplicaSet │ +│ (자동 생성) (자동 생성) │ +│ │ │ │ +│ ┌────┴────┐ ┌────┴────┐ │ +│ ▼ ▼ ▼ ▼ │ +│ ┌─────┐ ┌─────┐ ┌─────┐ ┌─────┐ │ +│ │Pod 1│ │Pod 2│ ◀── HPA 스케일링 ──▶ │Pod 1│ │Pod 2│ │ +│ └─────┘ └─────┘ └─────┘ └─────┘ │ +└──────────────────────────────────────────────────────────────────────────────────────┘ + │ + ▼ +┌──────────────────────────────────────────────────────────────────────────────────────┐ +│ ④ 백엔드 서비스 계층 │ +│ │ +│ ┌─────────────────┐ ┌─────────────────┐ │ +│ │ redis-service │ │ db-service │ │ +│ │ port: 6379 │ │ port: 5432 │ │ +│ └────────┬────────┘ └────────┬────────┘ │ +│ ▼ ▼ │ +│ ┌─────────────────┐ ┌─────────────────┐ │ +│ │ Redis Pod │ │ Postgres Pod │ │ +│ │ + Volume │ │ + Volume │ │ +│ └─────────────────┘ └─────────────────┘ │ +└──────────────────────────────────────────────────────────────────────────────────────┘ + │ + ▼ +┌──────────────────────────────────────────────────────────────────────────────────────┐ +│ ⑤ 설정 및 스토리지 계층 │ +│ │ +│ ConfigMap Secret PV/PVC │ +│ ┌──────────┐ ┌──────────┐ ┌───────────────────────────────────┐ │ +│ │ DB_HOST │ │ DB_PASS │ │ PersistentVolume │ │ +│ │ REDIS │ │ API_KEY │ │ ▲ │ │ +│ │ _HOST │ │ TLS_CERT │ │ │ Bound │ │ +│ └────┬─────┘ └────┬─────┘ │ PersistentVolumeClaim │ │ +│ │ │ │ ▲ │ │ +│ └────────┬────────┘ │ │ Mount │ │ +│ ▼ │ Pod │ │ +│ Pod 환경변수 └───────────────────────────────────┘ │ +└──────────────────────────────────────────────────────────────────────────────────────┘ +``` + +--- + +## 2. 사용자 요청부터 응답까지: 트래픽 흐름 + +### example-voting-app의 실제 흐름 + +``` +사용자 (브라우저) + │ + │ HTTP 요청: http://노드IP:31000 + ▼ +┌─────────────────────────────────────────────────────────┐ +│ NodePort Service (vote-service) │ +│ - 외부 포트: 31000 (모든 노드에서 접근 가능) │ +│ - 서비스 포트: 8080 │ +│ - 타겟 포트: 80 (Pod의 컨테이너 포트) │ +└─────────────────────────────────────────────────────────┘ + │ + │ label selector: app=vote + ▼ +┌─────────────────────────────────────────────────────────┐ +│ Pod (vote) │ +│ - Python Flask 앱 │ +│ - 투표 데이터를 Redis에 저장 │ +└─────────────────────────────────────────────────────────┘ + │ + │ 내부 통신: redis:6379 + ▼ +┌─────────────────────────────────────────────────────────┐ +│ Redis Pod │ +│ - 투표 데이터 큐잉 │ +└─────────────────────────────────────────────────────────┘ + │ + │ Worker가 폴링 + ▼ +┌─────────────────────────────────────────────────────────┐ +│ Worker Pod │ +│ - Redis → PostgreSQL로 데이터 이동 │ +└─────────────────────────────────────────────────────────┘ + │ + │ 내부 통신: db:5432 + ▼ +┌─────────────────────────────────────────────────────────┐ +│ PostgreSQL Pod │ +│ - 영구 저장 │ +└─────────────────────────────────────────────────────────┘ + │ + │ Result 앱이 조회 + ▼ +┌─────────────────────────────────────────────────────────┐ +│ Result Pod → result-service:31001 → 사용자 │ +│ - 실시간 결과 표시 (WebSocket) │ +└─────────────────────────────────────────────────────────┘ +``` + +--- + +## 3. Deployment → ReplicaSet → Pod 계층 구조 + +### 현재 프로젝트의 vote-deployment.yaml + +```yaml +apiVersion: apps/v1 +kind: Deployment # ① 최상위: 선언적 업데이트 관리 +metadata: + name: vote +spec: + replicas: 1 # 원하는 Pod 수 + selector: + matchLabels: + app: vote + template: # Pod 템플릿 + spec: + containers: + - image: dockersamples/examplevotingapp_vote + name: vote +``` + +### 계층 구조가 필요한 이유 + +``` +Deployment (원하는 상태 선언) + │ + │ "나는 vote 앱이 3개 실행되길 원해" + │ + ▼ +ReplicaSet (복제 관리) + │ + │ "현재 Pod가 1개뿐이네, 2개 더 만들어야지" + │ "Pod 하나가 죽었네, 새로 만들어야지" + │ + ├──▶ Pod 1 (실제 컨테이너) + ├──▶ Pod 2 (실제 컨테이너) + └──▶ Pod 3 (실제 컨테이너) +``` + +### 롤링 업데이트 시나리오 + +``` +이미지 업데이트: v1 → v2 + +Deployment + │ + ├── ReplicaSet-v1 (이전) ReplicaSet-v2 (새로운) + │ │ │ + │ Pod(v1) ───────────────▶ Pod(v2) ← 점진적 교체 + │ Pod(v1) ───────────────▶ Pod(v2) + │ Pod(v1) ───────────────▶ Pod(v2) + │ + └── 롤백 가능: kubectl rollout undo +``` + +--- + +## 4. Service 타입별 트래픽 노출 방식 + +``` +┌───────────────────────────────────────────────────────────────────────────────┐ +│ Service 타입 비교 │ +├───────────────────────────────────────────────────────────────────────────────┤ +│ │ +│ ClusterIP (기본값) │ +│ ┌─────────────────────────────────────────────────────────────┐ │ +│ │ 클러스터 내부에서만 접근 가능 │ │ +│ │ 예: redis-service, db-service │ │ +│ │ │ │ +│ │ vote-pod ──▶ redis:6379 ──▶ redis-pod │ │ +│ └─────────────────────────────────────────────────────────────┘ │ +│ │ +│ NodePort (현재 프로젝트에서 사용) │ +│ ┌─────────────────────────────────────────────────────────────┐ │ +│ │ 모든 노드의 특정 포트로 외부 노출 │ │ +│ │ │ │ +│ │ 외부 ──▶ Node1:31000 ──┐ │ │ +│ │ 외부 ──▶ Node2:31000 ──┼──▶ vote-service ──▶ vote-pod │ │ +│ │ 외부 ──▶ Node3:31000 ──┘ │ │ +│ └─────────────────────────────────────────────────────────────┘ │ +│ │ +│ LoadBalancer (클라우드 환경) │ +│ ┌─────────────────────────────────────────────────────────────┐ │ +│ │ 클라우드 LB가 자동 프로비저닝 │ │ +│ │ │ │ +│ │ 외부 ──▶ AWS ELB/GCP LB ──▶ Service ──▶ Pods │ │ +│ │ (퍼블릭 IP) │ │ +│ └─────────────────────────────────────────────────────────────┘ │ +│ │ +│ Ingress (HTTP/HTTPS 라우팅) │ +│ ┌─────────────────────────────────────────────────────────────┐ │ +│ │ 도메인/경로 기반 라우팅 + TLS 종료 │ │ +│ │ │ │ +│ │ vote.example.com ──┐ │ │ +│ │ ├──▶ Ingress ──┬──▶ vote-service │ │ +│ │ result.example.com─┘ └──▶ result-service │ │ +│ └─────────────────────────────────────────────────────────────┘ │ +└───────────────────────────────────────────────────────────────────────────────┘ +``` + +--- + +## 5. ConfigMap / Secret → Pod 환경변수 + +### 현재 프로젝트의 하드코딩된 값 vs 모범 사례 + +```yaml +# 현재 (하드코딩 - 권장하지 않음) +# db-deployment.yaml +env: +- name: POSTGRES_USER + value: postgres +- name: POSTGRES_PASSWORD + value: postgres # ❌ 비밀번호가 YAML에 노출됨 +``` + +### 모범 사례: ConfigMap + Secret 사용 + +```yaml +# configmap.yaml +apiVersion: v1 +kind: ConfigMap +metadata: + name: app-config +data: + DB_HOST: "db" + REDIS_HOST: "redis" + LOG_LEVEL: "info" + +--- +# secret.yaml +apiVersion: v1 +kind: Secret +metadata: + name: db-secret +type: Opaque +data: + POSTGRES_PASSWORD: cG9zdGdyZXM= # base64 인코딩됨 + +--- +# deployment에서 사용 +spec: + containers: + - name: app + envFrom: + - configMapRef: + name: app-config # 모든 ConfigMap 키를 환경변수로 + env: + - name: DB_PASSWORD + valueFrom: + secretKeyRef: + name: db-secret + key: POSTGRES_PASSWORD # 개별 Secret 키 +``` + +### 데이터 흐름 + +``` +┌──────────────┐ ┌──────────────┐ +│ ConfigMap │ │ Secret │ +│ (평문 설정) │ │ (민감 정보) │ +└──────┬───────┘ └──────┬───────┘ + │ │ + └────────┬───────────┘ + │ + ▼ + ┌───────────────┐ + │ Pod │ + │ ┌─────────┐ │ + │ │Container│ │ + │ │ │ │ + │ │ $DB_HOST│ │ ← 환경변수로 주입 + │ │ $DB_PASS│ │ + │ └─────────┘ │ + └───────────────┘ +``` + +--- + +## 6. PersistentVolume → PVC → Pod 볼륨 + +### 현재 프로젝트 (EmptyDir - 휘발성) + +```yaml +# redis-deployment.yaml +volumeMounts: +- mountPath: /data + name: redis-data +volumes: +- name: redis-data + emptyDir: {} # ⚠️ Pod 재시작시 데이터 손실! +``` + +### 프로덕션: PersistentVolume 사용 + +``` +┌─────────────────────────────────────────────────────────────────────────────────┐ +│ 스토리지 추상화 계층 │ +├─────────────────────────────────────────────────────────────────────────────────┤ +│ │ +│ StorageClass │ +│ ┌─────────────────────────────────────────────────────────────────┐ │ +│ │ "어떤 종류의 스토리지를 어떻게 프로비저닝할지 정의" │ │ +│ │ - standard: 기본 디스크 │ │ +│ │ - ssd: SSD 스토리지 │ │ +│ │ - nfs: 네트워크 파일 시스템 │ │ +│ └─────────────────────────────────────────────────────────────────┘ │ +│ │ │ +│ ▼ │ +│ PersistentVolume (PV) - 클러스터 리소스 (관리자 생성) │ +│ ┌─────────────────────────────────────────────────────────────────┐ │ +│ │ 실제 물리적 스토리지 (AWS EBS, GCP PD, NFS 등) │ │ +│ │ capacity: 10Gi │ │ +│ │ accessModes: [ReadWriteOnce] │ │ +│ └─────────────────────────────────────────────────────────────────┘ │ +│ │ │ +│ │ Bound (바인딩) │ +│ ▼ │ +│ PersistentVolumeClaim (PVC) - 네임스페이스 리소스 (사용자 요청) │ +│ ┌─────────────────────────────────────────────────────────────────┐ │ +│ │ "10Gi 용량의 ReadWriteOnce 스토리지가 필요해요" │ │ +│ └─────────────────────────────────────────────────────────────────┘ │ +│ │ │ +│ │ Mount (마운트) │ +│ ▼ │ +│ Pod │ +│ ┌─────────────────────────────────────────────────────────────────┐ │ +│ │ volumes: │ │ +│ │ - name: db-storage │ │ +│ │ persistentVolumeClaim: │ │ +│ │ claimName: postgres-pvc │ │ +│ │ │ │ +│ │ containers: │ │ +│ │ - volumeMounts: │ │ +│ │ - mountPath: /var/lib/postgresql/data │ │ +│ │ name: db-storage │ │ +│ └─────────────────────────────────────────────────────────────────┘ │ +│ │ +└─────────────────────────────────────────────────────────────────────────────────┘ +``` + +--- + +## 7. Horizontal Pod Autoscaler (HPA) + +``` +┌─────────────────────────────────────────────────────────────────────────────────┐ +│ HPA 동작 원리 │ +├─────────────────────────────────────────────────────────────────────────────────┤ +│ │ +│ Metrics Server │ +│ │ │ +│ │ CPU/메모리 메트릭 수집 │ +│ ▼ │ +│ ┌─────────────────────────────────────────────────────────────────┐ │ +│ │ HPA Controller │ │ +│ │ │ │ +│ │ 현재 CPU: 80% │ │ +│ │ 목표 CPU: 50% │ │ +│ │ │ │ +│ │ 필요한 replicas = 현재 replicas × (80/50) = 1.6 → 2 │ │ +│ └─────────────────────────────────────────────────────────────────┘ │ +│ │ │ +│ │ replicas 조정 │ +│ ▼ │ +│ Deployment (vote) │ +│ │ │ +│ ┌────┴────────────┐ │ +│ ▼ ▼ │ +│ ┌─────┐ ┌─────┐ │ +│ │Pod 1│ ──────▶ │Pod 2│ ← 자동 스케일 아웃 │ +│ └─────┘ └─────┘ │ +│ │ +└─────────────────────────────────────────────────────────────────────────────────┘ +``` + +### HPA 설정 예시 + +```yaml +apiVersion: autoscaling/v2 +kind: HorizontalPodAutoscaler +metadata: + name: vote-hpa +spec: + scaleTargetRef: + apiVersion: apps/v1 + kind: Deployment + name: vote + minReplicas: 2 + maxReplicas: 10 + metrics: + - type: Resource + resource: + name: cpu + target: + type: Utilization + averageUtilization: 50 +``` + +--- + +## 8. Ingress Controller & Service Mesh + +### Ingress (L7 라우팅) + +``` +┌─────────────────────────────────────────────────────────────────────────────────┐ +│ Ingress 아키텍처 │ +├─────────────────────────────────────────────────────────────────────────────────┤ +│ │ +│ 인터넷 │ +│ │ │ +│ ▼ │ +│ ┌─────────────────────────────────────────────────────────────────┐ │ +│ │ Ingress Controller (nginx/traefik) │ │ +│ │ (Deployment + Service LoadBalancer) │ │ +│ └─────────────────────────────────────────────────────────────────┘ │ +│ │ │ +│ │ Ingress 리소스 규칙 적용 │ +│ ▼ │ +│ ┌─────────────────────────────────────────────────────────────────┐ │ +│ │ Ingress Rules │ │ +│ │ │ │ +│ │ Host: vote.example.com │ │ +│ │ Path: / │ │ +│ │ Backend: vote-service:8080 │ │ +│ │ │ │ +│ │ Host: result.example.com │ │ +│ │ Path: / │ │ +│ │ Backend: result-service:8080 │ │ +│ │ │ │ +│ │ TLS: │ │ +│ │ Secret: tls-secret (cert + key) │ │ +│ └─────────────────────────────────────────────────────────────────┘ │ +│ │ +└─────────────────────────────────────────────────────────────────────────────────┘ +``` + +### Service Mesh (Istio) + +``` +┌─────────────────────────────────────────────────────────────────────────────────┐ +│ Service Mesh (Istio) 아키텍처 │ +├─────────────────────────────────────────────────────────────────────────────────┤ +│ │ +│ Control Plane (istiod) │ +│ ┌─────────────────────────────────────────────────────────────────┐ │ +│ │ - 설정 배포 │ │ +│ │ - 인증서 관리 │ │ +│ │ - 서비스 디스커버리 │ │ +│ └─────────────────────────────────────────────────────────────────┘ │ +│ │ │ +│ ▼ 설정 푸시 │ +│ Data Plane (Envoy Sidecars) │ +│ │ +│ ┌───────────────────────┐ ┌───────────────────────┐ │ +│ │ Pod (vote) │ │ Pod (redis) │ │ +│ │ ┌───────┐ ┌─────────┐ │ │ ┌───────┐ ┌─────────┐ │ │ +│ │ │ vote │◀│ Envoy │◀├────►│ │ Envoy │▶│ redis │ │ │ +│ │ │ app │ │ sidecar │ │ │ │sidecar│ │ │ │ │ +│ │ └───────┘ └─────────┘ │ │ └───────┘ └─────────┘ │ │ +│ └───────────────────────┘ └───────────────────────┘ │ +│ │ +│ Envoy가 제공하는 기능: │ +│ ✓ mTLS (서비스간 암호화) │ +│ ✓ 트래픽 관리 (카나리 배포, A/B 테스트) │ +│ ✓ 관측성 (분산 추적, 메트릭) │ +│ ✓ 서킷 브레이커, 재시도, 타임아웃 │ +│ │ +└─────────────────────────────────────────────────────────────────────────────────┘ +``` + +--- + +## 9. 모니터링 스택 (Prometheus + Grafana) + +``` +┌─────────────────────────────────────────────────────────────────────────────────┐ +│ 모니터링 아키텍처 │ +├─────────────────────────────────────────────────────────────────────────────────┤ +│ │ +│ ┌─────────────────┐ │ +│ │ Grafana │ ◀── 대시보드 + 알림 설정 │ +│ │ (시각화) │ │ +│ └────────┬────────┘ │ +│ │ PromQL 쿼리 │ +│ ▼ │ +│ ┌─────────────────┐ │ +│ │ Prometheus │ ◀── 메트릭 저장소 (시계열 DB) │ +│ │ (수집+저장) │ │ +│ └────────┬────────┘ │ +│ │ Pull 방식 수집 (scrape) │ +│ │ │ +│ ┌────────┼────────┬────────────────────┬──────────────────┐ │ +│ ▼ ▼ ▼ ▼ ▼ │ +│ ┌─────┐ ┌─────┐ ┌─────────────┐ ┌───────────┐ ┌──────────────┐ │ +│ │vote │ │redis│ │ kube-state- │ │ node- │ │ cadvisor │ │ +│ │/met │ │/met │ │ metrics │ │ exporter │ │(컨테이너메트릭)│ │ +│ │rics │ │rics │ │(k8s객체상태)│ │(노드메트릭)│ │ │ │ +│ └─────┘ └─────┘ └─────────────┘ └───────────┘ └──────────────┘ │ +│ │ +│ 수집되는 메트릭 예시: │ +│ - container_cpu_usage_seconds_total │ +│ - container_memory_usage_bytes │ +│ - kube_pod_status_phase │ +│ - node_cpu_seconds_total │ +│ │ +└─────────────────────────────────────────────────────────────────────────────────┘ +``` + +### Alertmanager 연동 + +``` +┌─────────────────────────────────────────────────────────────────────────────────┐ +│ Alertmanager 연동 │ +├─────────────────────────────────────────────────────────────────────────────────┤ +│ │ +│ Prometheus Alertmanager │ +│ ┌──────────────────┐ ┌──────────────────────────────────┐ │ +│ │ Alert Rules: │ ────▶ │ - 중복 제거 (Dedup) │ │ +│ │ │ │ - 그룹화 (Grouping) │ │ +│ │ - Pod 죽음 │ │ - 라우팅 (Routing) │ │ +│ │ - 메모리 > 90% │ │ - 알림 전송 │ │ +│ │ - 5xx 에러 급증 │ └──────────────┬───────────────────┘ │ +│ └──────────────────┘ │ │ +│ ▼ │ +│ ┌─────────┬─────────┬─────────┐ │ +│ │ Slack │ Email │PagerDuty│ │ +│ └─────────┴─────────┴─────────┘ │ +│ │ +└─────────────────────────────────────────────────────────────────────────────────┘ +``` + +--- + +## 10. 로깅 스택 + +### ELK Stack + +``` +┌─────────────────────────────────────────────────────────────────────────────────┐ +│ ELK Stack │ +├─────────────────────────────────────────────────────────────────────────────────┤ +│ │ +│ ┌─────────────────┐ │ +│ │ Kibana │ ◀── 로그 검색 + 시각화 │ +│ │ (UI/검색) │ │ +│ └────────┬────────┘ │ +│ │ │ +│ ▼ │ +│ ┌─────────────────┐ │ +│ │ Elasticsearch │ ◀── 로그 인덱싱 + 저장 │ +│ │ (저장/검색) │ │ +│ └────────┬────────┘ │ +│ │ │ +│ ▼ │ +│ ┌─────────────────┐ │ +│ │ Logstash │ ◀── 로그 파싱 + 변환 │ +│ │ (처리/변환) │ │ +│ └────────┬────────┘ │ +│ │ │ +│ ┌───────────────────────┼───────────────────────┐ │ +│ ▼ ▼ ▼ │ +│ ┌────────────┐ ┌────────────┐ ┌────────────┐ │ +│ │ Fluentd │ │ Fluentd │ │ Fluentd │ │ +│ │(DaemonSet) │ │(DaemonSet) │ │(DaemonSet) │ │ +│ └─────┬──────┘ └─────┬──────┘ └─────┬──────┘ │ +│ │ │ │ │ +│ ┌─────┴─────┐ ┌─────┴─────┐ ┌─────┴─────┐ │ +│ │ Node 1 │ │ Node 2 │ │ Node 3 │ │ +│ │ │ │ │ │ │ │ +│ │ vote-pod │ │ redis-pod │ │ db-pod │ │ +│ │ stdout │ │ stdout │ │ stdout │ │ +│ └───────────┘ └───────────┘ └───────────┘ │ +│ │ +└─────────────────────────────────────────────────────────────────────────────────┘ +``` + +### Loki Stack (경량 대안) + +``` +┌─────────────────────────────────────────────────────────────────────────────────┐ +│ Loki Stack │ +├─────────────────────────────────────────────────────────────────────────────────┤ +│ │ +│ ┌─────────────┐ ┌─────────────┐ ┌───────────────┐ │ +│ │ Grafana │ ◀── │ Loki │ ◀── │ Promtail │ │ +│ │ (시각화) │ │ (저장소) │ │ (로그 수집) │ │ +│ └─────────────┘ └─────────────┘ └───────────────┘ │ +│ │ │ +│ 장점: DaemonSet으로 │ +│ - Prometheus와 통합 각 노드에서 실행 │ +│ - 경량 (인덱싱 안함) │ +│ - 라벨 기반 쿼리 │ +│ │ +└─────────────────────────────────────────────────────────────────────────────────┘ +``` + +--- + +## 11. CI/CD 파이프라인 + +### 현재 프로젝트의 GitHub Actions + +```yaml +# .github/workflows/call-docker-build-vote.yaml +name: Build Vote +on: + push: + branches: ['main'] + paths: ['vote/**'] + +jobs: + call-docker-build: + uses: dockersamples/.github/.github/workflows/reusable-docker-build.yaml@main + with: + dockerhub-enable: true + ghcr-enable: true + image-names: | + ghcr.io/dockersamples/example-voting-app-vote + dockersamples/examplevotingapp_vote +``` + +### 전체 CI/CD 파이프라인 + +``` +┌─────────────────────────────────────────────────────────────────────────────────┐ +│ CI/CD 파이프라인 │ +├─────────────────────────────────────────────────────────────────────────────────┤ +│ │ +│ 개발자 │ +│ │ │ +│ │ git push │ +│ ▼ │ +│ ┌─────────────────────────────────────────────────────────────────┐ │ +│ │ GitHub / GitLab │ │ +│ │ │ │ +│ │ ┌─────────────────────────────────────────────────────────┐ │ │ +│ │ │ CI Pipeline (GitHub Actions) │ │ │ +│ │ │ │ │ │ +│ │ │ 1. 코드 체크아웃 │ │ │ +│ │ │ 2. 테스트 실행 │ │ │ +│ │ │ 3. Docker 이미지 빌드 │ │ │ +│ │ │ 4. 이미지 레지스트리 푸시 (GHCR, DockerHub) │ │ │ +│ │ │ 5. 매니페스트 업데이트 (GitOps 방식) │ │ │ +│ │ └─────────────────────────────────────────────────────────┘ │ │ +│ │ │ │ +│ └─────────────────────────────────────────────────────────────────┘ │ +│ │ │ +│ │ 이미지 태그 변경 │ +│ ▼ │ +│ ┌─────────────────────────────────────────────────────────────────┐ │ +│ │ CD (GitOps - ArgoCD / Flux) │ │ +│ │ │ │ +│ │ Git 저장소 (k8s-manifests) │ │ +│ │ │ │ │ +│ │ │ 감시 (Watch) │ │ +│ │ ▼ │ │ +│ │ ┌──────────────────────────────────────┐ │ │ +│ │ │ ArgoCD │ │ │ +│ │ │ │ │ │ +│ │ │ Git 상태 ←→ 클러스터 상태 비교 │ │ │ +│ │ │ │ │ │ +│ │ │ 차이 발견 → 자동 동기화 (Sync) │ │ │ +│ │ └──────────────────────────────────────┘ │ │ +│ │ │ │ │ +│ │ │ kubectl apply │ │ +│ │ ▼ │ │ +│ │ ┌──────────────────────────────────────┐ │ │ +│ │ │ Kubernetes Cluster │ │ │ +│ │ │ │ │ │ +│ │ │ vote-deployment (새 이미지로 롤아웃)│ │ │ +│ │ └──────────────────────────────────────┘ │ │ +│ │ │ │ +│ └─────────────────────────────────────────────────────────────────┘ │ +│ │ +└─────────────────────────────────────────────────────────────────────────────────┘ +``` + +--- + +## 12. 모든 것이 연결된 전체 그림 + +``` +┌─────────────────────────────────────────────────────────────────────────────────────────┐ +│ Production Kubernetes 환경 │ +└─────────────────────────────────────────────────────────────────────────────────────────┘ + + ┌──────────────┐ + │ 개발자 │ + └──────┬───────┘ + │ git push + ▼ +┌─────────────────────────────────────────────────────────────────────────────────────────┐ +│ CI/CD Layer │ +│ ┌──────────────────┐ ┌──────────────────┐ ┌──────────────────┐ │ +│ │ GitHub Actions │───▶│ Container │───▶│ ArgoCD │ │ +│ │ (빌드/테스트) │ │ Registry │ │ (GitOps 배포) │ │ +│ └──────────────────┘ └──────────────────┘ └────────┬─────────┘ │ +└──────────────────────────────────────────────────────────┬┬─────────────────────────────┘ + ││ + ┌──────────────┐ ││ + │ 사용자 │ ││ + └──────┬───────┘ ││ + │ ││ + ▼ ▼▼ +┌─────────────────────────────────────────────────────────────────────────────────────────┐ +│ Ingress Layer │ +│ ┌──────────────────────────────────────────────────────────────────────────────────┐ │ +│ │ LoadBalancer → Ingress Controller (nginx) → TLS 종료 → 라우팅 │ │ +│ └──────────────────────────────────────────────────────────────────────────────────┘ │ +└────────────────────────────────────────────┬────────────────────────────────────────────┘ + │ + ▼ +┌─────────────────────────────────────────────────────────────────────────────────────────┐ +│ Service Mesh Layer (Optional: Istio/Linkerd) │ +│ ┌──────────────────────────────────────────────────────────────────────────────────┐ │ +│ │ mTLS │ 트래픽 관리 │ 서킷 브레이커 │ 분산 추적 │ │ +│ └──────────────────────────────────────────────────────────────────────────────────┘ │ +└────────────────────────────────────────────┬────────────────────────────────────────────┘ + │ + ▼ +┌─────────────────────────────────────────────────────────────────────────────────────────┐ +│ Service Layer │ +│ │ +│ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │ +│ │vote-service │ │result-service│ │redis-service │ │ db-service │ │ +│ │ (NodePort) │ │ (NodePort) │ │ (ClusterIP) │ │ (ClusterIP) │ │ +│ └──────┬───────┘ └──────┬───────┘ └──────┬───────┘ └──────┬───────┘ │ +│ │ │ │ │ │ +└──────────┼───────────────────┼───────────────────┼───────────────────┼──────────────────┘ + │ │ │ │ + ▼ ▼ ▼ ▼ +┌─────────────────────────────────────────────────────────────────────────────────────────┐ +│ Workload Layer │ +│ │ +│ ┌───────────────────────────────────────────────────────────────────────────────┐ │ +│ │ HPA (Auto Scaling) │ │ +│ └───────────────────────────────────────────────────────────────────────────────┘ │ +│ │ │ +│ Deployment─────────▶ ReplicaSet ──────▶ Pods │ +│ │ +│ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │ +│ │ vote pods │ │ result pods │ │ worker pods │ │ redis/db │ │ +│ │ (Python) │ │ (Node.js) │ │ (.NET) │ │ pods │ │ +│ └──────────────┘ └──────────────┘ └──────────────┘ └──────────────┘ │ +│ │ │ +└───────────────────────────────────────────────────────────────────────┼─────────────────┘ + │ + ▼ +┌─────────────────────────────────────────────────────────────────────────────────────────┐ +│ Config & Storage Layer │ +│ │ +│ ┌──────────────┐ ┌──────────────┐ ┌──────────────────────────────────────┐ │ +│ │ ConfigMap │ │ Secret │ │ PV ←─ PVC ←─ Pod Volume Mount │ │ +│ │ (설정값) │ │ (비밀번호) │ │ (영구 스토리지) │ │ +│ └──────────────┘ └──────────────┘ └──────────────────────────────────────┘ │ +│ │ +└─────────────────────────────────────────────────────────────────────────────────────────┘ + +┌─────────────────────────────────────────────────────────────────────────────────────────┐ +│ Observability Layer │ +│ │ +│ ┌────────────────────────┐ ┌────────────────────────┐ ┌────────────────────────┐ │ +│ │ Monitoring │ │ Logging │ │ Tracing │ │ +│ │ │ │ │ │ │ │ +│ │ Prometheus + Grafana │ │ Loki/ELK + Fluentd │ │ Jaeger / Zipkin │ │ +│ │ │ │ │ │ │ │ +│ │ - CPU/Memory 메트릭 │ │ - 컨테이너 로그 수집 │ │ - 분산 요청 추적 │ │ +│ │ - 커스텀 메트릭 │ │ - 중앙 로그 검색 │ │ - 지연 시간 분석 │ │ +│ │ - 알림 (Alertmanager) │ │ - 로그 분석 │ │ - 에러 추적 │ │ +│ └────────────────────────┘ └────────────────────────┘ └────────────────────────┘ │ +│ │ +└─────────────────────────────────────────────────────────────────────────────────────────┘ +``` + +--- + +## 핵심 요약 + +| 구성 요소 | 역할 | 현재 프로젝트 상태 | +|----------|------|------------------| +| **Deployment** | 애플리케이션 배포 관리 | ✅ 구현됨 | +| **Service** | 네트워크 접근 제공 | ✅ NodePort 사용 | +| **Ingress** | HTTP/HTTPS 라우팅 | ❌ 미구현 (직접 NodePort 사용) | +| **ConfigMap/Secret** | 설정 분리 | ⚠️ 하드코딩됨 | +| **PV/PVC** | 영구 스토리지 | ⚠️ EmptyDir 사용 (휘발성) | +| **HPA** | 자동 스케일링 | ❌ 미구현 | +| **Service Mesh** | 서비스간 통신 관리 | ❌ 미구현 | +| **Monitoring** | 메트릭 수집/시각화 | ❌ 미구현 | +| **Logging** | 로그 수집/분석 | ❌ 미구현 | +| **CI/CD** | 자동 빌드/배포 | ✅ GitHub Actions | + +--- + +## 결론 + +이 모든 구성 요소들이 **하나의 목표**를 위해 협력합니다: + +> **"안정적이고, 확장 가능하며, 관측 가능한 서비스를 운영하는 것"** + +각 레이어는 독립적으로 동작하면서도 서로 유기적으로 연결되어 있습니다. 처음부터 모든 것을 구현할 필요는 없으며, 서비스의 성숙도와 요구사항에 따라 점진적으로 추가해 나가면 됩니다.