k8s를 운영할 땐 네트워크 PV(Persistent Volume)를 통해 스토리지를 공유해 사용하는 것이 일반적이다.
이에 네트워크 PV를 구성하는 방법을 정리해본다.
Rocky Linux 9.5를 기준으로 작성하였다.
1. NFS 구축
네트워크 PV를 구축하는 방법은 다양하나 이 글에서는 NFS를 이용하기로 한다.
먼저 마스터 노드에 NFS 서버를 설치하자.
NFS로 공유할 디렉터리의 권한이 777임을 주의하자.
필자는 NFS에 접근 가능한 노드를 모두 신뢰하기에 세팅 편의를 위해 777 권한을 주었으나 썩 바람직한 방법은 아니다.
$ sudo dnf install nfs-utils -y $ sudo systemctl enable nfs-server $ sudo systemctl start nfs-server $ sudo mkdir /storage/k8s $ sudo chmod 777 /storage/k8s
이제 NFS로 공유할 디렉터리와 공유 대상 네트워크 대역을 입력한다.
필자의 k8s 워커 노드는 10.10.10.64/26 대역을 사용하므로 이를 적용하였다.
참고로 마스터 노드는 이 대역에 포함되지 않아도 무방하다.
$ sudo vim /etc/exports > /storage/k8s 10.10.10.0/26(rw,sync,no_subtree_check) $ sudo exportfs -arv $ sudo systemctl restart nfs-server
이제 워커 노드에도 NFS 서버를 설치하면 준비는 끝이다.
$ sudo dnf install nfs-utils -y
2. nfs 동적 프로비저닝
nfs만을 사용하는 경우 존재하는 디렉터리만을 네트워크 PV로 사용할 수 있는 문제가 있다.
이를 해결하기 위해 nfs 동적 프로비저닝(nfs-subdir-external-provisioner) 도구를 설치한다. [Github]
이 도구를 사용하면 PVC(PV Claim, PV 요청)가 발생할 때 자동으로 PV가 생성된다.
이제 helm을 통해 동적 프로비저닝 도구를 설치해보자.
아래는 위에서 설정한 nfs 서버의 /k8s 디렉터리를 nfs-csi 이름으로 동적 프로비저닝하되
PVC가 삭제되면서 디렉터리를 아카이빙하지 않고 바로 삭제(archiveOnDelete)하는 명령어이다.
아래 명령어를 실행하면 nfs-csi라는 이름의 storageClass가 생성된다.
참고로 storageClass가 생성된 이후로 archiveOnDelete와 같은 파라미터는 수정이 불가능하며, storageClass 삭제 시 연결된 PV와 PVC도 모두 삭제된다는 점을 주의하자.
$ helm repo add nfs-subdir https://kubernetes-sigs.github.io/nfs-subdir-external-provisioner $ helm install nfs-provisioner nfs-subdir/nfs-subdir-external-provisioner \ --set nfs.server=<NFS_SERVER_IP> \ --set nfs.path=/k8s \ --set storageClass.name=nfs-csi \ --set storageClass.archiveOnDelete=false
3. 서비스 배포
서비스를 배포하면서 PVC를 함께 배포하면 PVC 이름대로 PV가 자동 생성된다.
예를 들어 다음 매니페스트 파일에서는 web-pvc 이름으로 1GiB의 PV가 생성될 것이다.
참고로 nfs의 경우 RWX(ReadWriteMany)를 지원하기에 여러 PVC가 하나의 PV를 공유해 사용할 수 있다.
아래 매니페스트 파일처럼 PVC를 배포하고 이 PVC를 이용해 Volume을 마운트하면 된다.
# temporary-webserver.yaml --- apiVersion: v1 kind: PersistentVolumeClaim metadata: name: web-pvc spec: accessModes: - ReadWriteOnce # 단일 노드 읽기/쓰기 resources: requests: storage: 1Gi # 1GB 스토리지 요청 storageClassName: nfs-csi # 기존에 생성한 nfs 프로바이저 이름 --- apiVersion: apps/v1 kind: Deployment metadata: name: web spec: replicas: 1 selector: matchLabels: app: web template: metadata: labels: app: web spec: containers: - name: nginx image: nginx:alpine ports: - containerPort: 80 volumeMounts: - name: web-storage mountPath: "/usr/share/nginx/html" # 웹 콘텐츠 디렉토리 volumes: - name: web-storage persistentVolumeClaim: claimName: web-pvc # 위에서 정의한 PVC 참조
끝이다.