볼륨이란, 호스트에 미리 준비된 사용 가능한 디렉토리를 일컫는다. 쿠버네티스에서는 볼륨 리소스를 생성/삭제할 수 없다. 파드에서 볼륨을 사용하기 위해 매니페스트에 볼륨을 지정하기만 할 수 있다. 볼륨은 플러그인 형태로 제공되는데, ConfigMap 과 Secret 도 볼륨 플러그인의 종류이다. 대표적인 볼륨 플러그인은 아래와 같다.
- emptyDir
- hostPath
- downwardAPI
- projected
- nfs
- iscsi
- cephfs
1. emptyDir
노드에서 파드로 할당되는 호스트의 임시 디스크 영역으로, 파드가 종료되면 같이 삭제된다. 직접 마운트할 호스트의 영역을 지정할 수는 없다. 아래 매니페스트와 같이 emptyDir 볼륨을 마운트할 수 있다.
apiVersion: v1
kind: Pod
metadata:
name: sample-emptydir
spec:
containers:
- image: nginx:1.27
name: nginx-container
volumeMounts:
- name: cache-volume
mountPath: /cache
volumes:
- name: cache-volume
emptyDir: {}
아래 커맨드로 컨테이너의 /cache 마운트 경로에 할당된 디스크를 확인해보자
$ kubectl exec -it sample-emptydir -- df -h | grep cache
/dev/mapper/ubuntu--vg-ubuntu--lv 11G 6.6G 3.1G 69% /cache
emptyDir.sizeLimit 항목을 사용하여 해당 볼륨의 사이즈 제한을 걸 수 있다. 아래 매니페스트처럼 지정한다.
apiVersion: v1
kind: Pod
metadata:
name: sample-emptydir-limit
spec:
containers:
- image: nginx:1.27
name: nginx-container
volumeMounts:
- name: cache-volume
mountPath: /cache
volumes:
- name: cache-volume
emptyDir:
sizeLimit: 128Mi
아래 커맨드와 같이 pod 를 --watch 옵션으로 감시하며, 컨테이너 내부에서 볼륨 마운트 된 경로에 150MB 용량의 더미 파일을 생성한다.
$ kubectl get pods --watch
NAME READY STATUS RESTARTS AGE
sample-emptydir-limit 1/1 Running 0 2m57s
# 별도의 세션에서 실행
$ kubectl exec -it sample-emptydir-limit -- dd if=/dev/zero of=/cache/dummy bs=1M count=150
150+0 records in
150+0 records out
157286400 bytes (157 MB, 150 MiB) copied, 0.803752 s, 196 MB/s
# watch 중인 파드 상태가 아래처럼 바뀌었음을 확인
NAME READY STATUS RESTARTS AGE
sample-emptydir-limit 0/1 Completed 0 5m45s
$ kubectl describe pods sample-emptydir-limit
...
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
...
Warning Evicted 5m46s kubelet Usage of EmptyDir volume "cache-volume" exceeds the limit "128Mi".
Normal Killing 5m46s kubelet Stopping container nginx-container
용량 초과로 인해 파드가 종료된 것을 알 수 있다.
emptyDir 은 호스트 노드의 디스크 뿐 아니라 RAM 영역인 tmpfs 영역에서 사용할 수도 있다. 아래처럼 emptyDir.medium 항목에 Memory 를 설정한다.
apiVersion: v1
kind: Pod
metadata:
name: sample-emptydir-memory
spec:
containers:
- image: nginx:1.27
name: nginx-container
volumeMounts:
- name: cache-volume
mountPath: /cache
volumes:
- name: cache-volume
emptyDir:
medium: Memory
sizeLimit: 128Mi
다시 아래 커맨드로 확인해보면 노드의 tmpfs 영역이 볼륨으로 마운트된 것을 볼 수 있다.
$ kubectl exec -it sample-emptydir-memory -- df -h | grep cache
tmpfs 128M 0 128M 0% /cache
하지만, Memory 영역을 마운트한 경우에는 sizeLimit 을 초과한 용량을 사용하려고 하면 한도까지만 write 가 되고, 파드가 종료되지는 않는다는 차이가 있다.(공식문서에는 해당 스펙이 기재되어 있지 않지만 실제로 이렇게 동작함. kublet 설정에 따라 다를 수 있음.)
$ kubectl exec -it sample-emptydir-memory -- dd if=/dev/zero of=/cache/dummy bs=1M count=150
$ kubectl get pods
NAME READY STATUS RESTARTS AGE
sample-emptydir-memory 1/1 Running 0 16m
# 128M 까지만 기록됨
$ kubectl exec -it sample-emptydir-memory -- ls -lh /cache/dummy
-rw-r--r-- 1 root root 128M Jan 27 14:54 /cache/dummy
파드에는 컨테이너별로 사용할 수 있는 메모리 제한을 걸 수 있는데, 이는 볼륨의 emptyDir.sizeLimit 에 지정한 메모리 제한보다 더 우선 적용되는 항목이기 때문에, 아래 매니페스트로 파드를 생성한 후 70MB의 더미 파일을 만들면 OOM에 의해 파드가 종료된다. 파드의 컨테이너 메모리 제한은 spec.containers[].resources.limits.memory 에 지정할 수 있다.(실제로 해보면 나의 경우에는 파드가 종료되지 않는다...)
apiVersion: v1
kind: Pod
metadata:
name: sample-emptydir-memory-with-memory-limits
spec:
containers:
- image: nginx:1.27
name: nginx-container
resources:
limits:
memory: 64Mi
volumeMounts:
- mountPath: /cache
name: cache-volume
volumes:
- name: cache-volume
emptyDir:
medium: Memory
sizeLimit: 128Mi
2. hostPath
hostPath 는 emptyDir 과 다르게 호스트 노드의 지정한 영역을 마운트하는 방식이다. 파드가 종료되어도 호스트의 해당 영역은 그대로 유지된다. type 을 지정해야 하는데, 지정 가능한 값은 아래와 같다.
| type | 설명 |
| DirectoryOrCreate | 지정한 경로에 디렉토리가 없으면 0755 권한으로 빈 디렉토리를 생성 |
| Directory | 지정한 경로에 디렉토리가 없으면 파드 생성에 실패 |
| FileOrCreate | 지정한 경로에 파일이 없으면 0644 권한으로 빈 파일을 생성 |
| File | 지정한 경로에 파일이 없으면 파드 생성에 실패 |
| Socket | 지정한 경로에 UNIX 소켓 파일이 필요(Docker/CRI 소켓 연결시 사용) |
| CharDevice | 지정한 경로에 문자 디바이스가 필요 |
| BlockDevice | 지정한 경로 블록 디바이스가 필요 |
하지만, hostPath 는 파드가 노드의 파일 시스템에 직접 접근하므로 보안상 위험하여 권장되지 않는다.
매니페스트 예시는 아래와 같다.
apiVersion: v1
kind: Pod
metadata:
name: sample-hostpath
spec:
containers:
- image: nginx:1.27
name: nginx-container
volumeMounts:
- name: hostpath-sample
mountPath: /srv
volumes:
- name: hostpath-sample
hostPath:
path: /etc
type: DirectoryOrCreate
# 호스트 노드의 OS 정보 확인
$ kubectl exec -it sample-hostpath -- cat /srv/os-release | grep "PRETTY_NAME"
PRETTY_NAME="Debian GNU/Linux 12 (bookworm)"
3. downwardAPI
downwardAPI 는 파드 정보나 컨테이너 정보를 파일로 컨테이너 내에 배치하기 위한 플러그인이다. 파드의 정보는 fieldRef 로, 컨테이너의 정보는 resourceFieldRef 로 가져올 수 있다. 아래 매니페스트를 적용해보자.
apiVersion: v1
kind: Pod
metadata:
name: sample-downward-api
spec:
containers:
- name: nginx-container
image: nginx:1.27
volumeMounts:
- name: downward-api-volume
mountPath: /srv
volumes:
- name: downward-api-volume
downwardAPI:
items:
- path: "podname"
fieldRef:
fieldPath: metadata.name
- path: "cpu-request"
resourceFieldRef:
containerName: nginx-container
resource: requests.cpu
아래 커맨드로 파드명과 컨테이너의 CPU 요구사항이 파일로 배치되었는지 확인한다.
$ kubectl exec -it sample-downward-api -- tail -n +1 /srv/podname /srv/cpu-request
==> /srv/podname <==
sample-downward-api
==> /srv/cpu-request <==
0
4. projected
projected 는 Secret, ConfigMap, downwardAPI, serviceAccountToken 를 하나의 볼륨 마운트 경로에 통합하는 플러그인이다. 여러가지 볼륨으로 관리되는 기밀/설정 정보를 컨테이너 내 하나의 디렉터리에 배치하고자 할 때 사용한다. 아래의 매니페스트 예시를 보자.
(sample-db-auth 시크릿과 sample-configmap 컨피그맵은 미리 생성되어 있어야 한다. 없다면 아래를 참고하여 생성하자.)
apiVersion: v1
kind: Pod
metadata:
name: sample-projected
spec:
containers:
- name: nginx-container
image: nginx:1.27
volumeMounts:
- name: projected-volume
mountPath: /srv
volumes:
- name: projected-volume
projected:
sources:
- secret:
name: sample-db-auth
items:
- key: username
path: secret/username.txt
- configMap:
name: sample-configmap
items:
- key: nginx.conf
path: configmap/nginx.conf
- downwardAPI:
items:
- path: "podname"
fieldRef:
fieldPath: metadata.name
$ kubectl exec -it pod/sample-projected -- tail -n +1 /srv/secret/username.txt /srv/configmap/nginx.conf /srv/podname
==> /srv/secret/username.txt <==
root
==> /srv/configmap/nginx.conf <==
user nginx;
worker_processes auto;
error_log /var/log/nginx/error.log;
pid /run/nginx.pid;
==> /srv/podname <==
sample-projected
sample-db-auth 시크릿의 username 값은 base64 디코딩되어 마운트되는 것을 알 수 있다.
'Kubernetes' 카테고리의 다른 글
| [Kubernetes] ConfigMap 과 Secret 볼륨 마운트시 퍼미션 변경 및 동적 업데이트 (0) | 2026.01.25 |
|---|---|
| [Kubernetes] ConfigMap 사용법 2가지(환경 변수로 설정, 볼륨으로 마운트) (0) | 2026.01.11 |
| [Kubernets] ConfigMap 을 생성하는 3가지 방법 (0) | 2026.01.11 |
| [Kubernetes] 운영중에 Secret 을 업데이트하기 (0) | 2026.01.11 |
| [Kubernets] Secret 사용법 2가지(환경 변수로 설정, 볼륨으로 마운트) (0) | 2026.01.10 |
