DevOps/Kubernetes

[Kubernetes] 동적 프로비저닝 (Dynamic Provisioning) ( + NFS 동적 프로비저닝)

TTOII 2022. 5. 29. 21:04
728x90

✔️ Dynamic Provisioning (동적 프로비저닝)

출처 : https://velog.io/@hyun6ik

지금까지 PV를 사용하려면 미리 외부 스토리지를 준비해야만 했다. 

예를 들어 AWS EBS를 PV로 사용하려면 EBS를 미리 생성한 뒤, 볼륨 ID를 YAML 파일에 직접 입력하는 방식으로 사용했다. 하지만 매번 이렇게 볼륨 스토리지를 직접 수동으로 생성하고 스토리지에 대한 접근 정보를 YAML 파일에 적는 것은 귀찮은 일이다.

이를 위해 쿠버네티스는 Dynamic Provisioning 기능을 제공한다.

다이나믹 프로비저닝은 PVC이 요구하는 조건과 일치하는 PV이 존재하지 않는다면 자동으로 PV와 외부 스토리지를 함께 프로비저닝하는 기능이다. 따라서 Dynamic Provisioning을 사용하면 EBS와 같은 외부 스토리지를 직접 미리 생성해 둘 필요가 없다. PVC를 생성하면 외부 스토리지가 자동으로 생성되기 때문이다.

 

Dynamic Provisioning에서도 스토리지 클래스를 사용할 수 있는데 Dynamic Provisioning은 스토리지 클래스의 정보를 참고해 외부 스토리지를 생성한다.


즉, 클러스터 관리자가 PV provisioner를 배포하고 하나 이상의 스토리지 클래스 객체를 정의해서 개발자가 작성한 PVC 요청이 있을 때 마다 새 PV를 생성할 수 있게 한다.

 

단, Dynamic Provisioning을 모든 쿠버네티스 클러스터에서 범용적으로 사용할 수 있는 것은 아니며, 다이나믹 프로비저닝 기능이 지원되는 스토리지 프로비저너가 미리 활성화돼 있어야 한다.

 

✔️ NFS Dynamic Provisioner 구성

스토리지 클래스 | Kubernetes

쿠버네티스에는 내장 NFS 프로비저너가 없다. NFS를 위한 스토리지 클래스를 생성하려면 외부 프로비저너를 사용해야 한다.
예시는 다음과 같다.

NFS subdir external provisioner

 

 vagrant@k8s-node1  ~  sudo mkdir /nfsvolume

root 밑에 nfsvolume 디렉토리를 만든다.

 

 vagrant@k8s-node1  ~  git clone https://github.com/kubernetes-sigs/nfs-subdir-external-provisioner.git

git 레포지토리를 동기화 시킨다.

 

 vagrant@k8s-node1  ~  ls
annotation  cont  deploy  kubespray  label  namespace  nfs-subdir-external-provisioner  pod  podlife  svc  test  test.yml  volume

 vagrant@k8s-node1  ~  cd nfs-subdir-external-provisioner 

 vagrant@k8s-node1  ~/nfs-subdir-external-provisioner   master  ls
CHANGELOG.md     Dockerfile            LICENSE   OWNERS          README.md   SECURITY_CONTACTS  cloudbuild.yaml  code-of-conduct.md  docker  go.sum         vendor
CONTRIBUTING.md  Dockerfile.multiarch  Makefile  OWNERS_ALIASES  RELEASE.md  charts             cmd              deploy              go.mod  release-tools
 vagrant@k8s-node1  ~/nfs-subdir-external-provisioner   master  cd deploy

deploy 디렉토리에 들어온다.

 

 vagrant@k8s-node1  ~/nfs-subdir-external-provisioner/deploy   master  ls
class.yaml  deployment.yaml  objects  rbac.yaml  test-claim.yaml  test-pod.yaml

 vagrant@k8s-node1  ~/nfs-subdir-external-provisioner/deploy   master  kubectl create -f rbac.yaml 
serviceaccount/nfs-client-provisioner created
clusterrole.rbac.authorization.k8s.io/nfs-client-provisioner-runner created
clusterrolebinding.rbac.authorization.k8s.io/run-nfs-client-provisioner created
role.rbac.authorization.k8s.io/leader-locking-nfs-client-provisioner created
rolebinding.rbac.authorization.k8s.io/leader-locking-nfs-client-provisioner created

rbac.yaml 파일 적용하기

 

 vagrant@k8s-node1  ~/nfs-subdir-external-provisioner/deploy   master  vi deployment.yaml     
          env: # App에 제공할 환경 변수 
            - name: PROVISIONER_NAME
              value: k8s-sigs.io/nfs-subdir-external-provisioner
            - name: NFS_SERVER
              value: 192.168.100.100
            - name: NFS_PATH
              value: /nfsvolume
      volumes:
        - name: nfs-client-root
          nfs:
            server: 192.168.100.100
            path: /nfsvolume

deployment.yaml 수정해서 NFS 서버 위치 지정하기

 

 vagrant@k8s-node1  ~/nfs-subdir-external-provisioner/deploy  master ±  kubectl create -f deployment.yaml 
deployment.apps/nfs-client-provisioner created

deployment.yaml 파일 적용하기

 

 vagrant@k8s-node1  ~/nfs-subdir-external-provisioner/deploy  master ±  cat class.yaml            
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: nfs-client
provisioner: k8s-sigs.io/nfs-subdir-external-provisioner # or choose another name, must match deployment's env PROVISIONER_NAME'
parameters:
  archiveOnDelete: "false"

 vagrant@k8s-node1  ~/nfs-subdir-external-provisioner/deploy  master ±  kubectl create -f class.yaml     
storageclass.storage.k8s.io/nfs-client created

class.yaml 파일까지 적용하면 설치 완료

 

 vagrant@k8s-node1  ~/nfs-subdir-external-provisioner/deploy  master ±  kubectl get deploy,rs,po        
NAME                                     READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/nfs-client-provisioner   1/1     1            1           64s

NAME                                                DESIRED   CURRENT   READY   AGE
replicaset.apps/nfs-client-provisioner-758f8cd4d6   1         1         1       64s

NAME                                          READY   STATUS    RESTARTS   AGE
pod/nfs-client-provisioner-758f8cd4d6-wpjbt   1/1     Running   0          64s

확인

 

 vagrant@k8s-node1  ~/nfs-subdir-external-provisioner/deploy  master ±  kubectl get sc          
NAME         PROVISIONER                                   RECLAIMPOLICY   VOLUMEBINDINGMODE   ALLOWVOLUMEEXPANSION   AGE
nfs-client   k8s-sigs.io/nfs-subdir-external-provisioner   Delete          Immediate           false                  39s

클라우드가 아니므로 기본적으로 Immediate로 설정된다.

 

mypvc.yaml

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: mypvc-dynamic
spec:
  accessModes:
    - ReadWriteMany
  resources:
    requests:
      storage: 1G
  storageClassName: 'nfs-client'
 vagrant@k8s-node1  ~/volume/nfs-dynamic  kubectl create -f mypvc.yaml 
persistentvolumeclaim/mypvc-dynamic created

 vagrant@k8s-node1  ~/volume/nfs-dynamic kubectl get pv,pvc           
NAME                                                        CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS   CLAIM                   STORAGECLASS   REASON   AGE
persistentvolume/pvc-cf9ea92a-aa68-4df1-9fa4-91d953c04d2d   1G         RWX            Delete           Bound    default/mypvc-dynamic   nfs-client              6s

NAME                                  STATUS   VOLUME                                     CAPACITY   ACCESS MODES   STORAGECLASS   AGE
persistentvolumeclaim/mypvc-dynamic   Bound    pvc-cf9ea92a-aa68-4df1-9fa4-91d953c04d2d   1G         RWX            nfs-client     6s

mypvc-dynamic를 생성했고 Bound 상태이며 연결될 볼륨은 랜덤한 이름으로 생성된 pvc-cf9ea92a-aa68-4df1-9fa4-91d953c04d2dpv의 이름과 일치한다. 용량은 1G이고 STORAGECLASSnfs-client이다.


pvc 입장에서 CLAIM은 default NS의 mypvc-dynamic이다.

이와 같이 pvc만 만들면 STORAGECLASS에 의해 자동으로 pv가 생성된다.

 

 vagrant@k8s-node1  ~/volume/nfs-dynamic  sudo ls -l /nfsvolume 
total 8
drwxrwxrwx 2 root     root     4096 May 24 05:18 default-mypvc-dynamic-pvc-cf9ea92a-aa68-4df1-9fa4-91d953c04d2d

디렉토리가 만들어진 것을 확인할 수 있다.
NS명 + pvc명 + pv명으로 디렉토리가 생성되었고 데이터는 해당 디렉토리에 저장된다.

 

 vagrant@k8s-node1  ~/volume/nfs-dynamic  sudo ls -l /nfsvolume/default-mypvc-dynamic-pvc-cf9ea92a-aa68-4df1-9fa4-91d953c04d2d 
total 0

 vagrant@k8s-node1  ~/volume/nfs-dynamic  echo "<h1> Hello NFS Dynamic Provision </h1>" | sudo tee /nfsvolume/default-mypvc-dynamic-pvc-cf9ea92a-aa68-4df1-9fa4-91d953c04d2d/index.html
<h1> Hello NFS Dynamic Provision </h1>

디렉토리에 index.html 파일을 만든다.

 

myweb-rs.yaml

apiVersion: apps/v1
kind: ReplicaSet
metadata:
  name: myweb-rs
spec:
  replicas: 3
  selector:
    matchLabels:
      app: web
  template:
    metadata:
      labels:
        app: web
    spec:
      containers:
        - name: myweb
          image: httpd
          volumeMounts:
            - name: myvol
              mountPath: /usr/local/apache2/htdocs
      volumes:
        - name: myvol
          persistentVolumeClaim:
            claimName: mypvc-dynamic
 vagrant@k8s-node1  ~/volume/nfs-dynamic  kubectl create -f myweb-rs.yaml -f myweb-svc-lb.yaml
replicaset.apps/myweb-rs created
service/myweb-svc-lb created

리소스를 생성한다.

 

 vagrant@k8s-node1  ~/volume/nfs-dynamic  kubectl get po                                      
NAME                                      READY   STATUS    RESTARTS   AGE
myweb-rs-lsmnd                            1/1     Running   0          9s
myweb-rs-st9d4                            1/1     Running   0          9s
myweb-rs-xhv65                            1/1     Running   0          9s
nfs-client-provisioner-758f8cd4d6-wpjbt   1/1     Running   0          11m

 vagrant@k8s-node1  ~/volume/nfs-dynamic  curl 192.168.100.240                                
<h1> Hello NFS Dynamic Provision </h1>
 vagrant@k8s-node1  ~/volume/nfs-dynamic  kubectl delete -f .             
persistentvolumeclaim "mypvc-dynamic" deleted
replicaset.apps "myweb-rs" deleted
service "myweb-svc-lb" deleted

 vagrant@k8s-node1  ~/volume/nfs-dynamic  kubectl get pv,pvc                                                              
No resources found

 vagrant@k8s-node1  ~/volume/nfs-dynamic  kubectl get sc                                  
NAME                   PROVISIONER                                   RECLAIMPOLICY   VOLUMEBINDINGMODE   ALLOWVOLUMEEXPANSION   AGE
nfs-client (default)   k8s-sigs.io/nfs-subdir-external-provisioner   Delete          Immediate           false                  28h

RECLAIMPOLICYDelete이므로 pvc를 지우면 pv도 같이 지워진다.
데이터를 남기고 싶으면 Retain 정책을 사용하면 된다.

728x90