- Volumes
- Persistent Volumes(PV) ← 오늘 볼 내용
- Projected Volumes
- Ephemeral Volumes
- Storage Classes
2. Persistent Volumes(PV)
https://kubernetes.io/docs/concepts/storage/persistent-volumes/
Persistent Volumes은 이름과 같이 영구 볼륨이라고 불린다.
AWS서비스를 이용해본 사람이라면 EBS(Elastic Block Storage)와 동일한 개념이라고 생각하면 쉽게 이해가 될 것이다.
쿠버네티스에서는 PV를 생성하고 PVC(Persistent Volumes Claim)을 생성하여 PV의 연결점을 생성하여 컨테이너에 마운트하는 방식으로 동작한다.
이러한 PV는 볼륨 내부의 데이터가 파드가 종료되더라도 유지되는 특성을 가진다.
PV에서 사용되는 옵션들에 대해 먼저 보자.
PV 옵션
persistentVolumeReclaimPolicy
- Retain : PV가 해제되어도 PV가 그대로 보존된다. 데이터를 영구적으로 보존해야하는 경우 사용되며 수동으로 PV를 재사용하려면 관리자가 해당 PV를 수동으로 삭제해야 한다.
- Delete : PV가 해제되면 PV와 연결된 스토리지 자원(AWS EBS 등)가 삭제된다. 새로운 PVC가 해당 PV를 요청하면, 시스템은 새로운 스토리지를 할당하여 새 PV를 생성한다.
- Recycle(Deprecated) : 더 이상 사용되지 않는다. 쿠버네티스 공식 문서에 의하면 동적 프로비저닝을 대신 사용하는 것을 권장한다. PV가 해제되면 PV 내 데이터는 모두 삭제되고 빈 PV 상태가 되는 것이다.
volumeBindingMode
- Immediate : 즉시 바인딩이 활성화된다. PV가 생성되자마자 가장 빠른 PVC에 즉시 바인딩된다. 이 옵션을 사용하면 PV를 할당하는 데 더 높은 확률로 성공한다.
- WaitForFirstConsumer : 첫 번째 PVC가 해당 PV를 사용할 때까지 기다린다. PV는 생성되어도 PVC와 즉시 바인딩되지 않습니다. 대신, 첫 번째 PVC가 해당 PV를 사용하려고 할 때까지 대기한다. 이 옵션은 PV를 미리 만들어 놓고, 나중에 필요한 PVC가 나타날 때까지 PV를 보존하는 데 사용된다.
accessMode
- ReadWriteOnce : 하나의 노드에서 해당 볼륨이 읽기-쓰기로 마운트 될 수 있다. ReadWriteOnce 접근 모드에서도 파드가 동일 노드에서 구동되는 경우에는 복수의 파드에서 볼륨에 접근할 수 있다.
- ReadOnlyMany : 볼륨이 다수의 노드에서 읽기 전용으로 마운트 될 수 있다.
- ReadWriteMany : 볼륨이 다수의 노드에서 읽기-쓰기로 마운트 될 수 있다.
- ReadWriteOncePod : 볼륨이 단일 파드에서 읽기-쓰기로 마운트될 수 있다. 전체 클러스터에서 단 하나의 파드만 해당 PVC를 읽거나 쓸 수 있어야하는 경우 ReadWriteOncePod 접근 모드를 사용한다. 이 기능은 CSI 볼륨과 쿠버네티스 버전 1.22+ 에서만 지원된다.
volumeMode
기본적으로 대부분의 PV는 Filesystem 모드로 설정되어 파일 시스템을 사용하며 특별한 경우에만 Block을 사용한다.
- Filesystem : 볼륨을 파일 시스템으로 사용하도록 지정
- Block : 볼륨을 파일 시스템으로 사용하도록 지정
mountOptions
PV 또는 PVC를 마운트할 때 파일 시스템에 대한 추가 설정을 할 수 있다.
apiVersion: v1
kind: PersistentVolume
metadata:
name: pv0003
spec:
capacity:
storage: 5Gi
volumeMode: Filesystem
accessModes:
- ReadWriteOnce
persistentVolumeReclaimPolicy: Recycle
storageClassName: slow
mountOptions:
- hard
- nfsvers=4.1
nfs:
path: /tmp
server: 172.17.0.2
참고 :
클러스터 내에서 퍼시스턴트볼륨을 사용하려면 볼륨 유형과 관련된 헬퍼(Helper) 프로그램이 필요할 수 있다. 이 예에서 퍼시스턴트볼륨은 NFS 유형이며 NFS 파일시스템 마운트를 지원하려면 헬퍼 프로그램인 /sbin/mount.nfs가 필요하다.
다음 명령을 입력하여 nfs를 설치한다.
apt-get update
apt-get install nfs-common
퍼시스턴트 볼륨의 유형
퍼시스턴트볼륨 유형은 플러그인으로 구현된다. 쿠버네티스는 현재 다음의 플러그인을 지원한다.
- cephfs - CephFS 볼륨
- csi - 컨테이너 스토리지 인터페이스 (CSI)
- fc - Fibre Channel (FC) 스토리지
- hostPath - HostPath 볼륨 (단일 노드 테스트 전용. 다중-노드 클러스터에서 작동하지 않음. 대신 로컬 볼륨 사용 고려)
- iscsi - iSCSI (SCSI over IP) 스토리지
- local - 노드에 마운트된 로컬 스토리지 디바이스
- nfs - 네트워크 파일 시스템 (NFS) 스토리지
- rbd - Rados Block Device (RBD) 볼륨
아래의 PersistentVolume 타입은 사용 중단되었다. 이 말인 즉슨, 지원은 여전히 제공되지만 추후 쿠버네티스 릴리스에서는 삭제될 예정이라는 것이다.
- awsElasticBlockStore - AWS Elastic Block Store (EBS) (v1.17에서 사용 중단)
- azureDisk - Azure Disk (v1.19에서 사용 중단)
- azureFile - Azure File (v1.21에서 사용 중단)
- cinder - Cinder (오픈스택 블록 스토리지) (v1.18에서 사용 중단)
- flexVolume - FlexVolume (v1.23에서 사용 중단)
- gcePersistentDisk - GCE Persistent Disk (v1.17에서 사용 중단)
- portworxVolume - Portworx 볼륨 (v1.25에서 사용 중단)
- vsphereVolume - vSphere VMDK 볼륨 (v1.19에서 사용 중단)
Storage Class
PV를 알기 전에 간단하게 StorageClass에 대해 설명하자면 PV를 동적으로 생성하여 바인딩하는 역할을 한다.
일반적으로 클라우드 환경에서 동적으로 프로비저닝하는 경우가 대부분이지만 온프레미스 환경에서도 스토리지 클래스를 생성하여 사용하는 경우도 있다.
온프레미스에서 사용하는 경우
> 이 경우 스토리지 클래스가 있음에도 PV는 따로 생성해야 한다.
Storage Class | PV | PVC |
apiVersion: storage.k8s.io/v1 kind: StorageClass metadata: name: local-storage provisioner: kubernetes.io/no-provisioner volumeBindingMode: WaitForFirstConsumer |
apiVersion: v1 kind: PersistentVolume metadata: name: example-pv spec: capacity: storage: 1Gi volumeMode: Filesystem accessModes: - ReadWriteOnce storageClassName: local-storage local: path: /path/to/local/disk nodeAffinity: required: nodeSelectorTerms: - matchExpressions: - key: kubernetes.io/hostname operator: In values: - node1 |
apiVersion: v1 kind: PersistentVolumeClaim metadata: name: example-pvc spec: storageClassName: local-storage accessModes: - ReadWriteOnce resources: requests: storage: 1Gi |
AWS 클라우드에서 사용하는 경우
Storage Class | PVC |
apiVersion: storage.k8s.io/v1 kind: StorageClass metadata: name: fast provisioner: kubernetes.io/aws-ebs volumeBindingMode: WaitForFirstConsumer allowVolumeExpansion: true reclaimPolicy: Retain parameters: type: gp2 fsType: ext4 iopsPerGB: "10" |
apiVersion: v1 kind: PersistentVolumeClaim metadata: name: example-pvc spec: accessModes: - ReadWriteOnce storageClassName: fast resources: requests: storage: 5Gi |
Static
PV는 PVC와 StorageClass를 사용해서 동적으로 프로비저닝되도록 할 수 있지만 PV를 직접 생성하고 PVC에 volumeName 필드를 명시하면 해당 PVC를 통해 수동으로 파드에 바인드할 수 있다.
다만 이 방식으로 PV와 PVC를 생성하면 자동으로 기본 스토리지 클래스로 설정해서 생성하게 된다.
결국 모든 PV는 스토리지 클래스를 반드시 하나씩 가지는 것이다.
아래 yaml 파일은 수동으로 PVC를 구성하여 마운트하기 위한 방법으로 구조는 다음과 같다.
PV | PVC |
apiVersion: v1 kind: PersistentVolume metadata: name: test-pv spec: capacity: storage: 5Gi volumeMode: Filesystem accessModes: - ReadWriteOnce persistentVolumeReclaimPolicy: Retain hostPath: path: /mnt/data |
apiVersion: v1 kind: PersistentVolumeClaim metadata: name: test-pvc spec: accessModes: - ReadWriteOnce resources: requests: storage: 2Gi volumeName: test-pv # 수동으로 설정하는 방법 |
파드 명세는 다음과 같다.
Pod |
apiVersion: v1 kind: Pod metadata: name: test-pod spec: containers: - image: nginx:1.25 name: nginx-container volumeMounts: - name: test-vol mountPath: /test-path volumes: - name: test-vol persistentVolumeClaim: claimName: test-pvc |
파드 내부에 진입한 후 바인딩한 PV내부에 test.txt라는 이름의 파일을 생성했다.
이 PV는 영구 볼륨이기에 파드가 죽더라도 데이터가 보존된다.
위 예시에서는 수동으로 구성하였지만 보통 PV는 클라우드 환경에서 StorageClass를 사용하여 동적으로 프로비저닝되도록 한다.
AWS와 GCP, AZURE와 같은 클라우드 프로바이더를 통해 서비스를 운영하는 경우 StorageClass를 사용하여 AWS EBS, GCE Persistent Disk, Azure Disk와 같은 볼륨을 동적으로 프로비저닝할 수 있다.
하지만 클라우드를 쓰지 않는 온프레미스의 경우는 동적으로 프로비저닝하는 기능은 없으며 StorageClass를 생성하더라도 PV는 따로 생성해주어야 한다.
Dynamic
동적 프로비저닝되는 모습을 보여주려면 클라우드 서비스 내에서 쿠버네티스를 실행해야 하는데 현재 내의 실습 환경은 개인 VM에 쿠버네티스를 설치하여 사용하는 것이기에 화면을 캡쳐하여 보여줄 수는 없다.
그래도 코드의 설명을 통해 과정을 설명할 것이다.
서두에서 예시로 보았던 AWS 클라우드를 사용하는 사례를 보자.
Storage Class | PVC |
apiVersion: storage.k8s.io/v1 kind: StorageClass metadata: name: fast provisioner: kubernetes.io/aws-ebs volumeBindingMode: WaitForFirstConsumer allowVolumeExpansion: true reclaimPolicy: Retain parameters: type: gp2 fsType: ext4 iopsPerGB: "10" |
apiVersion: v1 kind: PersistentVolumeClaim metadata: name: example-pvc spec: accessModes: - ReadWriteOnce storageClassName: fast resources: requests: storage: 5Gi |
위 내용을 보면 PV는 없고 PVC와 StorageClass만 존재한다.
StorageClass를 확인하면 provisioner를 볼 수 있는데 이 필드를 통해 어떤 클라우드 프로바이더를 이용하는지 명시할 수 있다.
parameters에는 AWS EBS 볼륨을 생성하는데 필요한 상세 설정이 담겨있다.
PVC는 storageClassName을 통해 StorageClass의 이름을 명시하면 StorageClass의 parameters에서 명시한 설정대로 EBS 볼륨을 생성한다.
StorageClass와 PVC에는 모두 사용할 볼륨 리소스의 양을 기재할 수 있는데 둘 중 더 큰 값을 사용하여 볼륨을 생성한다.
원시 블럭 볼륨을 사용한 PV
원시 블럭 즉 순수 디스크를 직접 PV로 활용하겠다는 의미다.
PV | PVC | Pod |
apiVersion: v1 kind: PersistentVolume metadata: name: block-pv spec: capacity: storage: 10Gi accessModes: - ReadWriteOnce volumeMode: Block persistentVolumeReclaimPolicy: Retain fc: targetWWNs: ["50060e801049cfd1"] lun: 0 readOnly: false |
apiVersion: v1 kind: PersistentVolumeClaim metadata: name: block-pvc spec: accessModes: - ReadWriteOnce volumeMode: Block resources: requests: storage: 10Gi |
apiVersion: v1 kind: Pod metadata: name: pod-with-block-volume spec: containers: - name: fc-container image: fedora:26 command: ["/bin/sh", "-c"] args: [ "tail -f /dev/null" ] volumeDevices: - name: data devicePath: /dev/xvda volumes: - name: data persistentVolumeClaim: claimName: block-pvc |
알아두면 좋은 내용
Finalizers
사용중인 스토리지 오브젝트를 보호목적으로 존재한다.
PV에 저장되는 데이터의 손실을 막기위해 PV는 다른 PVC를 통해 바인드되어있는 경우 삭제되지 않는다.
삭제를 하더라도 Terminating 상태에 머무르며 PVC가 없어질 때까지 기다린다.
상세 정보를 보면 Finalizers에 kubernetes.io/pv-protection라는 값이 있는데 이 값이 존재하는 한 PV는 삭제되지 않는다.
상세 내역에 test-pvc라는 PVC가 연결되어있는 것을 볼 수 있는데 이것이 제거되지 않는 요인이다.
PVC만 제거하면 PV는 바로 제거된다.
PVC에도 동일한 필드가 있다.
PVC의 경우는 컨테이너가 해당 볼륨을 사용중일 때는 지운다고 한들 지워지지 않는다.
파드가 제거되고 더이상 바인딩된 상태가 아닐 때 PVC는 완전히 제거된다.
데이터 소스를 사용하여 PV를 생성하는 내용과 네임스페이스 간 볼륨 데이터 소스를 사용하도록 설정할 수도 있다.
이 부분은 외부 구성 요소를 설치하여 사용하는 부분이므로 여기서는 다루지는 않을 것이다.
궁금하다면 공식 문서를 통해 직접 확인하길 바란다.
'Kubernetes' 카테고리의 다른 글
Kubernetes 기초 - Storage(4) (0) | 2024.01.22 |
---|---|
Kubernetes 기초 - Storage(3) (0) | 2024.01.22 |
Kubernetes 기초 - Storage(1) (0) | 2024.01.12 |
Kubernetes 기초 - Scheduling(6) (0) | 2024.01.10 |
Kubernetes 기초 - Scheduling(5) (0) | 2024.01.09 |