05_01 쿠버네티스 볼륨 기초 실습 가이드
📚 실습 개요
이 실습에서는 쿠버네티스의 기본 볼륨 타입인 emptyDir과 hostPath를 직접 사용해보면서 볼륨의 기본 개념과 활용 패턴을 학습합니다.
기본실습 : https://github.com/sysnet4admin/_Lecture_k8s_learning.kit/tree/main/ch5 추가실습 : 본문 코드 참조.
🎯 학습 목표
- emptyDir 볼륨의 특성과 사용 사례 이해
- hostPath 볼륨의 장단점과 주의사항 파악
- Deployment와 DaemonSet에서의 볼륨 활용 차이점 학습
- 실제 로그 수집 시나리오 구현
📋 사전 준비
필요 환경
- Kubernetes 클러스터 (minikube, k3s, 또는 관리형 클러스터)
- kubectl CLI 도구
- 기본적인 YAML 문법 지식
디렉터리 구조 확인
# 실습용 디렉터리 생성
mkdir -p ~/k8s-volume-lab
cd ~/k8s-volume-lab🔧 실습 1: emptyDir 볼륨 기본 사용법
1-1. 기본 emptyDir 실습
pod-emptydir-basic.yaml
apiVersion: v1
kind: Pod
metadata:
name: emptydir-basic-pod
labels:
app: emptydir-test
spec:
containers:
- name: writer
image: busybox:1.35
command: ["/bin/sh"]
args: ["-c", "while true; do echo 'Hello from writer' >> /shared/data.txt; date >> /shared/data.txt; sleep 5; done"]
volumeMounts:
- name: shared-storage
mountPath: /shared
- name: reader
image: busybox:1.35
command: ["/bin/sh"]
args: ["-c", "while true; do echo '=== Reading shared data ==='; cat /shared/data.txt 2>/dev/null || echo 'No data yet'; echo; sleep 10; done"]
volumeMounts:
- name: shared-storage
mountPath: /shared
volumes:
- name: shared-storage
emptyDir: {} # 기본 emptyDir실행 및 확인
# Pod 생성
kubectl apply -f pod-emptydir-basic.yaml
# Pod 상태 확인
kubectl get pods -w
# writer 컨테이너 로그 확인
kubectl logs emptydir-basic-pod -c writer
# reader 컨테이너 로그 확인
kubectl logs emptydir-basic-pod -c reader
# 볼륨 내용 직접 확인
kubectl exec emptydir-basic-pod -c reader -- cat /shared/data.txt1-2. 메모리 기반 emptyDir 실습
pod-emptydir-memory.yaml
apiVersion: v1
kind: Pod
metadata:
name: emptydir-memory-pod
spec:
containers:
- name: cache-app
image: nginx:1.21-alpine
volumeMounts:
- name: memory-cache
mountPath: /var/cache/nginx
- name: disk-storage
mountPath: /usr/share/nginx/html
ports:
- containerPort: 80
volumes:
- name: memory-cache
emptyDir:
medium: Memory # 메모리 기반
sizeLimit: 100Mi
- name: disk-storage
emptyDir:
sizeLimit: 1Gi # 디스크 기반, 크기 제한실행 및 성능 테스트
# Pod 생성
kubectl apply -f pod-emptydir-memory.yaml
# Pod IP 확인
kubectl get pod emptydir-memory-pod -o wide
# 메모리 마운트 확인
kubectl exec emptydir-memory-pod -- df -h
# 메모리 볼륨 위치 확인
kubectl exec emptydir-memory-pod -- mount | grep memory-cache🏠 실습 2: hostPath 볼륨 활용
2-1. Deployment에서 hostPath 사용
deploy-hostpath.yaml (실습 PDF 기반)
apiVersion: apps/v1
kind: Deployment
metadata:
name: deploy-hostpath
labels:
app: deploy-hostpath
spec:
replicas: 3
selector:
matchLabels:
app: deploy-hostpath
template:
metadata:
labels:
app: deploy-hostpath
spec:
containers:
- name: host-mon
image: sysnet4admin/sleepy:2.0
volumeMounts:
- mountPath: /host-log
name: hostpath-directory
volumes:
- name: hostpath-directory
hostPath:
path: /var/log2-2. DaemonSet에서 hostPath 사용
ds-hostpath.yaml (실습 PDF 기반)
apiVersion: apps/v1
kind: DaemonSet
metadata:
name: ds-hostpath
labels:
app: ds-hostpath
spec:
selector:
matchLabels:
app: ds-hostpath
template:
metadata:
labels:
app: ds-hostpath
spec:
containers:
- name: host-mon
image: sysnet4admin/sleepy:2.0
volumeMounts:
- mountPath: /host-log
name: hostpath-directory
volumes:
- name: hostpath-directory
hostPath:
path: /var/log실행 및 비교 분석
# 두 리소스 모두 배포
kubectl apply -f deploy-hostpath.yaml
kubectl apply -f ds-hostpath.yaml
# Pod 분산 확인
kubectl get pods -o wide -l app=deploy-hostpath
kubectl get pods -o wide -l app=ds-hostpath
# 각 Pod에서 호스트 로그 확인
kubectl exec deploy-hostpath-xxx -- ls -la /host-log
kubectl exec ds-hostpath-xxx -- ls -la /host-log🔍 실습 3: 실제 로그 수집 시나리오
3-1. Nginx 로그 수집 구현
nginx-logging-pod.yaml
apiVersion: v1
kind: Pod
metadata:
name: nginx-with-logging
spec:
containers:
# 메인 애플리케이션
- name: nginx
image: nginx:1.21
ports:
- containerPort: 80
volumeMounts:
- name: nginx-logs
mountPath: /var/log/nginx
# 커스텀 nginx 설정으로 로그 활성화
command: ["/bin/sh"]
args: ["-c", "nginx && tail -f /var/log/nginx/access.log"]
# 로그 수집 사이드카
- name: log-collector
image: busybox:1.35
command: ["/bin/sh"]
args: ["-c", "while true; do echo '=== Nginx Access Logs ==='; tail -n 5 /logs/access.log 2>/dev/null || echo 'No logs yet'; echo; sleep 30; done"]
volumeMounts:
- name: nginx-logs
mountPath: /logs
volumes:
- name: nginx-logs
emptyDir: {}3-2. 로그 rotation 시뮬레이션
log-rotation-demo.yaml
apiVersion: v1
kind: Pod
metadata:
name: log-rotation-demo
spec:
containers:
- name: app
image: busybox:1.35
command: ["/bin/sh"]
args: ["-c", "
counter=0;
while true; do
echo \"Log entry $counter at $(date)\" >> /logs/app.log;
counter=$((counter + 1));
if [ $((counter % 100)) -eq 0 ]; then
echo \"Rotating log at $counter entries\";
mv /logs/app.log /logs/app.log.old;
echo \"New log file started\" >> /logs/app.log;
fi;
sleep 1;
done"]
volumeMounts:
- name: app-logs
mountPath: /logs
- name: log-monitor
image: busybox:1.35
command: ["/bin/sh"]
args: ["-c", "while true; do echo '=== Current log ==='; tail -n 3 /logs/app.log 2>/dev/null; echo '=== Old log ==='; tail -n 3 /logs/app.log.old 2>/dev/null; echo; sleep 10; done"]
volumeMounts:
- name: app-logs
mountPath: /logs
volumes:
- name: app-logs
emptyDir:
sizeLimit: 50Mi📊 실습 4: 성능 및 제한사항 테스트
4-1. 볼륨 크기 제한 테스트
volume-limit-test.yaml
apiVersion: v1
kind: Pod
metadata:
name: volume-limit-test
spec:
containers:
- name: space-filler
image: busybox:1.35
command: ["/bin/sh"]
args: ["-c", "
echo 'Testing volume size limit...';
for i in $(seq 1 10); do
echo \"Creating 10MB file $i\";
dd if=/dev/zero of=/data/file$i bs=1M count=10 2>/dev/null || echo \"Failed at file $i\";
df -h /data;
sleep 2;
done;
echo 'Keeping container alive...';
tail -f /dev/null"]
volumeMounts:
- name: limited-storage
mountPath: /data
volumes:
- name: limited-storage
emptyDir:
sizeLimit: 50Mi # 50MB 제한4-2. hostPath 타입별 동작 테스트
hostpath-types-test.yaml
apiVersion: v1
kind: Pod
metadata:
name: hostpath-types-test
spec:
containers:
- name: tester
image: busybox:1.35
command: ["/bin/sh"]
args: ["-c", "
echo 'Testing hostPath types...';
echo 'Directory contents:'; ls -la /host-dir/ || echo 'Directory access failed';
echo 'File contents:'; cat /host-file/hostname || echo 'File access failed';
echo 'Creating test file:'; echo 'test data' > /host-dir/test.txt || echo 'Write failed';
tail -f /dev/null"]
volumeMounts:
- name: host-directory
mountPath: /host-dir
- name: host-file
mountPath: /host-file
volumes:
- name: host-directory
hostPath:
path: /tmp
type: Directory
- name: host-file
hostPath:
path: /etc
type: Directory🔧 실습 5: 문제 상황 시뮬레이션
5-1. Pod 재시작 시 데이터 손실 확인
# 1. emptyDir Pod에 데이터 생성
kubectl exec emptydir-basic-pod -c writer -- echo "Important data" > /shared/important.txt
# 2. 데이터 확인
kubectl exec emptydir-basic-pod -c reader -- cat /shared/important.txt
# 3. Pod 삭제 및 재생성
kubectl delete pod emptydir-basic-pod
kubectl apply -f pod-emptydir-basic.yaml
# 4. 데이터 손실 확인
kubectl exec emptydir-basic-pod -c reader -- cat /shared/important.txt
# 결과: 파일이 존재하지 않음 (데이터 손실)5-2. hostPath의 노드 종속성 확인
# 1. hostPath Pod에서 데이터 생성
kubectl exec ds-hostpath-xxx -- echo "Node-specific data" > /host-log/nodedata.txt
# 2. 해당 노드에서 직접 확인
# (노드에 SSH 접근 가능한 경우)
cat /var/log/nodedata.txt
# 3. Pod를 다른 노드로 강제 이동
kubectl delete pod ds-hostpath-xxx
# DaemonSet이므로 다른 노드에 재생성됨
# 4. 새로운 노드에서 데이터 확인
kubectl exec ds-hostpath-yyy -- cat /host-log/nodedata.txt
# 결과: 파일이 존재하지 않음 (다른 노드이므로)📈 결과 분석 및 비교
emptyDir vs hostPath 비교표
| 특성 | emptyDir | hostPath |
|---|---|---|
| 데이터 생존 | Pod 생명주기와 동일 | 노드 재부팅까지 유지 |
| 공유 범위 | 같은 Pod 내 컨테이너간 | 같은 노드의 모든 Pod |
| 성능 | 높음 (로컬 스토리지) | 높음 (로컬 스토리지) |
| 보안 | Pod 격리됨 | 호스트 노출 위험 |
| 이식성 | 높음 | 낮음 (노드 종속) |
| 사용 사례 | 임시 공유, 캐시 | 로그 수집, 시스템 모니터링 |
활용 패턴별 권장사항
✅ emptyDir 권장 상황
- 사이드카 패턴: 로그 수집, 프록시
- 초기화 컨테이너: 설정 파일 준비
- 임시 작업 공간: 빌드, 압축 해제
- 고성능 캐시: 메모리 기반 캐시
✅ hostPath 권장 상황
- 로그 수집: DaemonSet으로 노드별 로그 수집
- 시스템 모니터링: 노드 리소스 모니터링
- 개발/디버깅: 호스트 파일 직접 접근
- 레거시 통합: 기존 호스트 애플리케이션 연동
❌ 피해야 할 상황
- 데이터베이스: 영구 데이터는 PV/PVC 사용
- 프로덕션 데이터: hostPath는 보안 위험
- 다중 노드 공유: NFS 등 네트워크 스토리지 필요
🧹 실습 정리
리소스 정리
# 모든 실습 Pod 삭제
kubectl delete pod emptydir-basic-pod emptydir-memory-pod nginx-with-logging log-rotation-demo volume-limit-test hostpath-types-test
# Deployment와 DaemonSet 삭제
kubectl delete deployment deploy-hostpath
kubectl delete daemonset ds-hostpath
# 확인
kubectl get pods학습한 명령어 정리
# 볼륨 관련 확인 명령어
kubectl describe pod <pod-name> # 볼륨 마운트 정보 확인
kubectl exec <pod> -- df -h # 마운트된 볼륨 크기 확인
kubectl exec <pod> -- mount | grep <볼륨> # 마운트 포인트 확인
kubectl logs <pod> -c <container> # 특정 컨테이너 로그 확인🎓 핵심 학습 포인트
1. 볼륨의 기본 개념
- emptyDir: Pod 내 컨테이너간 데이터 공유
- hostPath: 호스트 노드의 파일시스템 접근
- 생명주기: 볼륨 타입에 따른 데이터 지속성 차이
2. 실무 적용 가이드라인
- 보안: hostPath 사용 시 보안 정책 수립 필요
- 이식성: 환경 독립적인 애플리케이션을 위해 hostPath 최소화
- 성능: 용도에 맞는 볼륨 타입 및 옵션 선택
3. 다음 단계 준비
- PV/PVC: 영구 볼륨과 볼륨 클레임 학습 준비
- StorageClass: 동적 프로비저닝 이해 필요
- StatefulSet: 상태 유지 애플리케이션 패턴 학습
📚 추가 참고 자료
공식 문서
실습 완료일: 2025-11-17
난이도: 초급 → 중급
소요 시간: 약 30분