Kubernetes部署NFS持久存储(静态和动态) 参考文章
https://www.jianshu.com/p/5e565a8049fc
NFS简介
NFS是网络文件系统Network File System的缩写,NFS服务器可以让PC将网络中的NFS服务器共享的目录挂载到本地的文件系统中,而在本地的系统中来看,那个远程主机的目录就好像是自己的一个磁盘分区一样。
kubernetes使用NFS共享存储有两种方式:
1.手动方式静态创建所需要的PV和PVC。
2.通过创建PVC动态地创建对应PV,无需手动创建PV。
1.k8s集群前提准备 在master节点上部署NFS服务器
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 yum -y install nfs-utils mkdir -p /nfs/data/chmod -R 777 /nfs/datavim /etc/exports /nfs/data *(rw,no_root_squash,sync ) exportfs -r exportfs systemctl restart rpcbind systemctl enable rpcbind systemctl restart nfs systemctl enable nfs rpcinfo -p localhost showmount -e 192.168.88.111
所有node节点安装客户端,开机启动
1 2 yum -y install nfs-utils systemctl start nfs && systemctl enable nfs
2.静态申请PV卷 添加pv卷对应目录,这里创建2个pv卷,则添加2个pv卷的目录作为挂载点。
1 2 3 4 5 6 7 8 9 10 11 12 mkdir -p /nfs/data/pv001vim /etc/exports /nfs/data *(rw,no_root_squash,sync ) /nfs/data/pv001 *(rw,no_root_squash,sync ) exportfs -r systemctl restart rpcbind && systemctl restart nfs
创建PV 下面创建名为pv001的PV卷,配置文件 nfs-pv001.yaml 如下: vim nfs-pv001.yaml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 apiVersion: v1 kind: PersistentVolume metadata: name: nfs-pv001 labels: pv: nfs-pv001 spec: capacity: storage: 1Gi accessModes: - ReadWriteOnce persistentVolumeReclaimPolicy: Recycle storageClassName: nfs nfs: path: /nfs/data/pv001 server: 192.168 .1 .1
配置说明:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 ① capacity 指定 PV 的容量为 1G。 ② accessModes 指定访问模式为 ReadWriteOnce,支持的访问模式有: 2.1ReadWriteOnce – PV 能以 read-write 模式 mount 到单个节点。 2.2ReadOnlyMany – PV 能以 read-only 模式 mount 到多个节点。 2.3ReadWriteMany – PV 能以 read-write 模式 mount 到多个节点。 ③ persistentVolumeReclaimPolicy 指定当 PV 的回收策略为 Recycle,支持的策略有: 3.1Retain – 需要管理员手工回收。 3.2Recycle – 清除 PV 中的数据,效果相当于执行 rm -rf /thevolume/*。 3.3Delete – 删除 Storage Provider 上的对应存储资源,例如 AWS EBS、GCE PD、Azure Disk、OpenStack Cinder Volume 等。 ④ storageClassName 指定 PV 的 class 为 nfs。相当于为 PV 设置了一个分类,PVC 可以指定 class 申请相应 class 的 PV。 ⑤ 指定 PV 在 NFS 服务器上对应的目录。
创建对应pv:
1 2 3 4 5 6 7 kubectl apply -f nfs-pv001.yaml kubectl get pv
STATUS 为 Available,表示 pv就绪,可以被 PVC 申请。
创建PVC 接下来创建一个名为pvc001的PVC,配置文件 nfs-pvc001.yaml 如下:vim nfs-pvc001.yaml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 apiVersion: v1 kind: PersistentVolumeClaim metadata: name: nfs-pvc001 spec: accessModes: - ReadWriteOnce resources: requests: storage: 1Gi storageClassName: nfs selector: matchLabels: pv: nfs-pv001
执行yaml文件创建 pvc:
1 2 3 4 5 6 7 8 9 10 11 12 13 kubectl apply -f nfs-pvc001.yaml kubectl get pvc kubectl get pv
从 kubectl get pvc 和 kubectl get pv 的输出可以看到 pvc001绑定到pv001,申请成功。注意pvc绑定到对应pv通过labels标签方式实现,也可以不指定,将随机绑定到pv。 接下来就可以在 Pod 中使用存储了,Pod 配置文件 nfs-pod001.yaml 如下:vim nfs-pod001.yaml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 kind: Pod apiVersion: v1 metadata: name: nfs-pod001 spec: containers: - name: myfrontend image: nginx volumeMounts: - mountPath: "/var/www/html" name: nfs-pv001 volumes: - name: nfs-pv001 persistentVolumeClaim: claimName: nfs-pvc001
与使用普通 Volume 的格式类似,在 volumes 中通过 persistentVolumeClaim 指定使用nfs-pvc001申请的 Volume。
执行yaml文件创建nfs-pdo001:
1 2 3 4 5 6 7 8 9 kubectl apply -f nfs-pod001.yaml kubectl get pod
验证 PV 是否可用:
1 2 3 4 kubectl exec nfs-pod001 touch /var/www/html/index001.html ls /nfs/data/pv001/
进入pod查看挂载情况
1 2 3 4 5 6 7 kubectl exec -it nfs-pod001 /bin/bash
删除pv 删除pod,pv和pvc不会被删除,nfs存储的数据不会被删除。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 kubectl delete -f nfs-pod001.yaml kubectl get pv kubectl get pvc ls /nfs/data/pv001/
继续删除pvc,pv将被释放,处于 Available 可用状态,并且nfs存储中的数据被删除。
1 2 3 4 5 6 7 8 9 10 kubectl delete -f nfs-pvc001.yaml kubectl get pv ls /nfs/data/pv001/
继续删除pv
1 2 3 kubectl delete -f nfs-pv001.yaml
动态申请PV卷 External NFS驱动的工作原理 K8S的外部NFS驱动,可以按照其工作方式(是作为NFS server还是NFS client)分为两类:
1.nfs-client:也就是我们接下来演示的这一类,它通过K8S的内置的NFS驱动挂载远端的NFS服务器到本地目录;然后将自身作为storage provider,关联storage class。当用户创建对应的PVC来申请PV时,该provider就将PVC的要求与自身的属性比较,一旦满足就在本地挂载好的NFS目录中创建PV所属的子目录,为Pod提供动态的存储服务。
2.nfs:与nfs-client不同,该驱动并不使用k8s的NFS驱动来挂载远端的NFS到本地再分配,而是直接将本地文件映射到容器内部,然后在容器内使用ganesha.nfsd来对外提供NFS服务;在每次创建PV的时候,直接在本地的NFS根目录中创建对应文件夹,并export出该子目录。 利用NFS动态提供Kubernetes后端存储卷 本文将介绍使用nfs-client-provisioner这个应用,利用NFS Server给Kubernetes作为持久存储的后端,并且动态提供PV。前提条件是有已经安装好的NFS服务器,并且NFS服务器与Kubernetes的Slave节点都能网络连通。将nfs-client驱动做一个deployment部署到K8S集群中,然后对外提供存储服务。 nfs-client-provisioner 是一个Kubernetes的简易NFS的外部provisioner,本身不提供NFS,需要现有的NFS服务器提供存储
部署nfs-client-provisioner,在master上操作
首先克隆仓库获取yaml文件
1 2 3 git clone https://github.com/kubernetes-incubator/external-storage.git cp -R external-storage/nfs-client/deploy/ $HOME cd deploy
修改deployment.yaml文件
这里修改的参数包括NFS服务器所在的IP地址(192.168.1.1),以及NFS服务器共享的路径(/nfs/data),两处都需要修改为你实际的NFS服务器和共享目录。
cat deployment.yaml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 apiVersion: v1 kind: ServiceAccount metadata: name: nfs-client-provisioner --- kind: Deployment apiVersion: extensions/v1beta1 metadata: name: nfs-client-provisioner spec: replicas: 1 strategy: type: Recreate 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: fuseim.pri/ifs - name: NFS_SERVER value: 192.168 .1 .1 - name: NFS_PATH value: /nfs/data volumes: - name: nfs-client-root nfs: server: 192.168 .1 .1 path: /nfs/data
部署deployment.yaml
1 kubectl apply -f deployment.yaml
查看创建的POD
1 2 3 4 kubectl get pod -o wide
创建StorageClass storage class的定义,需要注意的是:provisioner属性要等于驱动所传入的环境变量PROVISIONER_NAME的值。否则,驱动不知道知道如何绑定storage class。 此处可以不修改,或者修改provisioner的名字,需要与上面的deployment的PROVISIONER_NAME名字一致。 (此yaml无需修改)
cat class.yaml
1 2 3 4 5 6 7 apiVersion: storage.k8s.io/v1 kind: StorageClass metadata: name: managed-nfs-storage provisioner: fuseim.pri/ifs parameters: archiveOnDelete: "false"
部署yaml文件
1 kubectl apply -f class.yaml
查看创建的storageclass
配置授权 如果集群启用了RBAC,则必须执行如下命令授权provisioner。(k8s1.6+默认开启) 此yaml无需修改
cat rbac.yaml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 kind: ServiceAccount apiVersion: v1 metadata: name: nfs-client-provisioner --- 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 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 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 subjects: - kind: ServiceAccount name: nfs-client-provisioner namespace: default roleRef: kind: Role name: leader-locking-nfs-client-provisioner apiGroup: rbac.authorization.k8s.io
部署yaml文件
1 kubectl create -f rbac.yaml
测试 创建测试PVC
1 kubectl create -f test-claim.yaml
可以看到PVC状态为Bound,绑定的volume为pvc-a17d9fd5-237a-11e9-a2b5-000c291c25f3。
查看自动创建的PV
然后,我们进入到NFS的export目录,可以看到对应该volume name的目录已经创建出来了。 其中volume的名字是namespace,PVC name以及uuid的组合: