• 更新 PVC 的 .Status.Conditions,表明此时处于 Resizing 状态。

  • 通过特定的 Unix Domain Socket 调用外部 CSI 插件ControllerExpandVolume 接口

  • 更新 PV 的 .Spec.Capacity。

  • 若 CSI 支持文件系统在线扩容,ControllerExpandVolume 接口返回值中 NodeExpansionRequired 字段为 true,External-Resizer更新 PVC 的 .Status.Conditions 为 FileSystemResizePending 状态;若不支持则扩容成功,External-Resizer更新 PVC 的 .Status.Conditions 为空,且更新 PVC 的 .Status.Capacity。

Volume Manager(Kubelet 组件)观察到存储卷需在线扩容,于是通过特定的 Unix Domain Socket 调用外部 CSI 插件的NodeExpandVolume 接口实现文件系统扩容。

[](()5. livenessprobe


[](()1)功能

检查 CSI 插件是否正常。

[](()2)原理

通过对外暴露一个 / healthz HTTP 端口以服务 kubelet 的探针探测器,内部是通过特定的 Unix Domain Socket 调用外部 CSI 插件Probe 接口

[](()CSI 接口介绍

=============================================================================

三方存储厂商需实现 CSI 插件的三大接口:IdentityServer、ControllerServer、NodeServer

[](()1. IdentityServer


IdentityServer 主要用于认证 CSI 插件的身份信息。

// IdentityServer is the server API for Identity service.

type IdentityServer interface {

// 获取CSI插件的信息,比如名称、版本号

GetPluginInfo(context.Context, *GetPluginInfoRequest) (*GetPluginInfoResponse, error)

// 获取CSI插件提供的能力,比如是否提供ControllerService能力

GetPluginCapabilities(context.Context, *GetPluginCapabilitiesRequest) (*GetPluginCapabilitiesResponse, error)

// 获取CSI插件健康状况

Probe(context.Context, *ProbeRequest) (*ProbeResponse, error)

}

[](()2. ControllerServer


ControllerServer 主要负责存储卷及快照的创建/删除以及挂接/摘除操作。

// ControllerServer is the server API for Controller service.

type ControllerServer interface {

// 创建存储卷

CreateVolume(context.Context, *CreateVolumeRequest) (*CreateVolumeResponse, error)

// 删除存储卷

DeleteVolume(context.Context, *DeleteVolumeRequest) (*DeleteVolumeResponse, error)

// 挂接存储卷到特定节点

ControllerPublishVolume(context.Context, *ControllerPublishVolumeRequest) (*ControllerPublishVolumeResponse, error)

// 从特定节点摘除存储卷

ControllerUnpublishVolume(context.Context, *ControllerUnpublishVolumeRequest) (*ControllerUnpublishVolumeResponse, error)

// 验证存储卷能力是否满足要求,比如是否支持跨节点多读多写

ValidateVolumeCapabilities(context.Context, *ValidateVolumeCapabilitiesRequest) (*ValidateVolumeCapabilitiesResponse, error)

// 列举全部存储卷信息

ListVolumes(context.Context, *ListVolumesRequest) (*ListVolumesResponse, error)

// 获取存储资源池可用空间大小

GetCapacity(context.Context, *GetCapacityRequest) (*GetCapacityResponse, error)

// 获取ControllerServer支持功能点,比如是否支持快照能力

ControllerGetCapabilities(context.Context, *ControllerGetCapabilitiesRequest) (*ControllerGetCapabilitiesResponse, error)

// 创建快照

CreateSnapshot(context.Context, *CreateSnapshotRequest) (*CreateSnapshotResponse, error)

// 删除快照

DeleteSnapshot(context.Context, *DeleteSnapshotRequest) (*DeleteSnapshotResponse, error)

// 获取所有快照信息

ListSnapshots(context.Context, *ListSnapshotsRequest) (*ListSnapshotsResponse, error)

// 扩容存储卷

ControllerExpandVolume(context.Context, *ControllerExpandVolumeRequest) (*ControllerExpandVolumeResponse, error)

}

[](()3. NodeServer


NodeServer 主要负责存储卷挂载/卸载操作。

// NodeServer is the server API for Node service.

type NodeServer interface {

// 将存储卷格式化并挂载至临时全局目录

NodeStageVolume(context.Context, *NodeStageVolumeRequest) (*NodeStageVolumeResponse, error)

// 将存储卷从临时全局目录卸载

NodeUnstageVolume(context.Context, *NodeUnstageVolumeRequest) (*NodeUnstageVolumeResponse, error)

// 将存储卷从临时目录bind-mount到目标目录

NodePublishVolume(context.Context, *NodePublishVolumeRequest) (*NodePublishVolumeResponse, error)

// 将存储卷从目标目录卸载

NodeUnpublishVolume(context.Context, *NodeUnpublishVolumeRequest) (*NodeUnpublishVolumeResponse, error)

// 获取存储卷的容量信息

NodeGetVolumeStats(context.Context, *NodeGetVolumeStatsRequest) (*NodeGetVolumeStatsResponse, error)

// 存储卷扩容

NodeExpandVolume(context.Context, *NodeExpandVolumeRequest) (*NodeExpandVolumeResponse, error)

// 获取NodeServer支持功能点,比如是否支持获取存储卷容量信息

NodeGetCapabilities(context.Context, *NodeGetCapabilitiesRequest) (*NodeGetCapabilitiesResponse, error)

// 获取CSI节点信息,比如最大支持卷个数

NodeGetInfo(context.Context, *NodeGetInfoRequest) (*NodeGetInfoResponse, error)

}

[](()K8s CSI API 对象

===================================================================================

K8s 为支持 CSI 标准,包含如下 API 对象:

  • CSINode

  • CSIDriver

  • VolumeAttachment

[](()1. CSINode


apiVersion: storage.k8s.io/v1beta1

kind: CSINode

metadata:

name: node-10.212.101.210

spec:

drivers:

  • name: yodaplugin.csi.alibabacloud.com

nodeID: node-10.212.101.210

topologyKeys:

  • kubernetes.io/hostname

  • name: pangu.csi.alibabacloud.com

nodeID: a5441fd9013042ee8104a674e4a9666a

topologyKeys:

  • topology.pangu.csi.alibabacloud.com/zone

作用:

  1. 判断外部 CSI 插件是否注册成功。在 Node Driver Registrar 组件向 Kubelet 注册完毕后,Kubelet 会创建该资源,故不需要显式创建 CSINode 资源。

  2. 将 Kubernetes 中 Node 资源名称与三方存储系统中节点名称(nodeID)一一对应。此处Kubelet会调用外部 CSI 插件NodeServer 的 GetNodeInfo 函数获取 nodeID。

  3. 显示卷拓扑信息。CSINode 中 topologyKeys 用来表示存储节点的拓扑信息,卷拓扑信息会使得Scheduler在 Pod 调度时选择合适的存储节点。

[](()2. CSIDriver


apiVersion: storage.k8s.io/v1beta1

kind: CSIDriver

metadata:

name: pangu.csi.alibabacloud.com

spec:

插件是否支持卷挂接(VolumeAttach)

attachRequired: true

Mount阶段是否CSI插件需要Pod信息

podInfoOnMount: true

指定CSI支持的卷模式

volumeLifecycleModes:

  • Persistent

作用:

  1. 简化外部 CSI 插件的发现。由集群管理员创建,通过 kubectl get csidriver 即可得知环境上有哪些 CSI 插件。

  2. 自定 义Kubernetes 行为,如一些外部 CSI 插件不需要执行卷挂接(VolumeAttach)操作,则可以设置 .spec.attachRequired 为 false。

[](()3. VolumeAttachment


apiVersion: storage.k8s.io/v1

kind: VolumeAttachment

metadata:

annotations:

csi.alpha.kubernetes.io/node-id: 21481ae252a2457f9abcb86a3d02ba05

finalizers:

  • external-attacher/pangu-csi-alibabacloud-com

name: csi-0996e5e9459e1ccc1b3a7aba07df4ef7301c8e283d99eabc1b69626b119ce750

spec:

attacher: pangu.csi.alibabacloud.com

nodeName: node-10.212.101.241

source:

persistentVolumeName: pangu-39aa24e7-8877-11eb-b02f-021234350de1

status:

attached: true

作用:VolumeAttachment 记录了存储卷的挂接/摘除信息以及节点信息。

[](()支持特性

=========================================================================

[](()1. 拓扑支持


在 StorageClass 中有 AllowedTopologies 字段:

apiVersion: storage.k8s.io/v1

kind: StorageClass

metadata:

name: csi-pangu

provisioner: pangu.csi.alibabacloud.com

parameters:

type: cloud_ssd

volumeBindingMode: Immediate

allowedTopologies:

  • matchLabelExpressions:

  • key: topology.pangu.csi.alibabacloud.com/zone

values:

  • zone-1

  • zone-2

外部 CSI 插件部署后会为每个节点打标,打标内容NodeGetInfo 函数返回的 [AccessibleTopology] 值(详见 Node Driver Registrar 部分)。

External Provisioner在调用 CSI 插件的 CreateVolume 接口之前,会在请求参数设置 AccessibilityRequirements:

  • 对于 WaitForFirstConsumer

  • 当 PVC 的 anno 中包含 “volume.kubernetes.io/selected-node” 且不为空,则先获取对应节点 CSINode 的 TopologyKeys,然后根据该 TopologyKeys 键从 Node 资源的 Label 获取 Values 值,最后拿该 Values 值与 StorageClass 的 AllowedTopologies 比对,判断其是否包含于其中;若不包含则报错。

  • 对于 Immediately

  • 将 StorageClass 的 AllowedTopologies 的值填进来,若 《一线大厂Java面试题解析+后端开发学习笔记+最新架构讲解视频+实战项目源码讲义》无偿开源 威信搜索公众号【编程进阶路】 StorageClass 没有设置 AllowedTopologies 则将所有包含 TopologyKeys 键的节点 Value 添进来。

[](()Scheduler 如何处理使用存储卷调度

基于社区 1.18 版本调度器

调度器的调度过程主要有如下三步:

  • 预选(Filter):筛选满足 Pod 调度要求的节点列表。

  • 优选(Score):通过内部的优选算法为节点打分,获得最高分数的节点即为选中的节点。

  • 绑定(Bind):调度器将调度结果通知给 kube-apiserver,更新 Pod 的 .spec.nodeName 字段。

调度器预选阶段:处理 Pod 的 PVC/PV 绑定关系以及动态供应 PV(Dynamic Provisioning),同时使调度器调度时考虑 Pod 所使用 PV 的节点亲和性。详细调度过程如下:

  1. Pod 不包含 PVC 直接跳过。

  2. FindPodVolumes

  • 获取 Pod 的 boundClaims、claimsToBind 以及 unboundClaimsImmediate。

  • boundClaims:已 Bound 的 PVC

  • claimsToBind:PVC 对应 StorageClass 的 VolumeBindingMode 为 VolumeBindingWaitForFirstConsumer

  • unboundClaimsImmediate:PVC 对应 StorageClass 的 VolumeBindingMode 为 VolumeBindingImmediate

  • 若 len(unboundClaimsImmediate) 不为空,表示这种 PVC 需要立即绑定 PV(即存 PVC 创建后,立刻动态创建 PV 并将其绑定到 PVC,该过程不走调度),若 PVC 处于 unbound 阶段则报错。

  • 若 len(boundClaims) 不为空,则检查 PVC 对应 PV 的节点亲和性与当前节点的 Label 是否冲突,若冲突则报错(可检查 Immediate 类型的 PV 拓扑)。

  • 若 len(claimsToBind) 不为空

  • 先检查环境中已有的 PV 能否与该 PVC 匹配(findMatchingVolumes),将能够匹配 PVC 的 PV 记录在调度器的 cache 中。

  • 未匹配到 PV 的 PVC 走动态调度流程,动态调度主要通过 StorageClass 的 AllowedTopologies 字段判断当前调度节点是否满足拓扑要求(针对 WaitForFirstConsumer 类型的 PVC)。

调度器优选阶段不讨论。

调度器 Assume 阶段

调度器会先 Assume PV/PVC,再 Assume Pod。

  1. 将当前待调度的 Pod 进行深拷贝。

  2. AssumePodVolumes(针对 WaitForFirstConsumer 类型的 PVC)

  • 更改调度器 cache 中已经 Match 的 PV 信息:设置 annotation:pv.kubernetes.io/bound-by-controller=“yes”。

  • 更改调度器 cache 中未匹配到 PV 的 PVC,设置 annotation:volume.kubernetes.io/selected-node=【所选节点】。

  1. Assume Pod 完毕
  • 更改调度器 cache 中 Pod 的 .Spec.NodeName 为【所选节点】。

调度器 Bind 阶段

BindPodVolumes:

  • 调用 Kubernetes 的 API 更新集群中 PV/PVC 资源,使其与调度器 Cache 中的 PV/PVC 一致。

  • 检查 PV/PVC 状态:

  • 检查所有 PVC 是否已处于 Bound 状态。

  • 检查所有 PV 的 NodeAffinity 是否与节点 Label 冲突。

  • 调度器执行 Bind 操作:调用 Kubernetes 的 API 更新 Pod 的 .Spec.NodeName 字段。

[](()2. 存储卷扩容


存储卷扩容部分在 External Resizer 部分已提到,故不再赘述。用户只需要编辑 PVC 的 .Spec.Resources.Requests.Storage 字段即可,注意只可扩容不可缩容。

若 PV 扩容失败,此时 PVC 无法重新编辑 spec 字段的 storage 为原来的值(只可扩容不可缩容)。参考 K8s 官网提供的 PVC 还原方法:

https://kubernetes.io/docs/concepts/storage/persistent-volumes/#recovering-from-failure-when-expanding-volumes

[](()3. 单节点卷数量限制


卷数量限制在 Node Driver Registrar 部分已提到,故不再赘述。

[](()4. 存储卷监控


存储商需实现 CSI 插件的 NodeGetVolumeStats 接口,Kubelet 会调用该函数,并反映在其 metrics上:

  • kubelet_volume_stats_capacity_bytes:存储卷容量

  • kubelet_volume_stats_used_bytes:存储卷已使用容量

  • kubelet_volume_stats_available_bytes:存储卷可使用容量

  • kubelet_volume_stats_inodes:存储卷 inode 总量

  • kubelet_volume_stats_inodes_used:存储卷 inode 使用量

  • kubelet_volume_stats_inodes_free:存储卷 inode 剩余量

[](()5. Secret


CSI 存储卷支持传入 Secret 来处理不同流程中所需要的私密数据,目前 StorageClass 支持如下 Parameter:

  • csi.storage.k8s.io/provisioner-secret-name

  • csi.storage.k8s.io/provisioner-secret-namespace

  • csi.storage.k8s.io/controller-publish-secret-name

  • csi.storage.k8s.io/controller-publish-secret-namespace

  • csi.storage.k8s.io/node-stage-secret-name

  • csi.storage.k8s.io/node-stage-secret-namespace

  • csi.storage.k8s.io/node-publish-secret-name

  • csi.storage.k8s.io/node-publish-secret-namespace

  • csi.storage.k8s.io/controller-expand-secret-name

  • csi.storage.k8s.io/controller-expand-secret-namespace

Secret 会包含在对应 CSI 接口的参数中,如对于 CreateVolume 接口而言则包含在 CreateVolumeRequest.Secrets 中。

[](()6. 块设备


apiVersion: apps/v1

kind: StatefulSet

metadata:

name: nginx-example

spec:

selector:

matchLabels:

app: nginx

serviceName: “nginx”

volumeClaimTemplates:

  • metadata:

name: html

spec:

accessModes:

  • ReadWriteOnce

volumeMode: Block

storageClassName: csi-pangu

resources:

requests:

storage: 40Gi

template:

metadata:

labels:

app: nginx

spec:

containers:

一文读懂容器存储接口 CSI相关推荐

  1. 容器存储接口 CSI学习

    一 CSI 概述 K8s持久化存储经历了从 in-tree Volume 到CSI Plugin(out-of-tree)的迁移,一方面是为了将k8s的核心主干代码与Volume相关代码解耦,便于更好 ...

  2. 认识K8s容器存储接口CSI

    容器存储接口(Container Storage Interface),简称 CSI,CSI试图建立一个行业标准接口的规范,借助CSI容器编排系统(CO)可以将任意存储系统暴露给自己的容器工作负载. ...

  3. 一文读懂浏览器存储与缓存机制

    浏览器存储 Cookie Cookie 是 HTTP 协议的一种无状态协议.当请求服务器时,HTTP 请求都需要携带 Cookie,用来验证用户身份.Cookie 由服务端生成,存储在客户端,用来维持 ...

  4. 云原生的基石,一文读懂容器、Docker、Pod到底是什么!

    作者 | Aholiab 责编 | Carol 出品 | CSDN(ID:CSDNnews) 封图|CSDN下载自视觉中国 云原生(Cloud Native),是2013年由Pivotal公司率先提出 ...

  5. 云原生的基石,一文读懂容器、Docker、Pod到底是什么

    课程概要 云原生(Cloud Native),是2013年由Pivotal公司率先提出的概念.云原生以容器化.微服务.可持续交付性,帮助企业构建和运行可弹性扩展的应用.由于云原生应用构建简便快捷,部署 ...

  6. 一文读懂 K8s 持久化存储流程

    作者 | 孙志恒(惠志)  阿里巴巴开发工程师 **导读:**众所周知,K8s 的持久化存储(Persistent Storage)保证了应用数据独立于应用生命周期而存在,但其内部实现却少有人提及.K ...

  7. Kubernetes 1.13 版本发布:Kubeadm简化群集管理、容器存储接口(CSI)和CoreDNS作为默认DNS现已普遍可用

    Kubernetes 1.13 版本发布 Kubeadm简化群集管理.容器存储接口(CSI)和CoreDNS作为默认DNS现已普遍可用 我们很高兴地宣布推出Kubernetes 1.13,这是我们20 ...

  8. 一文读懂HDMI和VGA接口针脚定义

    一文读懂HDMI和VGA接口针脚定义 摘自:http://www.elecfans.com/yuanqijian/jiekou/20180423666604.html   HDMI概述 HDMI是高清 ...

  9. 一文读懂Java中File类、字节流、字符流、转换流

    一文读懂Java中File类.字节流.字符流.转换流 第一章 递归:File类: 1.1:概述 java.io.File 类是文件和目录路径名的抽象表示,主要用于文件和目录的创建.查找和删除等操作. ...

最新文章

  1. netstat -ano 查看机器端口占用情况
  2. oracle em 按钮乱码解决办法
  3. fastd java下载_配置 FastDFS Java 客户端
  4. SpringCloud学习笔记(十)----服务熔断与限流 Sentinel
  5. python字典的常用方法_python操作字典类型的常用方法(推荐)
  6. Asp.Net MVC 身份验证-Forms
  7. MySQL安装配置+Navicat安装配置
  8. 会玩儿!网易云音乐推出“还郑州一个七夕”特别策划
  9. ipmitool 远程操作BMC控制服务器
  10. 每天吃多少才不会胖?食物和卡路里对照表
  11. Linux EXPORT_SYMBOL宏详解
  12. 不可不读的百句良言!!
  13. 27.FastAPI应用生产环境部署
  14. ctf编码,解密总结
  15. WireShark教程 – 黑客发现之旅(5) – (nmap)扫描探测
  16. 行人重识别模型搭建与训练
  17. From Microservices to Data Microservices-pivotal-专题视频课程
  18. 元宇宙的新鲜度,终归离不开一个“玩”字
  19. 兄弟hl4150cdn感叹号5_打印质量问题解决方法
  20. 中级网络工程师——第一章计算机组成与原理

热门文章

  1. “打农药”都不省心:勒索病毒冒充王者荣耀外挂
  2. vue如何使用滴滴的cube-ui组件
  3. 计算机科学与技术和机械类,机械科学与技术杂志
  4. 三步解决mybatis-plus逻辑删除
  5. poc weblogic 漏洞利用_Weblogic 漏洞利用总结
  6. 电脑死机(蓝屏)的时候,到底是怎么回事?
  7. 基于一种交互式的光伏组件特性曲线算法(Matlab代码实现)
  8. 物联网毕设 -- 智能宠物投喂器(图传+APP+ESP32-CAN)
  9. SWERC13 Trending Topic
  10. Mapbar 地图 API 实例