nfs-client-provisioner简介

nfs-client-provisioner 可动态为kubernetes提供pv卷,是Kubernetes的简易NFS的外部provisioner,本身不提供NFS,需要现有的NFS服务器提供存储。持久卷目录的命名规则为:${namespace}-${pvcName}-${pvName}

K8S的外部NFS驱动可以按照其工作方式(是作为NFS server还是NFS client)分为两类:

nfs-client:

它通过K8S内置的NFS驱动挂载远端的NFS服务器到本地目录;然后将自身作为storage provider关联storage class。当用户创建对应的PVC来申请PV时,该provider就将PVC的要求与自身的属性比较,一旦满足就在本地挂载好的NFS目录中创建PV所属的子目录,为Pod提供动态的存储服务。

nfs-server:

与nfs-client不同,该驱动并不使用k8s的NFS驱动来挂载远端的NFS到本地再分配,而是直接将本地文件映射到容器内部,然后在容器内使用ganesha.nfsd来对外提供NFS服务;在每次创建PV的时候,直接在本地的NFS根目录中创建对应文件夹,并export出该子目录。

本文将介绍使用nfs-client-provisioner这个应用,利用NFS Server给Kubernetes作为持久存储的后端,并且动态提供PV。前提条件是有已经安装好的NFS服务器,并且NFS服务器与Kubernetes的Slave节点网络能够连通。将nfs-client驱动做为一个deployment部署到K8S集群中,然后对外提供存储服务

安装准备

  • **树莓派k8s集群:**最好3节点,单节点也可以。  
root@pi4-master01:~# kubectl get nodes -o wide
NAME           STATUS   ROLES    AGE     VERSION    INTERNAL-IP    EXTERNAL-IP   OS-IMAGE           KERNEL-VERSION     CONTAINER-RUNTIME
pi4-master01   Ready    master   4d18h   v1.15.10   192.168.5.18   <none>        Ubuntu 20.04 LTS   5.4.0-1011-raspi   docker://18.9.9
pi4-node01     Ready    node     4d17h   v1.15.10   192.168.5.19   <none>        Ubuntu 20.04 LTS   5.4.0-1011-raspi   docker://18.9.9
pi4-node02     Ready    node     4d17h   v1.15.10   192.168.5.20   <none>        Ubuntu 20.04 LTS   5.4.0-1011-raspi   docker://18.9.9
  • 树莓派k8s集群已安装helm
root@pi4-master01:~/k8s/cluster-monitoring-0.37.0# helm version
Client: &version.Version{SemVer:"v2.15.0", GitCommit:"c2440264ca6c078a06e088a838b0476d2fc14750", GitTreeState:"clean"}
Server: &version.Version{SemVer:"v2.15.0+unreleased", GitCommit:"9668ad4d90c5e95bd520e58e7387607be6b63bb6", GitTreeState:"dirty"}

NFS服务器准备

笔者手里正好有一台威联通TS-251+,可以直接开通NFS服务。读者可以自行搭建NFS服务器。比如临时在master节点上安装NFS,把master节点作为NFS服务器。

  • 安装 NFS 软件包
apt install nfs-kernel-server  # 安装 NFS服务器端
  • 添加 NFS 共享目录
vim /etc/exports

若需要把 “/nfs-share” 目录设置为 NFS 共享目录,请在该文件末尾添加下面的一行:

/nfs-share *(rw,sync,no_root_squash)

新建“/nfs-share”目录,并为该目录设置最宽松的权限:

mkdir /nfs-share
chmod -R 777 /nfs-share
  • 启动 NFS 服务
systemctl restart nfs-kernel-server
  • 确认NFS服务是否启动正常
root@pi4-master01:~# showmount -e 192.168.5.18
Export list for 192.168.5.18:
/nfs-share *
  • 集群所有节点安装nfs客户端
apt install -y nfs-common

建议master节点安装ansible,并和nodes节点配置ssh免密登录,这样可以在master节点直接执行

ansible pi4k8s -m shell -a 'apt install -y nfs-common'

安装nfs-client-provisioner

这里我们选择用helm安装,helm有一个默认仓库stable,指向https://kubernetes-charts.storage.googleapis.com, 国内访问比较困难,所以网上很多安装helm的文档都以https://kubernetes.oss-cn-hangzhou.aliyuncs.com/charts 来代替。但最近发现,这个仓库也不再更新了,很多chart的最新版本都没有,这里提供一个新地址http://mirror.azure.cn/kubernetes/charts 经简单验证,发现这个仓库至少比阿里的那个仓库新,建议切换。

root@pi4-master01:~# helm repo remove stable
"stable" has been removed from your repositories
root@pi4-master01:~# helm repo add stable http://mirror.azure.cn/kubernetes/charts/
"stable" has been added to your repositories
root@pi4-master01:~# helm repo list
NAME   	URL
local  	http://127.0.0.1:8879/charts
stable 	http://mirror.azure.cn/kubernetes/charts/
root@pi4-master01:~# helm search nfs-client
NAME                         	CHART VERSION	APP VERSION	DESCRIPTION
stable/nfs-client-provisioner	1.2.8        	3.1.0      	nfs-client is an automatic provisioner that used your *al...
  • 使用helm安装
helm install -n nfs-client-provisioner \
stable/nfs-client-provisioner \
--set nfs.server=192.168.5.18 \
--set nfs.path=/nfs-share \
--set storageClass.name=nfs-client \
--set image.repository=quay.io/external_storage/nfs-client-provisioner-arm \
--set image.tag=latest

nfs.server为NFS服务器的IP地址,在nfsv4中nfs.path直接使用/nfs-share 即可。storageClass.name默认为nfs-client,可自定义,另外也可以将nfs-client作为默认storageclass,这样在申请pvc时不需在指定storageclass name。因为我们的树莓派k8s集群已经设置了local-path为默认storageclass,这里就不再切换了,具体命令可以参考如下:

helm install -n nfs-client-provisioner \
stable/nfs-client-provisioner \
--set nfs.server=192.168.5.18 \
--set nfs.path=/nfs-share \
--set storageClass.name=nfs-client \
--set image.repository=quay.io/external_storage/nfs-client-provisioner-arm \
--set image.tag=latest \
--set storageClass.defaultClass=true
  • 查看创建的pod
root@pi4-master01:~# kubectl get pod|grep nfs
NAME                                             READY   STATUS    RESTARTS   AGE
nfs-client-provisioner-5d7dd8f468-f2ctd           1/1     Running   0          6s
  • 查看创建的storageclass
root@pi4-master01:~# kubectl get storageclass|grep nfs
nfs-client             cluster.local/nfs-client-provisioner   23m

验证

  • 创建一个yaml文件
(
cat <<EOF
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: nfs-pvc
spec:
  storageClassName: "nfs-client"
  accessModes:
    - ReadWriteMany
  resources:
    requests:
      storage: 10Mi
---
kind: Pod
apiVersion: v1
metadata:
  name: test-pod
spec:
  containers:
  - name: test-pod
    image: arm64v8/busybox
    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: nfs-pvc

EOF
) > pvc-test.yaml
  • 运行yaml文件
root@pi4-master01:/home/charts/nfs-client-provisioner# kubectl apply -f pvc-test.yaml
  • pvc将自动创建并自动申请pv
root@pi4-master01:/home/charts/nfs-client-provisioner# kubectl get pvc,pv
NAME                            STATUS   VOLUME                                     CAPACITY   ACCESS MODES   STORAGECLASS   AGE
persistentvolumeclaim/nfs-pvc   Bound    pvc-627b935c-0419-49b4-b6bb-530a7d8860ad   10Mi       RWX            nfs-client     47s

NAME                                                        CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS   CLAIM                                           STORAGECLASS   REASON   AGE
persistentvolume/pvc-627b935c-0419-49b4-b6bb-530a7d8860ad   10Mi       RWX            Delete           Bound    default/nfs-pvc                                 nfs-client              47s
  • 查看/nfs-share目录,自动创建了存储卷目录,SUCCESS字段成功写入该目录下
root@pi4-master01:/# ll /nfs-share/default-nfs-pvc-pvc-627b935c-0419-49b4-b6bb-530a7d8860ad/
总用量 8
drwxrwxrwx 2 root root 4096 8月   8 20:36 ./
drwxrwxrwx 5 root root 4096 8月   8 20:36 ../
-rw-r--r-- 1 root root    0 8月   8 20:36 SUCCESS