[CL]Kubeadm 오케스트레이션 설계 설명서 - 100-hours-a-week/12-marong-Wiki GitHub Wiki
☸️ 오케스트레이션 설계 설명서 (마롱 서비스 Kubernetes 마이그레이션)
Kubernetes 아키텍처
서비스 특성 기반의 스케일링 요구
마롱(Marong)은 사용자들이 특정 그룹 내에서 마니또 관계를 기반으로 소셜 활동을 진행하는 서비스로, 서비스의 트래픽은 단순히 일정한 흐름을 보이는 것이 아니라 특정 이벤트 시점에 폭발적으로 증가하는 경향이 있습니다.
🎯 예상 트래픽 집중 상황
-
마니또가 공개되는 시간대
→ 사용자가 동시에 자신의 마니또를 확인하고, 관련 콘텐츠를 조회하며 트래픽 급증
-
이벤트성 캠페인 시작 시점
→ 예: “오늘 18시, 크리스마스 마니또가 공개됩니다!” 같은 시간 고정 이벤트
-
그룹별 마니또 시작일
→ 예: 대학교/회사 단위로 단체 마니또 시작 시, 가입 및 활동 요청 동시 발생
-
알림 or 메시지 폭주 타이밍
→ 마니또 메시지 도착 or 알림 기능이 전체 사용자에게 푸시되는 순간
오케스트레이션 도구의 필요성 및 이점
마롱 서비스는 기존 EC2 기반의 빅뱅 배포 → CI/CD 도입 → 3-Tier 분리 구조 → Docker 도입을 거쳐 지속적으로 인프라를 진화시켜 왔습니다. 이제 오케스트레이션 도구인 Kubernetes를 도입하여 다음과 같은 이점을 확보하고자 합니다.
문제 | Kubeadm 도입 시 해결 방법 |
---|---|
급작스런 트래픽 폭증 | HPA(Horizontal Pod Autoscaler)를 활용한 실시간 파드 수 증가 |
서버 과부하 시 전체 중단 | Pod 단위의 격리 실행 + 워커 노드 분산 처리 |
특정 파드 장애 발생 시 | Self-healing 기능으로 자동 재기동 및 다른 노드로 재배치 |
한 서버에 모든 서비스 집중 | 프론트/백엔드/AI 파드를 독립적으로 분산 배치 가능 |
왜 Kubeadm이어야 하는가?
✅ 장점
-
직접 설정 유연성: CNI, CSI, 인증 방식 등을 직접 선택 가능
-
표준 유지: GKE, EKS와 달리 배포 구조에 대한 종속성이 없고, k8s 구조 학습에 적합
-
구성 요소 독립 설정: Etcd, API Server, Controller Manager, Scheduler 분리 배포 가능
-
보안 커스터마이징: 조직별 인증 정책, Secrets 관리, RBAC 등을 맞춤 설정 가능
-
단계적 확장 용이: 초기 소규모 구성 → 다중 노드 구성 → MSA 확장 가능
⚠️ 제약사항
-
완전 자동화되지 않음: kOps, EKS와 달리 수작업 설정 필요
-
인프라 관리 필요: LoadBalancer 구성, 노드 모니터링 등 직접 운영 책임
-
업데이트 수동: 클러스터 버전 업그레이드는 자동화되지 않음 (버전 관리 필요)
클러스터 구성 및 산정 근거
📌 노드 구성
노드 역할 | 수량 | 스펙 예시 | 비고 |
---|---|---|---|
Master Node | 1 | 2vCPU / 4GB RAM | High Availability 향후 적용 예정 |
Worker Node | 3 | 4vCPU / 8GB RAM | MSA 서비스용 (배포 분산 목적) |
📌 서비스별 Replica 수
서비스 | Replica 수 | 이유 |
---|---|---|
파드 API | 2 | 높은 트래픽 대비, 무중단 배포 고려 |
프론트엔드 | 2 | 트래픽 분산 및 무중단 배포 필요 |
백엔드 | 2 | 비즈니스 로직 처리, 다수의 서비스 요청 대응 필요 |
마니또 매칭 | 1 | 트래픽 적음, 내부 호출 중심 |
맛집 추천 | 2 | 외부 API 연동 지연 대비 |
사용자 인증 | 2 | 로그인 트래픽 집중 시 가용성 확보 |
네트워크 정책 및 보안 구성
- CNI 플러그인: Calico 선택 예정 → 네트워크 정책 설정 가능 + 경량화
- Pod 간 네트워크 통제: Namespace 및 Label 기반의 NetworkPolicy 정의 예정
- 노드 간 통신 보안: kube-proxy 설정을 통해 Control Plane ↔ Worker 간 인증 통신 구성
모니터링 및 로깅 전략
- Metrics: Prometheus + Grafana 스택 구성 예정
- 로그 수집: Loki + Fluent Bit 또는 EFK(Stack) 사용 검토 중
- 알림 시스템: AlertManager와 Discord Webhook 연동 계획
기술적, 운영적 측면의 확장성
-
기존 구조에서는 SFTP로 매번 파일을 수동 배포해야 했고, 업데이트 시마다 다운타임이 발생함
-
Kubeadm 기반 구조로 전환하면 Deployment/Service 구성으로 무중단 Rolling Update가 가능
-
향후 Helm, ArgoCD를 통한 자동화된 배포 파이프라인 구축 가능
-
모듈별 컨테이너화를 통해 프론트/백엔드/AI 파이프라인을 독립적으로 운영 → 빠른 테스트와 배포 가능
-
온프레미스 기반 또는 GCP VM 기반 Kubernetes 클러스터 구성 시, 직접적인 제어권 유지 + 유연한 커스터마이징 가능
☸️ Kubernetes Cluster 및 서비스 구성 정보 문서 (kubeadm + Calico 기준)
0. 패키지 설치 및 환경 구성
# Swap 메모리 해제
swapoff -a
sudo sed -i
free -h
reboot
sudo apt-get update
sudo apt-get install ca-certificates curl
sudo install -m 0755 -d /etc/apt/keyrings
sudo curl -fsSL https://download.docker.com/linux/ubuntu/gpg -o /etc/apt/keyrings/docker.asc
sudo chmod a+r /etc/apt/keyrings/docker.asc
# Add the repository to Apt sources
echo "Add the repository to Apt sources"
echo \
"deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/ubuntu \
$(. /etc/os-release && echo "$VERSION_CODENAME") stable" | \
sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
sudo apt-get update
sudo apt-get install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
cat <<EOF | sudo tee /etc/modules-load.d/containerd.conf
overlay
br_netfilter
EOF
sudo modprobe overlay
sudo modprobe br_netfilter
cat <<EOF | sudo tee /etc/sysctl.d/99-kubernetes-cri.conf
net.bridge.bridge-nf-call-iptables=1
net.ipv4.ip_forward=1
net.bridge.bridge-nf-call-ip6tables=1
EOF
service containerd restart
sudo sysctl --system
sed -i 's/SystemdCgroup = false/SystemdCgroup = true/g' /etc/containerd/config.toml
containerd config default | tee /etc/containerd/config.toml
sudo sed -i 's/SystemdCgroup = false/SystemdCgroup = true/g' /etc/containerd/config.toml
sudo service containerd restart
sudo apt-get update
# apt-transport-https may be a dummy package; if so, you can skip that package
sudo apt-get install -y apt-transport-https ca-certificates curl gpg
curl -fsSL https://pkgs.k8s.io/core:/stable:/v1.29/deb/Release.key | sudo gpg --dearmor -o /etc/apt/keyrings/kubernetes-apt-keyring.gpg
echo 'deb [signed-by=/etc/apt/keyrings/kubernetes-apt-keyring.gpg] https://pkgs.k8s.io/core:/stable:/v1.29/deb/ /' | sudo tee /etc/apt/sources.list.d/kubernetes.list
sudo apt-get update
echo "Installing latest versions"
sudo apt-get install -y kubelet kubeadm kubectl
echo "Fixate version to prevent upgrades"
sudo apt-mark hold kubelet kubeadm kubectl
보안 그룹 설정
Mater Node
포트 | 프로토콜 | 설명 |
---|---|---|
6443 | TCP | kube api |
2379-2380 | TCP | ETCD |
10250 | TCP | kubelet api |
10251 | TCP | kube scheduler |
10252 | TCP | kube controller manager |
179 | TCP | Calico BGP |
22 | TCP | SSH |
Worker Node
포트 | 프로토콜 | 설명 |
---|---|---|
10250 | TCP | kubelet api |
30000-32767 | TCP | Node Port Service |
6783-6784 | TCP, UDP | Calico overlay |
179 | TCP | Calico BGP |
22 | TCP | SSH |
1. kubeadm 명령 및 토큰
항목 | 내용 |
---|---|
클러스터 초기화 | sudo kubeadm init --upload-certs |
워커 노드 조인 | sudo kubeadm join 10.0.0.10:6443 --token abcdef.0123456789abcdef --discovery-token-ca-cert-hash sha256:xxxxxxxxxxxxxxxx |
네트워크 플러그인 설치 (Calico) | kubectl apply -f https://raw.githubusercontent.com/projectcalico/calico/v3.27.2/manifests/calico.yaml |
2. 서비스 파드 구성 정보
파드 이름 | 컨테이너 이미지 | 환경변수 | 포트 | 리플리카 수 |
---|---|---|---|---|
frontend |
ghcr.io/marong/fe:latest |
VITE_API_URL=http://be:8000 |
3000:3000 |
1 |
backend |
ghcr.io/marong/be:latest |
DB_HOST=mariadb , AI_URL=http://ai:5000 |
8000:8000 |
1 |
ai-service |
ghcr.io/marong/ai:latest |
MODEL_PATH=/models/rec.pkl |
5000:5000 |
1 |
3. 핵심 리소스 YAML
frontend-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: frontend
spec:
replicas: 1
selector:
matchLabels:
app: frontend
template:
metadata:
labels:
app: frontend
spec:
containers:
- name: frontend
image: ghcr.io/marong/fe:latest
ports:
- containerPort: 3000
env:
- name: VITE_API_URL
value: "http://backend:8000"
---
apiVersion: v1
kind: Service
metadata:
name: frontend
spec:
selector:
app: frontend
ports:
- protocol: TCP
port: 3000
targetPort: 3000
type: ClusterIP
4. Helm, ArgoCD 설치
# Helm 설치
curl -O https://raw.githubusercontent.com/helm/helm/main/scripts/get-helm-3
bash ./get-helm-3
# Namespace 생성
kubectl create namespace argocd
# Helm Install
helm repo add argo https://argoproj.github.io/argo-helm
helm fetch argo/argo-cd
helm install argocd argo/argo-cd --namespace argocd
# ArgoCD 초기 비밀번호
kubectl -n argocd get secret argocd-initial-admin-secret -o jsonpath="{.data.password}" | base64 -d
☸️ 모니터링 전략 및 장애 대응 방안
모니터링 아키텍처
항목 | 구성 |
---|---|
Metrics 수집 | Prometheus (kube-state-metrics, Node Exporter 포함) |
대시보드 시각화 | Grafana |
로그 수집 및 분석 | Loki + Fluent Bit |
장애 감지 및 알림 | AlertManager → Discord Webhook 연동 |
노드 헬스체크 | kubelet, Node Exporter 기반 모니터링 |
구성 흐름
- Prometheus가 각 노드와 파드로부터 CPU, Memory, Disk, Network 사용량 메트릭을 주기적으로 수집
- AlertManager가 설정된 임계값 초과 시 Discord로 실시간 알림 전송
- Grafana 대시보드에서 실시간 모니터링
- Loki + Fluent Bit을 통해 Pod/Node별 로그 수집 및 쿼리 가능
노드 장애 발생 시 서비스 유지 방안
상황 | 대응 전략 |
---|---|
워커 노드 1대 장애 | - Kubernetes가 자동으로 장애 노드 상태 감지- 장애 노드의 파드를 남은 워커 노드에 자동 재스케줄링- Deployment의 ReplicaSet이 필요한 파드 수를 유지 |
컨트롤 플레인 장애 | - 현재는 싱글 마스터지만, 향후 HA 구성(다중 마스터) 검토 예정- etcd 백업을 통한 복구 계획 수립 필요 |
네트워크 장애 | - Calico를 통한 Pod 간 네트워크 이중 경로 설정 검토 |
추가: Prometheus에서 Node Ready 상태를 모니터링하여, NotReady 전환 시 즉각 Alert 발송 → 수동/자동 대응
파드 롤링 업데이트 과정 예시
RollingUpdate는 하나씩 파드를 교체해 무중단으로 새 버전으로 배포하는 방식입니다.
RollingUpdate 기본 전략
maxUnavailable: 1
maxSurge: 1
동작 예시
- 기존 2개 파드가 정상 운영 중 (
backend-1
,backend-2
) - 새 이미지로 Deployment 업데이트 적용
- 새 파드(
backend-3
)가 생성되어 헬스체크 진행 - 헬스체크 성공 시 기존 파드 하나(
backend-1
) 삭제 - 다시 새 파드(
backend-4
)가 생성 → 헬스체크 통과 - 나머지 기존 파드(
backend-2
) 삭제 - 전체 롤링 업데이트 완료 → 사용자 체감 다운타임 없음
관련 설정 예시 (Deployment YAML)
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 1
maxUnavailable: 1
추가로 Canary 배포 전략(트래픽 일부만 새 버전으로 보내기)도 이후 고려 가능
최종 정리
- 노드 장애 → 파드 자동 재스케줄링
- 파드 장애 → 자동 재기동
- 롤링 업데이트 → 무중단 배포 지원
- 모니터링 → 실시간 알림 + 장애 감지 자동화
- 장기적으로는 마스터 HA 구성, DR(Disaster Recovery) 계획 추가 검토