Study/Kubernetes

Kubernetes에서 NFS와 PV,PVC,를 이용한 데이터 관리하기

ABCD 2024. 6. 27.

Why??

Kubernetes 환경에서는 우리가 사용하고 싶은 application을 이미지화해서 쉽게 배포하고 관리할 수 있습니다.

 

하지만, Storage에 대한 문제가 있는데요.

 

우리 컨테이너화해서 사용하고 있는 Pod에 쇼핑몰 홈페이지가 있다고 가정해봅시다.
우리는 쇼핑몰 홈페이지에서 등록하는 상품을 100개 등록했고, 해당 상품마다 이미지가 20개씩 들어있다고 해봅시다.

분산화한 개발이 아닐 경우, 우리는 해당 프로젝트가 있는 host의 어딘가에 저장을 하게됩니다. 예를 들면 /project/image라는 폴더에 저장을 하겠죠.

 

하지만, 분산화시켜 사용 중 해당 Pod이 알 수 없는 이유 때문에 깨져 Pod이 내려갔다가 다시 생성되었다고 가정해 봅시다.

그러면 우리가 처음에 배포한 이미지를 바탕으로 쇼핑몰 홈페이지 프로젝트가 배포되기 때문에 우리가 작성해 두었던 상품 100개에 대한 각각의 이미지 20개들은 없는 상태로 운영이 될겁니다.

이를 방지하기 위해 Kubernetes에서는 PV, PVC라는 개념을 사용합니다.

PV

PVPersistent Volume의 약자로 볼륨을 영구적으로 사용하는 것이죠.
볼륨을 영구적으로 사용한다는 것은 pod에서 생성한 데이터를 영구적으로 보관한다는 뜻입니다.

PVC

PVCPersistent Volume Claim의 약자로 볼륨을 영구적으로 사용할 곳에 요청을 보내는 정보입니다.

NFS

NFSNetwork File System의 약자로 네트워크를 통한 파일을 통신하는 것입니다.
예를 들면 우리는 samba를 통해 smb프로토콜을 사용해서 네트워크를 통해 공유폴더를 지정하고 binding시킬 수 있습니다.
이것을 가능하게 해주는 것이라고 생각하면 됩니다.

 

IBM의 문서에서는 다음과 같이 정의합니다.

  • 서버가 반출한 파일 시스템을 개인용 컴퓨터가 마운트할 수 있도록 해주는 개인용 컴퓨터를 위한 프로그램

Setting

NFS 관련 패키지 설치

우선 가장 먼저 모든 노드에 NFS 설치를 해주어야 합니다.
단, 서버에 접근을 하는 노드들(worker)의 경우에는 nfs-common만 설치하면 됩니다.

sudo apt-get update
sudo apt-get install -y nfs-common nfs-kernel-server rpcbind portmap

NFS 서버에서 공유할 디렉터리를 생성

이제 공유폴더를 생성하고 권한을 변경해주어야 합니다.

# /mnt 폴더로 이동
cd /mnt
# /mnt 폴더에 `share`폴더 생성
shdu mkdir share
# `share`폴더의 권한을 전체허용으로 변경
sudo chmod 777 share

NFS 서비스 설정파일 수정

공유할 디렉터리 경로와 현재 사용하고 있는 서버 인스턴스의 서브넷 범위를 지정합니다.

sudo echo '/mnt/share ${host-ip}/${subnet-range}(rw,sync,no_subtree_check)' >> /etc/exports

 

예를 들어 보겠습니다.

sudo echo '/mnt/share 172.26.0.0/16(rw,sync,no_subtree_check)' >> /etc/exports

 

작성한 내용을 확인해 보겠습니다.
아래 명령어 입력후 아래와 같이 나온다면 정상적으로 등록된 것입니다.

$ cat /etc/exports

# /etc/exports: the access control list for filesystems which may be exported
#               to NFS clients.  See exports(5).
#
# Example for NFSv2 and NFSv3:
# /srv/homes       hostname1(rw,sync,no_subtree_check) hostname2(ro,sync,no_subtree_check)
#
# Example for NFSv4:
# /srv/nfs4        gss/krb5i(rw,sync,fsid=0,crossmnt,no_subtree_check)
# /srv/nfs4/homes  gss/krb5i(rw,sync,no_subtree_check)
#
/mnt/share 172.26.0.0/16(rw,sync,no_subtree_check)

 

설정을 적용하고 재시작합니다.

sudo exportfs -a
sudo systemctl restart nfs-kernel-server

테스트 html 파일 생성

echo 'hello Persistent Volume!!' >> /mnt/share/index.html

pv.yaml 파일 생성

이제 Persistent Volume을 생성하기 위해 파일을 생성해 주어야 합니다.
제가 작성한 예시로 예시를 보여드릴게요.

apiVersion: v1
kind: PersistentVolume
metadata:
  name: nfs-pv
  labels:
    type: nfs
spec:
  capacity:
    storage: 10Gi
  accessModes:
    - ReadWriteMany
  nfs:
    server: ${nfs-server-ip} # nfs서버로 사용할 ip
    path: /mnt/share
  mountOptions:
    - nfsvers=4.1 # nfsstat -s를 통해 버전을 확인해보자.

pvc.yaml

Persistent Volume설정 파일을 생성했습니다.
이제 해당 Volume으로 요청을 보낼 수 있는 Claim파일을 생성할 차례입니다.

 

selector하위의 matchExpresstions의 설정으로 pv.yaml파일의 meatadata에서 labels를 찾아 key: value값으로 매칭시킵니다. 그리고 operator로 그 관계를 정의하게 됩니다.

 

In의 경우 무조건 해당 값과 일치해야한다고 선언하는 것입니다. 다음 문서를 통해 상세하게 알 수 있습니다. 참고

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: pvc
spec:
  storageClassName: "" # 공백으로 설정시 자동으로 default 잡아줍니다.
  accessModes:
    - ReadWriteMany
  resources:
    requests:
      storage: 4Gi
  selector:
    matchExpressions:
      - key: type
        operator: In
        values:
          - nfs

nginx.yaml

테스트용 nginx.yaml 파일을 생성해 보겠습니다.

apiVersion: v1
kind: Pod
metadata:
  name: nginx
  labels:
    app: nfs-nginx
spec:
  containers:
    - name: nfs-nginx
      image: nginx
      ports:
        - containerPort: 80
          name: "http-server"
      volumeMounts:
        - name: nginx-storage
          mountPath: "/usr/share/nginx/html"
  volumes:
    - name: nginx-storage
      persistentVolumeClaim:
        claimName: pvc

테스트

이제 테스트를 해보겠습니다. 위에서 작성한 .yaml파일을 적용시켜 줍니다.

kubectl apply -f pv.yaml
kubectl apply -f pvc.yaml
kubectl apply -f nginx.yaml

 

이제 해당 Pod에 접속해서 파일이 온전해 존재하는게 보이는지 확인하면 됩니다.

kubectl exec -it ${pod-name} -- bash

# 접속후 해당 파일 읽기
cat /usr/share/nginx/html/index.html

 

위의 두 명령어 실행 후 우리가 처음에 작성한 hello Persistent Volume!!가 나온다면 성공적으로 설치가 완료된 것입니다.


Issue

Pod의 status가 Pending상태로 지속되는 문제 발생(storage class관련 이슈)

pvc,yaml파일을 생성할 때 설정한 storageClass가 보일겁니다.
공식문서나 다른 글들을 보면 이 값을 공백("")으로 넣으면 디폴트로 자동으로 잡아준다고 적혀있는걸 확인할 수 있습니다.

바로~ 위의 과정을 진행했지만, PodPending상태로 지속되는 현상이 발생하였습니다.

로그를 확인해보니 pod 생성을 기다리는 중이라는 메시지만 나옵니다.

 

그래서 describe를 통해 envent를 확인해 보았습니다.
확인해보니 Persistent Volume이 생성하는 과정에서 실패하는 문제가 발생.

kubectl get sc

 

위 명령어를 실행시켜보니 아무것도 나오지 않는겁니다...

문제는 바로... Storage Class가 없어서 발생하는 문제였습니다.

 

디폴트로 자동으로 잡아주지만, 그마저 무엇인가 하나라도 있어야 가능했던 겁니다.

그래서 storage class를 생성하고 해결하였습니다.

apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: standard
  annotations:
    storageclass.kubernetes.io/is-default-class: "true"
provisioner: kubernetes.io/aws-ebs
parameters:
  type: gp2
kubectl apply -f storage-class.yaml

kubectl get sc

 

정상적으로 생성된 모습을 확인할 수 있습니다.

kube@kube01:~$ kubectl get sc

NAME                 PROVISIONER             RECLAIMPOLICY   VOLUMEBINDINGMODE   ALLOWVOLUMEEXPANSION   AGE
standard (default)   kubernetes.io/aws-ebs   Delete          Immediate           false                  167m

Pod의 상태가 ContainerCreating으로 지속되는 문제 발생

위의 문제로 Pending상태에서는 벗어났습니다.
하지만, 바로 다음 문제에 봉착하고 말았죠.

 

이번엔 무한으로 컨테이너생성중... 이라는 메시지...

이 문제를 해결하기 위해 수많은 고민을 해본 결과 도출한 가능성은 바로!!!!!

 

'NFS가 통신을 해서 디스크를 마운트 시킬텐데, 접속하려는 노드에서도 NFS를 설치해야 하지 않을까??' 였습니다.

 

단순히 ip를 통해 알아서 가져올 수 있을 줄 알았던 생각이 무색하게 바로 설치를 진행... 바로 해결되었습니다.

 

필자의 경우에는 서버에서 설치한 패키지를 전부 설치하였지만, 나중에 찾아본 결과 서버로 접근하려는 컴퓨터의 경우에는 nfs-common만 설치해도 가능하다는 것을 알았습니다.

 

그렇기 때문에 NFS 서버에 접속을 하려는 PC의 경우는 아래 명령어로 설치합니다.

sudo apt-get update
sudo apt-get install -y nfs-common
728x90
반응형

댓글

💲 추천 글