본문 바로가기
k8s

Kubernetes에서 NAS 사용하기

by marble25 2023. 3. 26.

쿠버네티스 환경에서 nas를 마운트해서 사용하고 싶었는데 방법이 어떤 것이 있을지 찾아보았다.

NFS

NFS(Network File System)

nfs는 네트워크에 파일을 저장하는 방식으로, 사용자가 원격 컴퓨터에 있는 파일 및 디렉토리에 액세스할 수 있게 한다. 주로 NAS에서 사용한다.

Kubernetes에서 NFS 사용하기

  1. pod에 직접 마운트

    마운트가 필요한 파드에 직접 값을 넣어주는 방법이 존재한다.

     volumes:
           - name: nas-cli-volume
             nfs:
               server: xxx.xxx.xxx.xxx
               path: <nas-mount-dir>

    그러나 추상화 측면에서 좋지 않아 보이고, 모든 pod마다 nfs 정보를 가지고 있는 것이 좋지 않아 보인다.

  2. nfs-pod-provisioner를 통해 pv 생성을 pvc 요청할 때마다 해줌

    (kubernetes) - nfs storage사용하기

    pvc를 요청 → nfs-pod-provisioner에서 pv를 dynamic하게 생성 → 마운트 완료 의 과정으로 진행된다.

    사용하는 입장에서는 pv를 선언할 필요 없이 pvc만 선언하면 provisioner에서 알아서 해주는 다이나믹 프로비저닝 방식이다.

    Provisioner

    rbac

     apiVersion: v1
     kind: ServiceAccount
     metadata:
       name: nfs-client-provisioner
       # replace with namespace where provisioner is deployed
       namespace: default
     ---
     kind: ClusterRole
     apiVersion: rbac.authorization.k8s.io/v1
     metadata:
       name: nfs-client-provisioner-runner
     rules:
       - apiGroups: [""]
         resources: ["nodes"]
         verbs: ["get", "list", "watch"]
       - apiGroups: [""]
         resources: ["persistentvolumes"]
         verbs: ["get", "list", "watch", "create", "delete"]
       - apiGroups: [""]
         resources: ["persistentvolumeclaims"]
         verbs: ["get", "list", "watch", "update"]
       - apiGroups: ["storage.k8s.io"]
         resources: ["storageclasses"]
         verbs: ["get", "list", "watch"]
       - apiGroups: [""]
         resources: ["events"]
         verbs: ["create", "update", "patch"]
     ---
     kind: ClusterRoleBinding
     apiVersion: rbac.authorization.k8s.io/v1
     metadata:
       name: run-nfs-client-provisioner
     subjects:
       - kind: ServiceAccount
         name: nfs-client-provisioner
         # replace with namespace where provisioner is deployed
         namespace: default
     roleRef:
       kind: ClusterRole
       name: nfs-client-provisioner-runner
       apiGroup: rbac.authorization.k8s.io
     ---
     kind: Role
     apiVersion: rbac.authorization.k8s.io/v1
     metadata:
       name: leader-locking-nfs-client-provisioner
       # replace with namespace where provisioner is deployed
       namespace: default
     rules:
       - apiGroups: [""]
         resources: ["endpoints"]
         verbs: ["get", "list", "watch", "create", "update", "patch"]
     ---
     kind: RoleBinding
     apiVersion: rbac.authorization.k8s.io/v1
     metadata:
       name: leader-locking-nfs-client-provisioner
       # replace with namespace where provisioner is deployed
       namespace: default
     subjects:
       - kind: ServiceAccount
         name: nfs-client-provisioner
         # replace with namespace where provisioner is deployed
         namespace: default
     roleRef:
       kind: Role
       name: leader-locking-nfs-client-provisioner
       apiGroup: rbac.authorization.k8s.io

    StorageClass

     apiVersion: storage.k8s.io/v1
     kind: StorageClass
     metadata:
       name: nfs-client
     provisioner: k8s-sigs.io/nfs-subdir-external-provisioner # or choose another name, must match deployment's env PROVISIONER_NAME'
     parameters:
       archiveOnDelete: "false"

    Provisoner

     apiVersion: apps/v1
     kind: Deployment
     metadata:
       name: nfs-client-provisioner
       labels:
         app: nfs-client-provisioner
       # replace with namespace where provisioner is deployed
       namespace: default
     spec:
       replicas: 1
       strategy:
         type: Recreate
       selector:
         matchLabels:
           app: nfs-client-provisioner
       template:
         metadata:
           labels:
             app: nfs-client-provisioner
         spec:
           serviceAccountName: nfs-client-provisioner
           containers:
             - name: nfs-client-provisioner
               image: k8s.gcr.io/sig-storage/nfs-subdir-external-provisioner:v4.0.2
               volumeMounts:
                 - name: nfs-client-root
                   mountPath: /persistentvolumes
               env:
                 - name: PROVISIONER_NAME
                   value: k8s-sigs.io/nfs-subdir-external-provisioner
                 - name: NFS_SERVER # do not change
                   value: xxx.xxx.xxx.xxx # Ip of the NFS SERVER
                 - name: NFS_PATH # do not change
                   value: <nfs-path>  # path to nfs directory setup
           volumes:
             - name: nfs-client-root
               nfs:
                 server: xxx.xxx.xxx.xxx
                 path: <nfs-path>

    실제 사용하기

    pvc

     apiVersion: v1
     kind: PersistentVolumeClaim
     metadata:
       name: task-pv-claim
     spec:
       storageClassName: nfs-client
       accessModes:
         - ReadWriteOnce
       resources:
         requests:
           storage: 20Gi

    pod

     apiVersion: v1
     kind: Pod
     metadata:
       name: task-pv-pod
     spec:
       volumes:
         - name: task-pv-storage
           persistentVolumeClaim:
             claimName: task-pv-claim
       containers:
         - name: task-pv-container
           image: nginx
           ports:
             - containerPort: 80
               name: "http-server"
           volumeMounts:
             - mountPath: "/usr/share/nginx/html"
               name: task-pv-storage

    동적 프로비저닝 방식이기 때문에 따로 pv를 관리하지 않아도 nfs-client-provisioner deployment에서 자동으로 pv를 생성해준다.

    Deployment에서 클러스터 레벨의 pv를 생성할 수 있는 이유는 nfs-client-provisioner 서비스 어카운트에 nfs-client-provisioner-runner 클러스터 롤과 leader-locking-nfs-client-provisioner 롤이 바인딩되어 kubernetes api를 자유롭게 호출할 수 있기 때문이다. Deployment 내에서 pv를 만들면서 mounting될 path도 host에 자연스럽게 만들어 준다.

    단점

    • NFS가 제한하는 total size보다 더 많은 양을 allocate할 수 있다.
    • Storage resize나 expansion를 지원하지 않는다.

'k8s' 카테고리의 다른 글

[TIL] regcred 알아보기  (0) 2023.04.24
K8S 컴포넌트 정리  (0) 2023.03.31
Kubernetes 스토리지 구조  (0) 2023.03.26
[TIL] pod에서 서비스 접속하기  (0) 2022.07.10
Minikube, Kubeadm, Kind, K3S  (0) 2022.05.08