关系
生命周期相关概念
2.1 静态构建:集群管理员创建若干PV卷。这些卷对象带有真实存储的细节信息,并且对集群用户可用(可见)。PV卷对象存在于Kubernetes API中,可供用户消费使用。
2.2动态构建:如果集群中已经有的PV无法满足PVC的需求,那么集群会根据PVC自动构建一个PV,该操作是通过Storageclass 实现的。想要实现这个操作,前提是PVC必须设置StorageClass,否则会无法动态构建该PV,可以通过启用DefaultstorageClass来实现PV的构建。
2.3 绑定:当用户创建一个 PVC对象后,主节点会监测新的 PVC对象,并且寻找与之匹配的PV卷,找到PV卷后将二者绑定在一起。如果找不到对应的PV,则需要看PVC是否设置StqrageClass来决定是否动态创建PV,若没有配置,PVC就会—致处于未绑定状态,直到有与之匹配的PV后才会申领绑定关系。
2.4 使用:Pod 将PVC当作存储卷来使用,集群会通过PVC找到绑定的PV,并为Pod挂载该卷。Pod 一旦使用PVC绑定PV后,为了保护数据,避免数据丢失问题,PV对象会受到保护,在系统中无法被删除。
2.5 回收策略:当用户不再使用其存储卷时,他们可以从API中将PVC对象删除,从而允许该资源被回收再利用。Persistentvolume对象的回收策略告诉集群,当其被从申领中释放时如何处理该数据卷。目前,数据卷可以被 Retained(保留)、Recyced(回收)或Deleted(删除)。
2.6 保留:回收策略Retain 使得用户可以手动回收资源。当Persistentvolumeclaim对象被删除时,Persistentvolume卷仍然存在,对应的数据卷被视为"已释放(released) "。由于卷上仍然存在这前一申领人的数据,该卷还不能用于其他申领。管理员可以通过下面的步骤来手动回收该卷:
1)删除 Persistentvolume对象。与之相关的、位于外部基础设施中的存储资产(如AWS EBS、GCE PD、Azure Disk或 Cinder卷)在PV删除之后仍然存在。
2)根据情况,手动清除所关联的存储资产上的数据。
3)手动删除所关联的存储资产。如果你希望重用该存储资产,可以基于存储资产的定义创建新的Persistentvolume卷对象。
4)删除:对于支持Delete回收策略的插件,删除动作会将Persistentvolume对象从Kubernetes中移除,同时也会从外部基础设施(如AwS EBS、GCE PD、Azure Disk 或 Cinder卷)中移除所关联的存储资产。动态制备的卷会继承基StorageClass中设置的回收策略,该策略默认为Delete。管理员需要根据用户的期望来配置StorageClass;否则PV卷被创建之后必须要被编辑或者修补。
5)回收:动态制备。如果下层卷插件支持,回收策略Recycle会在卷上执行一些基本的擦除(rm -rf /thevolume/*)操作,之后允许该卷用于新的PVC申领。
生命周期相关概念
Available:空闲,未被绑定
Bound:已经被PVC绑定
Released : PVC被册删除,资源已回收,俚是PV未被重新使用
Failed:自动回收失败
创建pv文件:vi /opt/pv.yaml
apiVersion: v1
kind: PersistentVolume #描述资源对象为PV类型
metadata:
name : pv0001 #PV的名字
spec:
capacity: #容量配置
storage: 5Gi # pv的容量
volumeMode: Filesystem #存储类型为文件系统
accessModes: #访问模式:ReadWriteOnce、ReadWriteMany、ReadOnlyMany
- ReadWriteMany #可被单节点独写
persistentVolumeReclaimPolicy: Retain #回收策略
storageClassName: sc0001 # 创建PV的存储类名,需要与 pvc 的相同
mountOptions: #加载配置l
- hard #使用硬挂载方式
- nfsvers=4.1 #使用NFSv4.1版本
nfs: #连接到nfs
path: /root/data/nfs #存储路径
server: 192.168.248.11 # nfs服务地址
创建资源:kubectl apply -f /opt/pv.yaml
查看: kubectl get pv
查看详情:kubectl describe pv pv0001
创建pvc文件:vi /opt/pvc.yaml
apiVersion: v1
kind: PersistentVolumeClaim #资源类型为 PVC
metadata:
name: pvc0001
spec:
accessModes:
- ReadWriteMany #权限需要与对应的pv相同
volumeMode: Filesystem
resources:
requests:
storage: 5Gi #资源可以小于 pv 的,但是不能大于,如果大于就会匹配不到 pv
storageClassName: sc0001 #名字需要与对应的pv相同
创建资源:kubectl apply -f /opt/pvc.yaml
查看:kubectl get pvc
查看详情:kubectl describe pvc pvc0001
创建pod:vi /opt/testpvc.yaml
apiVersion: v1
kind : Pod
metadata:
name: test-pvc-pd
spec:
containers:
- image: nginx
name: nginx-volume
volumeMounts:
- mountPath: /usr/share/nginx/html #挂载到容器的哪个目录
name: test-volume #挂载哪个volume
volumes:
- name: test-volume
persistentVolumeClaim:
claimName: pvc0001 #要关联到哪个pvc
创建资源:kubectl apply -f /opt/testpvc.yaml
进入:vi /root/data/nfs/index.html
111
进入pod并且查看
kubectl exec -it test-pvc-pd sh
cd /usr/share/nginx/html
cat index.html
什么是StorageClass
StorageClass又称为PV动态供给,是k8s1.4之后引入的一个新资源,StorageClass主要实现了存储卷PV按需创建,动态创建,当Pod需要使用PVC时,StorageClass会自动创建一个PV,并与PVC进行绑定,相比于传统的PV、PVC,管理员不再需要创建PV,PV由StorageClass自动创建。
1.PV的属性。比如,存储类型,Volume的大小等。
2.创建这种PV需要用到的存储插件,即存储制备器。有了这两个信息之后,Kubernetes就能够根据用户提交的PVC,找到一个对应的StorageClass,之后Kubernetes就会调用该StorageClass声明的存储插件,进而创建出需要的PV。
为什么需要StorageClass
传统的PV和PVC属于静态的,静态的PV和PVC都需要运维手动来创建,如果有很多个Pod需要同时使用PVC,而一个PV只能挂载到一个Pod中,这时运维的工作量将会很大。
而且不同的应用程序对于存储性能的要求可能也不尽相同,比如读写速度、并发性能等,为了解决这一问题,Kubernetes 又为我们引入了一个新的资源对象:StorageClass,通过 StorageClass 的定义,管理员可以将存储资源定义为某种类型的资源,比如快速存储、慢速存储等,用户根据 StorageClass 的描述就可以非常直观的知道各种存储资源的具体特性了,这样就可以根据应用的特性去申请合适的存储资源了。
运行原理
要使用 StorageClass,我们就得安装对应的自动配置程序,比如我们这里存储后端使用的是 nfs,那么我们就需要使用到一个 nfs-client 的自动配置程序,我们也叫它 Provisioner(制备器),这个程序使用我们已经配置好的 nfs 服务器,来自动创建持久卷,也就是自动帮我们创建 PV。
1. 自动创建的 PV 以${namespace}-${pvcName}-${pvName}这样的命名格式创建在 NFS 服务器上的共享数据目录中
2. 而当这个 PV 被回收后会以archieved-${namespace}-${pvcName}-${pvName}这样的命名格式存在 NFS 服务器上。
逻辑图
实操StorageClass步骤
1.创建nfs-client-provisioner程序的rbac授权角色账号,以及角色,然后将账户与rbac账号进行绑定,使nfs-client-provisioner对pv、pvc有增删改查权限
2.创建制备器nfs-client-provisioner,同时指定操作用户为前面创建的rbac授权角色账号
3.创建StorageClass存储类并且指定外部制备器,自动创建PV时,就将PV存储到了nfs-client对应的nfs存储上
4.创建一个pod,并且指向StorageClass存储类,验证是否能自动创建PV
编写账号权限创建脚本:vi /opt/nfs-provisioner-rbac.yaml
ps:定义了一个 ServiceAccount
,然后定义了两个 ClusterRole
,在分别在ClusterRoleBinding中进行绑定
apiVersion: v1
kind: ServiceAccount
metadata:
name: nfs-client-provisioner
namespace: kube-system
---
kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: nfs-client-provisioner-runner
namespace: kube-system
rules:
- 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
namespace: kube-system
subjects:
- kind: ServiceAccount
name: nfs-client-provisioner
namespace: kube-system
roleRef:
kind: ClusterRole
name: nfs-client-provisioner-runner
apiGroup: rbac.authorization.k8s.io
---
kind: Role
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: leader-locking-nfs-client-provisioner
namespace: kube-system
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
namespace: kube-system
subjects:
- kind: ServiceAccount
name: nfs-client-provisioner
roleRef:
kind: Role
name: leader-locking-nfs-client-provisioner
apiGroup: rbac.authorization.k8s.io
创建资源:kubectl apply -f /opt/nfs-provisioner-rbac.yaml
编写制备器创建脚本:vi /opt/sc-nfs-storage.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: nfs-client-provisioner
namespace: kube-system
labels:
app: nfs-client-provisioner
spec:
replicas: 1
strategy:
type: Recreate
selector:
matchLabels:
app: nfs-client-provisioner
template:
metadata:
labels:
app: nfs-client-provisioner
spec:
serviceAccountName: nfs-client-provisioner
containers:
- name: nfs-client-provisioner
image: registry.cn-beijing.aliyuncs.com/pylixm/nfs-subdir-external-provisioner:v4.0.0
volumeMounts:
- name: nfs-client-root
mountPath: /persistentvolumes
env:
- name: PROVISIONER_NAME
value: fuseim.pri/ifs
- name: NFS_SERVER
value: 192.168.248.10
- name: NFS_PATH
value: /root/data/nfs
volumes:
- name: nfs-client-root
nfs:
server: 192.168.248.10
path: /root/data/nfs
创建资源:kubectl apply -f /opt/sc-nfs-storage.yaml
编写StorageClass创建脚本:vi /opt/storageClass.yaml
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: managed-nfs-storage
provisioner: fuseim.pri/ifs #外部制备器提供者,编写为提供者的名称
parameters:
archiveOnDelete: "false" #是否存档,false 表示不存档,会删除 oldPath下面的数据,true 表示存档,会重命名路径
reclaimPolicy: Retain #回收策略,默认为Delete可以配置为 Retain I
volumeBindingMode: Immediate #默认为Imediate,表示创建PVC立即进行绑定,只有 azuredisk和AuSelasticblockstore支持其他值
创建资源:kubectl apply -f /opt/storageClass.yaml
编写nginx应用创建脚本:vi /opt/sc-nginx.yaml
---
apiVersion: v1
kind: Service
metadata:
name: nginx-sc
labels:
app: nginx-sc
spec:
type: NodePort
ports:
- name: web
port: 80
protocol: TCP
selector:
app: nginx-sc
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: nginx-sc
spec:
replicas: 1
serviceName: "nginx-sc"
selector:
matchLabels:
app: nginx-sc
template:
metadata:
labels:
app: nginx-sc
spec:
containers:
- image: nginx
name: nginx-sc
imagePullPolicy: IfNotPresent
volumeMounts:
- mountPath: /usr/share/nginx/html
name: nginx-sc-test-pvc
volumeClaimTemplates:
- metadata:
name: nginx-sc-test-pvc
spec:
storageClassName: managed-nfs-storage
accessModes:
- ReadWriteMany
resources:
requests:
storage: 1Gi
创建资源:kubectl apply -f /opt/sc-nginx.yaml
查看:kubectl get pvc
kubectl get pv
ps:如果失败可以查看日志kubectl logs nfs-client-provisioner-6db49949bf-txqvl -n kube-system
也可以手动创建pvc,同时将storageClassName指向当前StorageClass,即第三大点的yaml的storageClassName属性