Kubernetes 개발·운영 실전 1편 — 로컬 개발 환경 구성 (Kind + Skaffold)
Kind로 로컬 Kubernetes 클러스터를 구성하고 Skaffold와 Tilt로 개발 루프를 단축하는 방법. 프로덕션과 동일한 환경에서 개발하는 실전 가이드.
왜 로컬 Kubernetes 환경이 필요한가
docker run으로 충분했던 시대는 지나갔습니다. 서비스가 Deployment, Service, ConfigMap, Ingress로 구성되는 순간, 로컬에서도 동일한 구조로 개발해야 합니다. 환경 차이로 발생하는 “로컬에선 됐는데 클러스터에서 안 됨” 문제를 원천 차단하는 것이 목표입니다.
1. Kind로 로컬 클러스터 구성
Kind(Kubernetes IN Docker)는 Docker 컨테이너를 노드로 사용하는 경량 클러스터입니다. CI 환경에서도 동일하게 사용할 수 있어 dev/CI 일관성이 높습니다.
설치
# macOS
brew install kind
# Linux
curl -Lo ./kind https://kind.sigs.k8s.io/dl/v0.23.0/kind-linux-amd64
chmod +x ./kind && mv ./kind /usr/local/bin/kind
멀티 노드 클러스터 설정
# kind-cluster.yaml
kind: Cluster
apiVersion: kind.x-k8s.io/v1alpha4
nodes:
- role: control-plane
kubeadmConfigPatches:
- |
kind: InitConfiguration
nodeRegistration:
kubeletExtraArgs:
node-labels: "ingress-ready=true"
extraPortMappings:
- containerPort: 80
hostPort: 80
- containerPort: 443
hostPort: 443
- role: worker
- role: worker
kind create cluster --config kind-cluster.yaml --name local
kubectl cluster-info --context kind-local
Ingress 컨트롤러 설치
kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/main/deploy/static/provider/kind/deploy.yaml
kubectl wait --namespace ingress-nginx \
--for=condition=ready pod \
--selector=app.kubernetes.io/component=controller \
--timeout=90s
2. Skaffold로 개발 루프 자동화
Skaffold는 코드 변경 감지 → 이미지 빌드 → 클러스터 배포를 자동화합니다. skaffold dev 명령 하나로 파일 저장 시마다 반영됩니다.
설치
# macOS
brew install skaffold
# Linux
curl -Lo skaffold https://storage.googleapis.com/skaffold/releases/latest/skaffold-linux-amd64
chmod +x skaffold && mv skaffold /usr/local/bin
skaffold.yaml 구성
apiVersion: skaffold/v4beta11
kind: Config
metadata:
name: my-app
build:
artifacts:
- image: my-app
docker:
dockerfile: Dockerfile
local:
push: false # 로컬 클러스터는 push 불필요
deploy:
kubectl:
manifests:
- k8s/*.yaml
portForward:
- resourceType: service
resourceName: my-app
port: 8080
localPort: 8080
개발 모드 실행
# 파일 변경 감지 + 자동 배포
skaffold dev
# 한 번만 빌드/배포
skaffold run
# 배포된 리소스 정리
skaffold delete
3. Tilt — 더 세밀한 제어가 필요할 때
Tilt는 Skaffold보다 설정이 유연하고 웹 UI 대시보드를 제공합니다. 마이크로서비스가 여러 개인 경우 서비스별 상태를 한눈에 볼 수 있습니다.
Tiltfile 기본 구성
# Tiltfile
docker_build('my-app', '.',
live_update=[
sync('./src', '/app/src'), # 소스 파일 실시간 동기화
run('cd /app && npm install', # 패키지 변경 시만 실행
trigger=['./package.json']),
]
)
k8s_yaml(['k8s/deployment.yaml', 'k8s/service.yaml'])
k8s_resource('my-app',
port_forwards=8080,
labels=['frontend']
)
tilt up # 웹 UI: http://localhost:10350
tilt down # 정리
4. 로컬 이미지 레지스트리 구성
Kind는 기본적으로 외부 레지스트리를 사용하는데, 로컬 레지스트리를 연결하면 이미지 push/pull 속도가 빨라집니다.
#!/bin/bash
# local-registry.sh
# 로컬 레지스트리 컨테이너 시작
docker run -d --restart=always -p 5001:5000 --name registry registry:2
# Kind 클러스터와 네트워크 연결
docker network connect kind registry
# Kind에 레지스트리 설정 등록
kubectl apply -f - <<EOF
apiVersion: v1
kind: ConfigMap
metadata:
name: local-registry-hosting
namespace: kube-public
data:
localRegistryHosting.v1: |
host: "localhost:5001"
help: "https://kind.sigs.k8s.io/docs/user/local-registry/"
EOF
이제 localhost:5001/my-app:latest로 이미지를 push하면 Kind 클러스터에서 바로 사용 가능합니다.
5. 실전 디렉터리 구조
my-project/
├── src/ # 애플리케이션 소스
├── Dockerfile
├── skaffold.yaml
├── kind-cluster.yaml
└── k8s/
├── namespace.yaml
├── deployment.yaml
├── service.yaml
├── ingress.yaml
└── configmap.yaml
로컬 개발에서도 k8s/ 디렉터리를 프로덕션과 동일한 구조로 유지하면, 환경별 차이를 최소화할 수 있습니다.
6. 자주 쓰는 디버깅 명령
# Pod 로그 실시간 확인
kubectl logs -f deployment/my-app
# Pod 내부 접속
kubectl exec -it deployment/my-app -- /bin/sh
# 이벤트 확인 (에러 원인 파악)
kubectl get events --sort-by='.lastTimestamp'
# 포트 포워딩 (서비스 직접 접근)
kubectl port-forward svc/my-app 8080:8080
# 리소스 상태 실시간 감시
watch kubectl get pods,svc,ingress
정리
| 도구 | 특징 | 추천 상황 |
|---|---|---|
| Kind | 경량, CI 친화적 | 단일 서비스, CI 파이프라인 |
| Skaffold | 설정 간단, 빠른 시작 | 초기 프로젝트, 소규모 팀 |
| Tilt | 웹 UI, 세밀한 제어 | 마이크로서비스, 복잡한 의존성 |
다음 편에서는 Namespace와 RBAC 설계를 다룹니다. 팀과 환경을 어떻게 분리하고 최소 권한을 부여하는지 알아봅니다.