---
title: "Kubernetes 볼륨 관리: 데이터 영속성과 효율적인 공유를 위한 완벽 가이드"
description: "Kubernetes에서 Volume은 컨테이너 재시작 시 데이터 보존을 돕는 저장소이며, hostPath와 PVC를 조합해 로그와 업로드 데이터를 분리 관리할 수 있다. PV와 PVC를 정의하고 Deployment에 연결하면, replica 재시작 후에도 PVC 덕분에 데이터가 유지된다. 또한 emptyDir는 임시 공유, NFS·CSI 등은 외부 스토리지 연동에 사용된다. ConfigMap으로 경로 설정을 유지하고, nodeSelector로 특정 노드에 워크로드를 고정할 수 있다."
date: "2025-10-15"
last_modified: "2026-05-15T08:36:00.000Z"
type: "Post"
tags:
  - "kubernetes"
  - "storage"
  - "Deployment"
categories:
  - "🤖 Computer Science"
series:
  - "k8s"
canonical_url: "https://blog.pieroot.xyz/k8s-volume-guide"
markdown_url: "https://blog.pieroot.xyz/k8s-volume-guide.md"
---

# Kubernetes 볼륨 관리: 데이터 영속성과 효율적인 공유를 위한 완벽 가이드

Kubernetes에서 Volume은 컨테이너 재시작 시 데이터 보존을 돕는 저장소이며, hostPath와 PVC를 조합해 로그와 업로드 데이터를 분리 관리할 수 있다. PV와 PVC를 정의하고 Deployment에 연결하면, replica 재시작 후에도 PVC 덕분에 데이터가 유지된다. 또한 emptyDir는 임시 공유, NFS·CSI 등은 외부 스토리지 연동에 사용된다. ConfigMap으로 경로 설정을 유지하고, nodeSelector로 특정 노드에 워크로드를 고정할 수 있다.

### Volume이란?

컨테이너가 재시작되거나 교체되어도 데이터를 유지하도록 도와주는 저장소입니다. Kubernetes에서는 다양한 Volume 타입으로 요구사항에 맞는 스토리지를 구성할 수 있습니다.

![image](https://blog.pieroot.xyz/api/image-proxy?id=c6d9043c-d372-4975-afda-fbd07e89bf2e&kind=s3&pageId=28d067c0-15d0-8023-8edc-fe6fbb1182c1&source=block&blockId=2e4067c0-15d0-805f-b8c3-f86fe2253440)

#### 볼륨의 주요 특징

- **Pod 수명 주기와 연결:** 기본 볼륨은 Pod가 존재하는 동안 유지되며, Pod가 삭제되면 함께 삭제됩니다.

- **다양한 볼륨 타입:** emptyDir, hostPath, configMap, secret 등 다양한 타입의 볼륨을 지원합니다.

- **컨테이너 간 데이터 공유:** 같은 Pod 내의 여러 컨테이너가 볼륨을 마운트하여 데이터를 공유할 수 있습니다.

### 1. PersistentVolume & PersistentVolumeClaim 생성

`volume.yaml` 은 업로드 파일을 위한 PV/PVC를 정의합니다. hostPath 기반이지만 PVC를 통해 Pod와 느슨하게 연결합니다.

```yaml
# volume.yaml
apiVersion: v1
kind: PersistentVolume
metadata:
  name: upload-pv
  namespace: volume
spec:
  capacity:
    storage: 10Gi
  accessModes:
    - ReadWriteOnce
  hostPath:
    path: /tmp/upload
    type: DirectoryOrCreate
  persistentVolumeReclaimPolicy: Retain
  storageClassName: ""
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: upload-pvc
  namespace: volume
spec:
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 10Gi
  volumeName: upload-pv
  storageClassName: ""
```

```bash
kubectl apply -f volume.yaml
kubectl get pv,pvc -n volume.yaml
```

> PV는 클러스터 범위 객체라 `namespace` 필드가 무시되지만, 파일과 동일한 패턴으로 관리하기 위해 그대로 두었습니다.

### 2. Deployment에서 Volume 사용

`deployment-volume.yaml`은 ConfigMap, Deployment, Service를 한 번에 배포합니다. 로그는 hostPath로, 업로드 디렉터리는 PVC로 구성됩니다.

```yaml
# deployment-volume.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: simple-file-server
  namespace: volume
spec:
  replicas: 3
  selector:
    matchLabels:
      app: simple-file-server
  template:
    metadata:
      labels:
        app: simple-file-server
    spec:
      nodeSelector:
        kubernetes.io/hostname: "worker"
      containers:
      - name: simple-file-server
        image: ghcr.io/jung-geun/simple-file-server:1.0
        ports:
        - containerPort: 3001
        env:
        - name: PORT
          valueFrom:
            configMapKeyRef:
              name: simple-file-server-config
              key: PORT
        - name: LOG_PATH
          valueFrom:
            configMapKeyRef:
              name: simple-file-server-config
              key: LOG_PATH
        - name: UPLOAD_DIR
          valueFrom:
            configMapKeyRef:
              name: simple-file-server-config
              key: UPLOAD_DIR
        volumeMounts:
        - name: log-storage
          mountPath: /var/log/app
        - name: upload-storage
          mountPath: /var/uploads
            
      volumes:
      - name: log-storage
        hostPath:
          path: /tmp/flask-logs
          type: DirectoryOrCreate
      - name: upload-storage
        persistentVolumeClaim:
          claimName: upload-pvc
```

Service는 `NodePort 30001`을 통해 외부에서 접근할 수 있습니다.

```bash
kubectl apply -f deployment-volume.yaml
kubectl get pods -n volume -l app=simple-file-server -o wide
kubectl get svc -n volume simple-file-server
```

> `nodeSelector`가 `worker` 노드를 가리키므로, 실제 노드 이름이 다르면 `kubernetes.io/hostname` 라벨 값을 확인하고 YAML을 수정하세요.

### 3. 로그와 업로드 데이터 확인

```bash
# 애플리케이션 호출로 로그와 파일 생성
for i in {1..3}; do curl http://localhost:30001; done

# Pod 내부 로그 확인
POD_NAME=$(kubectl get pod -n volume -l app=simple-file-server -o jsonpath='{.items[0].metadata.name}')
kubectl exec -n volume $POD_NAME -- cat /var/log/app/app.log

# 호스트 측 로그 확인 (hostPath)
cat /tmp/flask-logs/app.log

# 업로드 PVC가 마운트됐는지 확인
kubectl exec -n volume $POD_NAME -- ls -l /var/uploads
```

### 4. 데이터 영속성 테스트

```bash
# 현재 로그 및 업로드 디렉터리 확인
cat /tmp/flask-logs/app.log
ls -l /tmp/upload

# 모든 Pod 삭제 (ReplicaSet이 다시 생성)
kubectl delete pod -n volume -l app=simple-file-server
kubectl get pods -n volume -l app=simple-file-server -w

# 새 Pod에서도 이전 데이터가 유지되는지 확인
cat /tmp/flask-logs/app.log
ls -l /tmp/upload
```

### 5. 다른 Volume 타입 살펴보기

- **emptyDir**: 같은 Pod 안의 컨테이너 간 임시 데이터 공유에 적합. Pod 삭제 시 데이터가 사라집니다.

- **PersistentVolumeClaim**: NFS, CSI 드라이버 등 외부 스토리지를 Kubernetes 방식으로 추상화합니다.

- **CSI 드라이버**: AWS EBS, S3, Ceph, Longhorn 등 클라우드/온프레미스 스토리지를 사용할 때 필수.

#### emptyDir 예시

```yaml
volumes:
- name: shared-data
  emptyDir: {}
volumeMounts:
- name: shared-data
  mountPath: /data
```

#### PVC 예시 (커스텀)

```yaml
apiVersion: v1
kind: PersistentVolume
metadata:
  name: simple-file-server-logs-pv
spec:
  capacity:
    storage: 1Gi
  accessModes:
    - ReadWriteOnce
  hostPath:
    path: /mnt/simple-file-server/logs
    type: DirectoryOrCreate
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: simple-file-server-logs-pvc
spec:
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 500Mi
```

### 6. 로그 관리 팁

```bash
# 실시간 로그 tail
tail -f /tmp/flask-logs/app.log

# 로그 파일 크기 확인
du -h /tmp/flask-logs/app.log

# 로그 정리
> /tmp/flask-logs/app.log   # 내용만 초기화

# 또는
rm /tmp/flask-logs/app.log  # 파일 삭제 후 애플리케이션이 다시 생성하도록 유도
```

### 7. 정리

```bash
kubectl delete -f deployment-volume.yaml
kubectl delete -f volume.yaml
sudo rm -rf /tmp/flask-logs
sudo rm -rf /tmp/upload
```

### 핵심 정리

✅ **hostPath + PVC 조합**으로 로그와 업로드 데이터를 분리 관리

✅ **ConfigMap**으로 로그 경로/업로드 디렉터리 설정값 유지

✅ **Replica 재시작** 후에도 PVC 덕분에 업로드 데이터 유지

✅ **nodeSelector**로 특정 노드에 워크로드 고정 가능

### Volume 선택 가이드
