Kubernetes 입문 — 단일 노드부터 시작
Kubernetes는 어떤 역할을 수행하나요?
Kubernetes(이하 K8s)는 컨테이너 오케스트레이션 플랫폼으로, Docker 등의 컨테이너 런타임에서 실행되는 애플리케이션 인스턴스를 자동으로 배포, 확장, 관리하는 시스템입니다. 단일 노드 환경에서는 마스터 컴포넌트(API 서버, 컨트롤러 매니저, 스케줄러)와 워커 컴포넌트(kubelet, kube-proxy, 컨테이너 런타임)가 동일 서버에서 실행되어 클러스터 제어와 워크로드 실행을 통합 관리합니다. 이 구성은 개발 및 테스트 환경에서 멀티 노드 클러스터와 동일한 API와 워크플로우를 제공합니다.
단일 노드 Kubernetes 환경의 아키텍처는 어떻게 구성되나요?
단일 노드 K8s 클러스터는 하나의 물리 서버 또는 가상 머신 위에 모든 컴포넌트가 컨테이너 또는 시스템 데몬으로 실행됩니다.
마스터 컴포넌트(Control Plane)
**API 서버(kube-apiserver)**는 클러스터의 중앙 제어점으로, 모든 관리 작업의 진입점입니다. RESTful API를 통해 클라이언트(kubectl 포함)의 요청을 수신하고 클러스터 상태를 저장하는 etcd 데이터베이스와 통신합니다. API 서버는 기본적으로 TCP 6443 포트에서 리스닝합니다.
etcd는 분산 키-값 저장소로, K8s 클러스터의 모든 구성 데이터, 상태, 메타데이터를 저장합니다. Raft 합의 알고리즘을 사용하며, 단일 노드 환경에서도 동일하게 작동합니다. 기본 포트는 2379입니다.
**스케줄러(kube-scheduler)**는 생성된 Pod 객체를 분석하여 사용 가능한 노드에 할당합니다. CPU 요청/제한, 메모리 요청/제한, 노드 선택자, 친화성 규칙 등의 제약을 평가하고 최적의 노드를 선택합니다. 단일 노드에서는 모든 Pod을 해당 노드에 배치합니다.
**컨트롤러 매니저(kube-controller-manager)**는 여러 컨트롤 루프를 실행합니다. 주요 컨트롤러는 Deployment 컨트롤러(복제본 수 조정), StatefulSet 컨트롤러(순서 보장), DaemonSet 컨트롤러(모든 노드에 배포) 등입니다.
워커 컴포넌트(Data Plane)
kubelet은 노드에서 실행되는 에이전트로, API 서버로부터 Pod 명세를 받아 컨테이너 런타임에 지시합니다. Pod의 생명 주기를 관리하고 상태를 보고합니다. 기본적으로 TCP 10250 포트에서 실행됩니다.
kube-proxy는 네트워크 프록시로, Service 객체 정의에 따라 트래픽을 적절한 Pod으로 라우팅합니다. iptables 또는 IPVS 모드를 사용하여 클러스터 내부 DNS 해석 및 로드 밸런싱을 수행합니다.
컨테이너 런타임은 실제 컨테이너 실행을 담당합니다. Docker, containerd, CRI-O 등이 지원됩니다. kubelet은 CRI(Container Runtime Interface)를 통해 런타임과 통신합니다.
단일 노드 K8s 클러스터는 어떻게 구성하나요?
가장 접근성 높은 방법은 minikube, kind(Kubernetes in Docker), k3s 등의 경량 배포판을 사용하는 것입니다.
Minikube를 이용한 구성
Minikube는 VirtualBox, Hyper-V, Docker 등의 하이퍼바이저 위에 경량 K8s 환경을 생성합니다. 설치 이후 minikube start 명령으로 단일 노드 클러스터를 초기화하면 kubelet, API 서버, etcd 등이 자동으로 실행됩니다. 기본 메모리 할당은 2GB입니다.
설치 이후 kubectl로 클러스터 상태를 확인할 수 있습니다:
kubectl get nodes
NAME STATUS ROLES AGE VERSION
minikube Ready control-plane 2m34s v1.28.3
Kind(Kubernetes in Docker)를 이용한 구성
Kind는 Docker 컨테이너 자체를 K8s 노드로 사용합니다. 단일 노드 클러스터를 위한 YAML 설정:
kind: Cluster
apiVersion: kind.x-k8s.io/v1alpha4
nodes:
- role: control-plane
image: kindest/node:v1.28.0
Kind는 호스트 머신의 리소스를 Docker 컨테이너 격리 수준에서만 사용하므로, 다중 클러스터 테스트에 유리합니다.
K3s를 이용한 구성
K3s는 Rancher가 제공하는 경량 K8s 배포판으로, 전체 바이너리 크기가 약 100MB입니다. SQLite를 기본 데이터베이스로 사용하며 etcd를 선택적으로 구성할 수 있습니다. 설치:
curl -sfL https://get.k3s.io | sh -
K3s는 서버리스 환경, IoT 장치, 엣지 컴퓨팅 환경에서도 배포 가능합니다.
Pod 배포 메커니즘은 어떻게 작동하나요?
Pod는 K8s의 최소 배포 단위로, 하나 이상의 컨테이너를 포함하는 래퍼입니다. Deployment 객체를 생성하면 다음 프로세스가 실행됩니다:
- 매니페스트 전송: kubectl이 Deployment YAML을 API 서버로 전송합니다.
- 객체 저장: API 서버가 Deployment 정의를 etcd에 저장합니다.
- 컨트롤러 감지: Deployment 컨트롤러가 변화를 감지하고 ReplicaSet을 생성합니다.
- Pod 생성: ReplicaSet 컨트롤러가 지정된 복제본 수만큼 Pod 객체를 생성합니다.
- 스케줄링: 스케줄러가 Pod을 노드에 할당합니다. 단일 노드에서는 해당 노드가 자동 선택됩니다.
- kubelet 실행: 노드의 kubelet이 할당된 Pod 매니페스트를 읽고 컨테이너 런타임에 지시합니다.
- 네트워크 구성: kube-proxy가 Pod을 위한 네트워크 정책을 적용합니다.
- 상태 보고: kubelet이 Pod 상태를 API 서버로 업데이트합니다.
전체 프로세스는 일반적으로 3~10초 소요됩니다.
단일 노드 환경의 네트워크 구성은 어떻게 되나요?
Pod 간 통신
K8s는 모든 Pod에 고유한 IP 주소를 할당합니다. 단일 노드 환경에서는 Flannel, Calico, Weave 등의 네트워크 플러그인(CNI, Container Network Interface)이 Pod 네트워크를 구성합니다. Flannel은 기본적으로 10.244.0.0/16 서브넷을 사용하며, 각 Pod은 이 범위 내에서 고유한 IP를 받습니다.
Service를 통한 Pod 노출
Service 객체는 안정적인 엔드포인트를 제공하고 트래픽을 여러 Pod에 분산합니다. ClusterIP 타입 Service는 클러스터 내부 DNS 이름(예: myapp.default.svc.cluster.local)을 통해 접근할 수 있습니다. NodePort 타입은 호스트 머신의 지정된 포트(30000~32767 범위)를 통해 외부 접근을 허용합니다.
예시: NodePort Service 생성 시 트래픽 흐름:
호스트 머신(192.168.1.100:31234)
↓ (kube-proxy의 iptables 규칙)
↓
Service ClusterIP(10.96.45.67:80)
↓ (Service Selector 매칭)
↓
Pod IP(10.244.0.10:8080)
영구 스토리지는 단일 노드에서 어떻게 관리되나요?
PersistentVolume(PV)과 PersistentVolumeClaim(PVC)
K8s는 스토리지를 PersistentVolume 객체로 추상화합니다. 단일 노드 환경에서는 hostPath 타입 PV를 사용하여 호스트 머신의 디렉터리를 Pod에 마운트할 수 있습니다.
hostPath 설정 예시:
apiVersion: v1
kind: PersistentVolume
metadata:
name: pv-data
spec:
capacity:
storage: 10Gi
accessModes:
- ReadWriteOnce
hostPath:
path: /data/k8s
PersistentVolumeClaim은 스토리지 요청을 정의하며, Pod은 PVC를 마운트하여 실제 스토리지에 접근합니다. 단일 노드에서 hostPath를 사용할 경우 노드 장애 시 데이터 손실 위험이 있으므로, 프로덕션 환경에서는 사용하지 않습니다.
리소스 관리와 제한은 어떻게 설정하나요?
K8s에서 Pod 및 컨테이너의 리소스 사용을 제어하기 위해 requests와 limits를 정의합니다.
| 설정항목 | 단위 | 설명 | 예시 |
|---|---|---|---|
| CPU request | m(밀리코어) | 스케줄링 시 최소 보장 CPU | 250m = 0.25 vCPU |
| CPU limit | m(밀리코어) | 최대 사용 가능 CPU | 500m = 0.5 vCPU |
| Memory request | Mi/Gi | 스케줄링 시 최소 보장 메모리 | 256Mi = 256MB |
| Memory limit | Mi/Gi | 최대 사용 가능 메모리 | 512Mi = 512MB |
스케줄러는 request 값을 기준으로 Pod 배치 결정을 내리며, kubelet은 limit 값을 초과하는 리소스 사용을 강제 제한합니다. 메모리 초과 시 Pod은 OOMKilled(Out Of Memory Killed) 상태로 종료됩니다.
단일 노드 환경의 실제 적용 사례는 어떻게 되나요?
개발 및 테스트 환경
Minikube 또는 kind를 이용하여 개발자 로컬 머신에서 멀티 노드 클러스터와 동일한 K8s API를 경험할 수 있습니다. Docker Desktop에 내장된 K8s 클러스터는 단일 노드 구성으로 제공되며, 대한민국의 스타트업 및 중소 IT 개발팀에서 널리 사용 중입니다(GitHub 2024 개발자 환경 조사 참조).
엣지 컴퓨팅 및 IoT
K3s 기반 단일 노드 클러스터는 산업용 PC, 네트워크 기기, 의료 진단 장비 등 자원 제한 환경에 배포됩니다. Arm 아키텍처(Raspberry Pi 포함) 지원으로 엣지 노드에서 직접 실행 가능합니다.
애플리케이션 프로토타이핑
스타트업 및 신생 프로젝트에서 단일 노드 K8s를 통해 컨테이너 오케스트레이션 개념을 초기에 검증한 후 필요에 따라 멀티 노드로 확장합니다. 이 방식은 초기 인프라 비용 최소화와 학습 곡선을 완화합니다.
정리하면 Kubernetes 단일 노드 환경의 가치는 무엇인가요?
단일 노드 K8s는 마스터와 워커 컴포넌트를 단일 서버에서 통합 운영하면서도 멀티 노드 클러스터와 동일한 API, 워크플로우, 보안 모델을 제공합니다. Minikube, Kind, K3s 등의 경량 배포판을 통해 개발자가 로컬 환경에서 프로덕션과 동일한 구성을 테스트할 수 있으며, 엣지 디바이스나 리소스 제약 환경에 직접 배포 가능합니다. 리소스 요청/제한, 네트워크 정책, 스토리지 추상화 등의 기능을 통해 경량이면서도 완전한 오케스트레이션 환경을 구현할 수 있습니다. 다만 단일 노드는 고가용성 구성이 불가능하므로 프로덕션 미션 크리티컬 워크로드에는 부적합합니다.
자주 묻는 질문
Kubernetes와 Docker의 차이는 무엇인가요?
Docker는 컨테이너를 생성, 실행하는 런타임입니다. Kubernetes는 Docker 등의 런타임이 생성한 컨테이너 여러 개를 자동으로 배포, 확장, 관리하는 오케스트레이션 플랫폼입니다. Docker는 단일 호스트 관점의 도구이고, Kubernetes는 클러스터(다수 호스트) 관점의 시스템입니다.
단일 노드 Kubernetes에서 여러 Pod을 실행하면 서로 통신할 수 있나요?
가능합니다. K8s의 CNI(Container Network Interface) 플러그인이 모든 Pod에 고유한 IP 주소를 할당하고 네트워크를 구성합니다. 같은 노드의 Pod들은 이 네트워크를 통해 IP 주소로 직접 통신할 수 있습니다. 또한 Service 객체를 통해 DNS 이름으로도 접근 가능합니다.
hostPath PersistentVolume은 왜 프로덕션에 부적합한가요?
hostPath는 특정 노드의 로컬 디렉터리를 PV로 사용합니다. 단일 노드 환경에서는 노드 장애 시 데이터가 손실되고 복구 방법이 없습니다. 또한 다중 노드로 확장할 경우 Pod이 다른 노드로 이동하면 이전 노드의 데이터에 접근 불가능해집니다. 프로덕션에서는 NFS, Ceph, 클라우드 매니지드 스토리지(EBS, GCE Persistent Disk) 등을 사용해야 합니다.
단일 노드 Kubernetes의 메모리/CPU 오버헤드는 얼마나 되나요?
Minikube 기본 구성(메모리 2GB, CPU 2코어 할당 시)에서 K8s 컴포넌트(API 서버, etcd, kubelet 등)는 약 400~600MB 메모리를 사용합니다. 따라서 애플리케이션에 최소 1.4GB 이상의 메모리가 남습니다. 프로덕션 워크로드 테스트를 위해서는 호스트에 4GB 이상의 메모리 할당을 권장합니다.
Kubernetes 클러스터를 단일 노드에서 멀티 노드로 확장할 때 애플리케이션 코드 변경이 필요한가요?
불필요합니다. K8s API와 매니페스트(Deployment, Service, PersistentVolumeClaim 등) 정의는 노드 수와 무관하게 동일합니다. 단일 노드에서 작동하던 Deployment와 Service 정의를 그대로 멀티 노드 클러스터에 적용할 수 있습니다. 다만 hostPath PV는 멀티 노드 환경에서 작동하지 않으므로 공유 스토리지로 변경해야 합니다.