# OCP-NFS Dynamic provisioning

TASK DESCRIPTION

PV Binding이 자동으로 되도록 NFS Dynamic provisioning 설정을 합니다.
NFS dynamic provisioning을 하기 위한 nfs-provisioner Pod를 배포합니다.
github의 external-storage를 참조하십시오.

# git 설치

$ yum install -y git 

# nfs provisioner용 namespace 생성

$ oc new-project nfs

# nfs-provisioner 다운로드

$ mkdir -p /nfsprovider
$ cd /nfsprovider
$ git clone https://github.com/kubernetes-incubator/external-storage.git
$ cd external-storage/nfs-client/

# Service Account 생성 및 권한 설정

현재 namespace를 nfs로 변경  
$ oc project nfs  

rbac.yaml내의 namespace를 모두 ‘nfs’로 변경하고 적용함    
$ NAMESPACE=`oc project -q`
$ sed -i'' "s/namespace:.*/namespace: $NAMESPACE/g" ./deploy/rbac.yaml  
$ oc apply -f deploy/rbac.yaml

service account 'nfs-client-provisioner'에게 hostmount-anyuid SCC적용  
$ oc adm policy add-scc-to-user hostmount-anyuid -z nfs-client-provisioner

rbac.yaml
Service Account 'nfs-client-provisioner'을 만들고 필요한 role을 binding합니다.

apiVersion: v1
kind: ServiceAccount
metadata:
  name: nfs-client-provisioner
  # replace with namespace where provisioner is deployed
  namespace: nfs
---
kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  name: nfs-client-provisioner-runner
rules:
  - 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: nfs
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: nfs
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: nfs
subjects:
  - kind: ServiceAccount
    name: nfs-client-provisioner
    # replace with namespace where provisioner is deployed
    namespace: nfs
roleRef:
  kind: Role
  name: leader-locking-nfs-client-provisioner
  apiGroup: rbac.authorization.k8s.io

# storageclass 생성

OCP Local Image Registry 구성시 생성한 nfs-delete, nfs-retain외에 더 필요한 storage class가 있으면 생성합니다.

storageclass YAML sample 

apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: nfs-standard
provisioner: standard
reclaimPolicy: Retain
volumeBindingMode: Immediate

# nfs-provisioner Pod 배포

  • NFS서버 및 디렉토리 수정, namespace를 ‘nfs’로 변경
$ sed -i'' "s/namespace:.*/namespace: $NAMESPACE/g" ./deploy/deployment.yaml  
  • deployment.yaml수정
    아래 항목을 적절하게 수정합니다.
    • env.PROVISIONER_NAME: storage class에 지정한 provisioner name과 동일하게 변경
    • env.NFS_SERVER, volumes.nfs.server: nfs server의 IP
    • env.NFS_PATH, volumes.nfs.path: nfs server에 미리 만든 자동으로 volume이 생성될 상위 디렉토리
      nfs_path디렉토리 하위에 자동으로 PVC별 디렉토리가 생성됩니다.

중요
StorageClass생성 시 Provioner를 'kubernetes.io/no-provisioner'로 주면,
Dynamic provisoning이 안됩니다.

SAMPLE

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nfs-client-provisioner
  labels:
    app: nfs-client-provisioner
  # replace with namespace where provisioner is deployed
  namespace: nfs
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: quay.io/external_storage/nfs-client-provisioner:latest
          volumeMounts:
            - name: nfs-client-root
              mountPath: /persistentvolumes
          env:
            - name: PROVISIONER_NAME
              value: standard
            - name: NFS_SERVER
              value: 10.40.89.158
            - name: NFS_PATH
              value: /nfs/data
      volumes:
        - name: nfs-client-root
          nfs:
            server: 10.40.89.158
            path: /nfs/data
  • Pod 생성
$ oc apply -f ./deploy/deployment.yaml ​

# 테스트

  • 테스트용 PVC생성
$ vi test-claim.yaml

apiVersion: "v1"
kind: "PersistentVolumeClaim"
metadata:
  name: "test-claim"
spec:
  accessModes:
    - ReadWriteMany
  resources:
    requests:
      storage: 1Gi
  storageClassName: nfs-delete
  volumeMode: Filesystem

$ oc apply -f ./deploy/test-claim.yaml
$ oc get pvc

  • 테스트용 Pod생성
$ vi test-pod.yaml 

kind: Pod
apiVersion: v1
metadata:
  name: test-pod
spec:
  containers:
  - name: test-pod
    image: gcr.io/google_containers/busybox:1.24
    command:
      - "/bin/sh"
    args:
      - "-c"
      - "touch /mnt/SUCCESS && exit 0 || exit 1"
    volumeMounts:
      - name: nfs-pvc
        mountPath: "/mnt"
  restartPolicy: "Never"
  volumes:
    - name: nfs-pvc
      persistentVolumeClaim:
        claimName: test-claim


$ oc apply -f test-pod.yaml
  • mount 확인
    • nfs server의 nfs path로 이동
    • pvc명으로 자동 생성된 디렉토리 확인
    • 디렉토리 하위에 SUCCESS파일 있는지 확인 ​