本文分享自华为云社区《当创建一个pvc后,kubernetes会发生什么?》,作者:可以交个朋友。

一、背景

外部存储接入 Kubernetes 的方式主要有两种:In-Tree 和 Out-of-Tree:

  • In-Tree 是指存储驱动的源码都在 Kubernetes 代码库中,与 Kubernetes 一起发布、迭代、管理,这种方式灵活性较差,且门槛较高。
  • Out-of-Tree 是指存储插件由第三方编写、发布、管理,作为一种扩展与 Kubernetes 配合使用。Out-of-Tree 主要有 FlexVolume 和 CSI 两种实现方式,其中,FlexVolume 因为其命令式的特点,不易维护和管理,从 Kubernetes v1.23 版本开始已被弃用。因此 CSI 已经成为 Kubernetes 存储扩展( Out-of-Tree )的唯一方式。

外部存储最终的效果是将存储(磁盘、obs、nas盘等)挂载到容器中被业务使用,所以一般包括存在两个过程:

  • attach 是将存储介质在指定虚拟机上绑盘,部分存储介质才需要attach操作,比如容器中使用块存储,大致流程是1)需要先调用openstack接口,将某块evs绑到某个虚拟机上,成为虚拟机设备;2)在将存储设备挂载到容器目录上
  • mount 将某个存储挂载到对应文件系统上,是操作系统层面的行为,所有的存储介质挂载到容器中都需要mount阶段,比如容器中使用nas或者obs,本质上就是执行nfs命令将网络存储挂载到容器目录上

二、CSI 架构解读

kubernetes CSI存储插件的关键组件与推荐的容器化部署架构

三、动态创建 Volume 执行过程

以块类型存储为例,从声明pvc到pod挂载卷成功时序图:

1、涉及组件解读

  • PV Controller:负责处理集群中的pvc/pv对象,对pvc/pv对象进行状态转换,并根据需求进行数据卷的 Provision/Delete 操作(注:Static pv不会触发provisioner、Dynamic pv才会触发provisioner)

  • AD Controller:负责VolumeAttachement的生命周期管理,并通过external-attacher将设备挂载到目标节点或从目标节点卸载。VolumeAttachement是控制块存储设备的 Attach/Detach 操作的逻辑对象。(注:可通过kubelet配置文件开关控制节点是否由AD Controller管理)。

  • kubelet主要包含与存储相关的两个插件::1)Volume Manager:管理存储卷的 Mount/Unmount 操作、卷设备的格式化等操作(注:如果当前节点并没有交给AD Controller管理,那么就是volumeManager负责管理VolumeAttachement的生命周期);2)Volume Plugin:K8S平台为存储提供商提供存储接入的插件接口,其中包含in-tree的多种存储插件和out-tree的两种存储插件。通过该插件机制进而为容器应用提供各种类型的存储。社区推荐的是CSI架构的扩展插件

2、涉及资源解读

PV:PersistentVolume,集群级别的资源,由集群管理员 or External Provisioner创建。PV 的生命周期独立于使用 PV 的 Pod,PV 的 .Spec 中保存了存储设备的详细信息。

kind: PersistentVolume
apiVersion: v1
metadata:
name: pv-test
labels:
failure-domain.beta.kubernetes.io/region: cn-north-4
failure-domain.beta.kubernetes.io/zone: cn-north-4a
annotations:
pv.kubernetes.io/provisioned-by: xxxx-provisioner #存储提供者
spec:
capacity:
storage: 10Gi
csi:
driver: disk.csi.everest.io
volumeHandle: 698a99d8-xxx-xxxx-xxxx-ab80b1ecbf #使用的存储设备信息
volumeAttributes:
everest.io/disk-mode: SCSI
everest.io/disk-volume-type: ESSD
storage.kubernetes.io/csiProvisionerIdentity: xxxx-provisioner
accessModes:
- ReadWriteOnce
# 引用对象, 该pv由哪个pvc创建
claimRef:
kind: PersistentVolumeClaim
namespace: test
name: pvc-test
uid: xxxx-xxxx-xxxx-22bf9101f0ce
apiVersion: v1
persistentVolumeReclaimPolicy: Delete
storageClassName: csi-disk
volumeMode: Filesystem
nodeAffinity:
required:
nodeSelectorTerms:
- matchExpressions:
- key: failure-domain.beta.kubernetes.io/zone
operator: In
values:
- cn-north-4a
status:
phase: Bound
# available : 表示当前的pv没有被绑定
# bound: 已经被pvc挂载
# released: pvc没有在使用pv, 需要管理员手工释放pv
# failed: 资源回收失败
  • PVC:PersistentVolumeClaim,命名空间(namespace)级别的资源,由用户 or StatefulSet 控制器(根据VolumeClaimTemplate)创建。PVC 类似于 Pod,Pod 消耗 Node 资源,PVC 消耗 PV 资源。Pod 可以请求特定级别的资源(CPU 和内存),而 PVC 可以请求特定存储卷的大小及访问模式(Access Mode)。

kind: PersistentVolumeClaim
apiVersion: v1
metadata:
name: pvc-evs-test
namespace: test
uid: xxxx-xxxx-xxxx-22bf9101f0ce
labels:
failure-domain.beta.kubernetes.io/region: cn-north-4
failure-domain.beta.kubernetes.io/zone: cn-north-4a
annotations:
volume.kubernetes.io/selected-node: xxx.xxx.xxx.186
everest.io/disk-volume-type: ESSD
volume.kubernetes.io/storage-provisioner: xxxx-provisioner
spec:
# ReadWriteOnce:被单个节点mount为读写rw模式
# ReadOnlyMany 被多个节点mount为只读ro模式
# ReadWriteMany 被多个节点mount为读写rw模式
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 10Gi
volumeName: pv-test #绑定的pv name
# 使用的sc类型
storageClassName: csi-disk
# 存储模式,包含Filesystem(文件系统)和Block(块设备)
volumeMode: Filesystem
status:
# Pending:pvc刚创建还未与pv绑定
# Bound: pvc与pv完成绑定
# Lost:对应的pv被删除
phase: Bound
accessModes:
- ReadWriteOnce
  • SC:StorageClass 是集群级别的资源,由集群管理员创建。SC 为管理员提供了一种动态提供存储卷的“类”模板,SC 中的 .Spec 中详细定义了存储卷 PV 的不同服务质量级别、备份策略等等。

apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: csi-disk
parameters:
csi.storage.k8s.io/csi-driver-name: disk.csi.everest.io
csi.storage.k8s.io/fstype: ext4
everest.io/disk-volume-type: SATA
everest.io/passthrough: "true"
provisioner: xxxx-provisioner
# 回收策略, pvc和pv解绑,删除了pvc, pv里面的数据是否还保留
# Retain: 保留数据, 需要手工删除
# delete: pv删除
reclaimPolicy: Delete
# Immediate: pv创建好之后立马将pvc和pv进行绑定
# WaitForFirstConsumer: 延迟绑定,直到使用pvc的pod被调度到节点上
volumeBindingMode: Immediate
allowVolumeExpansion: true #是否允许扩容

3、涉及 CSI API 对象

CSINode

  • 判断外部 CSI 插件是否注册成功。在 Node Driver Registrar 组件向 Kubelet 注册完毕后,Kubelet 会创建该资源,故不需要显式创建 CSINode 资源
  • 将 Kubernetes 中 Node 资源名称与三方存储系统中节点名称(nodeID)一一对应。此处 Kubelet 会调用外部 CSI 插件 NodeServer 的 GetNodeInfo 函数获取 nodeID。
  • 显示卷拓扑信息。CSINode 中 topologyKeys 用来表示存储节点的拓扑信息,卷拓扑信息会使得 Scheduler 在 Pod 调度时选择合适的存储节点。
apiVersion: storage.k8s.io/v1
kind: CSINode
metadata:
annotations:
everest.io/node.localvolume.capacity: "null"
name: xxx.xxx.xxx.186
ownerReferences:
- apiVersion: v1
kind: Node
name: xxx.xxx.xxx.186
uid: 091cc415-b8bb-4173-8312-5f6318d4383f
uid: fea2c180-99b8-4195-a966-3953b8bab16a
spec:
# 节点上有哪些driver
drivers:
- allocatable:
count: 58
name: disk.csi.everest.io
nodeID: 7d279bf8-c70f-4179-842e-5e501d591d17
topologyKeys:
- failure-domain.beta.kubernetes.io/zone
- name: proxy.csi.everest.io
nodeID: 7d279bf8-c70f-4179-842e-5e501d591d17
topologyKeys: null
- name: sfsturbo.csi.everest.io
nodeID: 7d279bf8-c70f-4179-842e-5e501d591d17
topologyKeys: null
- name: nas.csi.everest.io
nodeID: 7d279bf8-c70f-4179-842e-5e501d591d17
topologyKeys: null
...
apiVersion: storage.k8s.io/v1
kind: CSINode
metadata:
annotations:
everest.io/node.localvolume.capacity: "null"
name: xxx.xxx.xxx.186
ownerReferences:
- apiVersion: v1
kind: Node
name: xxx.xxx.xxx.186
uid: 091cc415-b8bb-4173-8312-5f6318d4383f
uid: fea2c180-99b8-4195-a966-3953b8bab16a
spec:
# 节点上有哪些driver
drivers:
- allocatable:
count: 58
name: disk.csi.everest.io
nodeID: 7d279bf8-c70f-4179-842e-5e501d591d17
topologyKeys:
- failure-domain.beta.kubernetes.io/zone
- name: proxy.csi.everest.io
nodeID: 7d279bf8-c70f-4179-842e-5e501d591d17
topologyKeys: null
- name: sfsturbo.csi.everest.io
nodeID: 7d279bf8-c70f-4179-842e-5e501d591d17
topologyKeys: null
- name: nas.csi.everest.io
nodeID: 7d279bf8-c70f-4179-842e-5e501d591d17
topologyKeys: null
...

CSIDriver

  • 简化外部 CSI 插件的发现。由集群管理员创建,通过 kubectl get csidriver 即可得知环境上有哪些 CSI 插件。
  • 自定义Kubernetes 行为,如一些外部 CSI 插件不需要执行卷挂接(VolumeAttach)操作,则可以设置 .spec.attachRequired 为 false。
apiVersion: storage.k8s.io/v1
kind: CSIDriver
metadata:
name: disk.csi.everest.io
uid: 5d33a29b-4bf1-4ab8-815f-e97b207b991e
spec:
# 是否需要attache和mount,只有evs需要attach
attachRequired: true
podInfoOnMount: true
requiresRepublish: false
storageCapacity: false
volumeLifecycleModes:
- Persistent #volume生命周期,持久模式

VolumeAttachment

AD Controller 创建一个 VolumeAttachment,而 External-attacher 则通过观察该 VolumeAttachment,根据其状态属性来进行存储的挂载和卸载操作。

apiVersion: storage.k8s.io/v1
kind: VolumeAttachment
metadata:
annotations:
csi.alpha.kubernetes.io/node-id: xxxx-xxxx-xxxx-5e501d591d17
finalizers:
- everest-csi-attacher/disk-csi-everest-io
name: csi-d10b9f7e4dde469fa2b7f3461fcfef7862260883196647d6b7ae7bb17bc0e226
uid: 665b740f-a544-4f3e-9953-00b8d186c548
spec:
attacher: disk.csi.everest.io
nodeName:xxx.xxx.xxx.186
source:
persistentVolumeName: pv-test
status:
# 标记是否attached到节点上,attache后才能mount
attached: true
attachmentMetadata: #attach的设备信息
bus: scsi
device: /dev/sdg

四、存储拓展-延迟绑定

kubernetes里面有两个绑定:

  • kube-schedule将pod和node绑定
  • Pvc controller将pvc和pv绑定。正常情况下,kube-schedule绑定pod和node时候,如果pod有pvc,会等待pvc和pv绑定完成后根据pv所在的az选择node过滤一部分不满足节点,然后再完成绑定pod和node。延迟绑定场景,kube-schedule 先不等待PVC和PV绑定,先预调度node,然后把预调度结果写到PVC注解中,pvc控制接获取到预调度az信息后,再完成pv创建和pv绑定。所以,延迟绑定时延迟了pvc和pv绑定阶段。

stroageclass延迟绑定作用字段:VolumeBindingMode

  • Immediate :表示一旦创建了 PersistentVolumeClaim 也就完成了卷绑定和动态制备(不参与调度)。 对于由于拓扑限制而非集群所有节点可达的存储后端,PersistentVolume 会在不知道 Pod 调度要求的情况下绑定或者制备。
  • WaitForFirstConsumer :该模式将延迟 PersistentVolume 的绑定和制备,直到使用该 PersistentVolumeClaim 的 Pod 被创建。 PersistentVolume 会根据 Pod 调度约束指定的拓扑来选择或制备。 这些包括但不限于资源需求、 节点筛选器、 Pod 亲和性和互斥性、 以及污点和容忍度。

点击关注,第一时间了解华为云新鲜技术~

当创建pvc后,kubernetes组件如何协作的更多相关文章

  1. kubernetes组件

    kubernetes组件 @(马克飞象)[k8s] 组件 kubernetes除了必备的dns和网络组件外,官方推出大量的cluster-monitoring,dashboard,fluentd-el ...

  2. centos7下kubernetes(4.kubernetes组件)

    Kubenetes cluster 由master和node组成 Master是kubenetes的大脑.运行着以下进程:kube-apiserver.kube-scheduler.kube-cont ...

  3. Kubernetes组件与架构

    转载请标明出处: 文章首发于>https://www.fangzhipeng.com/kubernetes/2018/09/30/k8s-basic1/ 本文出自方志朋的博客 Kubernete ...

  4. 使用 C# 开发 Kubernetes 组件,获取集群资源信息

    写什么呢 前段时间使用 C# 写了个项目,使用 Kubernetes API Server,获取信息以及监控 Kubernetes 资源,然后结合 Neting 做 API 网关. 体验地址 http ...

  5. C#创建和使用ActiveX组件

    开发基于.Net平台上的程序员是很难从本质上把Visual C#和ActiveX组件联起来,虽然在使用Visual C#开发应用程序时,有时为了快速开发或者由于.Net FrameWork SDK的不 ...

  6. 多对多三种创建方式、forms组件、cookies与session

    多对多三种创建方式.forms组件.cookies与session 一.多对多三种创建方式 1.全自动 # 优势:不需要你手动创建第三张表 # 不足:由于第三张表不是你手动创建的,也就意味着第三张表字 ...

  7. Vue环境搭建-项目的创建-启动生命周期-组件的封装及应用

    vue项目环境的搭建 """ node >>> python:node是用c++编写用来运行js代码的 npm(cnpm) >>> p ...

  8. Kubernetes【K8S】(一):Kubernetes组件

    什么是Kubernetes ​ Kubernetes 是一个可移植的.可扩展的开源平台,用于管理容器化的工作负载和服务,可促进声明式配置和自动化.Kubernetes拥有一个庞大且快速增长的生态系统. ...

  9. 构建Docker平台【第三篇】安装 kubernetes 组件

    第一步:准备 1. 安装包: kubeadm-1.6.0-0.alpha.0.2074.a092d8e0f95f52.x86_64.rpm kubernetes-cni-0.3.0.1-0.07a8a ...

  10. 宝塔控制面板创建ftp后链接不上的解决方法

    很多的新手在安装宝塔面板并且创建完ftp管理后链接ftp居然链接不上?有许多朋友都不知道本站q302博客也是基于宝塔控制面板管理的,本站在安装网站完成后也和你们一样ftp链接不上,后面经过多次测试之后 ...

随机推荐

  1. 从零用VitePress搭建博客教程(3) - VitePress页脚、标题logo、最后更新时间等相关细节配置

    接上一节:从零用VitePress搭建博客教程(2) –VitePress默认首页和头部导航.左侧导航配置 五.默认主题相关细节配置 关于默认主题的标题,logo.页脚,最后更新时间等相关细节配置,我 ...

  2. 【NOI 2023 春测】 游寄

    3.2 发出发通知单:9:40 3.3 旷操,把背包扔到 \(\texttt{JF}\) 底下,和 Kaguya 一起去吃早饭. 在桥下面被老班抓到了() 我用椅子给 apj 搭了一张床. Apj 给 ...

  3. List 切割成小 list 分批处理数据

    使用 Google Guava 库中的方法对 bmList 进行分割. Lists.partition() 方法用于将一个列表按指定大小进行分割,返回一个包含分割后子列表的新列表. 在这个例子中,bm ...

  4. VMPFC可以融合既有的片段信息来模拟出将来的情感场景

    Ventromedial prefrontal cortex supports affective future simulation by integrating distributed knowl ...

  5. 推荐一个Node.js多版本管理的可视化工具

    关于Node.js的开发者来说,在开发机器上管理多个不同版本的Node.js是一个常见痛点.之前在开发者安全大全专栏中,提到过解决方法:使用nvm,如果对于nvm还不了解的话,可以前往了解. 对于TJ ...

  6. JavaSE面试题01:自增变量

    JavaSE面试题:自增变量 来源:https://runwsh.com/ 代码 public static void main(String[] args) { int i=1; i=i++; in ...

  7. 微信小程序敏感内容检测

    获取access_token access_token是公众号的全局唯一接口调用凭据,公众号调用各接口时都需使用access_token.开发者需要进行妥善保存.access_token的存储至少要保 ...

  8. 【luogu题解】T378828 位运算

    位运算 题目背景 题目由 daiyulong20120222 创作(me) 并由 QBW1117完善以及数据 . 题目描述 给定两个数\(x,y\) ,在给定一个位运算符号 \(c\). 请你列出 \ ...

  9. 时间复杂度为 O(nlogn) 的排序算法

    归并排序 归并排序遵循分治的思想:将原问题分解为几个规模较小但类似于原问题的子问题,递归地求解这些子问题,然后合并这些子问题的解来建立原问题的解,归并排序的步骤如下: 划分:分解待排序的 n 个元素的 ...

  10. python中面向对象有什么特点

    一:问题 python中面向对象有什么特点? 二:回答 python同其他面向对象语言一样,有3个特征:封装.继承.重写 简单理解就是:封装:把一系列属性和操作封装到一个方法里面,这样想要实现某种效果 ...