본 문서는 AWS EC2 인스턴스를 기반으로 Kubeadm을 이용하여 Kubernetes 멀티 노드 클러스터를 수동으로 구축한 구조에 대한 설정 명세서이다. 이 문서는 클러스터의 목적, 적용 대상, 구조 및 주요 구성 요소를 정의하며, 향후 운영 자동화 및 고도화를 위한 기준 자료로 활용될 수 있다.
목적 : Dev/Prod 환경을 분리한 Kubernetes 클러스터 구성으로 인프라 안정성과 확장성 확보
구축 방식 : AWS EC2 위에 Ubuntu 기반 인스턴스를 프로비저닝하고, Kubeadm을 통해 Master/Worker 노드로 클러스터 구성
항목
구성
마스터 노드 수
1대 (Control Plane)
워커 노드 수
2대 이상 (서비스 Pod 실행)
네트워크 구성
동일 VPC, 동일 보안 그룹
CNI 플러그인
Calico 기반 오버레이 네트워크
노드
구성 요소 및 역할
Master Node (EC2_1)
kube-apiserver, etcd, scheduler, controller-manager, CoreDNS 관리ArgoCD, Helm 서버 측 배포 주체
Worker Node 1~N (EC2_2, EC2_3)
Frontend, Backend 서비스 Pod 실행, Prometheus, Grafana(dev), Fluent Bit, Loki 실행, NGINX Ingress Controller 배포 대상
구성 요소
역할
Ingress
NGINX Ingress Controller를 통한 서비스별 라우팅
CI/CD
ArgoCD 기반 GitOps 배포
모니터링
Prometheus + Grafana + Loki + Fluent Bit 활용 (메트릭 + 로그 수집)
Helm
Helm Chart 기반 서비스 배포 및 설정 관리
보안
NAT Gateway + Bastion Host를 통한 SSH 접속 제어, RBAC 및 네임스페이스 분리 관리
네임스페이스
용도
포함 서비스
dev
개발용 환경
next.js, spring, grafana, prom
prod
운영 환경
next.js, spring, scouter, ingress
monitoring
공통 모니터링
prometheus, fluentbit, loki
argocd
GitOps 관리
argo-cd
kube-system
시스템 관리
ingress controller, CoreDNS 등
2.2.7 Kubernetes 리소스 명세서 (서비스별)
서비스(Pod)
Replica
CPU 요청 / 제한
메모리 요청 / 제한
이미지
HPA 설정
ConfigMap / Secret
next.js
2
100m / 200m
128Mi / 256Mi
nextjs:latest
X
env-config
spring
2
250m / 500m
512Mi / 1Gi
spring-backend:1.0
70% CPU
db-config / db-secret
prometheus
1
300m / 500m
512Mi / 1Gi
prom/prometheus
X
prom-config
grafana
1
100m / 300m
256Mi / 512Mi
grafana/grafana
X
grafana-config
fluentbit
1~2
100m / 200m
256Mi / 512Mi
fluent/fluent-bit
X
fluent-config
loki
1
200m / 400m
512Mi / 1Gi
grafana/loki
X
loki-config
ingress controller
1
200m / 300m
256Mi / 512Mi
k8s.gcr.io/ingress-nginx/controller:v1.8.0
X
-
argocd
1
200m / 400m
512Mi / 1Gi
argoproj/argocd
X
-
scouter agent
1 per spring
50m / 100m
128Mi / 256Mi
scouter-agent
X
-
인스턴스 타입 : t3.medium (이상)
AMI : Ubuntu 22.04 LTS (HVM)
VPC/서브넷 구성 : 프라이빗 Nat 서브넷 (Master, Worker)
노드 유형
포트
목적
Master
6443
Kubernetes API Server
Master
2379-2380
etcd 통신
Worker
30000-32767
NodePort용 서비스 통신
모두
22
SSH 접속
모두
80, 443
HTTP/HTTPS (Ingress용 ALB 등)
모두
10250
kubelet 통신
#! /bin/bash
set -e
# 1. Swap off
swapoff -a
sed -i.bak ' / swap / s/^/#/' /etc/fstab
# 2. containerd 설치
apt-get update && apt-get install -y containerd
containerd config default | tee /etc/containerd/config.toml
sed -i ' s/SystemdCgroup = false/SystemdCgroup = true/' /etc/containerd/config.toml
systemctl restart containerd
# 3. 커널 모듈 & sysctl
modprobe overlay
modprobe br_netfilter
tee /etc/sysctl.d/kubernetes.conf << EOF
net.bridge.bridge-nf-call-iptables=1
net.bridge.bridge-nf-call-ip6tables=1
net.ipv4.ip_forward=1
EOF
sysctl --system
# 4. Kubernetes 설치 (v1.28)
apt-get install -y apt-transport-https curl ca-certificates gpg
curl -fsSL https://pkgs.k8s.io/core:/stable:/v1.28/deb/Release.key | gpg --dearmor -o /etc/apt/keyrings/k8s.gpg
echo " deb [signed-by=/etc/apt/keyrings/k8s.gpg] https://pkgs.k8s.io/core:/stable:/v1.28/deb/ /" > /etc/apt/sources.list.d/kubernetes.list
apt-get update && apt-get install -y kubelet kubeadm kubectl
apt-mark hold kubelet kubeadm kubectl
sudo kubeadm init --pod-network-cidr=192.168.0.0/16
목적: Calico CNI를 위한 CIDR 지정 및 초기 마스터 노드 설정
sudo kubeadm join <MASTER_IP>:6443 --token <TOKEN> \
--discovery-token-ca-cert-hash sha256:<HASH>
토큰은 kubeadm token create
로 생성 가능 (기한: 24시간)
mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config
kubectl apply -f https://docs.projectcalico.org/v3.25/manifests/calico.yaml
설명: Pod 간 네트워크 통신을 위한 Calico 네트워크 플러그인 설치
서비스
컨테이너 이미지
환경변수
포트
Next.js
ghcr.io/yourorg/fe-app:main-xxxx
API_URL, NODE_ENV
3000
Spring
ghcr.io/yourorg/be-app:main-xxxx
DB_URL, REDIS_HOST
8080
FastAPI
ghcr.io/yourorg/ai-app:main-xxxx
MODEL_PATH, LOG_LEVEL
8000
ArgoCD
argoproj/argocd:v2.7.0
없음
8080
Prometheus
prom/prometheus:v2.44.0
config-mount
9090
Loki
grafana/loki:2.8.0
config-mount, S3 설정
3100
Fluent Bit
fluent/fluent-bit:2.1
output 설정, tag
2020 (TCP)
Grafana
grafana/grafana:10.0.0
GF_SECURITY_ADMIN_PASSWORD, GF_AUTH_ANONYMOUS_ENABLED
3000
2.6.1 Helm Provider 구성 (Terraform)
Terraform의 Helm provider를 사용해 클러스터 외부에서 Helm Chart를 설치
kubeadm 환경에서는 helm install
명령을 직접 수행하거나, provider로 관리
EKS와 달리 kubeconfig를 수동 구성해야 하며, OIDC 기반 인증이 아닌 토큰 기반 혹은 static config 필요
컴포넌트
Chart 이름
버전
설치 위치
설치 방식
ArgoCD
argo-cd
5.x
argocd
Helm (Terraform)
Prometheus
kube-prometheus-stack
45.x
monitoring
Helm
Grafana
grafana
10.x
monitoring
Helm
Loki
loki
2.x
monitoring
Helm
Fluent Bit
fluent-bit
2.x
monitoring
Helm
2.6.3 ArgoCD로 배포되는 서비스 목록
서비스
Git 경로
Git Revision
설치 위치 (Namespace)
설치 방식
Next.js
charts/fe-app
main
dev / prod
ArgoCD + Helm
Spring Boot
charts/be-app
main
dev / prod
ArgoCD + Helm
2.7.2 Fluent Bit → Loki → Grafana
Fluent Bit은 데몬셋(각 노드에 설치)으로, /var/log/containers/*.log
를 수집
로그를 Loki로 전송하며, Loki는 이를 시계열로 저장
Grafana는 Loki와 연결해 쿼리 기반 대시보드 및 시각화를 지원
Loki는 S3 연동을 통해 장기 저장도 가능함 (boltdb-shipper
+ S3 백엔드)
Node Exporter와 Kubelet 메트릭을 통해 노드/Pod 리소스 수집
Spring 서비스는 Micrometer + Actuator를 통해 /actuator/prometheus
엔드포인트 노출
Prometheus가 이를 scrape 하여 수집 → Grafana에서 대시보드 구성
개발환경(dev)은 Micrometer 기반 단순 수집, 운영(prod)은 시스템 전체 메트릭 포함
GitOps 방식으로 모든 리소스 배포는 GitHub 저장소 기준
ArgoCD는 Helm 기반 애플리케이션을 추적하며, HelmRelease CRD 기반 배포
dev/prod 네임스페이스에 따라 분리된 애플리케이션 정의 적용
방식
설명
예시
Application CRD
ArgoCD가 기본으로 사용하는 방식. Helm Chart도 이 안에서 values 설정 포함해서 직접 관리함.
argocd-app.yaml
안에 helm:
설정이 포함됨
HelmRelease (CRD)
Helm Controller
(예: Flux, Helm Operator)가 설치된 경우 사용하는 CRD. ArgoCD는 HelmRelease라는 Kubernetes 리소스를 추적함.
HelmRelease 리소스를 Git에 선언해두고 ArgoCD가 이를 배포함
각 서비스는 CPU/메모리 기준 HPA 설정 포함
예시: Spring 서비스 기준
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: backend-hpa
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: backend
minReplicas: 2
maxReplicas: 5
metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 60
Prometheus는 메트릭 장기 저장을 위해 PVC 연결 (/prometheus
)
PVC는 standard
스토리지 클래스 기준 5Gi ~ 20Gi로 설정 (EBS 사용)
dev / prod 환경 분리 :
Kubernetes 네임스페이스를 dev
, prod
로 구분하여 리소스 간 격리
ArgoCD Application 리소스에서 각 네임스페이스로 배포 목적지 설정
Helm values 파일도 dev/prod 별도로 관리 (values-dev.yaml
, values-prod.yaml
)
RBAC 및 리소스 쿼리 시 혼선을 줄이고, 운영자/개발자의 권한을 구분할 수 있음
CoreDNS는 클러스터 내 서비스 이름 기반의 DNS 해석을 담당
예: http://backend.dev.svc.cluster.local
형식으로 접근 가능
모든 Pod와 서비스는 DNS 등록을 통해 통신 가능
별도 설정 없이 kubeadm 설치 시 CoreDNS 자동 구성됨
RBAC(Role-Based Access Control)을 통해 사용자/서비스 계정별 권한 분리
admin-role
: 클러스터 관리자용, 모든 네임스페이스에서 리소스 제어 가능
readonly-role
: 개발자/QA용, 읽기 전용 권한만 부여
dev-role
: dev 네임스페이스 한정 권한
필요 시 OIDC 연동으로 사용자 인증도 연계 가능 (예: GitHub SSO)
클러스터 외부 접근은 Bastion EC2를 통해 제한
마스터/워커노드는 Private Subnet에 배치하여 직접 SSH 차단
Bastion만 Public Subnet에 위치하며, 특정 IP에만 포트 22 개방
Grafana : 대시보드는 JSON 내보내기 및 Git 관리
Loki : S3 연동을 통해 로그 장기 저장
Prometheus : 장기 보존이 필요한 경우 EBS-backed PVC 설정 (최소 20Gi)
Kubernetes 리소스 : Helm Chart 및 Kustomize 기반 Git 저장소에 원천 상태 보존 (GitOps)
클러스터는 비용 절감을 위해 시간대별 운영
오전 9시 ~ 오후 6시까지만 인스턴스 유지, 이후 자동 종료
Terraform 또는 AWS Lambda Scheduler를 통해 제어
ArgoCD와 Git 상태 동기화를 통해 재기동 시에도 상태 복원 가능