存储相关概念PV、PVC、StorageClass?
PV: 描述持久化存储数据卷(存储类型、挂载目录、远程存储服务器地址等)
PVC: 描述Pod希望使用的持久化存储的属性(存储大小、读写权限等)
StorageClass: 创建PV的模板,包含两方面内容:PV的属性(存储类型、大小等);创建PV的存储插件信息(例如ceph)
PVC
与PV
是如何进行绑定的?
- spec字段:PV的存储大小必须满足PVC的要求;
- StorageClass: PV与PVC的StorageClass字段必须一样;
VolumeController有哪些功能?
- PersistentVolumeController: 不断监听每个PVC,如果未绑定pv,则遍历所有可用PV与未绑定的PVC进行绑定(所谓绑定,就是将PV对象的名字填在PVC.spec.volumeName字段上)
- AttachDetachController: 不断检查每个Pod对应的
PV
,与Pod所在虚拟机的挂载情况,从而对PV执行Attach\Detach操作。 - VolumeManagerReconciler: 运行在每个节点,但独立于kubelet主循环外的Goroutine。
容器挂载持久化存储的两阶段处理
- 第一阶段:Attach。pod调度到节点上,当前节点的kubelet会根据Volume类型为pod创建Volume,如果是远程块存储,kubelet会调用存储接口创建远程磁盘并挂载到当前节点(
/dev/sdb
)。 - 第二阶段,Mount。kubelet格式化挂载的磁盘,并此磁盘挂载到宿主机的容器目录(
/var/lib/kubelet/pods/<podID>/volumes
)。
NFS较为简单,Attach的操作跳过(对于NFS来说,并无
磁盘
挂载虚拟机)
之后,kubelet将volume目录通过CRI中的Mounts参数传递给容器运行时(如,docker),就可以为Pod里的容器挂载持久化存储了。
删除PV时,需要执行什么操作?
- Unmount
- Detach
StorageClass存在的意义
手动创建维护PV的工作太庞杂,因此K8S提供了自动创建PV的机制Dynamic Provisioning
机制。而StorageClass
就是其工作机制的核心。
- 充当PV的模板,且只有StorageClass相同的PV与PVC才能绑定在一起;
- 指定PV的存储插件(Provisioner),当存储插件支持
Dynamic Provisioning
机制时,实现PV的自动创建。
LocalPath模式如何避免pv与pvc的绑定过程与Pod的调度过程冲突?
在StorageClass的定义时,声明属性volumeBindingMode=WaitForFirstConsumer
(延迟绑定),即pv与pvc的绑定延迟到pod调度之后,这样就不会与pod的调度策略冲突。
延迟绑定为什么与Dynamic Provisioning
机制冲突?
因为Dynamic Provisioning
机制会调用pvc指定的sc中的provisioner自动创建pv,一旦pv创建则固定node
K8S存储方案的演进过程是?
Volume Plugins:k8s早期版本中
Volume Plugins
是用于提供持久化存储的主要方式,由K8S核心团队维护。
缺点:新的存储类型、功能很难被引入和部署。FlexVolume: K8S-v1.8引入的一种存储插件扩展方式。外部插件以二进制文件与配置,并实现一定接口(init\attach\detach\waitforattach\isattached\mountdevice\unmountdevice\mount\unmount),kubelet通过插件在宿主机上执行接口命令。(FlexVolume仅仅是两阶段的执行者,无法管理pv的生命周期)
缺点:1. 不支持DynamicProvisioning; 2. FlexVolume每一次对插件可执行文件的调用是独立的,mount时的上下文无法在unmount时复用。CSI:设计思想,**把Dynamic Provision,以及 Kubernetes 里 的一部分存储管理功能,从主干代码里剥离出来,做成了几个单独的组件。**这些组件会监听API-Server与存储相关的变化,来执行具体的存储管理动作。这些管理动作(如arrach\mount阶段)实际是通过调用csi插件完成。
External Components(由K8S社区维护): K8S项目中剥离的存储管理功能;
- Driver Register: 负责将插件注册到kubelet
- External Provisioner: 监听PVC对象,当PVC创建时调用CSI Controller的CreateVolume方法创建PV(公有云则调用公有云的API,)完成Provision阶段;
- External Attacher: 监听VolumeAttechment对象,当其创建时调用CSI Controller的ControllerPublish方法,完成对应volume的Attach阶段;
以上三个组件会作为sidecar的形式与CSI插件位于同一个Pod中
Custom Components(CSI插件):
- CSI Identity:对外暴露插件本身的信息
- CSI Controller(Master节点): 定义对 CSI Volume(对应 Kubernetes 里的 PV)的管理接口(Create\Delete\Attach\Detach\Snapshot等),调用它的服务是
- CSI Node(Node节点):是由Kubelet的VolumeManagerReconciler 控制循环检测,并调用CSI Node的Mount完成磁盘格式化、挂载指定目录(Mount阶段)。
FlexVolume | Attach(挂载虚拟机)、Mount(格式化、挂载至宿主机目录) | |
CSI | Provision(创建磁盘)、Attach 和 Mount |
Docker与K8S有哪几种存储类型?
Docker容器有:
BindMount: 外部宿主机的磁盘存储到内部容器存储的映射关系。即存储位置局限在宿主机,存储介质只是物理磁盘,存储管理只有映射关系。
VolumeMount:
K8S容器编排存储:
- 普通Volume: 只用来提供共享的存储资源,声明周期与Pod相同
- PV: 生命周期与pod无关
Kubelet主循环
kubelet 主控制循环(Kubelet Sync Loop)
设计原则:主控制循环绝对不可以被 block。