[K8s] 쿠버네티스 볼륨 (emptyDir, hostPath, NFS, Persistent Volume...

[K8s] 쿠버네티스 볼륨 (emptyDir, hostPath, NFS, Persistent Volume...

Why Volume?

컨테이너는 기본적으로 stateless 앱 컨테이너를 사용한다. 상태가 없기 때문에 노드에 장애가 발생했을 때 다른 노드로 자유롭게 옮길 수 있는 장점을 가진다. 하지만 어떠한 이유로든 컨테이너가 실행되지 않거나 삭제되었을 때, 현재까지 저장된 데이터는 사라진다는 단점이 있다. 특성에 따라서 컨테이너에 문제가 발생하더라도 데이터 보존이 필요한 경우 가 있다. 이런 상황에서 볼륨(Volume)을 사용한다.

예를 들어 MySQL 같은 DB는 컨테이너는 종료하거나 재시작했을 때 저장된 데이터가 사라지면 치명적이다. PV(Persistent Volume)를 사용하면 기존에 데이터를 저장했던 노드가 아닌 다른 노드에서 컨테이너를 재시작하더라도 데이터를 저장한 볼륨을 그대로 사용할 수 있다. 볼륨이나 PV를 사용하면 단순히 서버 하나에서 데이터를 저장해 사용하는 것보다 안정적으로 서비스 운영이 가능하다.

emptyDir, hostPath, local처럼 컨테이너가 실행된 노드의 디스크를 볼륨으로 사용하는 옵션도 있다. NFS 볼륨 플러그인을 이용하면 하나의 컨테이너에 볼륨을 붙여서 NFS 서버로 설정하고, 다른 컨테이너에서 NFS 서버 컨테이너를 가져다가 사용할 수 있다.

emptyDir

파드가 실행되는 호스트의 디스크를 임시로 컨테이너에 볼륨으로 할당해서 사용하는 방법

파드가 사라지면 emptyDir에 할당해서 사용했던 볼륨의 데이터도 함께 사라진다

주로 메로리와 디스크를 함께 이용하는 대용량 데이터 계산에 사용

문제가 발생해서 컨테이너가 재시작되더라도 파드는 살아 있으므로 emptyDir에 저장해둔 데이터를 계속 이용 가능

볼륨 선언과 컨테이너에서 마운트하는 부분을 분리해서 설정

# emptyDir 설정 예시 apiVersion: v1 kind: Pod metadata: name: kubernetes-emptydir-pod spec: containers: - name: kubernetes-simple-pod image: arisu1000/simple-container-app:latest volumeMounts: # 마운트 - mountPath: /emptydir name: emptydir-vol volumes: # 볼륨 선언 - name: emptydir-vol emptyDir: {}

hostPath

파드가 실행된 호스트의 파일이나 디렉터리를 파드에 마운트

emptyDir과 다르게 호스트에 있는 실제 파일이나 디렉터리를 마운트 한다

파드를 재시작했을 때도 호스트에 데이터가 남아있음

파드가 재시작되어서 새로운 노드에서 시작할 경우, 새로운 노드의 hostPath를 사용함 (이전 노드에서 사용한 hostPath 접근 불가)

apiVersion: v1 kind: Pod metadata: name: kubernetes-hostpath-pod spec: containers: - name: kubernetes-hostpath-pod image: arisu1000/simple-container-app:latest volumeMounts: - mountPath: /test-volume name: hostpath-vol ports: - containerPort: 8080 volumes: - name: hostpath-vol hostPath: path: /tmp type: Directory

호스트의 /tmp 디렉터리를 컨테이너의 /test-volume 디렉터리에 마운트

NFS

NFS 서버를 이용해서 파드에 마운트

파드 하나에 안정성이 높은 외부 스토리지를 볼륨으로 설정한 후 해당 파드에 NFS 서버 설정

다른 파드는 NFS 볼륨으로 마운트

# NFS 서버 설정 apiVersion: apps/v1 kind: Deployment metadata: name: nfs-server labels: app: nfs-server spec: replicas: 1 selector: matchLabels: app: nfs-server template: metadata: labels: app: nfs-server spec: containers: - name: nfs-server image: arisu1000/nfs-server:latest ports: - name: nfs containerPort: 2049 - name: mountd containerPort: 20048 - name: rpcbind containerPort: 111 securityContext: privileged: true volumeMounts: - mountPath: /exports name: hostpath-vol volumes: - name: hostpath-vol hostPath: path: /tmp type: Directory

# NFS 서버에 접속할 클라이언트 컨테이너 설정 apiVersion: apps/v1 kind: Deployment metadata: name: kubernetes-nfsapp-pod labels: app: nfs-client spec: replicas: 2 selector: matchLabels: app: nfs-client template: metadata: labels: app: nfs-client spec: containers: - name: kubernetes-nfsapp-pod image: arisu1000/simple-container-app:latest volumeMounts: - mountPath: /test-nfs name: nfs-vol ports: - containerPort: 8080 volumes: - name: nfs-vol nfs: server: 10.233.92.29 # nfs-server 파드의 IP path: "/exports"

PV(Persistent Volume)와 PVC(Persistent Volume Claim)

쿠버네티스에서 볼륨의 구조는 PV와 PVC 2개로 분리되어 있다. PV는 볼륨 자체를 뜻하며 클러스터 안에서 자원으로 다룬다. 파드와는 별개로 관리되고 별도의 생명 주기(LifeCycle)가 있다.

PVC는 사용자가 PV에 하는 요청이다. 사용하고 싶은 용량, Read/Write 모드 등을 설정해서 요청한다. 쿠버네티스는 볼륨을 파드에 직접 할당하지 않고 중간에 PVC를 두어 파드와 파드가 사용할 스토리지를 분리한다. 그래서 파드 각각의 상황에 맞게 다양한 스토리지를 사용할 수 있게 한다.

큰 조직의 경우 PV는 쿠버네티스에서 관리하지 않는 외부 자원으로 두고 스토리지에 전문성이 있는 다른 부서에서 관리할 수 있도록 할 수 있다. 또한, AWS, GCP, Azure 등의 CSP 서비스에 있는 볼륨 관련 서비스를 이용할 수도 있다.

PV와 PVC를 분리하면 PV를 하나의 파드에서만 사용하는 것이 아닌 여러 개의 파드에서 하나의 PV를 사용할 수 있게 하고, PVC와 PV의 생명 주기를 분리함으로 데이터의 안정성을 조금 더 확보할 수 있다.

PV와 PVC의 생명 주기

프로비저닝(Provisioning)

PV를 만드는 단계, 2가지 방법 존재

PV를 미리 만들어 두고 사용하는 정적 방법

요청이 있을 때마다 PV를 만드는 동적 방법

바인딩(Binding)

프로비저닝으로 만들어진 PV를 PVC와 바인딩하는 단계

PVC에서 원하는 용량, 접근 방법을 명시해서 요청하면 거기에 맞는 PV 할당

요청에 실패하면 원하는 PV가 있을 때까지 대기함

PV와 PVC의 매핑은 1:1 관계

사용(Using)

PVC가 파드에 설정되고 파드는 PVC를 볼륨으로 인식해서 사용

할당된 PVC는 파드를 유지하는 동안 계속 사용하며 시스템에서 임의로 삭제 불가

반환(Reclaiming)

사용이 끝난 PVC는 삭제되고 PVC를 사용하던 PV를 초기화하는 과정

Retain , Delete , Recycle 정책이 있다 Retain : PV를 그대로 보존 Delete : PV를 삭제하고 연결된 외부 스토리지 쪽의 볼륨도 삭제 (동적 할당의 기본 반환 정책) Recycle : PV의 데이터들을 삭제하고 새로운 PVC에서 PV를 사용할 수 있도록 한다

, , 정책이 있다

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

정상적으로 설정되었고, 아직 Claim 없음

PVC 설정 템플릿

apiVersion: v1 kind: PersistentVolumeClaim metadata: name: pvc-hostpath spec: accessModes: - ReadWriteOnce volumeMode: Filesystem resources: requests: # 자원을 어마나 사용할 것인지 요청, 앞에서 만든 PV 용량을 초과하면 안됨 storage: 1Gi storageClassName: manual

PV가 PVC에 정상적으로 연결됨

파드에서 PVC를 볼륨으로 사용하기

apiVersion: apps/v1 kind: Deployment metadata: name: kubernetes-simple-app labels: app: kubernetes-simple-app spec: replicas: 1 selector: matchLabels: app: kubernetes-simple-app template: metadata: labels: app: kubernetes-simple-app spec: containers: - name: kubernetes-simple-app image: arisu1000/simple-container-app:latest ports: - containerPort: 8080 imagePullPolicy: Always volumeMounts: # 볼륨을 실제 컨테이너에 연결 - mountPath: "/tmp" name: myvolume volumes: # 사용할 볼륨 설정 - name: myvolume persistentVolumeClaim: # 사용할 PVC 설정 claimName: pvc-hostpath

References

https://arisu1000.tistory.com/27849?category=787056

쿠버네티스 입문 : 90가지 예제로 배우는 컨테이너 관리 자동화 표준

from http://imjeongwoo.tistory.com/134 by ccl(A) rewrite - 2021-10-12 21:26:55