六安关于建设审批的网站,wordpress多用户评论,ppt中仿网站链接怎么做,孟村住房建设局网站一、前言 Pod里面的容器都有自己独立的文件系统#xff0c;来自容器镜像#xff0c;用于保存容器运行的数据#xff0c;但容器的文件存储有两个弊端#xff0c;一个是无法持久化#xff0c;其生命周期与容器一致#xff0c;一旦容器销毁#xff0c;相关的数据也就随之一…一、前言 Pod里面的容器都有自己独立的文件系统来自容器镜像用于保存容器运行的数据但容器的文件存储有两个弊端一个是无法持久化其生命周期与容器一致一旦容器销毁相关的数据也就随之一起销毁二是无法共享Pod里多个容器之间无法共享数据会导致无法提供完整的服务比如监控容器需要读取业务容器提供的日志数据就无法实现。 为解决以上问题K8S提供多种类型存储卷。
二、存储卷类型 实际上在前面的章节中已经接触到各种卷比如在K8S初级入门系列之四-Namespace/ConfigMap/Secret章节中ConfigMap与Secret就是K8S公开给Pod的特殊类型的卷。K8S支持的存储卷类型有很多。
1、EmptyDir emptyDir用于同一Pod下多个容器间的共享存储其形式是存储临时数据的简单空目录既然是临时的一旦Pod删除其存储的内容也就丢失了。我们来看下面的场景: 该Pod中有两个容器分别为write-app和read-app,其中write-app将数据写入到/wite-app/logs文件下而read-app容器从/read-app/logs文件读取数据。/write-app/logs与/read-app/logs都指向同一个共享存储卷其类型为emptyDir这个完成两个容器的数据共享。其yaml如下
[rootk8s-master yaml]# cat emptydir-pod.yaml
apiVersion: v1
kind: Pod
metadata:name: emptydir-pod
spec:containers:- image: busyboxname: write-appvolumeMounts:- mountPath: /write-app/logsname: shared-dirargs:- /bin/sh- -c- echo this is write-app /write-app/logs/app.log; sleep 60000- image: busyboxname: read-appvolumeMounts:- mountPath: /read-app/logsname: shared-dirargs:- /bin/sh- -c- cat /read-app/logs/app.log; sleep 60000volumes:- name: shared-diremptyDir: {}
其yaml模型解析如下 在每个容器中定义挂载点并指定挂载的本地目录以及指向的卷名称。再定义一个卷设置卷名称和类型这样就通过卷名称将容器的挂载点与该卷进行关联。 执行该文件创建Pod后从read-app容器中查看下log数据
[rootk8s-master yaml]# kubectl apply -f emptydir-pod.yaml
pod/emptydir-pod created
[rootk8s-master yaml]# kubectl exec emptydir-pod -c read-app cat /read-app/logs/app.log
kubectl exec [POD] [COMMAND] is DEPRECATED and will be removed in a future version. Use kubectl exec [POD] -- [COMMAND] instead.
this is write-app
可以看到正确的读取到了write-app容器写入的字符从而实现了Pod内的存储共享。
2、HostPath EmptyDir是实现Pod内容器间的存储共享HostPath是实现节点内Pod间的文件共享。以上面的场景为例。 HostPath是Pod所在节点服务器上的文件存储(即/tmp),该节点上的两个Pod容器共享该文件存储。将上面的例子分拆成两个Pod其yaml文件如下
hostpath-write-pod.yaml
[rootk8s-master yaml]# cat hostpath-write-pod.yaml
apiVersion: v1
kind: Pod
metadata:name: hostpath-write-pod
spec:containers:- image: busyboxname: write-appvolumeMounts:- mountPath: /write-app/logsname: shared-dirargs:- /bin/sh- -c- echo this is write-app /write-app/logs/app.log; sleep 60000volumes:- name: shared-dirhostPath: path: /tmp
hostpath-read-pod.yaml内容如下:
[rootk8s-master yaml]# cat hostpath-read-pod.yaml
apiVersion: v1
kind: Pod
metadata:name: hostpath-read-pod
spec:containers:- image: busyboxname: read-appvolumeMounts:- mountPath: /read-app/logsname: shared-dirargs:- /bin/sh- -c- cat /read-app/logs/app.log; sleep 60000volumes:- name: shared-dirhostPath: path: /tmp 执行文件创建Pod成功后进入到read-app的Pod的容器查看数据读取。
[rootk8s-master tmp]# kubectl exec hostpath-read-pod -c read-app cat /read-app/logs/app.log
kubectl exec [POD] [COMMAND] is DEPRECATED and will be removed in a future version. Use kubectl exec [POD] -- [COMMAND] instead.
this is write-app 如EmptyDir类型一样能正确的读取到数据。按照HostPath的定义这个app.log的实体文件应该位于所在节点服务器的/tmp目录下我们查看下。
[rootk8s-node1 ~]# cd /tmp
[rootk8s-node1 tmp]# ll
total 12
-rw-r--r-- 1 root root 18 Apr 21 20:53 app.log
[rootk8s-node1 tmp]# cat app.log
this is write-app 可以看到确实在Pod所在的节点(这两个Pod调度到了node1,非master)上的/tmp目录下写入了app.log内容正是write-app写入的字符串。 当删除这两个Pod后该节点上的app.log文件还在从而也实现了持久化存储。 由于HostPath可以将容器的文件目录映射到节点的目录从而无需每次都进入容器查看数据要方便很多。比如我们在使用Ngnix容器时就可以将其配置文件和日志文件映射到节点的文件中直接在节点的文件系统就可以进行配置和查看。
3、NFS 在多个节点间如何共享存储卷呢K8S提供了多种方式
基于云计算厂商的特定存储比如Google的GCE持久化存储卷AWS的EBS微软的azureDisk等。基于网络文件存储如NFSCephFSGlusterFS等。
下面就以NFS为例介绍节点间的共享存储我们来改造上面的例子。 NFS的服务端安装到master节点上并配置/nfs/data的作为NFS的挂载路径安装过程这里就省略了可以自行查询相关文档。下面看下两个改造后的Pod的yaml文件
nfs-write-pod.yaml
[rootk8s-master yaml]# cat nfs-write-pod.yaml
apiVersion: v1
kind: Pod
metadata:name: nfs-write-pod
spec:tolerations:- key: node-role.kubernetes.io/masteroperator: Existseffect: NoSchedulecontainers:- image: busyboxname: write-appvolumeMounts:- mountPath: /write-app/logsname: shared-nfs-dirargs:- /bin/sh- -c- echo this is write-app /write-app/logs/app.log; sleep 60000volumes:- name: shared-nfs-dirnfs:server: 192.168.16.4path: /nfs/data 该pod将volumes的类型改为nfs并配置nfs的server(master节点ip)和path路径。为了将该Pod调度到master节点增加了tolerations属性这方面的内容可以参考K8S初级入门系列之五-Pod的高级特性
nfs-read-pod.yaml
[rootk8s-master yaml]# cat nfs-read-pod.yaml
apiVersion: v1
kind: Pod
metadata:name: nfs-read-pod
spec:containers:- image: busyboxname: read-appvolumeMounts:- mountPath: /read-app/logsname: shared-nfs-dirargs:- /bin/sh- -c- cat /read-app/logs/app.log; sleep 60000volumes:- name: shared-nfs-dirnfs:server: 192.168.16.4path: /nfs/data 执行以上yaml文件创建pod并查看pod状态
[rootk8s-master yaml]# kubectl get pod -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
nfs-read-pod 1/1 Running 0 23m 10.244.36.72 k8s-node1 none none
nfs-write-pod 1/1 Running 0 24m 10.244.235.199 k8s-master none none 可以看到nfs-write-pod按照要求调度到master节点上而nfs-read-pod调度到node1节点上进入nfs-read-pod读取日志文件。
[rootk8s-master data]# kubectl exec nfs-read-pod -c read-app cat /read-app/logs/app.log
kubectl exec [POD] [COMMAND] is DEPRECATED and will be removed in a future version. Use kubectl exec [POD] -- [COMMAND] instead.
this is write-app 可以正确的读取到日志内容。由于NFS配置的是master节点的/nfs/data目录。进入该目录看下内容
[rootk8s-master yaml]# cd /nfs/data
[rootk8s-master data]# ll
total 4
-rw-r--r-- 1 root root 18 Apr 29 20:30 app.log
[rootk8s-master data]# cat app.log
this is write-app
日志内容也已经写入了该文件。
三、PV/PVC 前面所介绍的分配存储的方式都是命令式的按照既定的指令创建存储。这里存在一个问题在实际工程中Pod的yaml文件一般是由开发人员维护而存储卷作为底层资源一般是由运维管理员维护这种方式导致各方的工作无法解耦这显然不符合K8S的设计理念。为了解决该问题K8S提供了PV和PVC对象。如下图所示 管理员根据现有卷资源申明式创建PV(Persisten Volume持久卷)指定PV的大小和所支持的访问模式注意的是这里仅是申明并没有分配实际的物理存储。开发人员根据需求申请PVC(Persistent VolumeClaim),指定所需的最小容量和访问模式并将PVC作为卷使用到Pod中。K8S根据PVC的申请找到匹配的PV并绑定到PVC此时PVC就可以作为持久卷在Pod中使用了。 可以将PV看做Class类而PVC是该Class的Object对象实现。
下面我们就来实现下上面的过程。
1、PV的创建
首先申明一个PV名为nfs-pv其yaml如下
[rootk8s-master yaml]# cat nfs-pv.yaml
apiVersion: v1
kind: PersistentVolume
metadata:name: nfs-pvlabels:pv: nfs-pv
spec:capacity:storage: 1GivolumeMode: FilesystemstorageClassName: my-storageaccessModes:- ReadWriteManypersistentVolumeReclaimPolicy: Recyclenfs:path: /nfs/dataserver: 192.168.16.4
我们来看下里面的核心属性:
1、capactity,定义PV的存储容量。
2、volumeMode卷模式包括以下两种:
Filesystem(文件系统)会被Pod挂载到某个目录默认的模式。Block(块)将卷作为原始块设备来使用该模式以块设备的方式交给 Pod 使用其上没有任何文件系统
3、storageClassName存储类别如果PV设定该类别那么只有请求了该类别的PVC才能与之绑定关于storyClass我们在第四节将专门介绍。
4、accessModes,访问模式有以下几种模式不同的卷插件类型支持的模式也不同。
ReadWriteOnce(RWO)可以被一个节点以读写方式挂载。ReadOnlyMany(ROX)可以被多个节点以只读方式挂载。ReadWriteMany(RWX)可以被多个节点以读写方式挂载。
5、persistentVolumeReclaimPolicy,当PV被释放后回收策略包括以下 几种
Retain 保留需要手动回收。Recycle 回收空间清除相关的文件。仅 NFS 和 HostPath 支持回收。本例的NFS就使用这种模式进行演示。Delete AWS EBS、GCE PD、Azure Disk 或 OpenStack Cinder 卷这类关联存储资产也被删除。
6、卷插件目前主要支持以下类型
cephfs - CephFS volumecsi - 容器存储接口 (CSI)fc - Fibre Channel (FC) 存储hostPath - HostPath 卷 仅供单节点测试使用不适用于多节点集群请尝试使用 local 卷作为替代iscsi - iSCSI (SCSI over IP) 存储local - 节点上挂载的本地存储设备nfs - 网络文件系统 (NFS) 存储rbd - Rados 块设备 (RBD) 卷 其他的卷插件如EBSazureDiskgcePersistentDisk等会在未来的版本中移除。本例中我们使用前面创建NFS类型。 执行该yaml文件完成PV创建并查看其状态
[rootk8s-master yaml]# kubectl get pv
NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE
nfs-pv 1Gi RWO Recycle Available my-storage 29m 这里我们关注下字段status为Available,表明当前的状态为可用后面我们会讲到PV的生命周期。
2、PVC的创建
接下来我们创建PVC(名为nfs-pvc)其yaml内容如下
[rootk8s-master yaml]# cat nfs-pvc.yaml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:name: nfs-pvc
spec:storageClassName: my-storageaccessModes:- ReadWriteManyresources:requests:storage: 1Giselector:matchLabels:pv: nfs-pv
同样我们也来看下核心属性参数
1、storageClassName卷类型可以指定需要绑定的特定的PV卷类型比如例子中的my-storage类型的PV也可以设置为,则被视为要请求的是没有设置存储类的 PV 卷。
2、accessModes,访问模式与PV的模式类型一致。
3、resources请求资源对所需资源的描述目前仅支持requests.storage
4、selector,对于PV的选择器通过对于Label Selector的设置可以实现对于已存在的PV筛选。 执行该yaml文件创建该PVC并查看状态。
[rootk8s-master yaml]# kubectl get pvc
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE
nfs-pvc Bound nfs-pv 1Gi RWX my-storage 7s 可以看到K8S已经为该PVC找到到合适的PV即前面创建的nfs-pv其PVC的状态的为Bound(绑定状态)。我们再来看下PV(nfs-pv)的状态
[rootk8s-master yaml]# kubectl get pv
NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE
nfs-pv 1Gi RWX Recycle Bound default/nfs-pvc my-storage 16m
此时PV也变成为Bound状态。
3、使用PVC创建Pod 最后我们创建Pod并使用上面创建的PVC作为卷。还以上面的场景为例对Pod进行改造。 pvc-read-pod.yaml
[rootk8s-master yaml]# cat pvc-read-pod.yaml
apiVersion: v1
kind: Pod
metadata:name: pvc-read-pod
spec:containers:- image: busyboxname: read-appvolumeMounts:- mountPath: /read-app/logsname: shared-pvc-dirargs:- /bin/sh- -c- cat /read-app/logs/app.log; sleep 60000volumes:- name: shared-pvc-dirpersistentVolumeClaim:claimName: nfs-pvc 将volumes修改为PVC并指定名称为刚创建的nfs-pvc。
pvc-read-pod.yaml
[rootk8s-master yaml]# cat pvc-read-pod.yaml
apiVersion: v1
kind: Pod
metadata:name: pvc-read-pod
spec:containers:- image: busyboxname: read-appvolumeMounts:- mountPath: /read-app/logsname: shared-pvc-dirargs:- /bin/sh- -c- cat /read-app/logs/app.log; sleep 60000volumes:- name: shared-pvc-dirpersistentVolumeClaim:claimName: nfs-pvc
同样将volumes修改为PVC。执行yaml文件创建Pod并查看状态
[rootk8s-master yaml]# kubectl get pod -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
pvc-read-pod 1/1 Running 0 80s 10.244.36.74 k8s-node1 none none
pvc-write-pod 1/1 Running 0 89s 10.244.235.200 k8s-master none none
Pod成功创建我们查看下NFS挂载的目录(即master节点的/data/nfs/)
[rootk8s-master yaml]# cd /nfs/data/
[rootk8s-master data]# ll
total 4
-rw-r--r-- 1 root root 18 Apr 30 21:07 app.log
[rootk8s-master data]# cat app.log
this is write-app
该目录下正确的生成了app.log文件并写入了正确的内容。
继续进入到nfs-read-pod读取该文件的内容。
[rootk8s-master data]# kubectl exec pvc-read-pod -c read-app cat /read-app/logs/app.log
kubectl exec [POD] [COMMAND] is DEPRECATED and will be removed in a future version. Use kubectl exec [POD] -- [COMMAND] instead.
this is write-app
一切正常至此创建的PVC已经挂载到Pod上并正常提供了卷服务。
4、生命周期
我们先总结下前面的生命周期状态的变化 接下来我们删除PVC看下PV
[rootk8s-master data]# kubectl delete pvc nfs-pvc
[rootk8s-master data]# kubectl get pv
NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE
nfs-pv 1Gi RWX Recycle Available my-storage 3h27m
在看下之前创建的文件切换到/nfs/data目录
[rootk8s-master data]# cd /nfs/data/
[rootk8s-master data]# ll
total 0 由于我们配置PV的persistentVolumeReclaimPolicy: Recycle(回收空间),所以PVC删除后文件被删除空间回收PV重新变为了Available状态可以再次被利用。补充以上的状态机图 四、StorageClass 通过PV和PVC完美地解耦了运维管理员和开发人员的工作但是也带来了新的问题一个K8S集群中有成千上万的PV运维人员需要手动创建出来而且在业务的迭代过程中需要根据不断提交的PVC来实现PV否则就可能PVC无法绑定PV导致创建失败。那有没有方式能根据PVC的申请来自动创建PV呢这样就可以进一步解放运维管理员的生产力投入到更有意义的工作中。 答案就是StorageClass对象它可以指定一个可以自动配置存储的插件我们叫它制备器(Provisioner),根据PVC的资源需求自动创建一个符合条件的PV分配实际存储资源并进行PVC绑定。 运维管理员仅配置StorageClass其他的过程都是K8S配合制备器自动完成。上面的协同模型就可以修改为以下 这种方式创建存储卷相比手动创建我们称之为动态存储卷。我们看下StorageClass的核心参数。
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:name: standard
provisioner: kubernetes.io/aws-ebs
parameters:type: gp2
provisioner制备器可以看做是每种卷插件的后端存储驱动。比如EBS的制备器可以制备EBS类型的卷。K8S为常用的卷插件提供内置的provisioner比如EBSAzureFileGCEPersistentDiskGlusterfs等一般是以kubernetes.io开头当然用户也可以按照规范自定义三方的制备器。parameters参数provisioner的参数不同的provisioner参数也不同。
下面就以NFS为例实现StorageClass的创建和使用过程。
1、创建NFS的StorageClass 由于NFS没有内置的 Provisioner 对象需要使用开源的其以Pod的方式运行GitHub的地址为GitHub - kubernetes-sigs/nfs-subdir-external-provisioner: Dynamic sub-dir volume provisioner on a remote NFS server. 下载deploy目录下的rbac.yaml,class.yaml,deploy.yaml修改一些内容使其与我们的NFS环境保持一致。修改后重新命名为 storage-nfs-rbac.yamlstorage-nfs-class.yamlstorage-nfs-deploy.yaml其内容参见文章后面的附录执行以上三个yaml文件完成StorageClass的创建,名称为nfs-client。
kubectl apply -f storage-nfs-rbac.yaml
kubectl apply -f storage-nfs-class.yaml
kubectl apply -f storage-nfs-deployment.yaml
2、创建指定StorageClass的PVC 接下来我们创建PVC并指定StorageClass(nfs-client),其yaml内容如下
[rootk8s-master yaml]# cat nfs-storage-pvc.yaml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:name: nfs-storage-pvc
spec:# 这里使用刚创建的storage namestorageClassName: nfs-clientaccessModes:- ReadWriteManyresources:requests:storage: 1Gi 执行该文件创建PVC查看状态
[rootk8s-master yaml]# kubectl apply -f nfs-storage-pvc.yaml
persistentvolumeclaim/nfs-storage-pvc created
[rootk8s-master yaml]# kubectl get pvc
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE
nfs-storage-pvc Bound pvc-f795e09b-1583-436b-869b-88a68d28ce64 1Gi RWX nfs-client 5s 可以看到已经创建完成并处于Bound状态这就说明已经有PV绑定了。在查看下PV的状态
[rootk8s-master yaml]# kubectl get pv
NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE
pvc-f795e09b-1583-436b-869b-88a68d28ce64 1Gi RWX Delete Bound default/nfs-storage-pvc nfs-client 10s
果然NFS的provisioner已经自动创建PV并完成了绑定。
3、创建使用PVC的Pod
接下来使用之前的Pod用例来验证下写入功能我们修改下yaml内容
[rootk8s-master yaml]# cat storageclass-write-pod.yaml
apiVersion: v1
kind: Pod
metadata:name: storageclass-write-pod
spec:tolerations:- key: node-role.kubernetes.io/masteroperator: Existseffect: NoSchedulecontainers:- image: busyboxname: write-appvolumeMounts:- mountPath: /write-app/logsname: shared-storageclass-dirargs:- /bin/sh- -c- echo this is write-app /write-app/logs/app.log; sleep 60000volumes:- name: shared-storageclass-dirpersistentVolumeClaim:claimName: nfs-storage-pvc 将PVC的claimName修改为本次的PVC名称nfs-storage-pvc执行该文件创建Pod成功后我们是否写入到NFS的挂载目录
[rootk8s-master yaml]# cd /nfs/data
[rootk8s-master data]# ll
total 4
drwxrwxrwx 2 root root 4096 May 1 22:36 default-nfs-storage-pvc-pvc-f795e09b-1583-436b-869b-88a68d28ce64
[rootk8s-master data]# cd default-nfs-storage-pvc-pvc-f795e09b-1583-436b-869b-88a68d28ce64/
[rootk8s-master default-nfs-storage-pvc-pvc-f795e09b-1583-436b-869b-88a68d28ce64]# ll
total 4
-rw-r--r-- 1 root root 18 May 1 22:36 app.log
[rootk8s-master default-nfs-storage-pvc-pvc-f795e09b-1583-436b-869b-88a68d28ce64]# cat app.log
this is write-app 可以看到在/nfs/data下K8S自动创建一个PVC名称加上随机数的文件夹Pod写入的日志文件app.log位于该目录下。
五、总结
本章节我们介绍了K8S的共享存储。
1、同一Pod的容器间共享存储可以使用EmptyDir。
2、同一节点的Pod的共享存储可以使用HostPath。
3、不同节点间Pod的共享存储可以使用云计算厂商提供的特定存储也可以使用标准的网络文件存储这里重点介绍了NFS。
4、为了解耦开发和运维人员的工作K8S设计了PV和PVC运维人员根据资源总量申明式创建大量的PV预先分配开发人员提交PVC申请K8S根据申请的资源自动找到合适的PV并进行绑定和实际资源分配。
5、为了进一步解放运维的工作K8S设计了StorageClass对象实现了动态创建存储卷。根据开发人员提供的PVC需求K8S配合制备器可以自动完成PV的创建和绑定从而省去预先创建PV的工作。 附:
K8S初级入门系列之一-概述
K8S初级入门系列之二-集群搭建
K8S初级入门系列之三-Pod的基本概念和操作
K8S初级入门系列之四-Namespace/ConfigMap/Secret
K8S初级入门系列之五-Pod的高级特性
K8S初级入门系列之六-控制器(RC/RS/Deployment)
K8S初级入门系列之七-控制器(Job/CronJob/Daemonset)
K8S初级入门系列之八-网络
K8S初级入门系列之九-共享存储
K8S初级入门系列之十-控制器(StatefulSet)
K8S初级入门系列之十一-安全
K8S初级入门系列之十二-计算资源管理 附件
storage-nfs-rbac.yaml
apiVersion: v1
kind: ServiceAccount
metadata:name: nfs-client-provisioner# replace with namespace where provisioner is deployednamespace: default
---
kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1
metadata:name: nfs-client-provisioner-runner
rules:- apiGroups: []resources: [nodes]verbs: [get, list, watch]- 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: ServiceAccountname: nfs-client-provisioner# replace with namespace where provisioner is deployednamespace: default
roleRef:kind: ClusterRolename: nfs-client-provisioner-runnerapiGroup: rbac.authorization.k8s.io
---
kind: Role
apiVersion: rbac.authorization.k8s.io/v1
metadata:name: leader-locking-nfs-client-provisioner# replace with namespace where provisioner is deployednamespace: default
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# replace with namespace where provisioner is deployednamespace: default
subjects:- kind: ServiceAccountname: nfs-client-provisioner# replace with namespace where provisioner is deployednamespace: default
roleRef:kind: Rolename: leader-locking-nfs-client-provisionerapiGroup: rbac.authorization.k8s.io
storage-nfs-class.yaml
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:name: nfs-client
# 这是为provisioner名称需要与deploy的env的PROVISIONER_NAME保持一致
provisioner: k8s-sigs.io/nfs-subdir-external-provisioner
parameters:archiveOnDelete: false
storage-nfs-deploy.yaml
apiVersion: apps/v1
kind: Deployment
metadata:name: nfs-client-provisionerlabels:app: nfs-client-provisioner# replace with namespace where provisioner is deployednamespace: default
spec:replicas: 1strategy:type: Recreateselector:matchLabels:app: nfs-client-provisionertemplate:metadata:labels:app: nfs-client-provisionerspec:serviceAccountName: nfs-client-provisionercontainers:- name: nfs-client-provisioner# 修改如下镜像地址image: chronolaw/nfs-subdir-external-provisioner:v4.0.2volumeMounts:- name: nfs-client-rootmountPath: /persistentvolumesenv:# 这是为provisioner名称需要与StorageClass的PROVISIONER_NAME保持一致- name: PROVISIONER_NAMEvalue: k8s-sigs.io/nfs-subdir-external-provisioner- name: NFS_SERVER# 修改此处的ip为nfs server ipvalue: 192.168.16.4- name: NFS_PATH# 修改此处的path为nfs 挂载的目录 ipvalue: /nfs/datavolumes:- name: nfs-client-rootnfs:server: 192.168.16.4path: /nfs/data