티스토리 뷰

728x90
반응형

서론

본 포스팅에서는 Kubernetes에서 Persistent Volume & Persistent Volume Claim을 사용하는 방법에 대해 알아보도록 하겠습니다.

먼저 Persistent Volume(이하 PV)에 대해 알아보겠습니다.

PV는 Kubernetes와 같은 PaaS Platform에서 필수요소입니다. Container가 추구하는 Agility & Resilance 의 근본이 되는 것은 바로 경량화입니다. Container 내부에 대용량의 데이터를 포함할 경우 빠른 Scale-Out에 제약이 발생할 수 있으며, 이는 컨테이너가 추구하는 Agility를 위반하게 됩니다.

이와 같은 문제를 해소하기 위해 스토리지 볼륨을 마운트 하여 사용해야 하는데 이를 Kubernetes에서는 PV라고 명칭하고 있습니다.

PV에 위치시키는 파일은 대체로 대용량 파일데이터나 변경되지 않는 정적파일 등의 애플리케이션 영역과 WEB/WAS/DB 등의 Log를 저장하는 용도 등으로 활용할 수 있습니다.

본문

1. PV yaml 파일 생성

apiVersion: v1

kind: PersistentVolume

metadata:

  name: wildfly-pv

  labels:

    name: wildfly-pv

spec:

  capacity:

    storage: 10Ti

  accessModes:

  - ReadWriteMany

  nfs:

    server: 192.168.56.104

    path: /mypath

---

kind: PersistentVolumeClaim

apiVersion: v1

metadata:

  name: wildfly-pvc

spec:

  accessModes:

  - ReadWriteMany

  resources:

   requests:

    storage: 10Ti

  selector:

    matchLabels:

      name: wildfly-pv

PV는 위와 같이 yaml 파일로 지정하여 생성할 수 있습니다.

주요 항목을 살펴보자면

- spec.capacity.storate : 스토리지 용량을 지정할 수 있습니다.

- spec.accessModes : AccessMode는 Volume의 Read/Write에 대한 권한을 제공하는 옵션입니다.

지정할 수 있는 옵션의 종류는 3가지로 다음과 같습니다.

a) ReadWriteOnce(RWO) : 하나의 노드가 볼륨을 Read/Write 가능하도록 마운트

b) ReadOnlyMany(ROX) : 여러개의 노드가 Read 전용으로 사용하도록 마운트

c) ReadWriteMany(RWX) : 여러개의 노드가 Read/Write 가능하도록 마운트

- spec.nfs : nfs 스토리지를 마운트합니다.

현재 PV yaml 파일에는 nfs를 지정하여 마운트하였지만, 다양한 형태의 스토리지 볼륨을 마운트할 수 있습니다.

Kubernetes 공식 홈페이지 : https://kubernetes.io/docs/concepts/storage/volumes/#types-of-volumes

 

위 이미지와 같이 Kubernetes Cluster에 Storage를 PV 형태로 추가하고 PVC로 Service에 할당해 주는 방식으로 구성됩니다.

다양한 형태의 Storage Plugin을 제공하지만, 이중 자주 사용하는 스토리지에 대해서 살펴보도록 하겠습니다.

2. 다양한 스토리지 볼륨

a) emptyDir

emptyDir은 Pod 내부의 Container들이 공유하는 임시 볼륨입니다. emptyDir은 Pod가 기동되면서 생성되고 종료되면서 삭제됩니다.

apiVersion: v1

kind: Pod

metadata:

  name: wildfly-pod

spec:

  containers:

    - image: ubuntu:18.04

      name: ubuntu-container

      command: ["tail","-f", "/dev/null"]

      volumeMounts:

        - mountPath: /cache

          name: emptydir-volume

    - image: httpd:latest

      name: httpd-container

      volumeMounts:

        - mountPath: /cache

          name: emptydir-volume

  volumes:

    - name: emptydir-volume

      emptyDir: {}

위와같이 구성할 경우 wildfly-pod 내부의 /cache 영역은 ubuntu & httpd-container 컨테이너가 공유하게 됩니다.

kubectl get pods --all-namespaces -o jsonpath="{..image}" |tr -s '[[:space:]]' '\n' |sort |uniq -c

[root@kubemaster deployment]# kubectl get pods --all-namespaces -o jsonpath="{..image}" |tr -s '[[:space:]]' '\n' |sort |uniq -c

      2 calico/cni:v3.7.3

      1 calico/kube-controllers:v3.7.3

      2 calico/node:v3.7.3

      2 coredns/coredns:1.6.0

      2 docker.io/calico/cni:v3.7.3

      1 docker.io/calico/kube-controllers:v3.7.3

      2 docker.io/calico/node:v3.7.3

      2 docker.io/coredns/coredns:1.6.0

      1 docker.io/library/nginx:1.17

      2 gcr.io/google-containers/cluster-proportional-autoscaler-amd64:1.6.0

      4 gcr.io/google-containers/k8s-dns-node-cache:1.15.8

      2 gcr.io/google-containers/kube-apiserver:v1.16.3

      2 gcr.io/google-containers/kube-controller-manager:v1.16.3

      4 gcr.io/google-containers/kube-proxy:v1.16.3

      2 gcr.io/google_containers/kubernetes-dashboard-amd64:v1.10.1

      2 gcr.io/google-containers/kube-scheduler:v1.16.3

      2 httpd:latest

      1 nginx:1.17

      2 quay.io/kubernetes-ingress-controller/nginx-ingress-controller:0.26.1

      2 ubuntu:18.04

[root@kubemaster deployment]#

위는 현재 Kubernetes Cluster에 기동되어 있는 Container 리스트입니다. 이중 httpd & ubuntu 이미지를 하나의 Container에 포함하여 Pod를 생성하였으며, 이 두 Container는 emptyDir로 지정된 /cache 영역을 공유하게 됩니다.

kubectl get pods --all-namespaces -o=jsonpath='{range .items[*]}{"\n"}{.metadata.name}{":\t"}{range .spec.containers[*]}{.image}{", "}{end}{end}' |\ sort

[root@kubemaster deployment]# kubectl get pods --all-namespaces -o=jsonpath='{range .items[*]}{"\n"}{.metadata.name}{":\t"}{range .spec.containers[*]}{.image}{", "}{end}{end}' |sort

calico-kube-controllers-584dcf688b-qj7vb:       docker.io/calico/kube-controllers:v3.7.3, 

calico-node-nzwvv:      docker.io/calico/node:v3.7.3, 

calico-node-q254k:      docker.io/calico/node:v3.7.3, 

coredns-58687784f9-jshnf:       docker.io/coredns/coredns:1.6.0, 

coredns-58687784f9-z9gdk:       docker.io/coredns/coredns:1.6.0, 

dns-autoscaler-79599df498-fvddt:        gcr.io/google-containers/cluster-proportional-autoscaler-amd64:1.6.0, 

kube-apiserver-kubemaster:      gcr.io/google-containers/kube-apiserver:v1.16.3, 

kube-controller-manager-kubemaster:     gcr.io/google-containers/kube-controller-manager:v1.16.3, 

kube-proxy-dm55b:       gcr.io/google-containers/kube-proxy:v1.16.3, 

kube-proxy-l9zzx:       gcr.io/google-containers/kube-proxy:v1.16.3, 

kubernetes-dashboard-556b9ff8f8-pkxw7:  gcr.io/google_containers/kubernetes-dashboard-amd64:v1.10.1, 

kube-scheduler-kubemaster:      gcr.io/google-containers/kube-scheduler:v1.16.3, 

nginx-ingress-controller-6fbff54876-lsd4l:      quay.io/kubernetes-ingress-controller/nginx-ingress-controller:0.26.1, 

nginx-proxy-kubeworker: docker.io/library/nginx:1.17, 

nodelocaldns-j64jh:     gcr.io/google-containers/k8s-dns-node-cache:1.15.8, 

nodelocaldns-kjkd9:     gcr.io/google-containers/k8s-dns-node-cache:1.15.8, 

wildfly-pod:    ubuntu:18.04, httpd:latest, 

[root@kubemaster deployment]#

위는 현재 Kubernetes Cluster에 기동되어 있는 Pod 들이 구성하고 있는 Container 정보입니다.

위 정보를 기반으로 emptyDir이 공유되는지 여부를 확인해 보겠습니다.

[root@kubeworker ~]# docker ps -a

CONTAINER ID        IMAGE                                      COMMAND                  CREATED             STATUS                      PORTS               NAMES

6e6608293b5f        httpd                                      "httpd-foreground"       16 minutes ago      Up 16 minutes                                   k8s_httpd-container_wildfly-pod_default_f4271129-e794-40bd-aa1e-3e6035d7f14a_0

00b1dfc3ac87        549b9b86cb8d                               "tail -f /dev/null"      16 minutes ago      Up 16 minutes                                   k8s_ubuntu-container_wildfly-pod_default_f4271129-e794-40bd-aa1e-3e6035d7f14a_0

...

...

[root@kubeworker ~]# docker exec -it 00b1dfc3ac87 bash → ubuntu container 접속

root@wildfly-pod:/# cd /cache

root@wildfly-pod:/cache# ls

root@wildfly-pod:/cache# echo "emptyDir test" >> Test.txt  ubuntu container에 /cache/Test.txt 파일 생성

root@wildfly-pod:/cache# ls -la

total 4

drwxrwxrwx. 2 root root 22 Jan  5 12:15 .

drwxr-xr-x. 1 root root 30 Jan  5 11:58 ..

-rw-r--r--. 1 root root 14 Jan  5 12:15 Test.txt

root@wildfly-pod:/cache# exit

exit

[root@kubeworker ~]# docker exec -it 6e6608293b5f bash → httpd container 접속

root@wildfly-pod:/usr/local/apache2# cd /cache

root@wildfly-pod:/cache# ls -la  httpd container에 /cache/Test.txt 파일 확인

total 4

drwxrwxrwx. 2 root root 22 Jan  5 12:15 .

drwxr-xr-x. 1 root root 41 Jan  5 11:58 ..

-rw-r--r--. 1 root root 14 Jan  5 12:15 Test.txt

root@wildfly-pod:/cache#

위와 같이 ubuntu container에서 생성한 Test.txt 파일이 httpd container 내부에서도 공유되는 것을 확인할 수 있습니다.

앞서 설명했지만, emptyDir은 휘발성 스토리지로 Pod가 내려가면 emptyDir이 삭제되므로, 임시로 공유할 파일을 위치시키는데 사용해야 합니다.

 

# 참조

- 두개의 Container의 Mount 위치를 동일하게 하지 않아도 상관 없습니다. ubuntu는 /cache1, httpd는 /cache2로 마운트하여 사용할 수 있습니다.

- emptyDir은 Default로 디스크에 저장하지만, emptyDir.medium 필드를 통해 메모리에 저장하여 사용할 수도 있습니다. tmpfs는 매우 빠르지만, Container가 생성될 때 할당되는 Memory Limit에 포함되어 할당되므로 사용에 유의해야 합니다.

b) hostpath

hostpath는 Internal Storate 영역으로 호스트 OS의 파일이나 디렉터리를 마운트하여 Pod와 공유하는 마운트 방식입니다.

hostpath 방식은 호스트 OS의 Docker(/var/lib/docker)에 접근해야 하거나 호스트 OS에서 개발한 환경을 Container 내부에 적용해야 하거나, 또는 반대로 컨테이너 환경에서 추가된 파일을 호스트 OS에서 사용해야 할 경우 유용하게 사용할 수 있습니다.

hostpath 방식의 경우 호스트 OS의 장애가 발생했을 경우 Pod를 실행할 수 없으며, 호스트 OS의 디스크에 대한 데이터 손실 또는 가용성 등에 대해 고려해야 합니다.

apiVersion: v1

kind: Pod

metadata:

  name: wildfly-pod

spec:

  containers:

    - image: httpd:latest

      name: httpd-container

      volumeMounts:

        - mountPath: /hostdir

          name: hostdir-volume

  volumes:

  - name: hostdir-volume

    hostPath:

      path: /root

      type: Directory

위와 같이 반영한 이후 pod 내부를 확인해 보면, 아래와 같이 호스트 OS의 파일 및 디렉토리가 공유되는 것을 확인할 수 있습니다.

[root@kubemaster ~]# ls -la

total 44

dr-xr-x---. 11 root root 4096 Jan  5 20:48 .

dr-xr-xr-x. 17 root root  224 Dec 25 16:59 ..

-rw-------.  1 root root 1403 Dec 25 16:59 anaconda-ks.cfg

drwx------.  4 root root   27 Dec 25 19:31 .ansible

-rw-------.  1 root root 8812 Jan  2 08:00 .bash_history

-rw-r--r--.  1 root root   18 Dec 29  2013 .bash_logout

-rw-r--r--.  1 root root  197 Dec 25 19:13 .bash_profile

-rw-r--r--.  1 root root  176 Dec 29  2013 .bashrc

drwx------.  3 root root   17 Dec 25 19:25 .cache

-rw-r--r--.  1 root root  100 Dec 29  2013 .cshrc

drwx------.  2 root root   25 Dec 25 21:33 .docker

drwxr-xr-x.  4 root root   41 Dec 25 20:41 git_repo

drwx------.  4 root root   51 Dec 25 22:17 .kube

drwxr-xr-x.  3 root root   64 Dec 25 20:23 kube-manifests

drwxr-----.  3 root root   19 Dec 25 19:04 .pki

-rw-------.  1 root root 1024 Jan  4 19:26 .rnd

drwx------.  2 root root   80 Dec 25 19:07 .ssh

-rw-r--r--.  1 root root  129 Dec 29  2013 .tcshrc

drwxr-xr-x.  2 root root   44 Jan  4 19:31 test.nrson.co.kr

[root@kubemaster ~]# kubectl get pods --all-namespaces

NAMESPACE       NAME                                        READY   STATUS    RESTARTS   AGE

default         wildfly-pod                                 1/1     Running   0          32s

ingress-nginx   nginx-ingress-controller-6fbff54876-lsd4l   1/1     Running   6          11d

kube-system     calico-kube-controllers-584dcf688b-qj7vb    1/1     Running   5          11d

kube-system     calico-node-nzwvv                           1/1     Running   6          11d

kube-system     calico-node-q254k                           1/1     Running   6          11d

kube-system     coredns-58687784f9-jshnf                    1/1     Running   5          11d

kube-system     coredns-58687784f9-z9gdk                    1/1     Running   5          11d

kube-system     dns-autoscaler-79599df498-fvddt             1/1     Running   5          11d

kube-system     kube-apiserver-kubemaster                   1/1     Running   5          11d

kube-system     kube-controller-manager-kubemaster          1/1     Running   5          11d

kube-system     kube-proxy-dm55b                            1/1     Running   5          11d

kube-system     kube-proxy-l9zzx                            1/1     Running   5          11d

kube-system     kube-scheduler-kubemaster                   1/1     Running   5          11d

kube-system     kubernetes-dashboard-556b9ff8f8-pkxw7       1/1     Running   7          11d

kube-system     nginx-proxy-kubeworker                      1/1     Running   5          11d

kube-system     nodelocaldns-j64jh                          1/1     Running   5          11d

kube-system     nodelocaldns-kjkd9                          1/1     Running   5          11d

[root@kubemaster ~]# kubectl exec -it wildfly-pod bash

root@wildfly-pod:/usr/local/apache2# cd /hostdir/

root@wildfly-pod:/hostdir# ls -la

total 28

dr-xr-x---. 7 root root  223 Jan  4 10:23 .

drwxr-xr-x. 1 root root   43 Jan  5 14:42 ..

drwx------. 3 root root   17 Dec 25 10:31 .ansible

-rw-------. 1 root root  892 Dec 28 16:21 .bash_history

-rw-r--r--. 1 root root   18 Dec 29  2013 .bash_logout

-rw-r--r--. 1 root root  197 Dec 25 10:13 .bash_profile

-rw-r--r--. 1 root root  176 Dec 29  2013 .bashrc

drwx------. 3 root root   17 Dec 25 10:25 .cache

-rw-r--r--. 1 root root  100 Dec 29  2013 .cshrc

drwx------. 2 root root   25 Dec 25 12:33 .docker

drwxr-----. 3 root root   19 Dec 25 10:20 .pki

drwx------. 2 root root   29 Dec 25 10:07 .ssh

-rw-r--r--. 1 root root  129 Dec 29  2013 .tcshrc

-rw-------. 1 root root 1403 Dec 25 08:02 anaconda-ks.cfg

-rw-r--r--. 1 root root    0 Jan  4 10:23 kubecfg.crt

root@wildfly-pod:/hostdir#

즉 호스트 OS의 /root 디렉토리가 Pod 내부에서 /hostdir 디렉토리 위치에 마운트 된것을 확인할 수 있습니다.

hostpath의 경우 ReadWriteOnce로만 적용이 가능하므로 Container 또는 서비스 별로 특정 디렉토리를 지정하여 로그에이전트가 수집하는 로그를 모으는 역할로 사용할 수 있습니다.

c) 네트워크 볼륨

Network Volume은 Persistent Volume(PV) 이외에 Persistent Volume Claim(이하 PVC)이 존재합니다.

Pod 또는 Service에 PV를 지정하기 위해서는 스토리지에 대한 정보를 알고 있어야 합니다. 앞서 살펴본 emptyDir, hostPath의 경우 별도의 정보가 필요없는(호스트 OS, Pod 내부 등) 스토리지 형태이므로 PV 자체를 적용하는데 문제는 없지만, 네트워크 볼륨 형태로 제공되는 PV를 적용하기 위해서는 앞선 볼륨 형태와 다르게 복잡도가 높아지게 됩니다. PV를 사용하고자 하는 사용자 입장에서 PV를 적용하는데 복잡도를 낮추고 설계된 정보를 요청 기반으로 적용할 수 있도록 한 것이 바로 PVC 입니다.

운영자가 생성한 PV를 PVC로 요청(claim)하여 적용합니다.

앞선 포스팅 초반에 추가한 yaml 파일을 다시한번 살펴보겠습니다.

apiVersion: v1

kind: PersistentVolume

metadata:

  name: wildfly-pv

  labels:

    name: wildfly-pv

spec:

  capacity:

    storage: 10Ti

  accessModes:

  - ReadWriteMany

  nfs:

    server: 192.168.56.104

    path: /mypath

---

kind: PersistentVolumeClaim

apiVersion: v1

metadata:

  name: wildfly-pvc

spec:

  accessModes:

  - ReadWriteMany

  resources:

   requests:

    storage: 10Ti

  selector:

    matchLabels:

      name: wildfly-pv

위와 같이 PVC는 PV로 추가된 wildfly-pv를 spec.selector.matchLabels.name의 형태로 추가하면, 몇몇 원하는 정보를 변경하여 적용할 수 있습니다. (storage size, accessMode 등)

대표적인 네트워크 볼륨으로는 iscsi, cephfs, glusterfs, nfs 등이 있습니다.

iscsi는 ReadWriteOnce, ReadOnlyMany의 accessModes를 지원하며, cephfs, glusterfs, nfs는 ReadWriteOnce, ReadOnlyMany, ReadWriteMany를 모두 지원합니다.

[root@kubemaster ~]# kubectl get pv --all-namespaces
NAME    CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS   CLAIM                               STORAGECLASS    REASON   AGE
wildfly-pv   10Ti                   RWX            Retain                          Bound    default/wildfly-pvc                                                                8d

[root@kubemaster ~]# kubectl get pvc --all-namespaces
NAMESPACE    NAME              STATUS   VOLUME    CAPACITY   ACCESS MODES   STORAGECLASS    AGE
default               wildfly-pvc     Bound      wildfly-pv   10Ti              RWX                                                            8d
[root@kubemaster ~]

위와 같이 추가된 pv, pvc 정보를 확인할 수 있습니다.

3. 유의 사항

a) PV와 PVC 연결 시 유의 사항

PV와 PVC를 연결하기 위해서는 Label 정보를 매칭 시켜주어야 합니다.

apiVersion: v1

kind: PersistentVolume

metadata:

  name: wildfly-pv

  labels:

    name: wildfly-pv

spec:

  capacity:

    storage: 10Ti

  accessModes:

  - ReadWriteMany

  nfs:

    server: 192.168.56.104

    path: /mypath

---

kind: PersistentVolumeClaim

apiVersion: v1

metadata:

  name: wildfly-pvc

spec:

  accessModes:

  - ReadWriteMany

  resources:

   requests:

    storage: 10Ti

  selector:

    matchLabels:

      name: wildfly-pv

네트워크 볼륨 예시로 포함된 yaml 파일의 파란색으로 표시된 label을 기반으로 PV와 PVC가 연결되며, 추가된 PVC를 Deployment에 적용하기 위해서는 다음과 같이 추가해 주어야 합니다.

apiVersion: apps/v1

kind: Deployment

metadata:

  name: wildfly-app-deployment

  labels:

    app: wildfly-app

spec:

  replicas: 1

  selector:

    matchLabels:

      app: wildfly-app

  template:

    metadata:

      labels:

        app: wildfly-app

    spec:

      containers:

      - name: wildfly-app

        image: 192.168.56.100:5000/middleware/wildfly/wildfly_custom_image:latest

        imagePullPolicy: Always

        ports:

        - containerPort: 8080

        volumeMounts:

         - name: wildfly-app-pvc

          mountPath: /data

      nodeSelector:

       test: worker

      volumes:

      - name: wildfly-app-pvc

        persistentVolumeClaim:

         claimName: wildfly-pvc

b) PV, PVC의 LifeCycle 변화

PV, PVC의 LifeCycle은 총 4가지 형태를 갖고 변화하게 됩니다.

- Available : PV 생성

- Bound : PVC에 의해 바인딩 되었을 경우

- Released : PVC가 삭제되었을 경우

- Fail : PV에 문제가 발생하였을 경우

LifeCycle은 Available → Bound → Released → Bound ... 순으로 반복되며, Released 즉 PVC가 삭제되었을 경우 실제 스토리지에 있는 파일을 어떻게 관리할 것인지에 대한 Reclaiming(재활용) 정책을 결정할 수 있습니다. 

PV, PVC의 Reclaiming 정책으로는 다음 세가지를 적용할 수 있습니다.

- Retain : 삭제하지 않고 PV의 내용 유지
- Recycle : 재 사용이 가능하며, 재 사용시에는 데이타의 내용을 자동으로 rm -rf 로 삭제한 후 재사용
- Delete : 볼륨의 사용이 끝나면, 볼륨 삭제 (AWS EBS, GCE PD,Azure Disk 등)

Reclaim 정책을 변경하고자 할 경우 아래와 같이 적용이 가능합니다.

kubectl patch pv nfs-pv -p '{"spec":{"persistentVolumeReclaimPolicy":"Retain"}}'

[root@kubemaster deployment]# kubectl patch pv wildfly-pv -p '{"spec":{"persistentVolumeReclaimPolicy":"Retain"}}'

persistentvolumes "wildfly-pv" patched

[root@kubemaster deployment]# 

c) PV Mount 경로 관리

PV, PVC의 경로는 다음과 같이 관리할 수 있습니다.

[pv.yaml]

apiVersion: v1
kind: PersistentVolume
metadata:
  name: k8s-pv
  labels:
    name: k8s-pv
spec:
  capacity:
    storage: 10Ti
  accessModes:
  - ReadWriteMany
  nfs:
    server: 192.168.56.100
    path: /volume1/k8s/nrson
---
kind: PersistentVolumeClaim
apiVersion: v1
metadata:
  name: k8s-pvc
spec:
  accessModes:
  - ReadWriteMany
  resources:
   requests:
    storage: 10Ti
  selector:
    matchLabels:
      name: k8s-pv

 

[deployment.yaml]

apiVersion: apps/v1
kind: Deployment
metadata:
  name: k8s-test-deployment
  labels:
    app: k8s-test
spec:
  replicas: 1
  selector:
    matchLabels:
      app: k8s-test
  template:
    metadata:
      labels:
        app: k8s-test
    spec:
      containers:
      - name: k8s-test
        image: 192.168.56.100:5000/middleware/wildfly/wildfly_custom_image:latest
        imagePullPolicy: Always
        resources:
          requests:
            cpu: "2"
            memory: "2Gi"
            ephemeral-storage: "30Gi"
          limits:
            cpu: "4"
            memory: "4Gi"
            ephemeral-storage: "30Gi"
        ports:
        - containerPort: 8090
        volumeMounts:
        - name: k8s-test
          mountPath: /k8s
      nodeSelector:
       kubernetes.io/hostname: kubeworker
      volumes:
      - name: k8s-test
        persistentVolumeClaim:
         claimName: k8s-pvc
---
apiVersion: v1
kind: Service
metadata:
  name: k8s-test
spec:
  selector:
    app: k8s-test
  ports:
    - protocol: TCP
      port: 8090
      targetPort: 8090
  type: ClusterIP
---
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: k8s-test-ingress
  namespace: default
spec:
  rules:
  - host: nrson.test.go.kr
    http:
      paths:
      - backend:
          serviceName: k8s-test
          servicePort: 8090
        path: /

pv를 생성하는 pv.yaml의

  nfs:
    server: 192.168.56.100
    path: /volume1/k8s/nrson

와 같이 /volume1/k8s의 경로가 NAS(nfs)의 Root 경로일때, 그 하위의 nrson 경로를 Mount 경로로 지정할 수 있습니다.

또한, deployment.yaml의

        volumeMounts:
        - name: k8s-test
          mountPath: /k8s

와 같이 pv에서 선언한 mount 경로(/volume1/k8s/nrson)를 deployment 내부에서 /k8s로 변경하여 마운트해서 사용할 수 있습니다.

4) NAS(nfs) 장애 발생 시 POD 동작 방식

a) 정상 상태일 때 POD 내부와 호스트 OS의 PV 확인

[root@kubemaster ~]# kubectl exec -it k8s-test-deployment-5fd667864c-v99kn bash

[jboss@k8s-test-deployment-5fd667864c-v99kn ~]$ ls

wildfly

[jboss@k8s-test-deployment-5fd667864c-v99kn ~]$ df -k

Filesystem                        1K-blocks       Used   Available Use% Mounted on

overlay                            47285700   12146416    35139284  26% /

tmpfs                                 65536          0       65536   0% /dev

tmpfs                               1940036          0     1940036   0% /sys/fs/cgroup

192.168.56.100:/volume1/k8s/nrson 37484137088 9875159552 27608977536  27% /k8s

/dev/mapper/rhel-root              47285700   12146416    35139284  26% /etc/hosts

shm                                   65536          0       65536   0% /dev/shm

tmpfs                               1940036         12     1940024   1% /run/secrets/kubernetes.io/serviceaccount

tmpfs                               1940036          0     1940036   0% /proc/acpi

tmpfs                               1940036          0     1940036   0% /proc/scsi

tmpfs                               1940036          0     1940036   0% /sys/firmware

[jboss@k8s-test-deployment-5fd667864c-v99kn ~]$ cd /k8s

[jboss@k8s-test-deployment-5fd667864c-v99kn k8s]$ ls -la

total 0

drwxrwxrwx. 1 jboss jboss  0 Jan 10 12:04 .

drwxr-xr-x. 1 root  root  50 Jan 10 12:05 ..

[jboss@k8s-test-deployment-5fd667864c-v99kn k8s]$ vi test.txt

[jboss@k8s-test-deployment-5fd667864c-v99kn k8s]$ ls -la

total 4

drwxrwxrwx. 1 jboss jboss 16 Jan 10  2020 .

drwxr-xr-x. 1 root  root  50 Jan 10 12:05 ..

-rwxrwxrwx. 1 jboss jboss  5 Jan 10  2020 test.txt

[jboss@k8s-test-deployment-5fd667864c-v99kn k8s]$ exit

exit

[root@kubemaster ~]# cd /root/mountk8s/nrson/

[root@kubemaster nrson]# ls

test.txt

[root@kubemaster nrson]#

실제 NAS(nfs)에 연결이 된 것인지 확인하기 위해 위와 같이 kubenetes에 생성된 PV를 확인합니다. 또한 Mount 된 /k8s로 들어가 파일을 생성하고 저장한 이후 Pod에서 빠져 나옵니다.

이후 Local Machine에 마운트한 경로로 들어가 파일이 제대로 생성되어 있는지 확인해 봅니다.

(VM Local Machine에는 mount -t nfs 192.168.56.100:/volume1/k8s/nrson /volume1/k8s/nrson 으로 마운트 되어 있습니다.)

위와 같이 파일이 정상적으로 생성되어 있는 것을 볼 수 있습니다.

 

b) 비정상 상태일 때 POD 내부와 호스트 OS의 PV 확인

장애 상황을 재현하기 위해 NAS(nfs) Webconsole에 접근하여 접근 권한을 해제한 후 테스트를 진행하였습니다.

[root@kubemaster ~]# kubectl exec -it k8s-test-deployment-5fd667864c-v99kn bash

→ 장애 발생 후 POD 내부에서는 PV 정보를 확인할 수 없음

[jboss@k8s-test-deployment-5fd667864c-v99kn ~]$ df -k

Filesystem            1K-blocks     Used Available Use% Mounted on

overlay                47285700 12124556  35161144  26% /

tmpfs                     65536        0     65536   0% /dev

tmpfs                   1940036        0   1940036   0% /sys/fs/cgroup

/dev/mapper/rhel-root  47285700 12124556  35161144  26% /etc/hosts

shm                       65536        0     65536   0% /dev/shm

tmpfs                   1940036       12   1940024   1% /run/secrets/kubernetes.io/serviceaccount

tmpfs                   1940036        0   1940036   0% /proc/acpi

tmpfs                   1940036        0   1940036   0% /proc/scsi

tmpfs                   1940036        0   1940036   0% /sys/firmware

→ PV가 정상으로 돌아온 이후 POD 내부에서는 PV 정보를 확인할 수 있음

[jboss@k8s-test-deployment-5fd667864c-v99kn ~]$ df -k

Filesystem                        1K-blocks       Used   Available Use% Mounted on

overlay                            47285700   12124600    35161100  26% /

tmpfs                                 65536          0       65536   0% /dev

tmpfs                               1940036          0     1940036   0% /sys/fs/cgroup

192.168.56.100:/volume1/k8s/nrson 37484137088 9875159552 27608977536  27% /k8s

/dev/mapper/rhel-root              47285700   12124600    35161100  26% /etc/hosts

shm                                   65536          0       65536   0% /dev/shm

tmpfs                               1940036         12     1940024   1% /run/secrets/kubernetes.io/serviceaccount

tmpfs                               1940036          0     1940036   0% /proc/acpi

tmpfs                               1940036          0     1940036   0% /proc/scsi

tmpfs                               1940036          0     1940036   0% /sys/firmware

[jboss@k8s-test-deployment-5fd667864c-v99kn ~]$ 

[jboss@k8s-test-deployment-5fd667864c-v99kn ~]$ cd /k8s

[jboss@k8s-test-deployment-5fd667864c-v99kn k8s]$ ls -la

total 4

drwxrwxrwx. 1 jboss jboss 16 Jan 10  2020 .

drwxr-xr-x. 1 root  root  50 Jan 10 12:05 ..

-rwxrwxrwx. 1 jboss jboss  5 Jan 10  2020 test.txt

[jboss@k8s-test-deployment-5fd667864c-v99kn k8s]$

위와 같이 Persistent Volume이 장애가 발생하여 연결이 끊어질 경우 Pod가 재기동 되거나 다운되는 현상은 발생하지 않지만, PV와의 연결이 끊어져 어플리케이션 Exception이 발생할 가능성이 매우 높은 상태가 됩니다.

또한 PV 장애가 해결되어 복구되면 Kubernetes에서는 자동으로 감지하여 PVC와 Pod를 연결해 줍니다.

결론

이번 포스팅에서는 Kubernetes의 PV & PVC에 대해 살펴보았습니다.

PV와 PVC는 컨테이너의 경량화와 직결되어 있는 중요한 요소입니다. 이번 포스팅에서 살펴본 내용은 물론 다양한 형태의 스토리지와 결합하여 사용할 수 있으며, 다양한 형태로 마운트되어 제공될 수 있습니다.

제공되는 스토리지 형태 또는 공유해야 할 파일 형태에 따라 옳바른 스토리지를 선택하고, 스토리지에 맞는 구성을 Kubernetes에 적용하는 것은 Kubernetes를 설계하는데 있어 매우 중요할 것입니다.

728x90
반응형