Profile picture

[k8s] NFS 볼륨 구성하기

JaehyoJJAng2023년 04월 24일

▶︎ PersistentVolume

컨테이너를 재시작하게 되면 이전 컨테이너에서 생성된 내부 데이터는 전부 사라지게 된다. 그렇기 때문에 호스트 서버의 볼륨과 컨테이너 내부의 볼륨을 마운트하여 유지하기 위해 사용하는 것이 **PersistentVolume(=PV)**이다.

호스트 서버의 공간 일부를 PV 볼륨으로 할당하여 사용하는 것이 가장 간단하지만 이 경우 하나의 노드만 PV를 사용할 수 있기 때문에 애플리케이션의 수평 확장은 불가능하다.(=hostPath)

그렇다고 저장소 서비스를 가져다 쓰기에는 많이 부담스러운 상황이라면 **NFS(Network File System)**를 사용하여 한 번에 여러 노드의 접근을 가능하게 하는 nfs 타입의 PV를 사용하면 된다.


▶︎ NFS 서버 구성

  • 모든 설치 작업은 Master Node에서 진행
  • 리눅스 배포판 : Rocky

1. Rocky OS 환경에서 NFS 서버를 구성하기 위해서는 다음 패키지가 필요하다.

yum update -y
yum install -y nfs-utils rpcbind portmap

2. NFS 서버에서 공유할 마운트포인트 지정

mkdir /mnt/shared
chmod -R 777/mnt/shared

3. NFS 서비스 설정파일을 수정. 공유할 디렉토리 경로와 현재 사용하고 있는 서버 인스턴스의 서브넷 범위 지정

echo '/mnt/shared 192.168.56.0/24(rw,sync,no_subtree_check)' | tee -a /etc/exports

4. 설정을 적용하고 서비스 재시작

exportfs -a
systemctl enable --now nfs-server.service

▶︎ NFS 클라이언트 구성

  • 워커 노드에서 진행

NFS 서버에 접속하는 노드에는 'nfs-utils' 패키지만 설치하면 된다.


▶︎ Manifest 작성

NFS 서버의 Private IP를 사용하여 PV, PVC를 작성 및 생성 해보자.


‣ PV 생성

nfs-pv.yaml

apiVersion: v1
kind: PersistentVolume
metadata:
  name: nfs-storage
  labels:
    type: nfs
spec:
  capacity:
    storage: 10Gi
  accessModes: ["ReadWriteMany"]
  nfs:
    server: "192.168.56.30" # NFS servers' IP
    path: /mnt/shared # NFS server's shared path
$ kubectl apply -f ./nfs-pv.yaml

‣ PVC 생성

nfs-pvc.yaml

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: nfs-storage-claim
spec:
  storageClassName: "" # 빈 문자열 줘야함 (중요)
  accessModes: ["ReadWriteMany"]
  resources:
    requests:
      storage: 3Gi
  selector:
    matchExpressions:
      - key: type
        operator: In
        values:
          - nfs
$ kubectl apply -f ./nfs-pvc.yaml

▶︎ NFS Volume 테스트

NFS 파일 공유가 정상적으로 처리되는지 확인하기 위해 간단하게 테스트해보자.
우선 nginx 이미지 기반의 Deployment를 배포해보자.


nginx-pod.yaml

---
apiVersion: v1
kind: Service
metadata:
  name: web-svc
  labels:
    role: web
spec:
  ports:
    - name: nginx-port
      protocol: TCP
      port: 80
      targetPort: 80
  selector:
    role: web
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: web
spec:
  replicas: 1
  strategy:
    type: RollingUpdate
    rollingUpdate:
      maxSurge: 0
      maxUnavailable: 1
  selector:
    matchLabels:
      role: web
  template:
    metadata:
      labels:
        role: web
    spec:
      containers:
        - name: nginx-container
          image: nginx:latest
          ports:
            - containerPort: 80
              protocol: TCP
          volumeMounts:
            - name: web-storage
              mountPath: /usr/share/nginx/html/
      volumes:
        - name: web-storage
          persistentVolumeClaim:
            claimName: nfs-storage-claim # 위에서 생성한 PVC name 키 값 입력 (name: nfs-storage-claim)
kubectl apply -f ./nginx-pod.yaml

이제 NFS가 정상적으로 동작하는지 테스트해보자.
먼저 마스터 노드의 /mnt/shared 디렉토리에 index.html을 하나 새로 만들자.

$ echo '<h1>Hello! NFS is Success!</h1>' > /mnt/shared/index.html

그리고 web-svc 서비스의 CLUSTER-IP를 조회하자

$ kubectl get svc web-svc
NAME      TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)   AGE
web-svc   ClusterIP   10.98.149.103   <none>        80/TCP    7m11s

curl로 웹 페이지를 조사해보자.

$ curl -X GET 10.98.149.103:80
<h1>Hello! NFS is Success!</h1>

짜잔. 로컬에서 작성한 /mnt/shared/index.html 파일이 컨테이너에서 실시간으로 반영되는 것을 확인할 수 있었다!.

컨테이너의 마운트 경로를 /usr/share/nginx/html 로 잡았던 이유는 nginx 이미지의 기본 html을 읽어들이는 경로가 /usr/share/nginx/html 이었기 때문이다!


Loading script...