클라우드 5단계: Kubeadm 오케스트레이션 - 100-hours-a-week/16-Hot6-wiki GitHub Wiki
상위 문서: 클라우드 위키
관련 문서: 클라우드 WHY? 문서
Kubeadm 오케스트레이션
개요
서비스의 규모가 커지고 운영 복잡도가 증가함에 따라, 기존의 Docker 단일 배포 방식으로는 안정적인 서비스 운영과 유연한 확장이 어려워졌습니다. 이에 따라, Kubernetes 기반의 오케스트레이션 시스템 도입을 검토하게 되었고, 그 첫 단계로 Kubeadm을 이용한 자체 클러스터 구성을 선택했습니다.
Kubeadm은 쿠버네티스 클러스터를 직접 구성하고 운영할 수 있는 도구로, 클라우드 서비스에 의존하지 않고도 세밀한 클러스터 제어가 가능하다는 장점이 있습니다. 이 문서에서는 Kubeadm 도입 배경, 클러스터 구조, 오케스트레이션 설계 및 기술 구성 명세를 정리하여, 왜 Kubernetes 기반 아키텍처로 확장하게 되었는지, 어떻게 확장할 것인지에대해 설명합니다.
목차
Kubeadm 도입 결정 및 범위
Docker 배포**에서 Kubeadm 오케스트레이션으로 확장한 이유는, 시스템의 복잡도, 운영 요구사항, 안정성 수준을 높이기 위해서입니다.
4단계 → 5단계로 확장하기로 한 이유 (Docker → Kubeadm)
구분 | 4단계: Docker 단일 배포 | 5단계: Kubernetes 오케스트레이션 |
---|---|---|
운영 단위 | 컨테이너 (1~수 개) | 클러스터 + 다수 컨테이너 |
관리 방식 | 수동/스크립트 | 자동화된 스케줄링, 복구 |
확장성 | 수동 스케일링 필요 | HPA 등 자동 확장 가능 |
무중단 배포 | 없음 | 롤링 업데이트/자동 롤백 지원 |
장애 복구 | 컨테이너 재시작 필요 | Self-healing 지원 |
CI/CD 연동 | 단순 배포 | Helm/ArgoCD 기반 고도화 |
네트워크/보안 | 호스트 기반 설정 | CNI, RBAC 제어 |
발전이 필요한 이유
- 서비스 복잡도 증가 → docker-compose로 관리 한계
- 운영 안정성과 자동 복구 필요
- 무중단 배포 및 자동 롤백 요구
- 자동화와 수평 스케일링 필요
Docker 배포는 소규모에 적합했다면, Kubernetes는 확장성과 안정성을 고려한 선택입니다.
Kubeadm 클러스터 구조 다이어그램
1. 클러스터 인프라 관점 아키텍처(Dev)
전체 구조 개요
이 아키텍처는 다음과 같은 주요 계층으로 구성되어 있습니다:
- 개발자 (Developer)
- Master Node (1개)
- Worker Node (1개)
- 내장 etcd 구성
- 모니터링 시스템 (Prometheus + Grafana)
1. 개발자 (Developer)
- 개발자는
kubectl
또는 CI 파이프라인을 통해 마스터 노드의 API Server에 직접 연결 kubeconfig
파일을 통해 인증하고 API 명령을 실행
운영 환경에서는 Load Balancer를 통해 접근하지만, Dev 환경에서는 직접 Master Node에 연결해도 충분합니다.
2. Master Node (1개)
Master 노드는 클러스터의 제어 역할을 수행하며, 다음 컴포넌트를 포함합니다:
구성 요소 | 역할 |
---|---|
apiserver |
클러스터 명령의 진입점 |
controller-manager |
파드 및 리소스 상태 관리 |
scheduler |
파드 배치 결정 |
etcd (내장) |
클러스터 상태 데이터 저장 (HA는 아님) |
exporter |
Prometheus 메트릭 제공용 컴포넌트 |
단일 마스터 구조로 비용을 절감하고 구성도 단순화되었습니다.
3. Worker Node (1개)
Worker 노드는 실제 컨테이너(Pod)가 실행되는 환경이며, 다음과 같은 요소를 포함합니다:
구성 요소 | 역할 |
---|---|
kubelet |
마스터에서 명령을 받아 컨테이너 생성/삭제 |
kube-proxy |
네트워크 라우팅 처리 |
CRI (Docker) |
컨테이너 실행 엔진 (테스트 목적엔 Docker도 사용 가능) |
실험 및 단일 애플리케이션 테스트에 적합한 경량 구성입니다.
4. etcd (내장)
etcd
는 마스터 노드 내부에 내장되어 구성되며, 클러스터 상태를 저장합니다.- 운영환경과 달리 HA 구성을 하지 않아도 되며, 단일 노드만으로 충분합니다.
구조 요약
계층 | 구성 요소 | 역할 요약 |
---|---|---|
개발자 접근 | API Server | kubectl 등으로 명령 실행 |
마스터 노드 | apiserver, scheduler 등 | 클러스터 제어 |
etcd | 내장 구성 | 상태 저장 (HA는 아님) |
워커 노드 | kubelet, proxy, CRI | 앱 실행 환경 |
모니터링 | Prometheus, Grafana | 메트릭 수집 및 시각화 |
중요 포인트
- 간소화한 싱글 노드 마스터 구성 (비용 최소화)
- 내장 etcd로 구성 간편화
- 운영 방식은 Prod와 동일하게 유지 가능 (kubectl, yaml, CI/CD 등)
- 모니터링 구성 유지로 리소스/상태 확인 가능
- 고가용성(HA)은 없는 테스트/개발용 전용 구성
왜 Dev 클러스터 인프라 관점 아키텍처를 저렇게 구성했나요?
2. 클러스터 인프라 관점 아키텍처(Prod)
전체 구조 개요
이 아키텍처는 다음과 같은 주요 계층으로 구성되어 있습니다.:
- Control Plane 노드: 1개
- etcd 노드: 1개
- Worker Node: 3개
- Load Balancer → 단일 API Server 연결
Load Balancer
구성 | 설명 |
---|---|
ALB (HTTPS) | 클라이언트 요청을 받아 Ingress로 전달 |
Ingress Controller | URI/호스트 기반 라우팅 |
Service (ClusterIP/NodePort) | 파드로 요청 전달 |
DNS (Route 53) | ALB 도메인에 연결 |
현재는 Control Plane이 1개이므로 API 접근은 해당 노드로만 라우팅됩니다.
Worker Node (3개)
각 워커 노드는 다음 컴포넌트를 가짐:
컴포넌트 | 설명 |
---|---|
kubelet |
파드 실행 및 상태 보고 |
kube-proxy |
서비스 요청 라우팅 |
container runtime |
Docker 또는 containerd |
실제 서비스(backend
, ai
, redis
, kafka
, promtail
등)는 워커 노드에서 실행되며,
Pod는 라벨과 selector를 통해 Service로 연결됩니다.
워커 노드에서는 실제 애플리케이션 Pod들이 실행됩니다.
Master Node (Control Plane)
구성 요소 | 역할 |
---|---|
kube-apiserver |
모든 요청을 수신하고 인증, 라우팅 처리 |
controller-manager |
리소스 상태 유지, 스케일링, 복제 컨트롤 |
scheduler |
파드를 어떤 워커에 띄울지 결정 |
kubelet |
(해당 노드에는 없음, 워커 전용) |
현재는 단일 Master Node로 운영 중이며, 필요 시 3개의 HA 마스터 구조로 확장 예정입니다.
4. External etcd
- 클러스터 상태 및 리소스 정의를 저장하는 Key-Value DB
- 현재는 단일 etcd 노드에서 운영 중이며,
고가용성 구성 (etcd1
,etcd2
,etcd3
)은 추후 확장 고려 대상입니다.
중요 포인트
- 워커-마스터-데이터 분리 아키텍처
- 구성 요소 역할 명확
왜 클러스터 인프라 관점 아키텍처(Prod)를 저렇게 구성했나요?
3. 애플리케이션 배포 관점 아키텍처 설계
Frontend
- S3 버킷에 정적 웹 페이지(React, Vue, HTML 등)가 배포되어 있습니다.
- API 요청은
Load Balancer Service
로 전달됨
Load Balancer → Ingress → Service
- LoadBalancer Service: ALB 또는 NLB를 사용해 외부 요청을 클러스터 내부로 라우팅
- Ingress Controller (ing): URI, 호스트 등 기반 라우팅 설정 담당
- Kubernetes Service (svc): 적절한 Pod로 라우팅하는 내부 LoadBalancer 역할
Backend
- 여러 개의 Pod가 배포되어 있고, 각각이 백엔드 애플리케이션을 실행 합니다.
- 수평 확장 가능 (HPA 적용 가능)
Database
- 외부에 있는 EC2 인스턴스에 MySQL 설치되어 운영 중
- Pod에서 EC2 인스턴스의 MySQL로 직접 접근함 (Private IP 사용 추정)
보안 그룹 구조 예정:
리소스 | 보안 그룹 역할 | 인바운드 허용 |
---|---|---|
ALB | 외부 요청 수신 | 443 (Internet) |
EKS Node | ALB → Ingress | 80/443 (ALB SG) |
DB EC2 | MySQL 서버 | 3306 (EKS Node SG) |
보안 흐름 요약:
- S3는 Public + HTTPS
- ALB는 Public + HTTPS → Ingress
- Ingress는 내부 서비스와 연결
- DB는 ALB가 아닌 EKS Node에서 오는 트래픽만 허용
기술 구성 명세 요약
항목 | 현재 상태 |
---|---|
Control Plane | 단일 Master 노드 |
etcd | 단일 노드 구성 |
Worker Node 수 | 3개 |
CNI | Calico |
로그 수집 | Loki + Promtail |
모니터링 | Prometheus + Grafana |
배포 자동화 | ArgoCD |
인증 및 접근 | VPN + kubeconfig 기반 |
Load Balancer | ALB + Ingress Controller 사용 중 |
Flannel vs Calico 심층 비교
Kubernetes 네트워크를 구성할 때 필수인 CNI 플러그인 선택은 클러스터 성능과 관리 난이도에 큰 영향을 줍니다. 이를 위해 Flannel과 Calico를 심층적으로 비교 분석했습니다.
주요 비교 항목
항목 | Flannel | Calico |
---|---|---|
핵심 기능 | Pod 간 통신 제공 (Overlay Network) | Pod 간 통신 + NetworkPolicy 지원 |
네트워크 정책 (NetworkPolicy) | 지원하지 않음 | Kubernetes NetworkPolicy 완전 지원 |
설치 난이도 | 매우 간단 | 약간 복잡 (IP-in-IP 모드 설정 필요) |
성능 | 단순 구조로 빠른 설치 및 가벼운 통신 | 고급 제어 가능하지만 약간의 오버헤드 존재 |
운영 규모 | 소규모 또는 테스트 환경 적합 | 중대규모 이상 실서비스에 적합 |
커뮤니티 지원 | 활발 | 매우 활발, Kubernetes 공식 문서에 적극 추천 |
선택 기준
- 보안과 세밀한 통제가 필요 없는 소규모/Dev 환경: Flannel이 적합
- NetworkPolicy 기반 세밀한 제어와 운영환경 보안을 고려: Calico가 필수
- 향후 서비스 확장성을 고려할 경우: 처음부터 Calico 선택이 유지보수에 유리
최종 결정
- Dev/Prod 모두 Calico를 사용하기로 결정했습니다.
- 이는 NetworkPolicy 지원, 향후 서비스 확장, 보안 정책 적용을 고려한 전략적 선택입니다.
- Dev 환경에서도 운영과 동일한 구조를 유지함으로써, 테스트/운영 간 이질성을 최소화할 수 있습니다.
오케스트레이션 설계 설명
비용
GCP 환경 기준으로 개발(Dev) 아키텍처와 운영(Prod) 아키텍처의 예상 비용을 다시 계산하였습니다. GCP 무료 크레딧을 고려하더라도, 아키텍처 이해와 AWS로 이전할 때 비교를 위해 정확히 측정해보았습니다. Kubernetes 클러스터 운영 시 노드(VM)의 사양, 개수, 지속 시간이 핵심 비용 요소입니다.
기준 가정
항목 | Dev 환경 (간단 구조) | Prod 환경 (실제 운영 구조) |
---|---|---|
마스터 노드 | 1개 (e2-standard-4) | 1개 (e2-standard-4) |
etcd 구성 | 마스터에 내장 | 외부 VM 1개 (e2-small) |
워커 노드 | 1개 (e2-medium) | 3개 (e2-standard-4) |
런타임 | containerd | containerd |
모니터링 | Prometheus + Grafana (1개 pod) | 동일 |
사용 시간 | 1개월 (720시간) | 동일 |
예상 비용 비교 (GCP 요금 기준)
항목 | Dev (1 Master, 1 Worker) | Prod (1 Master, 1 etcd, 3 Worker) |
---|---|---|
Control Plane | e2-standard-4 1대: 약 $108/월 | e2-standard-4 1대: 약 $108/월 |
워커 노드 | e2-medium 1대: 약 $25/월 | e2-standard-4 3대: 약 $324/월 |
etcd 노드 | 포함 (0) | e2-small 1대: 약 $24/월 |
Prometheus/Grafana | 1 pod 수준, 약 $1~2 | 약 $3~5 |
스토리지 | 미포함 또는 local | 30GB SSD x 5 = 약 $10~15 |
네트워크/Ingress | NodePort 사용 | L7 LoadBalancer 사용 약 $18~30 |
총합 | 약 $28~30/월 | 약 $480~500/월 |
※ GCP e2-medium 기준 시간당 약 $0.034, e2-standard-4 기준 약 $0.151, e2-small 기준 약 $0.034 ※ SSD 비용: $0.17/GB/월 ※ 실제 가격은 리전/할인/예약 여부에 따라 변동 가능
요약 비교
구분 | 개발(Dev) | 운영(Prod) |
---|---|---|
월 예상 비용 | 약 ₩40,000 (USD $30) | 약 ₩650,000 (USD $480~500) |
구성 복잡도 | 단일 노드 + 내장 etcd | 다중 노드 + 외부 etcd + LB 구성 |
확장성 | 낮음 (테스트 전용) | 높음 (실서비스 대비 가능) |
적합 용도 | 개발, 테스트 | 실서비스, 스테이징, 고가용성 요구 시 |
Dev/Prod 모두 네트워크 플러그인은 Calico를 사용합니다. Prod 환경은 HA 구성이 아니며, 단일 Master와 단일 etcd로 구성됩니다.
기술 구성 명세
kubeadm으로 만든 K8s 클러스터에 실제 서비스를 배포할 수 있게 해주는 구체적인 기술 설정을 정리하였습니다. 인프라 구축 → 배포 → 운영 흐름을 명확히 파악할 수 있도록 구성했습니다.
kubeadm init
)
클러스터 초기화 (kubeadm init \
--apiserver-advertise-address=10.0.0.10 \
--pod-network-cidr=10.244.0.0/16 \
--service-cidr=10.96.0.0/12 \
--control-plane-endpoint="k8s-master.onthe-top.com:6443" \
--upload-certs
옵션 설명
옵션 | 설명 |
---|---|
--apiserver-advertise-address |
마스터 노드의 내부 IP |
--pod-network-cidr |
CNI 플러그인에 사용할 Pod IP 범위 |
--service-cidr |
Kubernetes 서비스 클러스터 IP 범위 |
--control-plane-endpoint |
HA용 외부 로드밸런서 주소 또는 VIP |
--upload-certs |
추가 마스터 노드에 인증서 공유 |
kubeadm join
)
워커 노드 조인 명령 (kubeadm join k8s-master.onthe-top.com:6443 \
--token abcd12.34efgh5678ijklmn \
--discovery-token-ca-cert-hash sha256:123abc456def789... \
--control-plane \
--certificate-key 1122aabbccddeeff...
- 일반 워커 노드는
--control-plane
,--certificate-key
없이 조인합니다.
네트워크 플러그인 적용 (Calico 사용)
kubectl apply -f https://raw.githubusercontent.com/projectcalico/calico/v3.26.1/manifests/calico.yaml
Dev/Prod 모두 Calico를 사용합니다.
- Pod 간 통신 + NetworkPolicy 제어를 지원하기 위해 선택했습니다.
주요 서비스 구성 명세 (요약표)
서비스 이름 | 도커 이미지 | 포트 | 환경 변수 | Service 타입 |
---|---|---|---|---|
frontend (React/Nginx) | nginx:1.25 |
80 | 없음 | ClusterIP |
backend (Nest.js) | ghcr.io/myorg/backend:latest |
3000 | DB_HOST , JWT_SECRET , S3_KEY |
LoadBalancer |
ai-server (Python LLM) | ghcr.io/myorg/ai-server:latest |
5000 | MODEL_PATH , HF_TOKEN |
LoadBalancer |
mysql | mysql:8.0 |
3306 | MYSQL_ROOT_PASSWORD , MYSQL_DATABASE |
ClusterIP |
prometheus | prom/prometheus:latest |
9090 | --config.file=/etc/prometheus/prometheus.yml |
ClusterIP |
grafana | grafana/grafana:latest |
3000 | GF_SECURITY_ADMIN_PASSWORD |
NodePort |
Deployment.yaml
예시: backend 서비스 apiVersion: apps/v1
kind: Deployment
metadata:
name: backend
spec:
replicas: 2
selector:
matchLabels:
app: backend
template:
metadata:
labels:
app: backend
spec:
containers:
- name: backend
image: ghcr.io/myorg/backend:latest
ports:
- containerPort: 3000
env:
- name: DB_HOST
value: "mysql.default.svc.cluster.local"
- name: JWT_SECRET
valueFrom:
secretKeyRef:
name: jwt-secret
key: jwt
---
apiVersion: v1
kind: Service
metadata:
name: backend
spec:
type: LoadBalancer
selector:
app: backend
ports:
- port: 80
targetPort: 3000
jwt-secret
)
예시: Secret 설정 (apiVersion: v1
kind: Secret
metadata:
name: jwt-secret
type: Opaque
data:
jwt: c2VjcmV0X2tleQ== # base64 encoded "secret_key"
Prometheus ConfigMap 일부
apiVersion: v1
kind: ConfigMap
metadata:
name: prometheus-config
data:
prometheus.yml: |
global:
scrape_interval: 15s
scrape_configs:
- job_name: 'kubernetes'
static_configs:
- targets: ['backend:3000', 'ai-server:5000']
부가 정보
항목 | 설명 |
---|---|
인증 방식 | TLS 인증서 자동 생성 (/etc/kubernetes/pki ) |
kubeconfig 위치 | $HOME/.kube/config |
로깅 | 기본 stdout (추후 EFK 스택 고려 가능) |
모니터링 | Prometheus + Grafana (Helm으로 배포 가능) |
도메인 연결 | LoadBalancer IP → Cloud DNS A 레코드 등록 (예: api.mysite.com ) |
비용 산정
기준 가정
- 리전: ap-northeast-2 (서울)
- EC2 인스턴스 요금:
t3.medium
: 약 $0.0416/시간t3.large
: 약 $0.0832/시간t3.small
: 약 $0.0208/시간
- 월 사용 시간: 720시간
- EBS SSD 스토리지: 약 $0.114/GB/월 (gp3 기준)
- ALB: 약 $18~30/월
- Master 노드 포함 전체 수동 구성 (kubeadm)
- Prometheus, Loki, Alertmanager, ArgoCD는 EC2 내부에 공존
- GCP AI 서버는 동일하게 외부에 존재
개발 환경 (Dev)
구성 요소 | 인스턴스 타입 | 개수 | 예상 비용 (USD) | 설명 |
---|---|---|---|---|
Master Node | t3.medium | 1 | ~$30 | kubeadm 기반 Control Plane |
Worker Node | t3.medium | 1 | ~$30 | dev 전용 백엔드/Redis 실행용 |
모니터링/ArgoCD 노드 | t3.small | 1 | ~$15 | ArgoCD + Prometheus 공존 |
EBS 스토리지 | 30GB | 2 | ~$7 | 로그/메트릭 저장 |
VPN 서버 | t3.small | 1 | ~$15 | WireGuard |
합계 | - | - | $90~100/월 |
운영 환경 (Prod)
구성 요소 | 인스턴스 타입 | 개수 | 예상 비용 (USD) | 설명 |
---|---|---|---|---|
Master Node | t3.medium | 1 | ~$30 | 수동 관리, etcd 포함 |
Worker Node | t3.large | 3 | ~$180 | Redis/Kafka/Backend 실행 |
ArgoCD & 모니터링 노드 | t3.medium | 1 | ~$30 | Prometheus, Grafana, Loki 포함 |
EBS 스토리지 | 100GB | 3 | ~$34 | 메트릭, 캐시, 로그용 디스크 |
ALB (Ingress) | - | 1 | ~$25 | ACM 연동 포함 |
GCP AI 서버 | e2-medium | 3 | ~$93 | 외부 ComputeEngine |
VPN 서버 | t3.small | 1 | ~$15 | WireGuard |
합계 | - | - | $400~430/월 |
요약 비교
항목 | Dev 환경 | Prod 환경 |
---|---|---|
Control Plane | EC2 (kubeadm) | EC2 (kubeadm) |
운영 방식 | 완전 수동 | 완전 수동 |
월 예상 비용 | $90~100 | $400~430 |
배포 도구 | ArgoCD (수동 감시) | Argo Rollouts + Alertmanager |
구성 복잡도 | 단일 노드 | Master + 3 Workers + Infra |
장애 복구 비용 | 운영자 수동 대응 | 운영자 수동 대응 |
참고사항
- kubeadm 기반 구성은 Control Plane 자체가 EC2에서 직접 운영되므로 장애 발생 시 수동 복구 필요
- etcd 장애 시에는 운영자 수작업으로 snapshot 복원이 필요함
- 비용은 EKS와 유사하지만, 관리 부담 및 복구 복잡도가 크기 때문에 운영 리스크가 존재함
- Prometheus, Loki, ArgoCD 등도 클러스터 내부가 아닌 독립 노드에 위치하여 유지보수 필요