Volume

미리 준비된 사용 가능한 볼륨(호스트 볼륨/nfs 등) 등을 매니페스트에서 직접 지정하여 사용할 수 있게 하는 것이다. 사용자가 설정된 볼륨을 사용할 수 있지만, 쿠버네티스에서 신규 볼륨을 생성하거나 기존 볼륨을 삭제하는 작업은 할 수 없다. 또한, 매니페스트에서 볼륨 리소스를 생성하는 것도 불가능하다.

 

- emptyDir, hostPath, downwardAPI, projected, nfs, iscsi, cephfs

 

emptyDir

파드용 임시 디스크 영역으로 사용할 수 있다. 그리고 파드가 종료되면 삭제된다. 호스트의 임의 영역을 마운트할 수 없으며 호스트에 있는 파일을 참조할 수도 없다.

apiVersion: v1
kind: Pod
metadata:
  name: sample-emptydir-memory-with-memory-limits
spec:
  containers:
  - image: nginx:1.16
    name: nginx-container
    resources:
      limits:
        memory: 64Mi
    volumeMounts:
    - mountPath: /cache
      name: cache-volume
  volumes:
  - name: cache-volume
    emptyDir:
      medium: Memory #고속 tmpfs 메모리 영역, 삭제시 호스트 볼륨(컨테이너용 임시 디스크 영역) 사용
      sizeLimit: 128Mi

 

hostPath

쿠버네티스 노드상의 영역을 컨테이너에 매핑한다. 호스트의 임의 영역을 마운트할 수 있기 때문에 사용할 때는 호스트의 어떤 영역을 사용할지 지정해야한다. 보안상의 이유로 안전하지 않은 컨테이너가 업로드될 수 있으므로 사용하지 말 것을 권장한다.

Multi node 를 사용할 경우에는 hostPath를 사용하지말아야 한다. 그 이유는 Pod가 모든 노드에 동일한 데이터가 존재할 것으로 기대하기 때문이다. 대신에 , NFS 등 external replicated cluster storage를 사용해야한다. 

apiVersion: v1
kind: Pod
metadata:
  name: sample-hostpath
spec:
  containers:
  - image: nginx:1.16
    name: nginx-container
    volumeMounts:
    - mountPath: /srv
      name: hostpath-sample
  volumes:
  - name: hostpath-sample
    hostPath:
      path: /etc
      type: DirectoryOrCreate

Persistent Volume

외부 영구 볼륨을 제공하는 시스템과 연계하여 신규 볼륨을 생성하거나 기존 볼륨을 삭제하는 등의 작업이 가능하다. 

볼륨은 파드 정의 안에 직접 지정하는 형태로 연결하지만, 영구 볼륨은 개별 리소스로 생성한 후 사용한다. 즉 메니페스트를 사용하여 영구 볼륨 리소스를 생성해야한다. 또한, 영구 볼륨은 클러스터 리소스로 분류된다.

 

- GCE Persistent Disk, AWS Elastic Block Store, nfs, Container Storage Interface ...

 

접근 모드

- ReadWriteOnce(RWO) : 단일 노드에서 Read/Write 가능

- ReadOnlyMany(ROW) : 여러 노드에서 Read 가능

- ReadWriteMany(RWX) : 여러 노드에서 Read/Write 가능

 

Reclaim Policy

영구 볼륨을 사용한 후 처리 방법(삭제 또는 재사용)을 제어하는 정책이다. 즉, 영구 볼륨 클레임에서 사용된 후 그 볼륨 클레임이 삭제되었을 때 영구 볼륨 자체의 동작을 설정한다.

- Delete(default) : 영구 볼륨 자체가 삭제된다.

- Retain : 영구 볼륨 자체를 삭제하지 않고 유지한다. 또 다른 영구 볼륨 클레임에 의해 이 영구 볼륨이 다시 마운트되지 않는다.

- Recycle : 영구 볼륨 데이터를 삭제하고 재사용 가능한 상태로 만든다. 다른 영구 볼륨 클레임에서 다시 마운트 가능.

 

apiVersion: v1
kind: PersistentVolume
metadata:
  name: foo-pv
spec:
  storageClassName: ""
  claimRef:
    name: foo-pvc
    namespace: foo
  ...

Persistent Volume Claim

생성된 영구 볼륨 리소스를 할당하는 리소스다. 영구 볼륨은 클러스터에 볼륨을 등록만 하기 때문에 실제 파드에서 사용하려면 영구 볼륨 클레임을 정의하고 사용해야한다. 또한, 동적 프로비저닝 기능을 사용한 경우에는 영구 볼륨 클레임이 사용된 시점에 영구 볼륨을 동적으로 생성할 수 있다.

 

영구 볼륨 클레임에서 지정된 조건(용량, 레이블)을 기반으로 영구 볼륨에 대한 요청이 들어오면 스케줄러는 현재 가지고 있는 영구 볼륨에서 적당한 볼륨을 할당한다. 이때 주의해야할 것은 영구 볼륨 클레임 용량이 영구 볼륨 용량보다 작으면 할당된다는 점이다.

 

참고) The result of PVC deletion can be terminating because pvc is being used by a pod

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: sample-pvc
spec:
  selector:
    matchLabels:
      type: pv
    matchExpressions:
    - key: environment
      operator: In
      values:
      - stg
  resources:
    requests:
      storage: 3Gi
  accessModes:
  - ReadWriteOnce
  storageClassName: manual

파드에서 사용하는 예제는 아래와 같다.

 

apiVersion: v1
kind: Pod
metadata:
  name: sample-pvc-pod
spec:
  containers:
  - name: nginx-container
    image: nginx:1.16
    volumeMounts:
    - mountPath: "/usr/share/nginx/html"
      name: nginx-pvc
  volumes:
  - name: nginx-pvc
    persistentVolumeClaim:
      claimName: sample-pvc

참고)

- The same is true for ReplicaSets or Deployments. Add this to the pod template section of a Deployment on ReplicaSet.

volumeMounts를 하지 않는다면 Pod 재시작시 기존내용을 복구할 수 없다.

동적 프로비저닝

static provisioning : cloud provider에 디스크 요청 -> pv 생성 -> pvc 생성 -> pod definition 

영구 볼륨 클레임에서는 영구 볼륨을 미리 생성해 두고 영구 볼륨 클레임 요청에 따라 볼륨을 할당하는 순서로 진행되었다. 그래서 사전에 영구 볼륨을 생성해야 하는 번거로움과 영구 볼륨 클레임이 요청하는 용량 이상으로 영구 볼륨이 할당되어 낭비가 발생하는 문제가 있다.

apiVersion: v1
kind: PersistentVolume
metadata:
  name: pv-vol1
spec:
  accessModes:
    - ReadWriteOnce
  capacity:
    storage: 500Mi
  gcePersistentDisk:
    pdName: pd-disk
    fsType: ext4

 

이런 문제를 해결하는 것이 동적 프로비저닝(Dynamic Provisioning)이다.

 

동적 프로비저닝을 사용한 영구 볼륨 클레임의 경우 영구 볼륨 클레임이 생성되는 타이밍에 동적으로 영구 볼륨을 생성하고 할당한다. 동적 프로비저닝을 사용하려면 사전에 어떤 영구 볼륨을 생성할지 정의한 StorageClass를 생성해야한다.

 

참고) storage class의 VolumeBindingMode(waitForFirstConsumer) -> pvc만 생성시 해당 pvc를 사용하는 pod를 기다림(pvc status : waitForFirstConsumer)

apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: sample-storageclass
parameters:
  type: pd-ssd
provisioner: kubernetes.io/gce-pd
reclaimPolicy: Delete
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: sample-pvc-dynamic
spec:
  storageClassName: sample-storageclass
  accessModes:
  - ReadWriteOnce
  resources:
    requests:
      storage: 3Gi
apiVersion: v1
kind: Pod
metadata:
  name: sample-pvc-wait-pod
spec:
  containers:
  - name: nginx-container
    image: nginx:1.16
    volumeMounts:
    - mountPath: "/usr/share/nginx/html"
      name: nginx-pvc
  volumes:
  - name: nginx-pvc
    persistentVolumeClaim:
      claimName: sample-pvc-dynamic

 

영구 볼륨 클레임 조정을 사용한 볼륨 확장을 하고 싶을 경우 allowVolumeExpansion:true를 설정하자. 다만 영구 볼륨 클레임 조정은 디스크 크기를 확장할 수 있지만 축소할 수는 없다는 점에 주의하자. 또한 파드에 어태치된 볼륨 자체는 확장되는데, 그 위에 있는 파일 시스템 확장은 경우에 따라 잘라질 수 있다. 파일 시스템의 자동 확장은 파일 시스템으로 EXT3/EXT4/XFS를 사용하는 경우만 해당된다.

apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: sample-storageclass-resize
parameters:
  type: pd-ssd
provisioner: kubernetes.io/gce-pd
reclaimPolicy: Delete
allowVolumeExpansion: true

스테이트풀셋에서 영구 볼륨 클레임

스테이트풀셋의 워크로드에서는 영구 데이터 영역을 사용하는 경우가 많다. spec.volumeClaimTemplate을 사용하면 영구 볼륨 클레임을 별도로 정의하지 않아도 자동으로 영구 볼륨 클레임을 생성할 수 있다. 또 컨테이너 내부의 volumeMounts에 volumeClaimTemplate 이름을 지정하는 것으로 완료된다.

apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: sample-statefulset-with-pvc
spec:
  serviceName: stateful-with-pvc
  replicas: 2
  selector:
    matchLabels:
      app: sample-pvc
  template:
    metadata:
      labels:
        app: sample-pvc
    spec:
      containers:
      - name: sample-pvc
        image: nginx:1.16
        volumeMounts:
        - name: pvc-template-volume
          mountPath: /tmp
  volumeClaimTemplates:
  - metadata:
      name: pvc-template-volume
    spec:
      accessModes:
      - ReadWriteOnce
      resources:
        requests:
          storage: 10Gi
      storageClassName: sample-storageclass

 

참고)

how much capacity is now available to the PVC?

--> kubectl get pvc -> capacity

 

Debugging?

kubectl explain persistentvolume --recursive | less

kubectl exec webapp -- cat /log/app.log


출처

- [책] 쿠버네티스 완벽가이드 마사오 아오야마 지음, 박상욱 옮김

- https://kubernetes.io/docs/concepts/storage/storage-classes/

- https://kubernetes.io/docs/concepts/storage/persistent-volumes/#claims-as-volumes

- https://github.com/container-storage-interface/spec

- https://docs.docker.com/engine/extend/legacy_plugins/

'클라우드 컴퓨팅 > 쿠버네티스' 카테고리의 다른 글

Kubernetes Networking  (0) 2021.12.05
Docker Network  (0) 2021.12.05
Kubernetes Security - Authentication/Authorization  (0) 2021.11.10
Kubernetes TLS/PKI 살펴보기  (0) 2021.11.08
Kubernetes Monitoring with Prometheus  (0) 2021.10.27

+ Recent posts