E-NFS 볼륨, 스토리지 클래스 설정

개요

NFS 서버를 쿠버네티스에서 사용할 수 있게 해보자.
일단 크게 두 가지 방법이 있다.

내장 드라이버 활용

Pasted image 20241017094139.png
이렇게 볼륨에서 바로 파라미터로 주어서 사용할 수 있다.
이러한 방식은 내장(in-tree) 드라이버에 대해서 가능하다.
그런데 nfs는 이게 남아있다지만 사실 다른 내장 드라이버들은 사라지는 추세이기도 하고, 공식 문서에서도 다른 방식이 권장된다.

csi 드라이버 활용

CSI 규격에 맞춰서 만들어진 nfs 설정이 또 있다.
이 친구를 본격적으로 로컬 클러스터에서 활용할 것이다.

other way?

사실 다른 방법도 존재한다.
csi 드라이버는 아니면서 외부 드라이버인 방식.
대표적으로 nfs-subdir-external-provisioner가 있다.
이게 사람들이 가장 많이 사용하던 방식이라고 한다.
그런데 이제 CSI를 밀어주고 있는 판국에 굳이 과거의 방식을 사용하지 않아도 된다고 한다면 나는 사용할 필요를 크게 못 느끼겠다.
검색해봐도 크게 별다른 차이가 없다는 것 같기도 하다.
대신 추후 보안을 생각했을 때는 공식 지원되는 쪽이 더 안전하다는 것이 일견의 주장.

계획

그래서 이번에는 이 세 가지를 간단하게 사용해보고 비교해볼 수 있을 만치 비교해보는 게 목표이다.
궁극적으로 사용할 것은 이미 정해져있기는 하다.
그래도 왜 좋은지 이유를 알면 더 좋을 것이다.

세팅

T-NFS 서버 만들고, 연결하기
일단 nfs 서버를 마련한다.
나는 vm 하나를 파서 nfs 용으로 활용하기로 결정했다.
그래야 ip 세팅이 깔끔하게 잘 되기 때문이다.

Pasted image 20241017095559.png
이게 내가 사용하고자 하는 기본 파드 템플릿.
Nginx를 넣고, index.html을 수정한 값이 스토리지에 들어가게 할 생각이다.
Pasted image 20241017095851.png
기본 html 파일의 경로는 대충 다음과 같다.

내장 드라이버

Pasted image 20241017104640.png
컨테이너 안에서 접근하는 인덱스 경로는 이렇다.
이걸 그대로 nfs 디렉에 넣어줬다.
Pasted image 20241017104216.png
마운팅을 시킬 때는 해당 디렉토리의 위치를 진짜 그대로 연결해주어야만 하는 모양이다.
Pasted image 20241017105054.png
그래서 이렇게 경로를 넣어줬다.
nfs는 내가 export한 풀로 잡아서 지정해준다.
Pasted image 20241017105034.png
이렇게 접근이 가능한 모습.
Pasted image 20241017105231.png
공유된 파일시스템이라 nfs 노드에서 파일을 수정하니 바로 반영이 되는 것이 확인된다.

정리

이렇게 하는 방식은, nfs 서버의 파일시스템을 말그대로 내 컨테이너에 부착시켜주는 형태이다.
말그대로 nfs 클라이언트처럼 활용하겠다는 뜻.

참고로 문서에도 나와있지만, PersistentVolume를 nfs에서 가져오는 것도 가능하다.

Pasted image 20241017105750.png
이것도 여담인데, 공식 문서 예제에서는 클러스터에다 nfs 파드를 띄운 다음에 걔에다 연결을 시켜서 보여준다.
노드 죽을 때 영속성이 걱정돼서 스토리지를 고민하는 거니까 사실 이러한 접근법은 진짜 사용 예시로서만 바라보면 좋겠다.

CSI 드라이버

다음은 이제 내가 써보고 싶은 CSI 드라이버.
StorageClass로 활용하는 방식으로 해볼 것이다.
즉, PersistentVolume를 만들어서 공간을 확보한 후에 이걸 파드에 붙이는 방식.

Helmkubectl 두 가지 방법이 있고, 문서에 너무나도 친절하게 딸깍 명령어를 제공한다.
사실 이전에 클라우드 엔지니어 인턴 과제에서 kubectl 방식을 해봤기 때문

헬름

드라이버 설치

Pasted image 20241017113003.png
Pasted image 20241017113244.png
말할 것도 없이 그냥 따라하면 된다.
Pasted image 20241017115012.png
성공적으로 설치된 것을 확인할 수 있다.
Pasted image 20241017115040.png
헬름 리스트로는 이렇게 볼 수 있다.
네임스페이스 설정을 해야하는 건 또 몰랐네.

스토리지 쓰고 싶다!
퍼시트턴트 볼륨 - 쿠버네티스 공간 확보 10g
클레임 10 20

스토리지클래스
퍼볼클 - 마운팅

스토리지 클래스, pvc 생성

apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: nfs-csi
provisioner: nfs.csi.k8s.io
parameters:
  server: nfs-server.default.svc.cluster.local
  share: /
  # csi.storage.k8s.io/provisioner-secret is only needed for providing mountOptions in DeleteVolume
  # csi.storage.k8s.io/provisioner-secret-name: "mount-options"
  # csi.storage.k8s.io/provisioner-secret-namespace: "default"
reclaimPolicy: Delete
volumeBindingMode: Immediate
mountOptions:
  - nfsvers=4.1

대충 예제 옵션 가져왔다.
서버 주소는 당연히 바꿔줘야 할 것이다.

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: pvc-nfs-dynamic
  namespace: default
spec:
  accessModes:
    - ReadWriteMany
  resources:
    requests:
      storage: 10Gi
  storageClassName: nfs-csi

Pasted image 20241017115821.png
공유 경로를 제대로 설정하지 않아서 뜨는 에러 같다.
Pasted image 20241017120052.png
경로까지 제대로 지정해주자 pvc도 성공적으로 이뤄졌다.
Pasted image 20241017120232.png
내부에는 공간이 할당된 것으로 보이는 디렉토리가 생겼다.
그러나 내용물은 없는 상태이다.

Pasted image 20241017145707.png
어떤 것들이 설치되었나 궁금해서 조금 봤는데, 데몬셋으로 모든 노드에 nfs 파드를 배치한다.
그거랑 별개로 컨트롤러도 따로 둔다.

Pasted image 20241017120947.png
이번에도 이렇게 파드에 마운트를 시켜본다.
Pasted image 20241017121007.png
내용물은 현재 없으니 당연히 403이 뜬다.
Pasted image 20241017121246.png
함부러 nfs쪽에서 내가 파일을 넣어보았다.
Pasted image 20241017121306.png
응답이 성공적으로 이뤄진다.
Pasted image 20241017121500.png
또 nfs 서버 쪽에서 장난질하려는데 실패.
Pasted image 20241017130715.png
하하..

Pasted image 20241017122218.png
이번에는 디플로이먼트로 해보고 있다.
Pasted image 20241017130240.png
이들은 전부 같은 pvc를 두고 있다.
그래서 해당 내용을 수정하면 모든 파드가 동일하게 반응할 것이다.
Pasted image 20241017131026.png
이건 그냥 컨테이너 프로브 걸어둔 김에 한번 테스트도 해봤다.
파일을 없애버리자 서비스에서 엔드포인트가 제거됐다.

외부 드라이버

과거에 많이 사용된 nfs subdir external provisioner를 설치해본다.
이건 하고나서 바로 삭제할 것이다.
이것도 헬름으로 설치.

helm repo add nfs-subdir-external-provisioner https://kubernetes-sigs.github.io/nfs-subdir-external-provisioner/
helm install nfs-subdir-external-provisioner nfs-subdir-external-provisioner/nfs-subdir-external-provisioner \
    --set nfs.server=x.x.x.x \
    --set nfs.path=/exported/path

이번에는 방식이 조금 다르다.
CSI 드라이버에서는 드라이버를 설치하고, 스토리지 클래스에서 실제로 연결을 시켰다.
그러나 이번에는 정말 외부 프로비저너를 사용한다는 느낌이다.
Pasted image 20241017143610.png
꼭 저렇게 옵션으로 넣지 않고 파일을 받아서 하는 방법도 존재한다.
그러나 막상 보니까 여기를 꼭 채워놔야 한다, 이렇게 나와 있는 것이 아니라 조금 헷갈릴 만하다고 생각한다.
Pasted image 20241017143802.png
대단한 거 할 것도 아니라 그냥 네임스페이스에 질렀다.
간단하게 디플로이먼트로 구현된 것이 확인된다.
Pasted image 20241017145048.png
궁금해서 조금 더 뒤져봤다.
외부로 엔드포인트를 연결할 수 있도록 권한을 뚫어준 게 아닐까 생각한다.

Pasted image 20241017143857.png
아무튼, 별다른 설정 없이 성공적으로 스토리지 클래스가 생겼다.
Pasted image 20241017144120.png
pvc도 성공적으로 됐는데, 이 놈은 디렉토리가 실행파일로 생기냐..?
Pasted image 20241017144626.png
뭐.. 결국 여태 봤지만 모든 nfs 들은 내가 안 속에서 마음대로 파일을 수정하는 게 가능했다.
Pasted image 20241017144832.png
아까는 확인 못 했는데, pvc를 삭제하니까 archived로 이름이 바뀌었다.

helm uninstall nfs-subdir-external-provisioner

삭제도 참 쉬워서 좋다.

정리

세 가지의 nfs 사용 방식을 알아봤다.

사실 결론이랄 건 딱히 없다.
어차피 어느 쪽이든 다 크게 상관없는 선택지 같았다.
CSI가 아무래도 이후를 생각했을 때 더 좋지 않을까 정도이다.
프로그램의 안정성에 유지보수와 표준에 대한 정도가 고려된다면, CSI를 고르는 게 아무래도 더 낫지 않을까 한다.
Pasted image 20241017150205.png
뭐.. 지피티 형님 말로는 그렇다고 한다.
그러고 보니 CSI에 강제되는 몇몇 인터페이스들이 있는 것 같던데, 그런 기능에서 이점이 생기는 게 아닐까 싶기도 하다.

참고