Tools/K8S

Kubernetes PV & PVC

칼쵸쵸 2023. 8. 12. 10:24

볼륨 (Volume):

Kubernetes에서 볼륨은 컨테이너 내부와 외부 간의 데이터를 공유하기 위한 방법입니다. 볼륨은 컨테이너의 파일 시스템과 독립적으로 존재하며, 컨테이너가 종료되더라도 데이터가 보존됩니다. 예를 들어, 컨테이너 내부에서 생성한 데이터를 다른 컨테이너에서 사용하거나 호스트 시스템의 파일 시스템에 접근할 볼륨을 사용할 있습니다. 볼륨은 컨테이너에 지속적인 데이터 저장을 제공하지만, 볼륨 자체는 별도의 수명 주기나 관리를 가지지 않습니다.

 - 호스트 볼륨/nfs/iSCI/Ceph

- 컨테이너와 별개의 리소스 영역 , 노드의 스토리지 영역

 

영구 볼륨 (Persistent Volume):

영구 볼륨은 클러스터 내에서 생성되고 관리되는 스토리지 리소스입니다. 이러한 볼륨은 클러스터 노드에 연결되며, 데이터를 지속적으로 저장할 있습니다. 영구 볼륨은 스토리지 백엔드 (: NFS, iSCSI ) 연결되어 사용되며, 여러 컨테이너나 파드 간에 데이터를 공유하고 보존하는 사용될 있습니다.

https://aws.amazon.com/ko/blogs/tech/persistent-storage-for-kubernetes/

- Ceph/ AWS Elastic Block Store/ GCE Persistent Disk

 - 스토리지 영역을 추상화

- 컨테이너에서 생성,관리 가능

 

Access Modes

ReadWriteOnce (RWO):

읽기/쓰기 접근을 허용하며, 동시에 하나의 파드만 해당 볼륨을 마운트하여 사용할 있습니다.

예를 들어, 데이터베이스 서버에 사용될 있으며, 하나의 파드만 해당 데이터베이스에 읽기와 쓰기를 동시에 수행할 있습니다.

 

ReadOnlyMany (ROX):

읽기 전용 접근을 허용하며, 여러 파드가 볼륨을 마운트하여 데이터를 읽을 있지만 쓰기는 허용되지 않습니다.

예를 들어, 정적인 컨텐츠를 제공하는 서버에 사용될 있습니다. 여러 파드가 동일한 데이터를 읽어올 있지만 수정은 하나의 파드만 수행합니다.

 

ReadWriteMany (RWX):

읽기/쓰기 접근을 허용하며, 여러 파드가 동시에 볼륨을 마운트하여 데이터를 읽고 있습니다.

RWX 모드는 여러 파드가 동일한 데이터를 공유해야 하는 경우 유용합니다. 그러나 많은 스토리지 백엔드에서 지원되지 않을 있습니다.

 

Reclaim Policy

PV(Permanent Volume) Reclaim Policy Kubernetes 클러스터에서 사용되는 영구적인 스토리지 볼륨의 재활용 정책을 정의하는 방법을 말합니다. PV 클러스터 내에서 퍼시스턴트한 데이터를 저장하기 위해 사용되며, 이러한 데이터는 볼륨이 이상 필요하지 않을 어떻게 처리되어야 할지 결정하는 정책이 필요합니다. PV Reclaim Policy 가지 옵션 하나로 설정할 있습니다.

 

Retain: 옵션은 PV 데이터를 보존하는 정책입니다. PV 이상 사용되지 않더라도 해당 데이터가 삭제되지 않고 보존됩니다. 경우 별도로 PV 데이터를 수동으로 삭제해야 합니다. 주로 데이터 보존이 필요한 경우에 사용됩니다.

 

Delete: 옵션은 PV 이상 사용되지 않을 해당 데이터를 삭제하는 정책입니다. PV 삭제되면 해당 볼륨의 데이터도 자동으로 삭제됩니다. 주로 데이터 보안이 중요하지 않은 경우나 재사용되지 않는 데이터의 경우에 사용됩니다.

 

Recycle: 옵션은 지정된 볼륨의 내용을 삭제하고 다시 사용할 있도록 만드는 정책입니다. Kubernetes 클러스터에서는 이상 권장되지 않으며 대신 Dynamic Provisioning(동적 프로비저닝) 사용하는 것이 좋습니다.


영구
볼륨 클레임 (Persistent Volume Claim):

영구 볼륨 클레임은 파드가 영구 볼륨을 요청하고 사용할 있도록 해주는 리소스 요청 개체입니다. 파드가 영구 볼륨을 사용하기 위해서는 해당 볼륨의 클레임을 생성해야 합니다. 클레임은 파드가 필요로 하는 스토리지 요구 사항을 정의하며, 클러스터 내에서 사용 가능한 영구 볼륨 중에서 해당 요구 사항과 일치하는 볼륨을 바인딩합니다.

 

요약하면, k8s에서 볼륨은 컨테이너 데이터 공유를 위한 메커니즘이며, 영구 볼륨은 클러스터 내에서 지속적으로 데이터를 저장하는 스토리지 리소스를 나타내며, 영구 볼륨 클레임은 파드가 영구 볼륨을 요청하고 사용할 있도록 해주는 매개체입니다. 가지 개념을 조합하여 데이터를 안전하게 관리하고 파드 간에 공유하는 사용할 있습니다.

 

 

* 동적 프로비저닝(Dynamic Provisioning)

 Kubernetes 클러스터 내에서 스토리지 리소스를 필요에 따라 자동으로 프로비저닝하는 프로세스를 말합니다. 기존에는 먼저 스토리지를 만들고 이를 연결하는 방식이었다면 , 동적 프로비저닝은 애플리케이션이나 파드가 스토리지를 요청할 , 클러스터가 자동으로 필요한 스토리지 볼륨을 생성하고 연결해주는 기능을 제공합니다.

 

Storage Class는 컨테이너 애플리케이션에 사용되는 백엔드 영구 스토리지(예: Amazon EFS 파일 스토리지, Amazon EBS 블록 스토리지 등)의 클래스를 정의하는 추상화입니다.

Storage Class 기본적으로 두 가지를 포함합니다.

  1. 이름(Name): 스토리지 클래스 객체를 고유하게 식별하는 이름입니다.
  2. 제공자(Provisioner): 연결되는 스토리지 기술을 정의합니다. 예를 들어, provisioner는 Amazon EFS용 efs.csi.aws.com 또는 Amazon EBS용 ebs.csi.aws.com이 될 수 있습니다.

동적 프로비저닝을 사용하면 PV객체를 생성할 필요가 없습니다. 대신에, PVC를 생성할 때 내부적으로 자동으로 생성됩니다. Kubernetes는 Storage Class라는 다른 객체를 사용하여 이를 수행합니다.Storage Class 객체는 Kubernetes가 매우 다양한 스토리지 기술을 처리할 수 있는 이유입니다. Pod 관점에서 볼 때, EFS 볼륨, EBS 볼륨, NFS 드라이브 또는 기타 어떤 것이든, 그 Pod는 PVC 객체만 보게 됩니다. 실제 스토리지 기술을 다루는 모든 내부적인 논리는  Storage Class 객체가 사용하는 프로비저너에 의해 구현됩니다.

https://aws.amazon.com/ko/blogs/tech/persistent-storage-for-kubernetes/

 

 

Practice

1. Configure a volume to store these logs at /var/log/webapp on the host.

Use the spec provided below.

·       Name: webapp

·       Image Name: kodekloud/event-simulator

·       Volume HostPath: /var/log/webapp

·       Volume Mount: /log

 

apiVersion: v1
kind: Pod
metadata:
  name: webapp
spec:
  containers:
  - name: event-simulator
    image: kodekloud/event-simulator
    env:
    - name: LOG_HANDLERS
      value: file
    volumeMounts:
    - mountPath: /log
      name: log-volume

  volumes:
  - name: log-volume
    hostPath:
      # directory location on host
      path: /var/log/webapp
      # this field is optional
      type: Directory

볼륨을 hostPath로 생성하고 파드에서 볼륨을 이름과 path로 마운트 한다.

 

 

2. Create a Persistent Volume with the given specification.

 

·       Volume Name: pv-log

·       Storage: 100Mi

·       Access Modes: ReadWriteMany

·       Host Path: /pv/log

·       Reclaim Policy: Retain

 

apiVersion: v1
kind: PersistentVolume
metadata:
  name: pv-log
spec:
  persistentVolumeReclaimPolicy: Retain
  accessModes:
    - ReadWriteMany
  capacity:
    storage: 100Mi
  hostPath:
    path: /pv/log

 

 

3. Let us claim some of that storage for our application. Create a Persistent Volume Claim with the given specification.

 

·       Volume Name: claim-log-1

·       Storage Request: 50Mi

·       Access Modes: ReadWriteOnce

kind: PersistentVolumeClaim
apiVersion: v1
metadata:
  name: claim-log-1
spec:
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 50Mi

 

4. Why is the claim not bound to the available Persistent Volume?

controlplane ~ ➜  kubectl get pvc
NAME          STATUS    VOLUME   CAPACITY   ACCESS MODES   STORAGECLASS   AGE
claim-log-1   Pending                                                     16s

controlplane ~ ➜  kubectl get pv
NAME     CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS      CLAIM   STORAGECLASS   REASON   AGE
pv-log   100Mi      RWX            Retain           Available

PV와 PVC의 ACCESS MODES가 다른것을 볼 수 있다.

 

 

5. Update the Access Mode on the claim to bind it to the PV.

kind: PersistentVolumeClaim
apiVersion: v1
metadata:
  name: claim-log-1
spec:
  accessModes:
    - ReadWriteMany
  resources:
    requests:
      storage: 50Mi

accessModes를 ReadWriteMany(RWX)로 변경하여 PVC 새로 생성

 

 

6. You requested for 50Mi, how much capacity is now available to the PVC? 

controlplane ~ ➜  kubectl get pvc
NAME          STATUS   VOLUME   CAPACITY   ACCESS MODES   STORAGECLASS   AGE
claim-log-1   Bound    pv-log   100Mi      RWX                           35s

생성한 pvc의 capacity는 이전에 생성한 pv-log에 연결되어 100Mi인것을 확인할수 있다.

 

 

7. Update the webapp pod to use the persistent volume claim as its storage.

 

Replace hostPath configured earlier with the newly created PersistentVolumeClaim.

·       Name: webapp

·       Image Name: kodekloud/event-simulator

·       Volume: PersistentVolumeClaim=claim-log-1

·       Volume Mount: /log

 

apiVersion: v1
kind: Pod
metadata:
  name: webapp
spec:
  containers:
  - name: event-simulator
    image: kodekloud/event-simulator
    env:
    - name: LOG_HANDLERS
      value: file
    volumeMounts:
    - mountPath: /log
      name: log-volume

  volumes:
  - name: log-volume
    persistentVolumeClaim:
      claimName: claim-log-1

pvc를 claim-log-1로 연결하여 파드를 생성한다. /log 위치에 pvc를 활용한 영구 볼륨을 마운트 한다.

 

 

8. What is the Reclaim Policy set on the Persistent Volume pv-log? and What would happen to the PV if the PVC was destroyed?

controlplane ~ ➜  kubectl get pv
NAME     CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS   CLAIM                 STORAGECLASS   REASON   AGE
pv-log   100Mi      RWX            Retain           Bound    default/claim-log-1                           14m

retain인것을 확인 할 수 있다. PVC가 삭제되더라도 PV 데이터를 보존하는 정책이다. 그러나 재사용은 불가하다.

 

pvc를 삭제하려고 해도 파드가 해당 pvc를 사용중이기 때문에 terminating에서 멈춰버린다.

controlplane ~ ➜  kubectl delete pvc claim-log-1
persistentvolumeclaim "claim-log-1" deleted
^C
controlplane ~ ✖ kubectl get pvc
NAME          STATUS        VOLUME   CAPACITY   ACCESS MODES   STORAGECLASS   AGE
claim-log-1   Terminating   pv-log   100Mi      RWX

 

해당 pvc를 사용하는 pod를 삭제하면 삭제된다.

controlplane ~ ➜  kubectl delete pod webapp
pod "webapp" deleted

controlplane ~ ➜  kubectl get pvc
No resources found in default namespace.

 

PV는 release(바인딩이 안되었거나 변경된) 상태이다.

controlplane ~ ➜  kubectl get pv
NAME     CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS     CLAIM                 STORAGECLASS   REASON   AGE
pv-log   100Mi      RWX            Retain           Released   default/claim-log-1                           21m

 

9. How many Storage class? And What is the Volume Binding Mode used for this storage class (the one identified in the previous question)?

controlplane ~ ➜  kubectl get sc
NAME                        PROVISIONER                     RECLAIMPOLICY   VOLUMEBINDINGMODE      ALLOWVOLUMEEXPANSION   AGE
local-path (default)        rancher.io/local-path           Delete          WaitForFirstConsumer   false                  31m
local-storage               kubernetes.io/no-provisioner    Delete          WaitForFirstConsumer   false                  28s
portworx-io-priority-high   kubernetes.io/portworx-volume   Delete          Immediate              false                  28s

3개

 

10. What is the name of the Storage Class that does not support dynamic volume provisioning?

provisioner에 no-provisioner가 쓰여있는 local-storage

Volume Binding Mode는 WaitForFirstConsumer상태이다.

 

 

11. What is the Provisioner used for the storage class called portworx-io-priority-high?

kubernetes.io/portworx-volume 임을 확인 할 수 있다.

 

 

12. Why is the PVC in a pending state despite making a valid request to claim the volume called local-pv?

controlplane ~ ➜  kubectl get pvc
NAME        STATUS    VOLUME   CAPACITY   ACCESS MODES   STORAGECLASS    AGE
local-pvc   Pending                                      local-storage   15s

controlplane ~ ➜  kubectl describe pvc local-pvc | grep -A3 Events
Events:
  Type    Reason                Age                From                         Message
  ----    ------                ----               ----                         -------
  Normal  WaitForFirstConsumer  11s (x5 over 63s)  persistentvolume-controller  waiting for first consumer to be created before binding

local-pvc라는 pvc는 pending 상태이며 storageclass를 local-storage를 사용하고 있다.

해당 스토리지 클래스는 WaitForFirstConsumer volume bind 모드 이며

PV가 PVC에 바인딩되기 위해서는, PVC를 사용하여 스토리지를 요청하는 파드가 있어야 한다.

PV와 PVC 간의 연결이 필요한 시점까지 PV는 여전히 사용 가능한 상태로 남음.

PV와 PVC 간의 연결은 파드가 PVC를 사용하여 스토리지를 요청할 때 이루어 진다. 이로 인해 스토리지 자원이 미리 할당되지 않고 필요 시에 동적으로 할당되는 효과를 얻을 수 있다.

 

 

13. Create a new pod called nginx with the image nginx:alpine. The Pod should make use of the PVC local-pvc and mount the volume at the path /var/www/html.

The PV local-pv should in a bound state.

·       Pod created with the correct Image?

·       Pod uses PVC called local-pvc?

·       local-pv bound?

·       nginx pod running?

·       Volume mounted at the correct path?

apiVersion: v1
kind: Pod
metadata:
  name: nginx
  labels:
    name: nginx
spec:
  containers:
  - name: nginx
    image: nginx:alpine
    volumeMounts:
      - name: local-persistent-storage
        mountPath: /var/www/html
  volumes:
    - name: local-persistent-storage
      persistentVolumeClaim:
        claimName: local-pvc

해당 pvc를 사용하는 nginx 파드를 만든다.

 

local-pvc가 요청을 받고 연결하여 정상 바운드 된것을 확인 할 수 있다.

controlplane ~ ➜  kubectl get pvc
NAME        STATUS   VOLUME     CAPACITY   ACCESS MODES   STORAGECLASS    AGE
local-pvc   Bound    local-pv   500Mi      RWO            local-storage   8m33s

 

 

14. Create a new Storage Class called delayed-volume-sc that makes use of the below specs:

provisioner: kubernetes.io/no-provisioner
volumeBindingMode: WaitForFirstConsumer

apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: delayed-volume-sc
provisioner: kubernetes.io/no-provisioner
volumeBindingMode: WaitForFirstConsumer

kubectl create -f a.yaml로 생성하면 된다.

 

'Tools > K8S' 카테고리의 다른 글

K8S Ingress & Egress Gateway  (0) 2024.03.25
Kubernetes Secret  (0) 2023.07.21
Kubernetes Deployment  (0) 2023.07.01
Kubernetes ReplicaSet  (0) 2023.07.01
Kubernetes Config  (1) 2023.06.17