之前的文章中我们介绍了在k8s中hostPath的使用场景及用法,接下来我们来学习了解k8s中另外一种pv的使用场景及配置方法,首先hostPath相较于Local PV在真实的使用场景中存在一定的局限。
Pod不能随便漂移,需要固定到一个节点上,因为一旦漂移到其他节点的宿主机上就没有对应的数据了,所以在使用hostPath的时候会搭配使用nodeSelector来使用。
使用hostPath的这些节点一旦宕机,数据可能丢失。
好处是hostPath使用的是本地磁盘,读写性能相较于大多数存储来说要好的多。
所以在hostPath的基础上,Kubernetes依靠PV、PVC实现了一个新特性:Local Persistent Volume.
其实Local PV实现的功能非常类似于hostPath加上节点亲和性nodeAffinity,同时Local PV和普通的PV有一个很大的不同在于Local PV可以保证pod始终能够被正确的调度到它所请求的Local PV所在的节点上面。但值得注意的是:
对于普通的PV来说,Kubernetes都是先调度pod到某个节点上,然后再持久化节点上的Volume目录,进而完成Volume目录与容器的绑定挂载。
对于Local
PV来说,节点上可供使用的磁盘必事先准备好,因为它们在不同节点上的挂载情况可能不同,有的节点可能没这种磁盘,所以,这时候,调度器就必须能够知道所有节点与
Local PV 对应的磁盘的关联关系,然后根据这个信息来调度Pod,实际上就是在调度podde 的时候先考虑 Volume的分布情况。
如果文章对您有帮助,还想了解更过关于k8s相关的实战经验,请微信关注“IT运维图谱”公众号或着通过微信搜一搜关注公众号。
下面我们通过创建一个普通的pv和pvc来进行演示:
# cat pv-local.yml
apiVersion: v1
kind: PersistentVolume
metadata:
name: pv-local
spec :
capacity:
storage: 2Gi
volumeMode: Filesystem
accessModes:
- ReadWriteOnce
persistentVolumeReclaimPolicy: Delete
storageClassName: local-storage
local:
path: /data/localpv # k8s-node-03节点上的目录
nodeAffinity:
required:
nodeSelectorTerms:
- matchExpressions:
- key: kubernetes.io/hostname
operator: In
values :
- k8s-node-03
# cat pvc-local.yml
kind: PersistentVolumeClaim
apiVersion: v1
metadata:
name: pvc-local
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 2Gi
storageClassName: local-storage #指定sc,集群中没有这个sc不影响pvc与pv的绑定
使用kubectl创建上面的资源对象:
[root@k8s-master-01 Loacl-pv]# kubectl apply -f .
persistentvolume/pv-local created
persistentvolumeclaim/pvc-local created
[root@k8s-master-01 Loacl-pv]#
[root@k8s-master-01 Loacl-pv]#
[root@k8s-master-01 Loacl-pv]# kubectl get pv,pvc
NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE
persistentvolume/pv-local 2Gi RWO Delete Bound default/pvc-local local-storage 7s
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE
persistentvolumeclaim/pvc-local Bound pv-local 2Gi RWO local-storage 7s
可以看到现在PVC 和 PV 已经处于Bound 绑定状态了。但这不符合我们的需求的,比如现在我们的 Pod声明使用这个pvc-local,并且我们也明确规定这个 Pod 只能运行在 k8s-node-01这个节点上,如果按照上面我们这里的操作,这个pvc-Local就和pv-Local就绑定在一起了,但是这 PV的存储卷又在k8s-node-03 这节点上,显然就会pod和pv就存在冲突了,那么这个Pod的调度就会败,处于pinding状态。
我们编写一个nginx的pod部署清单进行验证:
# cat hostpath-nginx-pod.yaml
apiVersion: v1
kind: Pod
metadata:
name: hostpath-nginx-pod
labels:
app: hostpath-nginx-pod
spec:
volumes:
- name: pv-hostpath
persistentVolumeClaim:
claimName: pvc-local # 声明要使用的pvc
nodeSelector:
kubernetes.io/hostname: k8s-node-01 指定只能运行在k8s-node-01节点上
containers:
- name: nginx-pod
image: nginx:1.7.5
imagePullPolicy: IfNotPresent
ports:
- containerPort: 80
volumeMounts:
- mountPath: "/usr/share/nginx/html"
name: pv-hostpath
使用kubectl创建上面的pod部署清单并查看pod状态:
[root@k8s-master-01 Loacl-pv]# kubectl apply -f hostpath-nginx-pod.yaml
pod/hostpath-nginx-pod created
[root@k8s-master-01 Loacl-pv]# kubectl get pod -l app=hostpath-nginx-pod
NAME READY STATUS RESTARTS AGE
hostpath-nginx-pod 0/1 Pending 0 6s
可以看到pod处于pinding状态,使用describe查看pod事件信息提示:Warning FailedScheduling 3m20s default-scheduler 0/4 nodes are available: 1 node(s) didn’t match Pod’s node affinity/selector. preemption: 0/4 nodes are available: 1 Preemption is not helpful for scheduling, 3 No preemption victims found for incoming pod。
查看pod事件信息,提示没有可供调度的节点。
所以我们在使用LocaL PV 的时候,得想办法延迟这个绑定操作。
我们先删除上面创建的资源对象,然后可以通过创建 Storageclass来指定这个动作,在StorageClass中有一个volumeBindingMode=WaitForFirstConsumer 的属性,告诉 kubernetes 在发现这个StorageClass 关联的 PVC 与PV 可以绑定在一起时,不要立刻执行绑定操作,而是等到有声明使用该PVC 的 Pod 出现在调度器之后,调度器再综合考虑所有的调度规则,当然也包括每个 PV所在的节点位置,来统一决定这个Pod 声明的 PVC应该跟哪个 PV进行绑定。通过这个延迟绑定机制,原本实时发生的 PVC和PV的绑定过程,就被延迟到了 Pod第一次调度的时候在调度器中进行,从而保证了这个绑定结果不会影响Pod 的正常调度。
# cat local-sc.yml
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: local-storage
provisioner: kubernetes.io/no-provisioner
volumeBindingMode: WaitForFirstConsumer #延迟绑定参数,很重要
创建上面的sc清单,定义一个具备延迟绑定功能的sc
[root@k8s-master-01 Loacl-pv]# kubectl apply -f local-sc.yml
storageclass.storage.k8s.io/local-storage created
[root@k8s-master-01 Loacl-pv]#
[root@k8s-master-01 Loacl-pv]#
[root@k8s-master-01 Loacl-pv]#
[root@k8s-master-01 Loacl-pv]# kubectl get sc
NAME PROVISIONER RECLAIMPOLICY VOLUMEBINDINGMODE ALLOWVOLUMEEXPANSION AGE
csi-cephfs-sc (default) cephfs.csi.ceph.com Delete Immediate true 19d
csi-rbd-sc rbd.csi.ceph.com Delete Immediate true 19d
local-storage kubernetes.io/no-provisioner Delete WaitForFirstConsumer false 8s
现在apply上面的pv和pvc资源清单,并查看pv与pvc的绑定状态
[root@k8s-master-01 Loacl-pv]# kubectl apply -f .
persistentvolume/pv-local created
persistentvolumeclaim/pvc-local created
[root@k8s-master-01 Loacl-pv]# kubectl get pv,pvc
NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE
persistentvolume/pv-local 2Gi RWO Delete Available local-storage 5s
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE
persistentvolumeclaim/pvc-local Pending local-storage 5s
可以看到pv处于Available状态,pvc处于Pending状态,也就是等待绑定的状态,这就是因为上面我们配置的是延迟绑定,需要在有Pod 使用的时候才会来做绑定。
接下来我们创建一个测试的pod来进行验证
[root@k8s-master-01 Loacl-pv]# kubectl apply -f pod-demo.yaml
pod/pod-demo created
[root@k8s-master-01 Loacl-pv]# kubectl get pod -l app=pod-demo
NAME READY STATUS RESTARTS AGE
pod-demo 1/1 Running 0 12s
[root@k8s-master-01 Loacl-pv]# kubectl get pv,pvc
NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE
persistentvolume/pv-local 2Gi RWO Delete Bound default/pvc-local local-storage 10m
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE
persistentvolumeclaim/pvc-local Bound pv-local 2Gi RWO local-storage 10m
可以看到之前处于Pending状态的pvc和处于Available状态的pv都处于Bound状态了,并且pod也处于Running状态了。
我们可以进入pod中,手动生成一个测试的index.html文件,并访问测试页面
[root@k8s-master-01 Loacl-pv]# kubectl get pod -owide -l app=pod-demo
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
pod-demo 1/1 Running 0 14m 10.244.3.51 k8s-node-03 <none> <none>
# 进入容器常见测试页面
[root@k8s-master-01 Loacl-pv]# kubectl exec -it pod-demo -- bash
root@pod-demo:/# echo "Hello,this is a test pod for Loacl PV" > /usr/share/nginx/html/index.html
root@pod-demo:/#exit
# 在master节点上访问测试
[root@k8s-master-01 Loacl-pv]# curl 10.244.3.51
Hello,this is a test pod for Loacl PV
登录k8s-node-03节点,查看/data/localpv目录下面持久化下来的文件
[root@k8s-node-03 ~]# ll /data/localpv/index.html
-rw-r--r-- 1 root root 38 Jun 27 19:24 /data/localpv/index.html
[root@k8s-node-03 ~]# cat /data/localpv/index.html
Hello,this is a test pod for Loacl PV
通过上面的文字介绍加实践,相信大家已经对k8s中Local PV 资源对象有了全新的认识。
如果文章对您有帮助,还想了解更过关于k8s相关的实战经验,请微信关注“IT运维图谱”公众号或着通过微信搜一搜关注公众号。