이번 글에서는 쿠버네티스 스토리지 볼륨의 세 가지 유형인 emptyDir, HostPath, PersistentVolume(PV)에 대해 알아보고 간단한 실습까지 진행해볼 것이다.
쿠버네티에서 컨테이너는 기본적으로 비영속적이다. 파드가 삭제되거나 재실행되면 기존 컨테이너 내부의 파일 시스템도 초기화된다. 즉, 컨테이너 안에서 생성한 파일은 파드의 생명주기와 함께 사라지는 일시적 저장소이다.
따라서, 쿠버네티스에서는 이러한 문제점을 해결하기 위해 파드 외부와 데이터를 공유하거나 데이터를 보다 오래 유지할 수 있도록 볼륨(Volume)이라는 개념을 제공한다. 볼륨은 크게 다음과 같은 방식으로 제공될 수 있다.
emptyDir
, hostPath
)PersistentVolume
)쿠버네티스 볼륨은 크게 EmptyDir, HostPath, PV로 나뉘어진다.
파드 생명주기 동안 임시로 사용하는 디스크
파드가 노드에 최초로 할당될 때, 노드의 로컬 디스크에 빈 디렉터리를 생성한다.
해당 볼륨은 파드가 살아있는 동안만 존재하며, 파드가 삭제되면 함께 사라진다.
동일한 파드 내부의 여러 컨테이너가 데이터를 공유할 수 있다.
디렉터리는 대개 노드의 다음 경로에 생성된다 :
/var/lib/kubelet/pods/<pod-id>/volumes/kubernetes.io~empty-dir/<volume-name>
사용 예시 : 컨테이너 간에 로그 공유, 임시 캐시 데이터 저장
YAML 예시
apiVersion: v1
kind: Pod
metadata:
name: nginx-volume-01
spec:
containers:
- name: nginx-01
image: nginx:latest
volumeMounts:
- name: empty-volume
mountPath: /volume01
volumes:
- name: empty-volume
emptyDir: {}
파드에 실행 중인 호스트 노드의 파일 시스템 경로(특정 디렉터리)를 직접 마운트한다.
노드 내부 경로에 볼륨을 두므로, 동일한 노드에서 실행되는 파드 간에는 데이터를 공유할 수 있다.
하지만 다음과 같은 이유로 Kubernetes 공식 문서에서는 hostPath 사용을 권장하지 않으며, 반드시 신뢰할 수 있는 환경에서만 제한적으로 사용할 것을 권고한다.
간단 실습
# hostpath-volume.yaml
apiVersion: v1
kind: Pod
metadata:
name: nginx-volume-02
spec:
nodeSelector:
kubernetes.io/hostname: k8s-worker2
containers:
- name: nginx-container-01
image: nginx:latest
volumeMounts:
- name: hostpath-volume
mountPath: /volume02
volumes:
- name: hostpath-volume
hostPath:
path: /home/ubuntu/host-volume
type: DirectoryOrCreate
kubectl apply -f hostpath-volume.yaml
kubectl exec -it nginx-volume-02 -- /bin/bash
cd volume02
echo "hello world 01" > ./test01.txt
exit
# 노드 내부 디렉터리에서 test01.txt 확인 가능
ssh k8s-worker2
cd host-volume
ls
# 종료 후 다시 실행해도 test01.txt 확인 가능
kubectl delete -f volume-test02.yaml
kubectl apply -f hostpath-volume.yaml
kubectl exec -it nginx-volume-02 -- /bin/bash
cd volume02
클러스터 외부의 스토리지를 추상화한 객체로, AWS EBS, NFS 등 다양한 백엔드를 지원한다.
파드가 외부 스토리지와 연결되기 위해서는 다음 리소스들이 필요하다.
리소스 간 관계
파드는 PVC를 통해 PV에 접근하므로, 스토리지 백엔드가 변경되더라도 PVC를 유지하면 어플리케이션 영향 최소화 가능
간단 실습
이 실습에서는 편의상 별도로 외부 스토리지를 사용하지 않고, 클러스터 내의 다른 워커 노드를 NFS 서버로 사용하였다.
# pv.yaml
apiVersion: v1
kind: PersistentVolume
metadata:
name: pv-01
spec:
accessModes:
- ReadWriteOnce # 읽기/쓰기 권한이 있는 단일 파드에만 마운트 가능
capacity:
storage: 100Mi
persistentVolumeReclaimPolicy: Retain # PVC 삭제되더라도, PV 유지
storageClassName: pv-test-01 # 이 PV를 사용할 PVC의 storageClassName과 일치해야 함
nfs:
server: 10.0.2.8
path: /tmp/k8s-pv
# pvc.yaml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: pvc-01
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 30Mi
storageClassName: pv-test-01
# pod.yaml
apiVersion: v1
kind: Pod
metadata:
name: nginx-volume-03
spec:
nodeSelector:
kubernetes.io/hostname: k8s-worker1
containers:
- name: nginx-volume-container-01
image: nginx:latest
volumeMounts:
- name: nfs-pv-01
mountPath: /volume01
volumes:
- name: nfs-pv-01
persistentVolumeClaim:
claimName: pvc-01 # 볼륨은 pvc-01라는 pvc를 참조
kubectl apply -f pv.yaml
kubectl apply -f pvc.yaml
kubectl apply -f pod.yaml
kubectl exect -it nginx-volume-03 -- /bin/bash
cd volume01
echo "hello nfs pv" > ./test02.txt
exit
# 마운트한 nfs 서버에서 text02.txt 확인 가능
ssh k8s-worker2
cd /tmp/k8s-pv
ls
exit
# 삭제 후에도 nfs 서버에서 test02.txt 확인 가능
# pv를 삭제해도 그저 k8s 리소스만 삭제되는 것이며,
# nfs는 k8s 외부 시스템이므로 k8s는 이를 삭제할 권한도 능력도 없음.
kubectl delete -f pod.yaml
kubectl delete -f pvc.yaml
kubectl delete -f pv.yaml
ssh k8s-worker2
cd /tmp/k8s-pv
ls
이번 글에서는 쿠버네티스 볼륨의 세 가지 유형인 emptyDir
, hostPath
, 그리고 PersistentVolume
대해 알아보았다. 이번 글을 마지막으로 쿠버네티스 리소스에 대한 글을 마치겠다.