K8S - Deploy NFS Server on K8S
I want to test statefulset of k8s, a cluster storage is needed.
NFS is the easist solution. We can deploy a NFS server on K8S.
Due to the stateless of K8S, we should fix NFS Server on a specific server.
# kubectl create -f nfs-server.yml apiVersion: extensions/v1beta1 kind: Deployment metadata: name: nfs-server spec: replicas: 1 # <- no more replicas template: metadata: labels: app: nfs-server spec: nodeSelector: # <- use selector to fix nfs-server on k8s2.zhangqiaoc.com kubernetes.io/hostname: k8s2.zhangqiaoc.com containers: - name: nfs-server image: itsthenetwork/nfs-server-alpine:latest volumeMounts: - name: nfs-storage mountPath: /nfsshare env: - name: SHARED_DIRECTORY value: "/nfsshare" ports: - name: nfs containerPort: 2049 # <- export port securityContext: privileged: true # <- privileged mode is mandentory. volumes: - name: nfs-storage hostPath: # <- the folder on the host machine. path: /root/fileshare
create a service to expose the nfs to the other pods
# kubectl expose deployment nfs-server --type=ClusterIP # kubectl get svc NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 9d nfs-server ClusterIP 10.101.117.226 <none> 2049/TCP 14s
Testing:
# yum install -y nfs-utils # mkdir /root/nfsmnt # mount -v 10.101.117.226:/ /root/nfsmnt
Create a PV and PVC for testing
# kubectl create -f pv.yml apiVersion: v1 kind: PersistentVolume metadata: name: mypv1 spec: capacity: storage: 20Gi accessModes: - ReadWriteOnce persistentVolumeReclaimPolicy: Recycle nfs: path: "/" server: nfs-server # kubectl get PersistentVolume NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE mypv1 20Gi RWO Recycle Available 35s # kubectl create -f pvc.yml kind: PersistentVolumeClaim apiVersion: v1 metadata: name: mypvc1 spec: accessModes: - ReadWriteOnce resources: requests: storage: 100Mi # kubectl get PersistentVolumeClaim NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE mypvc1 Bound mypv1 20Gi RWO 13s
In order to use statefulset, we have to have a storage class. And the storage class needs a provisioner
create a service account named nfs-provisioner
# kubectl create -f serviceaccount.yml apiVersion: v1 kind: ServiceAccount metadata: name: nfs-provisioner
For rbac, we should create a clusterrole named nfs-provisioner-runner and a role, named leader-locking-nfs-provisioner
# kubectl create -f rbac.yml kind: ClusterRole apiVersion: rbac.authorization.k8s.io/v1 metadata: name: nfs-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-provisioner subjects: - kind: ServiceAccount name: nfs-provisioner namespace: default roleRef: kind: ClusterRole name: nfs-provisioner-runner apiGroup: rbac.authorization.k8s.io --- kind: Role apiVersion: rbac.authorization.k8s.io/v1 metadata: name: leader-locking-nfs-provisioner rules: - apiGroups: [""] resources: ["endpoints"] verbs: ["get", "list", "watch", "create", "update", "patch"] --- kind: RoleBinding apiVersion: rbac.authorization.k8s.io/v1 metadata: name: leader-locking-nfs-provisioner subjects: - kind: ServiceAccount name: nfs-provisioner # replace with namespace where provisioner is deployed namespace: default roleRef: kind: Role name: leader-locking-nfs-provisioner apiGroup: rbac.authorization.k8s.io
Then, we can deploy nfs client provisioner
# kubectl create -f deployment.yaml # https://github.com/kubernetes-incubator/external-storage/tree/master/nfs-client kind: Deployment apiVersion: extensions/v1beta1 metadata: name: nfs-provisioner spec: replicas: 1 strategy: type: Recreate template: metadata: labels: app: nfs-provisioner spec: serviceAccount: nfs-provisioner containers: - name: nfs-provisioner # image: registry.cn-hangzhou.aliyuncs.com/open-ali/nfs-client-provisioner image: quay.io/external_storage/nfs-client-provisioner:latest volumeMounts: - name: nfs-client-root mountPath: /persistentvolumes env: - name: PROVISIONER_NAME value: zhangqiaoc.com/nfs # this name will be used to create storage class - name: NFS_SERVER value: 10.101.117.226 # nfs server, service name may not be working - name: NFS_PATH value: / volumes: - name: nfs-client-root nfs: server: 10.101.117.226 path: / # kubectl create -f storageclass.yaml kind: StorageClass apiVersion: storage.k8s.io/v1 metadata: name: nfs provisioner: zhangqiaoc.com/nfs
For testing
# kubectl create -f test-claim.yml kind: PersistentVolumeClaim apiVersion: v1 metadata: name: test-claim1 spec: accessModes: - ReadWriteMany resources: requests: storage: 1Mi storageClassName: nfs # kubectl get pvc NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE test-claim1 Bound pvc-25c3b950-8ff1-11e9-9a33-000c29d8a18d 1Mi RWX nfs 16s