시리즈 안내
이 글은 “중소기업 쿠버네티스 구축” 시리즈의 1편입니다. 0편에서 “쿠버네티스가 무엇이고 왜 K3s인가”를 정리했다면, 이번 편에서는 실제로 클러스터를 몇 대로, 어떤 사양으로, 어떻게 나눌지 설계합니다. 아직 설치는 하지 않습니다. 종이 위에서 먼저 그림을 완성하는 단계입니다.
들어가며
집을 짓기 전에 설계도를 그리듯, 클러스터도 첫 명령어를 치기 전에 구조를 정해야 합니다. 노드를 몇 대로 할지, 각 노드에 어떤 역할을 줄지, IP는 어떻게 나눌지를 미리 정해두지 않으면, 나중에 서비스가 늘어났을 때 “이 IP는 뭐였더라?”, “이 노드에 이걸 띄워도 되나?” 하는 혼란이 시작됩니다.
이번 편의 목표는 세 가지입니다.
- 노드 구성 — 몇 대를, 어떤 역할로 나눌 것인가
- 노드 사양 — 각 노드에 CPU·RAM·디스크를 얼마나 줄 것인가
- IP 정책 — 노드와 서비스 IP를 어떤 규칙으로 할당할 것인가
이 세 가지가 정해지면, 다음 편부터는 그 설계대로 VM을 만들고 OS를 올리면 됩니다.
1. 노드 구성: 왜 4대인가
쿠버네티스 클러스터는 크게 컨트롤 플레인(control plane)과 워커(worker)로 나뉩니다.
- 컨트롤 플레인(마스터): 클러스터의 두뇌입니다. “어느 워커에 무엇을 띄울지” 결정하고, 전체 상태를 관리합니다. 실제 애플리케이션은 여기서 돌리지 않는 게 원칙입니다.
- 워커: 실제 애플리케이션 컨테이너(Pod)가 돌아가는 일꾼 노드입니다.
우리는 마스터 1대 + 워커 3대, 총 4대 구성으로 갑니다. 각 노드의 역할은 이렇게 나눴습니다.
| 노드 | 호스트명 | 역할 |
|---|---|---|
| 마스터 | dzpik8smsys | 컨트롤 플레인 (스케줄링·상태 관리) |
| 워커 #1 | dzpik8swapp | 앱 워크로드 (프론트엔드·API) |
| 워커 #2 | dzpik8swapp | 앱 워크로드 (프론트엔드·API) — #1과 이중화 |
| 워커 #3 | dzpik8sosys | 플랫폼 워크로드 (ArgoCD·MinIO·모니터링) |
역할을 나눈 이유
앱 워커를 2대(이중화)로 둔 이유는 가용성입니다. 프론트엔드와 API 같은 실서비스를 두 노드에 분산하면, 한 노드가 죽어도 나머지 노드에서 서비스가 계속됩니다. 쿠버네티스가 죽은 Pod를 살아 있는 노드로 자동 재배치해주죠.
플랫폼 워커를 따로 1대 둔 이유는 격리입니다. ArgoCD(배포 도구), MinIO(스토리지), 모니터링 같은 관리용 시스템을 실서비스와 같은 노드에 섞으면, 모니터링이 리소스를 많이 먹을 때 실서비스가 영향을 받을 수 있습니다. 성격이 다른 워크로드를 물리적으로 분리해두면 서로 간섭하지 않습니다.
단일 마스터는 괜찮은가?
운영 환경에서 완벽한 고가용성을 원하면 마스터도 3대로 묶는 HA 컨트롤 플레인을 구성합니다. 하지만 중소기업 규모에서는 마스터 1대로도 충분한 경우가 많고, 마스터가 잠깐 죽어도 이미 떠 있는 워크로드는 계속 동작합니다(새 배포·스케일링만 일시 중단). 리소스와 운영 복잡도를 고려해 우리는 단일 마스터로 시작하고, 필요해지면 나중에 HA로 확장하는 전략을 택했습니다.
2. 노드 사양: 얼마나 줘야 하나
VM을 만들 때 가장 고민되는 부분이 사양입니다. 너무 적게 주면 불안정하고, 너무 많이 주면 자원이 낭비됩니다. 실제 워크로드를 기준으로 산정한 권장 사양은 다음과 같습니다.
| 노드 | CPU | RAM | 디스크 | 용도 |
|---|---|---|---|---|
| 마스터 | 4 vCPU | 8192 MB | 210 GB | control plane, etcd |
| 앱 워커 ×2 | 8 vCPU | 16384 MB | 210 GB | 앱 워크로드 |
| 플랫폼 워커 | 8 vCPU | 16384 MB | 210 GB | ArgoCD·MinIO·모니터링 |
RAM은
8G가 아니라8192 MB처럼 정확한 MB 단위로 적었습니다. VM 생성 화면에서 보통 MB로 입력하기 때문에, 처음부터 정확한 숫자로 표기해두면 실수가 줄어듭니다.
산정 근거
마스터 (4 vCPU / 8192 MB) — 컨트롤 플레인은 워크로드를 직접 받지 않으므로 CPU·RAM이 많이 필요하진 않습니다. 다만 etcd(클러스터 상태 저장소)가 디스크 I/O에 민감하므로, 마스터 디스크는 SSD를 강력히 권장합니다. etcd가 느린 디스크에 올라가면 클러스터 전체가 느려집니다.
앱 워커 (8 vCPU / 16384 MB) — 실제로 돌릴 마이크로서비스를 기준으로 추산했습니다. Spring Boot 같은 JVM 앱은 노드당 5~7개 정도 돌린다고 보면, Pod 리소스 요청 합계 + OS·kubelet 오버헤드 + 트래픽 spike 여유를 더해 이 정도가 안정적입니다. 트래픽이 많으면 RAM을 32768 MB로 올리는 것도 좋은 선택입니다.
플랫폼 워커 (8 vCPU / 16384 MB) — ArgoCD, MinIO 정도는 가볍지만, 나중에 Prometheus + Grafana + Loki 같은 모니터링 스택이 들어오면 RAM을 가장 많이 먹는 노드가 됩니다. 그래서 앱 워커와 동일한 사양으로 여유를 뒀습니다.
디스크 분리
각 노드의 디스크는 용도별로 나눴습니다. OS 디스크 하나에 모든 걸 몰아넣지 않고, 데이터·로그·앱 영역을 분리하면 한쪽이 가득 차도 시스템 전체가 멈추지 않습니다.
OS 디스크 : 기본 (운영체제)
/app (20GB) : 애플리케이션 영역
/log (20GB) : 로그 (가득 차도 OS에 영향 없음)
/data (50GB) : 영속 데이터 (PV 저장소 등)
로그 분리가 중요한 이유: 로그가 OS 디스크를 가득 채우면 노드 전체가 마비됩니다.
/log를 따로 떼어두면, 로그가 폭주해도 그 파티션만 차고 시스템은 살아 있습니다. 운영 사고를 한 번이라도 겪어보면 이 분리의 가치를 절감하게 됩니다.
3. IP 정책: 규칙 없는 할당은 미래의 빚이다
여기가 이번 편에서 가장 강조하고 싶은 부분입니다. IP를 주먹구구로 할당하면 반드시 후회합니다.
서비스가 5개일 때는 외워도, 20개가 되면 “10.0.12.117이 뭐였지?”를 매번 찾아봐야 합니다. 그래서 처음부터 10단위로 용도를 묶는 규칙을 정했습니다.
IP 할당 정책 (예: 10.0.12.0/24 운영 대역)
.1 게이트웨이 (OPNsense)
.2-29 네트워크 인프라
.30-39 스토리지 (.30 TrueNAS)
.40-49 예약
.50-59 CI/CD (.51 Gitea+Jenkins)
.61-99 K8s 외부 서비스 (VM 기반)
.101-149 K8s 클러스터 노드
.150-199 예약 (확장용)
.200-220 MetalLB 풀 (.200 Ingress)
.221-254 예약
이렇게 묶어두면 IP만 봐도 그게 무엇인지 짐작할 수 있습니다. .30번대면 스토리지, .50번대면 CI/CD, .200번대면 로드밸런서 IP — 이런 식으로요.
클러스터 노드 IP
위 정책의 .101-149 구간을 노드에 할당합니다.
| 노드 | IP | 역할 |
|---|---|---|
| 마스터 | 10.0.12.101 | control plane |
| 앱 워커 #1 | 10.0.12.111 | app |
| 앱 워커 #2 | 10.0.12.112 | app |
| 플랫폼 워커 | 10.0.12.116 | platform |
마스터는
.101, 워커는.11x로 묶어 한눈에 구분되게 했습니다. “마스터는 101, 워커는 11x”처럼 외우기 쉬운 규칙이 운영 중 실수를 줄입니다.
dev와 prd 대역 분리
개발 환경과 운영 환경은 네트워크 대역 자체를 분리했습니다.
| 환경 | 대역 | 비고 |
|---|---|---|
| 개발 (dev) | 10.0.31.0/24 | 개발 K3s 클러스터 |
| 운영 (prd) | 10.0.12.0/24 | 운영 K3s 클러스터 |
같은 IP 할당 정책(10단위 묶음)을 두 대역에 동일하게 적용하면, dev에서 .101이 마스터였듯 prd에서도 .101이 마스터입니다. 환경은 달라도 규칙은 같으니 머릿속 지도 하나로 양쪽을 다 운영할 수 있습니다.
4. 클러스터 내부 네트워크: Pod와 Service CIDR
노드 IP(우리가 보는 실제 네트워크) 외에, 쿠버네티스는 내부 전용 가상 네트워크를 두 개 더 씁니다.
- Pod CIDR: 각 Pod에 부여되는 클러스터 내부 IP 대역
- Service CIDR: Service(여러 Pod를 묶는 가상 진입점)에 부여되는 대역
이건 클러스터 내부에서만 쓰이는 사설 대역이라 외부 네트워크와 겹치지만 않으면 됩니다. 다만 dev와 prd가 서로 통신할 가능성을 고려해, 두 환경의 내부 대역도 겹치지 않게 분리했습니다.
| 항목 | dev | prd |
|---|---|---|
| Pod CIDR | 10.42.0.0/16 | 10.44.0.0/16 |
| Service CIDR | 10.43.0.0/16 | 10.45.0.0/16 |
dev는 K3s 기본값(10.42/10.43)을 그대로 쓰고, prd는 한 칸씩 밀어 10.44/10.45로 분리했습니다. 이렇게 해두면 나중에 두 클러스터를 연결하거나 마이그레이션할 때 IP 충돌을 피할 수 있습니다.
이 CIDR 값들은 다음 편에서 K3s를 설치할 때 실제로 지정합니다. 지금은 “이런 게 있고, 왜 분리하는지”만 알아두면 됩니다.
5. 전체 아키텍처 그림
지금까지 정한 것을 한 장으로 모으면 이렇게 됩니다.
[외부 클라이언트]
│ HTTPS
▼
[OPNsense + Caddy] ← TLS 종단 + DNS
│ HTTP
▼
[MetalLB VIP 10.0.12.200]
│
▼
[Ingress-NGINX]
│ Host 헤더 라우팅
┌───────────────────┼───────────────────┐
▼ ▼ ▼
┌──────────────┐ ┌──────────────┐ ┌──────────────┐
│ 앱 워커 #1 │ │ 앱 워커 #2 │ │ 플랫폼 워커 │
│ .111 │ │ .112 │ │ .116 │
│ 프론트·API │ │ 프론트·API │ │ ArgoCD·MinIO │
│ role=app │ │ role=app │ │ role=platform │
└──────────────┘ └──────────────┘ └──────────────┘
└───────────────────┼───────────────────┘
│
┌──────────────┐
│ 마스터 .101 │
│ control plane │
│ (워크로드 X) │
└──────────────┘
role=app과 role=platform이라는 라벨이 보일 텐데, 이건 03편에서 노드에 실제로 붙일 역할 라벨입니다. 이 라벨을 기준으로 “이 워크로드는 app 노드에만, 저 워크로드는 platform 노드에만” 배치하도록 쿠버네티스에 지시할 수 있습니다.
마치며
1편에서는 설계도를 완성했습니다. 핵심을 정리하면:
- 4대 구성: 마스터 1 + 앱 워커 2(이중화) + 플랫폼 워커 1. 성격이 다른 워크로드를 노드로 분리했습니다.
- 사양: 마스터는 가볍게(4C/8G, SSD 필수), 워커는 넉넉하게(8C/16G). 디스크는 OS·app·log·data로 분리했습니다.
- IP 정책: 10단위로 용도를 묶는 규칙을 정해, IP만 봐도 용도를 알 수 있게 했습니다. dev/prd는 대역과 내부 CIDR까지 분리했습니다.
설계가 끝났으니, 다음 편부터는 손을 움직입니다. 02편에서는 4대 VM에 OS를 올린 직후 해야 할 공통 작업 — swap off, 시간 동기화, 커널 모듈, sysctl 설정 — 을 하나씩 진행합니다. 쿠버네티스가 정상 동작하기 위한 OS 차원의 토대를 다지는 단계입니다.
이전 글: 중소기업 쿠버네티스 구축 – 00. 쿠버네티스란: 개념과 도입 판단
다음 글: 중소기업 쿠버네티스 구축 – 02. OS 사전 준비: 전 노드 공통 세팅 (swap·chrony·커널 모듈·sysctl)