Kubernetes: 利用NFS动态提供后端存储

Posted 琦彦

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Kubernetes: 利用NFS动态提供后端存储相关的知识,希望对你有一定的参考价值。

目录

Kubernetes: 利用NFS动态提供后端存储

pv, pvc和storageclass关系

前提条件

nfs-client-provisioner

安装部署

方式1: 使用Helm

配置

方式2: 不使用Helm

授权

如果启用了RBAC

修改deployment文件并部署 deploy/deployment.yaml

修改StorageClass文件并部署 deploy/class.yaml

测试

最新版本nfs-subdir-external-provisioner

参考链接:





Kubernetes: 利用NFS动态提供后端存储




pv, pvc和storageclass关系

一幅示意图描述:

从图中我们可以看到,在这个体系中:

  • PVC 描述的,是 Pod 想要使用的持久化存储的属性,比如存储的大小、读写权限等。
  • PV 描述的,则是一个具体的 Volume 的属性,比如 Volume 的类型、挂载目录、远程存储服务器地址等。
  • 而 StorageClass 的作用,则是充当 PV 的模板。并且,只有同属于一个 StorageClass 的 PV 和 PVC,才可以绑定在一起。

当然,StorageClass 的另一个重要作用,是指定 PV 的 Provisioner(存储插件)。这时候,如果你的存储插件支持 Dynamic Provisioning 的话,Kubernetes 就可以自动为你创建 PV 了。

  • Kubernetes 为我们提供了一套可以自动创建 PV 的机制,即:Dynamic Provisioning。相比之下,人工管理 PV 的方式就叫作 Static Provisioning。Dynamic Provisioning 机制工作的核心,在于一个名叫 StorageClass 的 API 对象。

容器持久化存储涉及的概念比较多,试着总结一下整体流程。

用户提交请求创建pod,Kubernetes发现这个pod声明使用了PVC,那就靠PersistentVolumeController帮它找一个PV配对。

没有现成的PV,就去找对应的StorageClass,帮它新创建一个PV,然后和PVC完成绑定。

新创建的PV,还只是一个API 对象,需要经过“两阶段处理”变成宿主机上的“持久化 Volume”才真正有用:

  1. 第一阶段由运行在master上的AttachDetachController负责,为这个PV完成 Attach 操作,为宿主机挂载远程磁盘;
  2. 第二阶段是运行在每个节点上kubelet组件的内部,把第一步attach的远程磁盘 mount 到宿主机目录。这个控制循环叫VolumeManagerReconciler,运行在独立的Goroutine,不会阻塞kubelet主循环。

完成这两步,PV对应的“持久化 Volume”就准备好了,POD可以正常启动,将“持久化 Volume”挂载在容器内指定的路径。

PV 描述的,是持久化存储数据卷。这个 API 对象主要定义的是一个持久化存储在宿主机上的目录,比如一个 NFS 的挂载目录。通常情况下,PV 对象是由运维人员事先创建在 Kubernetes 集群里待用的。

PVC 描述的,则是 Pod 所希望使用的持久化存储的属性。比如,Volume 存储的大小、可读写权限等等。

PVC 对象通常由开发人员创建;或者以 PVC 模板的方式成为 StatefulSet 的一部分,然后由 StatefulSet 控制器负责创建带编号的 PVC。

本文翻译自nfs-client-provisioner的说明文档,本文将介绍使用nfs-client-provisioner这个应用,利用NFS Server给Kubernetes作为持久存储的后端,并且动态提供PV




前提条件

  1. 是有已经安装好的NFS服务器,并且NFS服务器与Kubernetes的Slave节点都能网络连通。
  2. 所有下文用到的文件来自于git clone https://github.com/kubernetes-incubator/external-storage.git的nfs-client目录。




nfs-client-provisioner

nfs-client-provisioner 是一个Kubernetes的简易NFS的外部provisioner,本身不提供NFS,需要现有的NFS服务器提供存储

  • PV以 ${namespace}-${pvcName}-${pvName}的命名格式提供(在NFS服务器上)
  • PV回收的时候以 archieved-${namespace}-${pvcName}-${pvName} 的命名格式(在NFS服务器上)




安装部署




方式1: 使用Helm

按照https://github.com/helm/charts/tree/master/stable/nfs-client-provisioner维护的helm chart的说明进行操作

helm install stable/nfs-client-provisioner --set nfs.server=xxxx --set nfs.path=/exported/path




配置

下表列出了此图表的可配置参数及其默认值。

范围描述默认
replicaCount要部署的 Provisioner 实例数1
strategyType指定用于用新 Pod 替换旧 Pod 的策略Recreate
image.repository供应商仓库quay.io/external_storage/nfs-client-provisioner
image.tag供应商镜像的版本v3.1.0-k8s1.11
image.pullPolicy镜像拉取策略IfNotPresent
storageClass.name存储类名称nfs-client
storageClass.defaultClass设置为默认 StorageClassfalse
storageClass.allowVolumeExpansion允许扩大存储量true
storageClass.reclaimPolicy用于回收废弃卷的方法Delete
storageClass.provisionerName供应商名称名称空值
storageClass.archiveOnDelete删除时归档 pvctrue
storageClass.accessModes设置 PV 访问模式ReadWriteOnce
nfs.serverNFS 服务器的主机名null(IP 或主机名)
nfs.path要使用的挂载点的基本路径/ifs/kubernetes
nfs.mountOptions挂载选项(例如’nfsvers=3’)空值
resources所需资源(例如 CPU、内存){}
rbac.create使用基于角色的访问控制true
podSecurityPolicy.enabled创建和使用 Pod 安全策略资源false
priorityClassName设置 pod priorityClassName空值
serviceAccount.create我们应该创建一个 ServiceAccounttrue
serviceAccount.name要使用的 ServiceAccount 的名称空值
nodeSelectorPod 分配的节点标签{}
affinity亲和度设置{}
tolerations要容忍的节点污点列表[]

其中使用https://github.com/helm/charts/tree/master/stable/nfs-server-provisioner包括一个内置的 NFS 服务器,并不用于连接到预先存在的 NFS 服务器。




方式2: 不使用Helm



授权

如果你的集群启用了RBAC,或者你正在运行OpenShift,则必须授权provisioner。

如果你在非默认的default名称空间/项目之外部署,可以编辑deploy/auth/clusterrolebinding.yaml或编辑oadm policy指令。




如果启用了RBAC

需要执行如下的命令来授权。

kubectl create -f deploy/auth/serviceaccount.yaml
serviceaccount "nfs-client-provisioner" created

kubectl create -f deploy/auth/clusterrole.yaml
clusterrole "nfs-client-provisioner-runner" created

kubectl create -f deploy/auth/clusterrolebinding.yaml
clusterrolebinding "run-nfs-client-provisioner" created

kubectl patch deployment nfs-client-provisioner -p '{"spec":{"template":{"spec":{"serviceAccount":"nfs-client-provisioner"}}}}'




修改deployment文件并部署 deploy/deployment.yaml

需要修改的地方只有NFS服务器所在的IP地址(10.0.0.200),以及NFS服务器共享的路径(/nfs,两处都需要修改为你实际的NFS服务器和共享目录

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
              # 必须与class.yaml中的provisioner的名称一致
              value: fuseim.pri/ifs
            - name: NFS_SERVER
              # NFS服务器的ip地址
              value: 10.0.0.200
            - name: NFS_PATH
              # 修改为实际创建的共享挂载目录
              value: /nfs
      volumes:
        - name: nfs-client-root
          nfs:
            # NFS服务器的ip地址
            server: 10.0.0.200
            # 修改为实际创建的共享挂载目录
            path: /nfs




修改StorageClass文件并部署 deploy/class.yaml

此处可以不修改,或者修改provisioner的名字,需要与上面的deployment的PROVISIONER_NAME名字一致。

apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: managed-nfs-storage
# 必须与deployment.yaml中的PROVISIONER_NAME一致
# or choose another name, must match deployment's env PROVISIONER_NAME'
provisioner: fuseim.pri/ifs
parameters:
  archiveOnDelete: "false"




测试

测试创建PVC

  • kubectl create -f deploy/test-claim.yaml

测试创建POD

  • kubectl create -f deploy/test-pod.yaml

在NFS服务器上的共享目录下的卷子目录中检查创建的NFS PV卷下是否有"SUCCESS" 文件。

[root@node2 ~]# cd /nfs/
[root@node2 nfs]# ll
total 4
drwxrwxrwx 2 root root  6 Oct 27 14:15 default-test-claim-pvc-f37dbcf5-bf9d-402c-9350-0b3b2efd9979
-rw-r--r-- 1 root root 19 Oct 26 10:49 index.txt

[root@node2 nfs]# cd default-test-claim-pvc-f37dbcf5-bf9d-402c-9350-0b3b2efd9979/
[root@node2 default-test-claim-pvc-f37dbcf5-bf9d-402c-9350-0b3b2efd9979]# ll
total 0
-rw-r--r-- 1 root root 0 Oct 27 14:19 SUCCESS

删除测试POD

  • kubectl delete -f deploy/test-pod.yaml

删除测试PVC

  • kubectl delete -f deploy/test-claim.yaml

在NFS服务器上的共享目录下查看NFS的PV卷回收以后是否名字以archived开头。


 

[root@node2 nfs]# ll
total 4
drwxrwxrwx 2 root root 21 Oct 27 14:19 archived-default-test-claim-pvc-f37dbcf5-bf9d-402c-9350-0b3b2efd9979
-rw-r--r-- 1 root root 19 Oct 26 10:49 index.txt



最新版本nfs-subdir-external-provisioner

这个仓库是从https://github.com/kubernetes-incubator/external-storage/tree/master/nfs-client迁移过来的。作为迁移的一部分:

  • 容器镜像名称和存储库已分别更改为k8s.gcr.io/sig-storagenfs-subdir-external-provisioner
  • 为了保持与早期部署文件的向后兼容性,NFS Client Provisioner 的命名保留nfs-client-provisioner在部署 YAML 中。
#
helm repo add nfs-subdir-external-provisioner https://kubernetes-sigs.github.io/nfs-subdir-external-provisioner/

# 
helm install nfs-subdir-external-provisioner nfs-subdir-external-provisioner/nfs-subdir-external-provisioner \\
    --set nfs.server=x.x.x.x \\
    --set nfs.path=/exported/path

我的命令

# 安装
helm install /usr/local/jt/nfs-subdir-external-provisioner \\
    --name nfs-storage \\
    --namespace=big-data \\
    --set nfs.server=10.0.0.200 \\
    --set nfs.path=/nfs \\
    --set storageClass.name=managed-nfs-storage
# 安装    
helm delete my-release    

https://github.com/kubernetes-sigs/nfs-subdir-external-provisioner




参考链接:

https://github.com/kubernetes-retired/external-storage/tree/master/nfs-client

https://github.com/kubernetes-sigs/nfs-subdir-external-provisioner

https://jimmysong.io/kubernetes-handbook/practice/using-nfs-for-persistent-storage.html#

以上是关于Kubernetes: 利用NFS动态提供后端存储的主要内容,如果未能解决你的问题,请参考以下文章

kubernetes对接NFS动态存储

使用nfs作为kubernetes动态storageClass存储

Rancher 使用 NFS Storage Classes 进行动态 NFS 存储

kubernetes使用NFS作为存储的操作步骤(保姆式分享)

在kubernetes中使用nfs-provisioner动态存储卷

基于NFS的PV动态供给(StorageClass)