볼륨을 사용해야 하는 이유는?
컨테이너 특성 상 어떠한 문제가 발생하여 컨테이너가 삭제 된다면 데이터도 같이 삭제되게 된다. 파일을 따로 보관해야 한다거나, 데이터 베이스를 사용할 경우 실시간으로 생성되던 데이터가 사라지면 큰 장애가 발생 하게 된다. 모종의 이유로 컨테이너를 사용할 때 중요한 데이터가 있다면, 볼륨을 사용하여 데이터를 보관해줘야 한다.
즉, Stateful한 Application 경우(Pod, Deployment) 데이터를 영속적으로 저장하기 위한 방법이 필요하다.
Storage Volume이란?
Pod의 일부분으로 정의되며 Pod와 동일한 Lifecycle을 가진다. 파드가 시작되면 Volume이 생성되고, 파드가 삭제되면 볼륨이 삭제된다는 것을 의미한다.
→ 쿠버네티스 Volume은 Pod의 구성 요소로 컨테이너와 동일하게 Pod Spec에서 정의된다.
Local Volume: hostPath, emptyDir
1) emptyDir
emptryDir은 Pod가 사라지면 볼륨도 같이 삭제되는 임시 볼륨의 성격을 가지고 있다. Pod가 실행되는 디스크의 공간에 볼륨 마운트를 하게 된다.
위의 이유로 Life cycle이 컨테이너가 아닌, Pod 단위로 되어있어서 컨테이너가 어떠한 문제로 삭제되어도 Pod는 계속 실행중이다. 따라서 데이터는 emptyDir에 의해 보관되게 된다. 컨테이너가 삭제되어 Pod가 삭제되는 순간 emptyDir로 보관중이던 모든 데이터는 삭제되게 된다.
apiVersion: v1
kind: Pod
metadata:
name: emptydir-pod
spec:
containers:
- name: nginx
image: nginx
volumeMounts:
- mountPath: /emptydir
name: emptydir-volume
volumes:
- name: emptydir-volume
emptyDir: {}
- spec.containers.volumeMounts.mountPath : 실행될 컨테이너 안에 마운트할 경로이다. 컨테이너 안에 해당 디렉토리가 없더라도 자동으로 생성해준다.
- spec.voluems : mountPath에서 작성한 volume을 emptydir-volume에서 사용하도록 지정해준다.
2) hostPath
emptydir와 반대로, 노드의 디스크에 볼륨을 생성하여 Pod가 삭제 되더라도 볼륨에 있던 데이터는 유지된다.
apiVersion: v1
kind: Pod
metadata:
name: hostpath-pod
spec:
containers:
- name: hostpath-pod
image: nginx
volumeMounts:
- mountPath: /hostpath
name: hostpath-volume
volumes:
- name: hostpath-volume
hostPath:
path: /tmp/hostpath # 해당 디렉토리가 존재해야 함
type: Directory
- spec.containers.volumeMounts.mountPath : 실행된 컨테이너 안에 마운트할 경로이다. 컨테이너 안에 해당 디렉토리가 없더라도 자동으로 생성 해준다.
- spec.voluems.hostPath : 노드에 마운트할 경로를 정해주고 해당 경로는 Directory라는 것을 명시한다.
- 해당 디렉토리는 노드에 생성되어 있어야 한다.
- 만약 생성이 안 되어 있을 경우 DirectoryOrCreate를 사용하여 디렉토리를 생성 해준다.
- 유의해야할 점은 Directory를 명시하고 path에 작성한 디렉토리가 없을 경우 ContainerCreating 상태에서 생성되지 않는다.
StorageClass
StorageClass기존에는 관리자가 PersistentVolume을 개발자(사용자)로 부터 요청을 받을 때마다 생성을 해 주었다. 그런데 k8s에서는 이 작업을 StorageClass를 통해 자동으로 수행 할 수 있다. 즉, 관리자는 PersistentVolume을 여러 개 만드는 대신 Profile(또는 MetaClass)과도 같은 Storage Object을 정의하여 사용자로 하여금 Storage Object를 사용하게 하는 것이다.
PV 설정 템플릿
apiVersion: v1
kind: PersistentVolume
metadata:
name: pv-hostpath
spec:
capacity:
storage: 2Gi# 용량 2Gi
volumeMode: Filesystem# 볼륨을 파일 시스템 형식으로 설정해서 사용
accessModes:# 읽기 쓰기 옵션
- ReadWriteOnce# 노드 하나에만 볼륨을 read/write 하도록 마운트
storageClassName: manual# 해당 스토리지 클래스에 맞는 PVC와 연결
persistentVolumeReclaimPolicy: Delete# PV 해제시 초기화 정책
hostPath:# 볼륨 플러그인
path: /tmp/k8s-pv
- accessModes : 리소스 제공자가 지원하는 방식으로 호스트에 퍼시스턴트볼륨을 마운트할 수 있다.
- ReadWriteOnce : 하나의 노드에서 해당 볼륨이 읽기-쓰기로 마운트할 수 있다. ReadWriteOnce 접근 모드에서도 파드가 동일 노드에서 구동되는 경우에는 복수의 파드에서 볼륨에 접근할 수 있다.
- ReadOnlyMany : 볼륨이 다수의 노드에서 읽기 전용으로 마운트 될 수 있다.
- ReadWriteMany : 볼륨이 다수의 노드에서 읽기-쓰기로 마운트 될 수 있다.
- ReadWriteOncePod : 볼륨이 단일 파드에서 읽기-쓰기로 마운트될 수 있다. 전체 클러스터에서 단 하나의 파드만 해당 PVC를 읽거나 쓸 수 있어야하는 경우 ReadWriteOncePod 접근 모드를 사용한다. 이 기능은 CSI 볼륨과 쿠버네티스 버전 1.22+ 에서만 지원된다.
- storageClassName : 빈 문자열은 명시적으로 설정해야 하며 그렇지 않으면 기본 스토리지클래스가 설정된다. 스토리지 클래스 네임을 지정하면 그에 맞는 pvc와 연결되게 된다.
- persistentVolumeReclaimPolicy : 사용자가 볼륨을 다 사용하고나면 리소스를 반환할 수 있는 API를 사용하여 PVC 오브젝트를 삭제할 수 있다.
- Retain(보존) : pvc가 삭제되어도 pv은 여전히 존재한다. 즉, 볼륨은 "릴리스 된" 것으로 간주된다. 데이터가 여전히 볼륨에 남아 있기 때문에 다른 요청에 대해서는 아직 사용할 수 없다. 그래서 스토리지에 있는 데이터를 수동으로 삭제하고 pv를 삭제하면 삭제된다. 만약, 동일한 스토리지의 자산을 재사용하려는 경우, 동일한 스토리지 자산 정의로 새 퍼시스턴트볼륨을 생성한다.
- Delete(삭제) : 쿠버네티스에서 퍼시스턴트볼륨 오브젝트와 외부 인프라(예: AWS EBS, GCE PD, Azure Disk 또는 Cinder 볼륨)의 관련 스토리지 자산을 모두 삭제한다. 동적으로 프로비저닝된 볼륨은 스토리지클래스의 반환 정책을 상속하며 기본값은 Delete이다.
👇🏻 참고 사이트
https://velog.io/@bonjaski0989/K8S-Local-Volume
https://timewizhan.tistory.com/entry/Kubernetes-Storage-StorageClass