Pod挂载LocalStoragePv过程理解

 1处的控制循环Control Loop应该是:VolumeManagerReconciler

-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

Local Persistent Volume: 利用pv&pvc这种松耦合机制来实现直接使用宿主机上的本地磁盘目录,而不依赖于远程存储服务,来提供“持久化”的容器 Volume

设计lpv过程需要考虑的两个问题:

1. 如何把本地磁盘抽象成 PV(一个 PV 一块盘):pv对应的目录所挂载的磁盘不应该是宿主机根目录使用的硬盘,因为一旦pv不使用独立的磁盘,将会变成完全不可控,比如磁盘很容易被其他进程应用写满,甚至造成整个宿主机宕机。而且同一个磁盘的不同的目录之间也缺乏最基础的 I/O 隔离机制.

2.  Pod 能被正确地调度到lpv 对应节点上(延迟绑定):常规的pv记录的是与节点无关的远程共享存储,而lpv则与某些节点关联在一起.

考虑这样的场景:

假设我的集群中有3个节点,分别是node1、node2、node3,其中node1和node2具有diskType=ssd的标签,且node1和node2已经使用独立的磁盘挂载到/mnt/disks/volA目录,node3使用独立的磁盘挂载到/mnt/disks/volB目录

假设我的集群已经创建好了两个pv,分别是pvA和pvB

pvA.yaml如下。字段nodeAffinity表明想要使用这个pv的pod只能被调度到带diskType=ssd标签的节点上,也就是node1、node2

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
apiVersion: v1
kind: PersistentVolume
metadata:
  name: example-pvA
spec:
  capacity:
    storage: 1Gi
  volumeMode: Filesystem
  accessModes:
  - ReadWriteOnce
  local: #local字段表明这是一个Local Persistent Volume的pv
    path: /mnt/disks/volA
  nodeAffinity:
    required:
      nodeSelectorTerms:
      - matchExpressions:
        - key: diskType
          operator: In
          values:
          - ssd

 pvB.yaml如下。字段nodeAffinity表明想要使用这个pv的pod只能被调度到带node3

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
apiVersion: v1
kind: PersistentVolume
metadata:
  name: example-pvB
spec:
  capacity:
    storage: 1Gi
  volumeMode: Filesystem
  accessModes:
  - ReadWriteOnce
  local: local字段表明这是一个Local Persistent Volume的pv
    path: /mnt/disks/volB
  nodeAffinity:
    required:
      nodeSelectorTerms:
      - matchExpressions:
        - key: kubernetes.io/hostname
          operator: In
          values:
          - node3

 

pvc.yaml文件如下

1
2
3
4
5
6
7
8
9
10
11
kind: PersistentVolumeClaim
apiVersion: v1
metadata:
  name: example-local-claim
spec:
  accessModes:
  - ReadWriteOnce
  resources:
    requests:
      storage: 1Gi
  storageClassName: local-storage

 

创建一个pod声明使用example-local-claim这个pvc,如果按照常规pv的处理模式来说,当pvc一旦创建,就会被volumeController的PersistentVolumeController控制循环检测到,并尝试寻找合适的pv进行绑定。Kubernetes将先调度 Pod 到某个节点上,然后,根据pv上定义的信息,通过“两阶段处理”来“持久化”这台机器上的 Volume 目录,进而完成 Volume 目录与容器的绑定挂载(将一个目录挂载到挂载点目录,而不是将一个设备挂载到挂载点目录)。在lpv上就不能通过这种方式处理了,因为如果pvc一经创建就选择一个pv绑定,在上面的例子中,如果pvc和pvB绑定,那么使用这个pvc的pod也就被限制在node3节点,如果pod这边又通过NodeAffinity节点亲和性或nodeSelector强制pod调度到节点node2,此时就会出现冲突,这个pod也就会一直pending了。

k8s的lpv是通过pvc和pv的延迟绑定来解决这个冲突的:创建一个storageClass,配置volumeBindingMode为WaitForFirstConsumer,且在pvA和pvB中声明使用这个storageClass

1
2
3
4
5
6
kind: StorageClass
apiVersion: storage.k8s.io/v1
metadata:
  name: local-storage
provisioner: kubernetes.io/no-provisioner
volumeBindingMode: WaitForFirstConsumer

 WaitForFirstConsumer表示第一个使用这个pvc的pod在调度过程中才决策合适的pv进行绑定。这样一来,k8s就可以综合考虑pod对Node的要求和pv对Node的要求,最终pvc选择和pvA进行绑定。

参考资料:

当前k8s支持的存储插件:https://kubernetes.io/docs/concepts/storage/persistent-volumes/#types-of-persistent-volumes

posted @   JL_Zhou  阅读(1674)  评论(0编辑  收藏  举报
编辑推荐:
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
点击右上角即可分享
微信分享提示