超10万字整理完k8s的volume卷之sc动态卷供应-超详细说明,代码和理论都超详细,建议跟着做一遍实验【3】
文章目录本地卷&网络卷【必看】持久性存储 【Persistent Volume】【必看】动态卷供应概念等说明动态卷和持久性存储的区别动态卷概念说明运行逻辑storageClass 的工作流程【必看】创建动态卷供应【以nfs为例】主机信息nfs文件共享配置文件创建并共享【nfs节点操作】nfs外部分配器配置安装git服务分配器包准备在master上安装nfs分配器部署storageClass
说明【必看】
- 总数将近11万,存储一共有4大类,本地卷、网络卷、持久性存储和动态卷供应 ,为了能够直观理解,所以我分成了3篇来发布;
初次看的时候,建议3篇都打开,按顺序学习和使实验,有助于理解哈。 后面查阅的时候看标题,点进相应的文章哈 - 这篇是第三篇
本地卷&网络卷【必看】【1】
- 这篇博客中还对volume做了说明,学习持久性存储之前,建议先去这篇文章中学习一下本地卷的概念和网络卷【特别是网络卷,因为持久性存储是网络卷的升级,指导网络卷以后,更容易理解持久性存储】
超10万字整理完k8s的volume卷之本地卷和网络卷详细说明,代码和理论都超详细,建议跟着做一遍实验【emptyDir、hostPath、nfs共享的网络卷】【1】
持久性存储 【必看】【2】
- 看这篇博客【上面的本地卷和网络卷是基础知识,足够用了,如果想更深学习,就去这篇博客】:
超10万字整理完k8s的volume卷之持久性存储-超详细说明,代码和理论都超详细,建议跟着做一遍实验【2】
动态卷供应概念等说明
动态卷和持久性存储的区别
- 前面讲持久性存储的时候,是要先创建pv 然后才能创建pvc。如果不同的命名空间里同时要创建不同的pvc,那么就需要提前把pv 创建好,这样才能为pvc 提供存储。这种操作方式太过于麻烦,所以可以通过storageClass(简称为sc)来解决这个问题。
- 最终的效果是,管理员不需要提前创建pv,只要创建好storageClass 之后就不用管pv 了,用户创建pvc 的时候,storageClass 会自动创建创建出来一个pv 和这个pvc 进行关联。
动态卷概念说明
- 动态卷供应允许按需创建存储卷。 如果没有动态供应,集群管理员必须手动地联系他们的云或存储提供商来创建新的存储卷, 然后在 Kubernetes 集群创建 PersistentVolume 对象来表示这些卷。 动态供应功能消除了集群管理员预先配置存储的需要。 相反,它在用户请求时自动供应存储。
运行逻辑
-
动态卷供应的实现基于 storage.k8s.io API 组中的 StorageClass API 对象。 集群管理员可以根据需要定义多个 StorageClass 对象,每个对象指定一个卷插件(又名 provisioner), 卷插件向卷供应商提供在创建卷时需要的数据卷信息及相关参数。
-
集群管理员可以在集群中定义和公开多种存储(来自相同或不同的存储系统),每种都具有自定义参数集。 该设计也确保终端用户不必担心存储供应的复杂性和细微差别,但仍然能够从多个存储选项中进行选择。
-
用口水话的方式说流程,就是持久性存储中,我们需要自己定义pv,然后pvc绑定pv,最后通过pvc创建pod嘛
而动态卷呢,实际上就是,我们只需要定义pvc即可,pv不需要我们定义,由storageClass自动定义pv。
如下图,能知道运行逻辑最好,不能知道就当这个图不存在,看下面实例再理解。
storageClass 的工作流程【必看】
- 定义storageClass 时必须要包含一个分配器(provisioner),不同的分配器指定了动态创建pv时使用什么后端存储。先看下面的3 个例子
- 第一个例子,分配器使用aws 的ebs 作为pv 的后端存储
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: ebs
provisioner: kubernetes.io/aws-ebs
parameters:
type: io1
iopsPerGB: "10"
fsType: ext4
- 第二个例子,分配器使用lvm 作为pv 的后端存储
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: csi-lvm
provisioner: lvmplugin.csi.alibabacloud.com
parameters:
vgName: volumegroup1
fsType: ext4
reclaimPolicy: Delete
- 第三个例子,使用hostPath 作为pv 的后端存储
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: csi-hostpath-sc
provisioner: hostpath.csi.k8s.io
reclaimPolicy: Delete
#volumeBindingMode: Immediate
volumeBindingMode: WaitForFirstConsumer
allowVolumeExpansion: true
-
我这提供一下相关包吧,想折腾的可以根据下面nfs的方式折腾一下
动态 storageClass.rar
-
这三个例子里,分别使用了不同的分配器,这些分配器有的是以aws-ebs 做pv 的后端存储,有的是以lv 作为pv 后端存储,有的是以hostPath 作为pv 后端存储。
-
上面3 个例子里所使用的分配器中,有一些是kubernetes 内置的分配器,比如kubernetes.io/aws-ebs,其他两个分配器不是kubernetes 自带的。kubernetes 自带的分配器包括:
- kubernetes.io/aws-ebs
- kubernetes.io/gce-pd
- kubernetes.io/glusterfs
- kubernetes.io/cinder
- kubernetes.io/vsphere-volume
- kubernetes.io/rbd
- kubernetes.io/quobyte
- kubernetes.io/azure-disk
- kubernetes.io/azure-file
- kubernetes.io/portworx-volume
- kubernetes.io/scaleio
- kubernetes.io/storageos
- kubernetes.io/no-provisioner
-
在动态创建pv 的时候,根据使用不同的后端存储,应该选择一个合适的分配器。但是像lvmplugin.csi.alibabacloud.com 和hostpath.csi.k8s.io 这样的分配器既然不是kubernetes 自带的,那是哪里来的呢?
- 这些非内置的分配器咱们暂且称之为外部分配器,这些外部分配器由第三方提供,是通过自定义CSIDriver(容器存储接口驱动)来实现的分配器。
- 所以整个流程就是,管理员创建storageClass 时会通过.provisioner 字段指定分配器。管理员创建好storageClass 之后,用户在定义pvc 时需要通过.spec.storageClassName 指定使用哪个storageClass。
当创建pvc 的时候,系统会通知storageClass,storageClass 会从它所关联的分配器来获取后端存储类型,然后动态的创建一个pv 出来和此pvc 进行关联。
- 所以,我们创建流程呢就是
- 1、配置SC
- 2、配置分配器【自带的可以不用配置】
- 3、创建pvc
创建动态卷供应【以nfs为例】
我前面已经用nfs 配置过共享文件夹了,因为配置起来相对简单,所以这里继续以nfs 作为后端存储来配置动态卷供应。
主机信息
- 下面4台主机呢,其中3台是一个集群,一台已经安装好nfs的服务
如果没有下面环境的,先搭建这么一套出来【k8s集群搭建和nfs服务端配置我博客中都有,如果不会的可以去翻翻博客先学习一下】
服务器名称(hostname) | 系统版本 | IP | 部署模块 |
---|---|---|---|
master | CentOS Linux release 7.6.1810 (Core) | 192.168.59.142 | k8s集群-master节点 |
node1 | CentOS Linux release 7.6.1810 (Core) | 192.168.59.143 | k8s集群-node节点 |
node2 | CentOS Linux release 7.6.1810 (Core) | 192.168.59.144 | k8s集群-node节点 |
etcd1 | CentOS Linux release 7.4.1708 (Core) | 192.168.59.156 | 仅部署nfs【未加入集群】 |
nfs文件共享配置
- 【nfs这个,建议先去我k8s分类中,找到
volume卷的网络卷配置
里面有详细说明nfs主机服务搭建和node节点服务安装】
文件创建并共享【nfs节点操作】
- 任意创建一个目录,并共享这个目录。
我使用/vdisk
[root@etcd1 ~]# mkdir /vdisk
[root@etcd1 ~]# vim /etc/exports
[root@etcd1 ~]# cat /etc/exports | tail -n 1
/vdisk *(rw,sync,no_root_squash)
[root@etcd1 ~]#
[root@etcd1 ~]# exportfs -arv
# 下面很多共享是做之前存储测试的,没有删除而已,无需在意
exporting *:/vdisk
exporting *:/nfs1
exporting *:/nfs
exporting *:/data/nfs5
exporting *:/data/nfs4
exporting *:/data/nfs3
exporting *:/data/nfs2
exporting *:/data/nfs1
[root@etcd1 ~]#
nfs外部分配器配置
因为kubernetes 里,nfs 没有内置分配器,所以需要下载相关插件来创建nfs 外部分配器。
安装git服务
[root@master volume]# yum install git -y
[root@master volume]# yum -y install unzip
分配器包准备
- 下载链接【这里面有nfs镜像和分配器】
k8s的动态卷之nfs分配器.rar - 下载好以后呢,上传到master节点上
[root@master volume]# ls | grep zip
external-storage-master.zip
[root@master volume]# ls | grep tar
nfs-client-provisioner.tar
[root@master volume]#
- 然后将nfs这个包拷贝到全部node节点
[root@master volume]# ls | grep tar
nfs-client-provisioner.tar
[root@master volume]# scp nfs-client-provisioner.tar node1:~
root@node1's password:
nfs-client-provisioner.tar 100% 44MB 28.7MB/s 00:01
[root@master volume]# scp nfs-client-provisioner.tar node2:~
root@node2's password:
nfs-client-provisioner.tar 100% 44MB 32.5MB/s 00:01
[root@master volume]#
- 然后在所有节点上解压这个nfs镜像
[root@master volume]# docker load -i nfs-client-provisioner.tar
8dfad2055603: Loading layer 4.284MB/4.284MB
a17ae64bae4f: Loading layer 2.066MB/2.066MB
bd01fa00617b: Loading layer 39.72MB/39.72MB
Loaded image: quay.io/external_storage/nfs-client-provisioner:latest
[root@master volume]#
[root@node1 ~]# docker load -i nfs-client-provisioner.tar
8dfad2055603: Loading layer 4.284MB/4.284MB
a17ae64bae4f: Loading layer 2.066MB/2.066MB
bd01fa00617b: Loading layer 39.72MB/39.72MB
Loaded image: quay.io/external_storage/nfs-client-provisioner:latest
[root@node1 ~]#
[root@node2 ~]# docker load -i nfs-client-provisioner.tar
8dfad2055603: Loading layer 4.284MB/4.284MB
a17ae64bae4f: Loading layer 2.066MB/2.066MB
bd01fa00617b: Loading layer 39.72MB/39.72MB
Loaded image: quay.io/external_storage/nfs-client-provisioner:latest
[root@node2 ~]#
在master上安装nfs分配器
解压项目并进入到目录
[root@master volume]# unzip external-storage-master.zip
....
# 很多输出内容
[root@master volume]
[root@master volume]# cd external-storage-master/
[root@master external-storage-master]# cd nfs-client/
[root@master nfs-client]# cd deploy/
[root@master deploy]# ls | grep rb
rbac.yaml
[root@master deploy]#
- 部署rbac 权限。
关于权限的设置后面章节会讲解,因为我们是在命名空间volume 里的,所以需要把rbac.yaml 里指定的命名空间更换为volume,然后部署rbac:
[root@master volume]# kubectl config get-contexts
CURRENT NAME CLUSTER AUTHINFO NAMESPACE
* context master ccx volume
context1-new master1 ccx1 default
[root@master volume]#
[root@master deploy]# pwd
/root/volume/external-storage-master/nfs-client/deploy
[root@master deploy]#
[root@master deploy]# sed -i 's/namespace: default/namespace: volume/g' rbac.yaml
[root@master deploy]#
[root@master deploy]# kubectl apply -f rbac.yaml
serviceaccount/nfs-client-provisioner created
clusterrole.rbac.authorization.k8s.io/nfs-client-provisioner-runner created
clusterrolebinding.rbac.authorization.k8s.io/run-nfs-client-provisioner created
role.rbac.authorization.k8s.io/leader-locking-nfs-client-provisioner created
rolebinding.rbac.authorization.k8s.io/leader-locking-nfs-client-provisioner created
[root@master deploy]#
- 配置文件编辑
需要修改3处参数,已经在内容中说明了
[root@master deploy]# cat -n deployment.yaml
1 apiVersion: apps/v1
2 kind: Deployment
3 metadata:
4 name: nfs-client-provisioner
5 labels:
6 app: nfs-client-provisioner
7 # replace with namespace where provisioner is deployed
# 修改当前所属命名空间【上面步骤有查看方式的】
8 namespace: volume
9 spec:
10 replicas: 1
11 strategy:
12 type: Recreate
13 selector:
14 matchLabels:
15 app: nfs-client-provisioner
16 template:
17 metadata:
18 labels:
19 app: nfs-client-provisioner
20 spec:
21 serviceAccountName: nfs-client-provisioner
22 containers:
23 - name: nfs-client-provisioner
24 image: quay.io/external_storage/nfs-client-provisioner:latest
# 增加镜像获取规则【上面分配器步骤已经将包导入了】
25 imagePullPolicy: IfNotPresent
26 volumeMounts:
27 - name: nfs-client-root
28 mountPath: /persistentvolumes
29 env:
30 - name: PROVISIONER_NAME
31 value: fuseim.pri/ifs
32 - name: NFS_SERVER
# nfs的共享ip
33 value: 192.168.59.156
34 - name: NFS_PATH
# nfs的共享目录
35 value: /vdisk
36 volumes:
37 - name: nfs-client-root
38 nfs:
# 下面nfsip和共享目录
39 server: 192.168.59.156
40 path: /vdisk
[root@master deploy]#
- 创建pod
创建需要一点时间,可能要多等会才能running
[root@master deploy]# kubectl apply -f deployment.yaml
deployment.apps/nfs-client-provisioner configured
[root@master deploy]# kubectl get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
nfs-client-provisioner-8464d69b6b-6gj48 0/1 Terminating 0 6m29s 10.244.166.148 node1 <none> <none>
[root@master deploy]# kubectl get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
nfs-client-provisioner-c8f4bcbd-cksn2 0/1 ContainerCreating 0 0s <none> node1 <none> <none>
[root@master deploy]# kubectl get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
nfs-client-provisioner-c8f4bcbd-cksn2 1/1 Running 0 3s 10.244.166.149 node1 <none> <none>
[root@master deploy]#
部署storageClass【master上操作】
-
创建了nfs 分配器之后,下面开始创建一个使用这个分配器的storageClass。【这是接着上面做的,所以期间没有切换过路径】
-
创建storageClass。
在当前目录里有一个名为class.yaml 的文件,用于创建storageClass,其中name可以其定义,其他部要修改即可。
注:这个class创建后不会有一个单独的pod显示,是正常的,最终kubectl get sc
能执行成功就行。
[root@master deploy]# kubectl get sc
No resources found
[root@master deploy]# cat -n class.yaml
1 apiVersion: storage.k8s.io/v1
2 kind: StorageClass
3 metadata:
# 可以自定义name
4 name: mysc
5 provisioner: fuseim.pri/ifs # or choose another name, must match deployment's env PROVISIONER_NAME'
6 parameters:
7 archiveOnDelete: "false"
[root@master deploy]#
[root@master deploy]# kubectl apply -f class.yaml
storageclass.storage.k8s.io/mysc created
[root@master deploy]# kubectl get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
nfs-client-provisioner-c8f4bcbd-cksn2 1/1 Running 0 3m2s 10.244.166.149 node1 <none> <none>
[root@master deploy]# kubectl get sc
NAME PROVISIONER RECLAIMPOLICY VOLUMEBINDINGMODE ALLOWVOLUMEEXPANSION AGE
mysc fuseim.pri/ifs Delete Immediate false 29s
[root@master deploy]#
查看sc命令
- 命令:
kubectl get sc
[root@master deploy]# kubectl get sc
NAME PROVISIONER RECLAIMPOLICY VOLUMEBINDINGMODE ALLOWVOLUMEEXPANSION AGE
mysc fuseim.pri/ifs Delete Immediate false 8m12s
[root@master deploy]#
配置文件增加一行内容
- 在1.20及以后的版本需要修改一个参数,查看方式:
[root@master volume]# kubectl version
Client Version: version.Info{Major:"1", Minor:"21", GitVersion:"v1.21.0", GitCommit:"cb303e613a121a29364f75cc67d3d580833a7479", GitTreeState:"clean", BuildDate:"2021-04-08T16:31:21Z", GoVersion:"go1.16.1", Compiler:"gc", Platform:"linux/amd64"}
Server Version: version.Info{Major:"1", Minor:"21", GitVersion:"v1.21.0", GitCommit:"cb303e613a121a29364f75cc67d3d580833a7479", GitTreeState:"clean", BuildDate:"2021-04-08T16:25:06Z", GoVersion:"go1.16.1", Compiler:"gc", Platform:"linux/amd64"}
[root@master volume]#
- 修改文件:
vim /etc/kubernetes/manifests/kube-apiserver.yaml
# 新增下面18行内容,然后重启服务
[root@master volume]# cat -n /etc/kubernetes/manifests/kube-apiserver.yaml | grep -C1 feature-gates=RemoveSelfLink=false
17 - --allow-privileged=true
18 - --feature-gates=RemoveSelfLink=false
19 - --authorization-mode=Node,RBAC
[root@master volume]#
[root@master volume]# systemctl restart kubelet.service
[root@master volume]#
配置动态卷【nfs】
这个就不多说了,动态卷呢,就是没有创建pv的这个流程,我们直接创建一个pvc,系统会自动给我们创建一个pv并且绑定到pvc上面。
配置文件说明
[root@master volume]# cat -n pvauto.yaml
1 apiVersion: v1
2 kind: PersistentVolumeClaim
3 metadata:
4 name: autopv #自定义的
5 annotations:
6 volume.beta.kubernetes.io/storage-class: "mysc" #这是指定sc的,如果只有一个sc,5和6行可不要,kubectl get sc 查看sc名称
7 spec:
8 accessModes:
9 - ReadWriteOnce # 这些都是模式而已,持久性存储中有说明的
10 volumeMode: Filesystem #文件类型罢了
11 resources:
12 requests:
13 storage: 300Mi #这是定义大小单位有M和G
14 storageClassName: mysc #指定sc名称,kubectl get sc 可查看
[root@master volume]#
创建pvc
- 创建前当前系统是没有pv和pvc的
[root@master volume]# kubectl get pv
No resources found
[root@master volume]#
[root@master volume]# kubectl get pvc
No resources found in volume namespace.
[root@master volume]#
- 编辑配置文件并创建
下面创建成功一个pvc以后,就可以看到pvc已经自动和一个pv绑定了。
[root@master volume]# cat -n pvauto.yaml
1 apiVersion: v1
2 kind: PersistentVolumeClaim
3 metadata:
4 name: autopv
5 annotations:
6 volume.beta.kubernetes.io/storage-class: "mysc"
7 spec:
8 accessModes:
9 - ReadWriteOnce
10 volumeMode: Filesystem
11 resources:
12 requests:
13 storage: 300Mi
14 storageClassName: mysc
[root@master volume]#
[root@master volume]# kubectl apply -f pvauto.yaml
persistentvolumeclaim/autopv created
[root@master volume]#
[root@master volume]# kubectl get pvc
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE
autopv Bound pvc-fab1494e-04f2-4aac-a188-18f6ff3fd51c 300Mi RWO mysc 9s
[root@master volume]#
[root@master volume]# kubectl get pv
NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE
pvc-fab1494e-04f2-4aac-a188-18f6ff3fd51c 300Mi RWO Delete Bound volume/autopv mysc 11s
[root@master volume]#
查看pv详细信息【自动生成pv说明】
前面说了,创建pvc呢,会自动生产一个pv,查看pv详细信息:kubectl describe pv pv_name
[root@master volume]# kubectl get pv
NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE
pvc-fab1494e-04f2-4aac-a188-18f6ff3fd51c 300Mi RWO Delete Bound volume/autopv mysc 6m8s
[root@master volume]#
[root@master volume]# kubectl describe pv pvc-fab1494e-04f2-4aac-a188-18f6ff3fd51c
Name: pvc-fab1494e-04f2-4aac-a188-18f6ff3fd51c
Labels: <none>
Annotations: pv.kubernetes.io/provisioned-by: fuseim.pri/ifs
Finalizers: [kubernetes.io/pv-protection]
StorageClass: mysc
Status: Bound
Claim: volume/autopv
Reclaim Policy: Delete
Access Modes: RWO
VolumeMode: Filesystem
Capacity: 300Mi
Node Affinity: <none>
Message:
Source:
Type: NFS (an NFS mount that lasts the lifetime of a pod)
Server: 192.168.59.156
Path: /vdisk/volume-autopv-pvc-fab1494e-04f2-4aac-a188-18f6ff3fd51c
ReadOnly: false
Events: <none>
[root@master volume]#
这个时候就可以看到自动生成的pv路径了,如上,Source下,这些信息就是nfs服务器的信息了
Source:
Type: NFS (an NFS mount that lasts the lifetime of a pod)
Server: 192.168.59.156
Path: /vdisk/volume-autopv-pvc-fab1494e-04f2-4aac-a188-18f6ff3fd51c
ReadOnly: false
Events: <none>
我们去nfs下验证一下这歌目录信息,并且来了,就随便创建2个文件吧,后面验证用。
[root@etcd1 ~]# cd /vdisk/
[root@etcd1 vdisk]# ls
volume-autopv-pvc-fab1494e-04f2-4aac-a188-18f6ff3fd51c
[root@etcd1 vdisk]# cd volume-autopv-pvc-fab1494e-04f2-4aac-a188-18f6ff3fd51c/
[root@etcd1 volume-autopv-pvc-fab1494e-04f2-4aac-a188-18f6ff3fd51c]# ls
[root@etcd1 volume-autopv-pvc-fab1494e-04f2-4aac-a188-18f6ff3fd51c]# touch nfs{test1,test2}
[root@etcd1 volume-autopv-pvc-fab1494e-04f2-4aac-a188-18f6ff3fd51c]# ls
nfstest1 nfstest2
[root@etcd1 volume-autopv-pvc-fab1494e-04f2-4aac-a188-18f6ff3fd51c]#
删除pvc说明
- 删除pvc会自动删除相应的pv,这个应该能理解吧。
注:因为pv的模式是Delete,这个pv被删除以后,对应的数据就会被直接删除【这个delete模式定义在上面sc安装的class.yaml
文件中定义的,这不多说,感兴趣的自行研究吧,我觉得动态卷的模式为delete挺合适的,就不想折腾】 【是删除pvc才会丢失数据,通过pvc创建的pod,删除pod后数据是不会丢失的】
[root@master volume]# kubectl get pv
NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE
pvc-fab1494e-04f2-4aac-a188-18f6ff3fd51c 300Mi RWO Delete Bound volume/autopv mysc 11m
[root@master volume]#
- 现在我们删除这个pv,并且去nfs服务器中查看目录文件是否被删除了。
[root@master volume]# kubectl delete pvc autopv
persistentvolumeclaim "autopv" deleted
[root@master volume]#
[root@master volume]# kubectl get pv
No resources found
[root@master volume]#
# 数据确实没了,成功。
[root@etcd1 ~]# cd /vdisk/
[root@etcd1 vdisk]# ls
[root@etcd1 vdisk]#
绑定pv创建pod
代码解释
- 先创建好pvc
[root@master volume]# kubectl apply -f pvauto.yaml
persistentvolumeclaim/autopv created
[root@master volume]# kubectl get pvc
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE
autopv Bound pvc-1b0b2fd3-71a0-4cf6-abc0-b5e4e4a37324 300Mi RWO mysc 7s
[root@master volume]# kubectl get pv
NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE
pvc-1b0b2fd3-71a0-4cf6-abc0-b5e4e4a37324 300Mi RWO Delete Bound volume/autopv mysc 11s
[root@master volume]#
- 下面是一些创建pod的基本参数规则,已经在代码后面注明作用了
这个和创建pod差不太多,只是卷定义稍有不同,pod更多参数可以参考pod创建自定义测试哦。
[root@master volume]# cat pvpod.yaml
apiVersion: v1 #自定义版本号
kind: Pod
metadata:
name: pvpod #自定义pod名称
spec:
containers:
- name: pv-pod #自定义名称
image: nginx #镜像名称
imagePullPolicy: IfNotPresent #定义镜像获取规则,默认pull
args: # 下面是自定义command的一种方式,只有一个容器不定义也可
- /bin/sh
- -c
- sleep 300000
volumeMounts:
- mountPath: /testdata #定义容器中的目录
name: volumedata #保证与卷的名称一致【卷名称在下面】
volumes:
- name: volumedata #定义卷的名称
persistentVolumeClaim:
claimName: ccx-pvc #指定逻辑卷对应的PVC名称【kubectl get pvc查看】
编辑文件并创建pod
创建这个pod呢,其实和前面持久性存储方式是一样的,仅仅需要修改pvc名称内容即可。而且动态卷和持久性本来就是一样的,就是创建流程不一样罢了。
[root@master volume]# cat -n pvpod.yaml
1 apiVersion: v1
2 kind: Pod
3 metadata:
4 name: pvpod
5 spec:
6 containers:
7 - name: pv-pod
8 image: nginx
9 imagePullPolicy: IfNotPresent
10 args:
11 - /bin/sh
12 - -c
13 - sleep 300000
14 volumeMounts:
15 - mountPath: /testdata
16 name: volumedata
17 volumes:
18 - name: volumedata
19 persistentVolumeClaim:
20 claimName: autopv
[root@master volume]#
[root@master volume]# kubectl apply -f pvpod.yaml
pod/pvpod created
[root@master volume]# kubectl get pod -o wide | grep pod
pvpod 1/1 Running 0 14s 10.244.166.151 node1 <none> <none>
[root@master volume]#
pod数据测试
额, 我就不多说明了,直接丢测试结果,过程可以去持久性存储里面的pod数据测试看,里面很详细。
#nfs
[root@etcd1 ~]# cd /vdisk/
[root@etcd1 vdisk]# ls
volume-autopv-pvc-1b0b2fd3-71a0-4cf6-abc0-b5e4e4a37324
[root@etcd1 vdisk]# cd volume-autopv-pvc-1b0b2fd3-71a0-4cf6-abc0-b5e4e4a37324/
[root@etcd1 volume-autopv-pvc-1b0b2fd3-71a0-4cf6-abc0-b5e4e4a37324]# touch nfs{test1,test2,test3}
[root@etcd1 volume-autopv-pvc-1b0b2fd3-71a0-4cf6-abc0-b5e4e4a37324]# ls
nfstest1 nfstest2 nfstest3
[root@etcd1 volume-autopv-pvc-1b0b2fd3-71a0-4cf6-abc0-b5e4e4a37324]#
#master
[root@master volume]# kubectl exec -it pvpod -- bash
root@pvpod:/# cd /testdata/
root@pvpod:/testdata# ls
nfstest1 nfstest2 nfstest3
root@pvpod:/testdata#
root@pvpod:/testdata# touch pvpod{hero1,hero2,hero3}
root@pvpod:/testdata# ls
nfstest1 nfstest2 nfstest3 pvpodhero1 pvpodhero2 pvpodhero3
root@pvpod:/testdata#
#nfs
[root@etcd1 volume-autopv-pvc-1b0b2fd3-71a0-4cf6-abc0-b5e4e4a37324]# ls
nfstest1 nfstest2 nfstest3 pvpodhero1 pvpodhero2 pvpodhero3
[root@etcd1 volume-autopv-pvc-1b0b2fd3-71a0-4cf6-abc0-b5e4e4a37324]#
- 上面数据测试没问题
注:我们删除pod以后数据其实还在,只是删除pvc,数据才会丢失
现在测试一下吧
#master
[root@master volume]# kubectl delete pod pvpod
pod "pvpod" deleted
[root@master volume]#
#nfs
[root@etcd1 ~]# cd /vdisk/
[root@etcd1 vdisk]# ls
volume-autopv-pvc-1b0b2fd3-71a0-4cf6-abc0-b5e4e4a37324
[root@etcd1 vdisk]# cd volume-autopv-pvc-1b0b2fd3-71a0-4cf6-abc0-b5e4e4a37324/
[root@etcd1 volume-autopv-pvc-1b0b2fd3-71a0-4cf6-abc0-b5e4e4a37324]# ls
nfstest1 nfstest2 nfstest3 pvpodhero1 pvpodhero2 pvpodhero3
[root@etcd1 volume-autopv-pvc-1b0b2fd3-71a0-4cf6-abc0-b5e4e4a37324]#
创建动态动态卷供应【官网】
上面的共享卷是nfs的方式,本地卷呢,很明显,就是存储卷在mater上。
配置动态卷供应
- 注:下面资料来源于官网,我只是照着做了测试而已【有补充】。
动态卷供应 - 要启用动态供应功能,集群管理员需要为用户预先创建一个或多个 StorageClass 对象。 StorageClass 对象定义当动态供应被调用时,哪一个驱动将被使用和哪些参数将被传递给驱动。 以下清单创建了一个 StorageClass 存储类 “slow”,它提供类似标准磁盘的永久磁盘。
[root@master volume]# cat bdpv.yaml
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: slow
provisioner: kubernetes.io/gce-pd
parameters:
type: pd-standard
[root@master volume]#
- 以下清单创建了一个 “fast” 存储类,它提供类似 SSD 的永久磁盘。
[root@master volume]# cat bdpv2.yaml
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: fast
provisioner: kubernetes.io/gce-pd
parameters:
type: pd-standard
[root@master volume]#
- 创建这2个sc
[root@master volume]# kubectl apply -f bdpv.yaml
storageclass.storage.k8s.io/slow created
[root@master volume]# kubectl apply -f bdpv2.yaml
storageclass.storage.k8s.io/fast created
[root@master volume]#
[root@master volume]# kubectl get sc
NAME PROVISIONER RECLAIMPOLICY VOLUMEBINDINGMODE ALLOWVOLUMEEXPANSION AGE
mysc fuseim.pri/ifs Delete Immediate false 6h12m
slow kubernetes.io/gce-pd Delete Immediate false 6s
[root@master volume]#
使用动态卷供应
-
用户通过在 PersistentVolumeClaim 中包含存储类来请求动态供应的存储。 在 Kubernetes v1.9 之前,这通过 volume.beta.kubernetes.io/storage-class 注解实现。然而,这个注解自 v1.6 起就不被推荐使用了。 用户现在能够而且应该使用 PersistentVolumeClaim 对象的 storageClassName 字段。 这个字段的值必须能够匹配到集群管理员配置的 StorageClass 名称(见下面)。
-
例如,要选择 “fast” 存储类,用户将创建如下的 PersistentVolumeClaim:
[root@master volume]# cat bdpvc.yaml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: claim1
spec:
accessModes:
- ReadWriteOnce
storageClassName: fast
resources:
requests:
storage: 30Gi
[root@master volume]#
该声明会自动供应一块类似 SSD 的永久磁盘。 在删除该声明后,这个卷也会被销毁。
- 创建该pvc,我创建的claim1状态为pending【有一个正常的,可以对比一下】
[root@master volume]# kubectl apply -f bdpvc.yaml
persistentvolumeclaim/claim1 created
[root@master volume]# kubectl get pvc
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE
autopv Bound pvc-1b0b2fd3-71a0-4cf6-abc0-b5e4e4a37324 300Mi RWO mysc 28m
claim1 Pending one 2m45s
[root@master volume]#
[root@master volume]# kubectl describe pvc claim1
Name: claim1
Namespace: volume
StorageClass: fast
Status: Pending
Volume:
Labels: <none>
Annotations: volume.beta.kubernetes.io/storage-provisioner: kubernetes.io/gce-pd
Finalizers: [kubernetes.io/pvc-protection]
Capacity:
Access Modes:
VolumeMode: Filesystem
Used By: <none>
Events: <none>
[root@master volume]#
[root@master volume]# kubectl describe pvc claim1
Name: claim1
Namespace: volume
StorageClass: fast
Status: Pending
Volume:
Labels: <none>
Annotations: volume.beta.kubernetes.io/storage-provisioner: kubernetes.io/gce-pd
Finalizers: [kubernetes.io/pvc-protection]
Capacity:
Access Modes:
VolumeMode: Filesystem
Used By: <none>
Events: <none>
[root@master volume]#
- 原因是因为我的集群在内网环境,没有我忘,配置卷:无法获取AWS云提供程序,所以状态就是pending,如果集群有外网,上面状态就会为Running了
说明
本来想找找上面的,有没有办法离线弄的,但网上找了很多文章,tm这些人全是复制粘贴的官网内容,没有一点帮助。
不过我在官网中看了较多资料,provisioner: kubernetes.io/gce-pd
好像是定义好的,我们直接用就行,我一直失败的原因,我怀疑是因为我的环境是没有外网的,所以本地卷就此打住吧。不折腾这个了。
设置默认值的行为
-
可以在群集上启用动态卷供应,以便在未指定存储类的情况下动态设置所有声明。 集群管理员可以通过以下方式启用此行为:
- 标记一个 StorageClass 为 默认;
- 确保 DefaultStorageClass 准入控制器在 API 服务端被启用。
-
管理员可以通过向其添加 storageclass.kubernetes.io/is-default-class 注解来将特定的 StorageClass 标记为默认。 当集群中存在默认的 StorageClass 并且用户创建了一个未指定 storageClassName 的 PersistentVolumeClaim 时, DefaultStorageClass 准入控制器会自动向其中添加指向默认存储类的 storageClassName 字段。
-
请注意,群集上最多只能有一个 默认 存储类,否则无法创建没有明确指定 storageClassName 的 PersistentVolumeClaim。
拓扑感知
在多区域集群中,Pod 可以被分散到多个区域。 单区域存储后端应该被供应到 Pod 被调度到的区域。 这可以通过设置卷绑定模式来实现。
使用aws 的ebs 作为pv 的后端存储
因为这个是系统自带的,所以我们不需要做分配器了,直接定义sc即可。
创建sc
[root@master volume]# cat ebs.yaml
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: ebs
provisioner: kubernetes.io/aws-ebs
parameters:
type: io1
iopsPerGB: "10"
fsType: ext4
[root@master volume]# kubectl apply -f ebs.yaml
storageclass.storage.k8s.io/ebs created
[root@master volume]#
[root@master volume]# kubectl get sc
NAME PROVISIONER RECLAIMPOLICY VOLUMEBINDINGMODE ALLOWVOLUMEEXPANSION AGE
ebs kubernetes.io/aws-ebs Delete Immediate false 7s
fast kubernetes.io/gce-pd Delete Immediate false 19m
mysc fuseim.pri/ifs Delete Immediate false 6h36m
slow kubernetes.io/gce-pd Delete Immediate false 24m
[root@master volume]#
创建pvc
[root@master volume]# cat pvauto2.yaml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: autopv2
#annotations:
#volume.beta.kubernetes.io/storage-class: "ebs"
spec:
accessModes:
- ReadWriteOnce
volumeMode: Filesystem
resources:
requests:
storage: 300Mi
storageClassName: ebs
[root@master volume]#
[root@master volume]# kubectl apply -f pvauto2.yaml
persistentvolumeclaim/autopv2 created
[root@master volume]#
[root@master volume]# kubectl get pvc
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE
autopv2 Pending ebs 3s
claim1 Pending fast 21m
[root@master volume]#
pending报错原因查看
[root@master volume]# kubectl describe pvc autopv2
Name: autopv2
Namespace: volume
StorageClass: ebs
Status: Pending
Volume:
Labels: <none>
Annotations: volume.beta.kubernetes.io/storage-provisioner: kubernetes.io/aws-ebs
Finalizers: [kubernetes.io/pvc-protection]
Capacity:
Access Modes:
VolumeMode: Filesystem
Used By: <none>
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Warning ProvisioningFailed 6s (x5 over 58s) persistentvolume-controller Failed to provision volume with StorageClass "ebs": Failed to get AWS Cloud Provider. GetCloudProvider returned <nil> instead
[root@master volume]#
上面报错翻译过来就是:persistentvolume controller无法使用StorageClass“ebs”配置卷:无法获取AWS云提供程序。GetCloudProvider返回了
说明
-
总结,还是因为没有外网,另外,还有一个问题,就是,使用这种自带的分配器,需要考虑账户问题,不知道这个是不是一定条件【或许上面官网的方法也缺这一步账号呢?,但官网没提到过账号这个问题啊,也不知道是不是只要通外网就行了】
-
使用aws的话,得要有自己的账户
可以把aws的账户密码存放在一个secret里,在创建sc的时候,里面指定这个secret。这样才能连接到你的aws账户里去 -
上面的内容是请教的大佬,我没实验过,你可以自己尝试一下哦。【因为我没有通外网的集群,就不折腾了】
更多推荐
所有评论(0)