컨테이너 기술은 애플리케이션을 빠르고 일관되게 배포할 수 있는 장점을 제공합니다. 하지만, 컨테이너 내부의 데이터는 휘발성(volatile)입니다. 즉, 컨테이너를 삭제하면 내부의 데이터도 함께 사라집니다.
그렇다면 Docker는 컨테이너 데이터를 어떻게 안전하게 저장하고 관리할까요? 이 때 등장하는 개념이 바로 저장소(Storage)인데, 이와 관련해서 이해해야 하는 다음 두가지 컨셉이 있습니다.
- Storage drivers
- Volume drivers
Storage Drivers
컨테이너에서 생성된 데이터를 보존하고 싶다면 영구 볼륨(persistent volume)을 추가할 수 있습니다. 이 볼륨은 컨테이너의 읽기/쓰기 계층(read/write layer)에 연결되며, 실제로 데이터를 어떻게 저장하고 관리할지는 Storage Driver가 담당합니다.
즉, Storage Driver는 컨테이너의 파일 시스템을 관리하며, 컨테이너가 데이터를 생성하거나 수정할 때 이 계층을 통해 처리가 이루어집니다.
Docker에서는 여러 종류의 Storage Driver를 지원하며, 대표적으로 AUFS, ZFS, BTRFS, Device Mapper, Overlay, Overlay2 등의 종류가 있습니다. 어떤 Storage Driver를 사용할지는 운영체제(OS) 환경과 Docker 버전에 따라 달라집니다. 예를 들어, Ubuntu 최신 버전에서는 기본적으로 overlay2를 사용하며, RHEL이나 CentOS에서는 devicemapper를 선택할 수 있습니다.
Storage Driver는 저장소를 제공할 뿐만 아니라, 이미지와 컨테이너의 계층 구조를 효율적으로 관리하고, 컨테이너 실행 시 데이터의 일관성과 무결성을 보장하는 중요한 역할을 합니다.
Volume drivers
한편, Volume Driver는 컨테이너에 연결되는 영구 볼륨을 관리하는 역할을 합니다. 이때 볼륨은 Storage Driver가 아니라 Volume Driver 플러그인에 의해 핸들링됩니다.
Docker에는 기본 Volume Driver 플러그인으로 local이 제공됩니다. 이 플러그인은 Docker 호스트 내에 볼륨을 생성하고 데이터를 /var/lib/docker에 저장합니다. 또한, 다양한 서드파티 Volume Driver를 사용하여 다음과 같은 외부 스토리지와 연동할 수도 있습니다.
- Azure File Storage
- Convoy
- VMware vSphere Storage 등
영구 볼륨 추가
Docker 기본 데이터 디렉토리
Docker를 설치하면, 시스템에는 자동으로 컨테이너 데이터를 저장하기 위한 기본 디렉토리, /var/lib/docker 가 생성되며, 이미지, 컨테이너, 볼륨 등과 관련된 모든 데이터가 이곳에 저장됩니다.
/var/lib/docker/
├── aufs/ # Storage Driver(aufs) 관련 데이터
├── containers/ # 실행 중인 컨테이너의 메타데이터 및 로그
├── image/ # Docker 이미지 관련 데이터
├── volumes/ # Docker 볼륨 데이터
└── network/ # 네트워크 설정 정보
1. 볼륨 마운트
docker volume create 명령을 사용하여 볼륨을 생성하면, Docker는 자동으로 /var/lib/docker/volumes/volume-name 이라는 폴더를 생성하고 이 폴더에 데이터를 저장합니다.
# 볼륨 생성
docker volume create volume-name
# 도커를 실행할 때, 도커 컨테이너의 read-write layer에 volume-name을 마운트
docker run -v volume-name:/var/lib/mysql mysql
이렇게 하면 컨테이너를 제거하더라도, 그 컨테이너가 생성한 데이터는 여전히 그대로 남아 있습니다.
[NOTE] 볼륨 생성 하지않고 도커를 실행하면 자동으로 볼륨이 생성됩니다.
2. 바인드 마운트
만약 마운트할려고 하는 폴더가 기본 폴더가 아니고 다른 곳에 있다면(예: /data/mysql), 다음처럼 실행하세요. 이것을 바인트 마운트라고 합니다.
docker run -v /data/mysql:/var/lib/mysql mysql
[NOTE] -v 대신에 --mount를 쓰세요.
docker run --mount type=bind,source=/data/mysql,target=/var/lib/mysql mysql
쿠버네티스 Pod의 볼륨 추가
쿠버네티스의 Pod는 Docker 컨테이너처럼 본질적으로 일시적(transient)으로 설계되어 있습니다. 즉, Pod가 생성되어 데이터를 처리한 후 삭제되면 그 안의 데이터도 함께 사라집니다. 하지만 Pod에 볼륨을 연결하면, Pod가 삭제되더라도 볼륨에 저장된 데이터는 유지할 수 있습니다.
apiVersion: v1
kind: Pod
metadata:
name: pvc-example
spec:
containers:
- name: app-container
image: nginx
volumeMounts:
- name: data-volume
mountPath: /opt
volumes:
- name: data-volume
hostPath:
path: /data
type: Directory
이런 구성은 단일 노드 환경에서는 아무 문제 없이 잘 동작합니다. 하지만 여러 사용자가 수많은 파드를 배포하는 대규모 환경에서는 어떻게 해야 할까요? 여러 사용자가 동시에 수많은 파드를 배포하는 대규모 클러스터 환경에서는, 스토리지를 일일이 Pod 정의 파일에 직접 설정하는 방식이 한계에 부딪히죠.
그래서 등장한 개념이 바로 중앙 집중형 스토리지 관리입니다. 관리자가 미리 큰 스토리지 풀(storage pool) 을 만들어 두면, 사용자들은 그 안에서 필요한 만큼만 나누어(PVC를 통해) 사용할 수 있습니다. 이 방식이 바로 Persistent Volume(PV, 영구 볼륨) 입니다.
Kubernetes에서 Persistent Volume은 클러스터 전체에서 공유되는 스토리지 풀이며, 관리자가 사전에 구성합니다. 그리고 사용자는 Persistent Volume Claim(PVC) 을 통해 자신의 애플리케이션에 필요한 스토리지를 이 풀에서 할당받아 사용할 수 있습니다.
다음은 PV(Persistent Volume)을 생성하는 정의 파일입니다.
#pv-definition.yaml
apiVersion: v1
kind: PersistentVolume
metadata:
name: my-pv
spec:
capacity:
storage: 5Gi
accessModes:
- ReadWriteOnce
persistentVolumeReclaimPolicy: Retain
storageClassName: manual
hostPath:
path: /mnt/data
accessMode accessMode 는 “이 볼륨을 호스트에 어떤 방식으로 마운트할 것인가?”를 정의하는 설정입니다. 즉, 누가, 어떤 권한으로, 몇 개의 노드에서 이 볼륨을 사용할 수 있는지를 결정합니다. 대표적으로 세 가지 모드가 있습니다
- ReadOnlyMany (ROX)
이 모드는 여러 노드에서 동시에 읽기 전용으로 접근할 수 있습니다. 여러 Pod가 볼륨을 함께 보지만 아무도 수정은 못 하는” 형태로, 공유 데이터를 배포하거나, 로그나 설정 파일처럼 읽기만 필요한 경우에 적합합니다.
- ReadWriteOnce (RWO)
가장 일반적으로 사용되는 모드입니다. 한 번에 오직 하나의 노드에서만 읽기/쓰기 가능한 방식이에요. 즉, 특정 Pod가 볼륨을 독점적으로 사용합니다.
- ReadWriteMany (RWX)
이 모드는 여러 노드가 동시에 읽기와 쓰기 모두 가능한 공유 볼륨입니다. 여러 Pod가 동일한 데이터를 함께 다뤄야 하는 환경에서 유용하죠. 다만, 이를 지원하려면 NFS(Network File System)나 CephFS 같은 공유 스토리지 시스템이 필요합니다.
pv-definition.yaml의 작성이 완료되었다면, 다음을 실행해서 Persistent Volume을 생성합니다.
# PV 생성
kubectl create -f pv-definition.yaml
# 확인
kubectl get persistentvolume
자, 이제 Pod에서 스토리지를 사용할 수 있도록 Persistent Volume Claim(PVC) 을 만들어보겠습니다. PVC가 생성되면, Kubernetes는 요청한 용량과 볼륨에 설정된 속성을 기준으로 적절한 Persistent Volume(PV)을 찾아 자동으로 연결(bind)해줍니다. 여기서 중요한 점은 각 PVC는 하나의 PV에만 바인딩된다는 것입니다.
바인딩 과정에서는 Kubernetes가 다음과 같은 조건을 확인합니다:
- PVC에서 요청한 용량이 충분한 PV인지
- 요청된 Access Mode (읽기/쓰기 권한)
- Volume Mode (파일 시스템 방식 또는 블록 스토리지)
- Storage Class 등 기타 설정
즉, PVC는 단순히 스토리지를 “달라”고 요청하는 것이 아니라, 요청 조건에 맞는 최적의 PV를 자동으로 연결받는 역할을 하는 셈입니다.
PVC 생성
# pvc-definition.yml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: my-pvc
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 5Gi
storageClassName: manual
다음을 실행하세요.
# pvc 생성
kubectl create -f pvc-definition.yml
# 확인
kubectl get persistentvolumeclaim
생성된 pvc를 삭제하려면, 다음을 실행합니다.
# pvc 삭제
kubectl delete persistentvolumeclaim myclaim
PVC 삭제
그런데 PVC를 삭제하면, 연결된 PV는 어떻게 될까요? PV가 더 이상 사용되지 않을 때 어떻게 처리할지 결정하는 설정이 Reclaim Policy입니다.
우선 기본값은 Retain 입니다.
- 이 경우 PVC가 삭제되더라도 PV는 그대로 남아 있습니다.
- 즉, PV는 관리자가 수동으로 삭제하기 전까지 유지되며, 다른 PVC가 바로 사용할 수는 없습니다.
- 데이터가 보존되므로 중요한 정보를 실수로 잃는 일을 막을 수 있다는 장점이 있습니다.
그 외 Delete와 Recycle이 있습니다.
Delete → PVC 삭제 시 자동 삭제
Recycle → 삭제 후 초기화하고 재사용 가능
'제품 > K8, Docker' 카테고리의 다른 글
| [k8] Node Affinity (0) | 2025.10.04 |
|---|---|
| [k8] Taints와 Tolerations (0) | 2025.09.28 |
| [k8] kubeadm을 이용한 Kubernetes 클러스터 구축하기 (0) | 2025.08.16 |
| Docker 커맨트 정리 (0) | 2024.09.23 |
| 볼륨을 이용한 컨테이너 데이터 유지하기 (0) | 2024.09.18 |