Kubernetes minikube로 Node API 배포하기 | Deployment·Service·kubectl 실전

Kubernetes minikube로 Node API 배포하기 | Deployment·Service·kubectl 실전

이 글의 핵심

minikube로 로컬 Kubernetes를 띄우고 Node API 컨테이너를 Deployment·Service로 배포하며 kubectl로 검증·디버깅하는 흐름을 한 번에 정리합니다.

들어가며

Kubernetes는 컨테이너를 선언적 YAML로 배치·스케일·복구하는 오케스트레이션 도구입니다. 프로덕션 전에 로컬에서 동일한 리소스 모델(Pod·Deployment·Service)을 익히려면 minikube가 여전히 널리 쓰이는 선택지입니다. Kubernetes minikube 배포 입문은 “클러스터를 띄우고, 이미지를 넣고, kubectl apply로 서비스까지 연결”까지의 최소 루프를 의미합니다.

Node.js API는 상태 없는 HTTP 서버에 잘 맞고, 헬스 엔드포인트graceful shutdown만 갖추면 Deployment의 liveness/readiness probe와 자연스럽게 맞물립니다. 이 글은 2026년 기준 minikube·containerd 환경을 가정하고, Docker로 빌드한 이미지를 클러스터에 올리는 두 가지 방식(minikube image load, minikube docker-env)을 모두 다룹니다.

배포 파이프라인에서는 Node.js 테스트·GitHub Actions CI/CD로 이미지 전에 품질을 고정하고, 단일 호스트 스택은 Docker Compose·Node.js 배포 가이드와 이어집니다. C++·네이티브 바이너리는 C++ Docker·C++ GitHub Actions에서 같은 빌드→이미지→실행 패턴을 확인할 수 있습니다. API 뒤의 데이터 계층은 Node.js DB 연동·C++ DB 연동과, 캐시·엣지는 Redis 캐싱·Nginx·PostgreSQL vs MySQL 선택과 연결해 읽으면 좋습니다. 노드·컨테이너 호스트 용량은 Linux 디스크/inode 이슈와도 맞닿습니다.

비유로 말씀드리면, Kubernetes는 함대를 지휘하는 시스템(원하는 척 수·버전을 선언하면 스케줄러가 맞춥니다)이고, ReplicaSet·Deployment자동 복구에 가깝습니다—Pod가 죽으면 같은 스펙으로 다시 띄우려 합니다. Service는 Pod가 바뀌어도 안정적인 접속 이름·포트를 유지하는 교량 역할을 합니다.

이 글을 읽으면

  • minikube 시작·중지와 kubectl 컨텍스트 연결 방법을 익히실 수 있습니다
  • Deployment·Service YAML로 Node API를 배포하고 포트포워드로 검증하실 수 있습니다
  • 로컬 전용 이미지 빌드·로드 패턴과 흔한 오류(ImagePullBackOff 등) 대응법을 파악하실 수 있습니다

목차

  1. 개념 설명
  2. 실전 구현
  3. 고급 활용
  4. 성능·비교
  5. 실무 사례
  6. 트러블슈팅
  7. 마무리

개념 설명

Kubernetes에서 Node API가 자리 잡는 방식

리소스역할
Pod컨테이너 실행의 최소 단위(보통 Deployment가 생성·유지)
Deployment원하는 레플리카 수, 롤링 업데이트, 이미지 버전을 선언
ServicePod에 안정적인 DNS·포트를 부여(ClusterIP, NodePort, LoadBalancer)

minikube는 단일 노드지만 API 서버·스케줄러·kubelet이 갖춰져 있어 프로덕션과 같은 kubectl 명령·매니페스트를 연습할 수 있습니다.

왜 minikube인가

  • 비용 없이 Ingress·HPA·Metrics API 등을 실습할 수 있습니다(애드온).
  • 팀 온보딩 시 “Docker Compose만 쓰던 사람”이 선언적 배포로 넘어가는 데 적합합니다.

실전 구현

1) 사전 준비

  • Docker 또는 minikube가 사용할 VM 드라이버
  • kubectl, minikube (패키지 매니저 또는 공식 바이너리, 2026년 기준 최신 안정판 권장)
minikube version
kubectl version --client

2) minikube 클러스터 기동

minikube start --driver=docker   # 또는 vm 드라이버
kubectl cluster-info
kubectl get nodes
  • minikube start --driver=docker: 로컬에 단일 노드 클러스터를 띄웁니다. Docker 드라이버는 호스트 Docker 위에 VM/노드가 올라가는 형태라 리소스를 적게 쓰는 편입니다.
  • kubectl cluster-info: API 서버 엔드포인트가 응답하는지 확인합니다.
  • kubectl get nodes: 노드가 Ready인지 봅니다.

kubectl이 minikube를 가리키는지 확인합니다.

kubectl config current-context
# 예: minikube

3) Node.js API 예시 (헬스 포함)

server.mjs:

import http from 'http';

const port = Number(process.env.PORT || 3000);

const server = http.createServer((req, res) => {
  if (req.url === '/health') {
    res.writeHead(200, { 'Content-Type': 'application/json' });
    res.end(JSON.stringify({ status: 'ok' }));
    return;
  }
  res.writeHead(200, { 'Content-Type': 'text/plain; charset=utf-8' });
  res.end('hello from node on k8s\n');
});

server.listen(port, '0.0.0.0', () => {
  console.log(`listening on ${port}`);
});

Dockerfile:

FROM node:22-alpine
WORKDIR /app
COPY server.mjs .
ENV NODE_ENV=production
EXPOSE 3000
USER node
CMD ["node", "server.mjs"]

로컬에서 빌드:

docker build -t demo-node-api:1.0.0 .

4) 이미지를 minikube가 보도록 하기 (택1)

방법 A — minikube Docker 데몬에 직접 빌드

eval $(minikube docker-env)
docker build -t demo-node-api:1.0.0 .
eval $(minikube docker-env -u)

방법 B — 호스트에서 빌드 후 로드

docker build -t demo-node-api:1.0.0 .
minikube image load demo-node-api:1.0.0

5) Deployment·Service 매니페스트

deployment.yaml:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: demo-node-api
spec:
  replicas: 2
  selector:
    matchLabels:
      app: demo-node-api
  template:
    metadata:
      labels:
        app: demo-node-api
    spec:
      containers:
        - name: api
          image: demo-node-api:1.0.0
          imagePullPolicy: IfNotPresent
          ports:
            - containerPort: 3000
          env:
            - name: PORT
              value: '3000'
          readinessProbe:
            httpGet:
              path: /health
              port: 3000
            initialDelaySeconds: 3
            periodSeconds: 5
          livenessProbe:
            httpGet:
              path: /health
              port: 3000
            initialDelaySeconds: 10
            periodSeconds: 10
---
apiVersion: v1
kind: Service
metadata:
  name: demo-node-api
spec:
  selector:
    app: demo-node-api
  ports:
    - port: 80
      targetPort: 3000
  type: ClusterIP

적용:

kubectl apply -f deployment.yaml
kubectl rollout status deployment/demo-node-api
kubectl get pods,svc
  • kubectl apply -f: 매니페스트를 선언 상태로 클러스터에 반영합니다(이미 있으면 필요한 부분만 갱신).
  • rollout status: 새 ReplicaSet으로 롤아웃이 끝났는지 기다립니다.
  • get pods,svc: Pod와 Service가 원하는 대로 떴는지 확인합니다.

6) 접속 확인

kubectl port-forward service/demo-node-api 8080:80
# 다른 터미널
curl -s http://127.0.0.1:8080/health
  • kubectl port-forward service/... 로컬포트:서비스포트: 클러스터 안의 ClusterIP Service를 로컬 포트로 임시로 이어 브라우저·curl로 검증할 때 씁니다.

매니페스트에서 읽을 포인트

  • readinessProbe: 트래픽을 받을 준비가 됐는지 봅니다. 실패하면 Service 엔드포인트에서 빠져 준비 안 된 Pod로 요청이 가지 않게 합니다.
  • livenessProbe: 데드락·무한 루프처럼 살아 있지만 일을 못 하는 컨테이너를 재시작하는 데 쓰입니다.
  • initialDelaySeconds / periodSeconds: 기동 직후 프로브 실패로 재시작 루프에 빠지지 않도록 유예와 주기를 조정합니다.

고급 활용

  • ConfigMap·Secret: 환경별 PORT가 아니라 외부 API 키·DB URL은 Secret으로 분리합니다.
  • Resource limits: resources.requests / limits로 OOM·스로틀링을 제어합니다.
  • Ingress 애드온: minikube addons enable ingress 후 Ingress 리소스로 호스트 기반 라우팅을 연습합니다.
  • 네임스페이스: kubectl create ns dev-n dev로 팀·환경을 격리합니다.

성능·비교

항목메모
레플리카로컬 CPU에 맞춰 1~2개가 일반적; 스케일 아웃은 워커 노드가 여럿인 클러스터에서 의미가 큼
프로브 주기너무 짧으면 부하, 너무 길면 트래픽이 죽은 Pod로 감—staging에서 조정
이미지 크기alpine 베이스·멀티스테이지 빌드로 풀 시간을 줄이면 롤아웃이 빨라짐

실무 사례

  • CI 파이프라인: 이미지를 레지스트리에 푸시한 뒤 image: registry/app:git-sha로 Deployment만 바꾸는 흐름으로 확장합니다(로컬은 레지스트리 없이 image load로 대체).
  • 개발자 랩톱: Compose로 띄우던 API를 동일 Dockerfile로 빌드해 minikube에 올려, 스테이징과 같은 YAML을 리뷰합니다.
  • 장애 연습: Pod 하나를 kubectl delete pod로 지워 ReplicaSet이 재생성하는지 확인합니다.

트러블슈팅

증상점검
ImagePullBackOff이미지가 노드에 없음 → minikube image load 또는 minikube docker-env 빌드 확인, imagePullPolicy: Never는 로컬 전용
CrashLoopBackOffkubectl logs deploy/demo-node-api --previous, 프로브 경로·포트 불일치
kubectl이 다른 클러스터를 봄kubectl config use-context minikube
Service는 있는데 연결 안 됨targetPort와 컨테이너 containerPort 일치, kubectl get endpoints demo-node-api

마무리

Kubernetes minikube 배포 입문의 핵심은 이미지를 클러스터가 읽을 수 있게 만든 뒤, Deployment로 Pod를 유지하고 Service로 안정적으로 노출하는 것입니다. 이 루프가 익숙해지면 프로덕션의 Ingress·GitOps·HPA로 확장하기 훨씬 수월합니다. Compose 기반 배포와 병행해 비교해 보세요.