Kubernetes: 利用NFS动态提供后端存储
Posted 琦彦
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Kubernetes: 利用NFS动态提供后端存储相关的知识,希望对你有一定的参考价值。
目录
修改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”才真正有用:
- 第一阶段由运行在master上的AttachDetachController负责,为这个PV完成 Attach 操作,为宿主机挂载远程磁盘;
- 第二阶段是运行在每个节点上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。
前提条件
- 是有已经安装好的NFS服务器,并且NFS服务器与Kubernetes的Slave节点都能网络连通。
- 所有下文用到的文件来自于
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 | 设置为默认 StorageClass | false |
storageClass.allowVolumeExpansion | 允许扩大存储量 | true |
storageClass.reclaimPolicy | 用于回收废弃卷的方法 | Delete |
storageClass.provisionerName | 供应商名称名称 | 空值 |
storageClass.archiveOnDelete | 删除时归档 pvc | true |
storageClass.accessModes | 设置 PV 访问模式 | ReadWriteOnce |
nfs.server | NFS 服务器的主机名 | null(IP 或主机名) |
nfs.path | 要使用的挂载点的基本路径 | /ifs/kubernetes |
nfs.mountOptions | 挂载选项(例如’nfsvers=3’) | 空值 |
resources | 所需资源(例如 CPU、内存) | {} |
rbac.create | 使用基于角色的访问控制 | true |
podSecurityPolicy.enabled | 创建和使用 Pod 安全策略资源 | false |
priorityClassName | 设置 pod priorityClassName | 空值 |
serviceAccount.create | 我们应该创建一个 ServiceAccount | true |
serviceAccount.name | 要使用的 ServiceAccount 的名称 | 空值 |
nodeSelector | Pod 分配的节点标签 | {} |
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-storage
和nfs-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动态提供后端存储的主要内容,如果未能解决你的问题,请参考以下文章
使用nfs作为kubernetes动态storageClass存储
Rancher 使用 NFS Storage Classes 进行动态 NFS 存储
kubernetes使用NFS作为存储的操作步骤(保姆式分享)