存储
卷
1、Container 中的文件在磁盘上是临时存放的,这给 Container 中运行的较重要的应用程序带来一些问题
(1)当容器崩溃时文件丢失,kubelet 会重新启动容器,但容器会以干净的状态重启
(2)第二个问题会在同一 Pod 中运行多个容器并共享文件时出现
(3)Kubernetes 卷(Volume)这一抽象概念能够解决这两个问题
2、Docker 也有卷(Volume) 的概念,但对它只有少量且松散的管理
(1)Docker 卷是磁盘上或者另外一个容器内的一个目录
(2)Docker 提供卷驱动程序,但是其功能非常有限
3、Kubernetes 支持很多类型的卷,Pod 可以同时使用任意数目的卷类型
(1)临时卷类型的生命周期与 Pod 相同,但持久卷可以比 Pod 的存活期长
(2)当 Pod 不再存在时,Kubernetes 也会销毁临时卷,不过 Kubernetes 不会销毁持久卷
(3)对于给定 Pod 中任何类型的卷,在容器重启期间数据都不会丢失
4、卷的核心是一个目录,其中可能存有数据,Pod 中的容器可以访问该目录中的数据
(1)所采用的特定的卷类型将决定该目录如何形成的、使用何种介质保存数据以及目录中存放的内容
(2)使用卷时, 在 .spec.volumes 字段中设置为 Pod 提供的卷,并在 .spec.containers[*].volumeMounts 字段中声明卷在容器中的挂载位置
(3)容器中的进程看到的文件系统视图,是由它们的容器镜像的初始内容,以及挂载在容器中的卷(如果定义了的话)所组成的,其中根文件系统同容器镜像的内容相吻合,任何在该文件系统下的写入操作,如果被允许的话,都会影响接下来容器中进程访问文件系统时所看到的内容
(4)卷挂载在镜像中的指定路径下,Pod 配置中的每个容器必须独立指定各个卷的挂载位置
(5)卷不能挂载到其他卷之上(不过存在一种使用 subPath 的相关机制),也不能与其他卷有硬链接
emptyDir
1、当 Pod 分派到某个节点上时,emptyDir 卷会被创建
(1)在 Pod 在该节点上运行期间,卷一直存在
(2)卷最初是空的
(3)尽管 Pod 中的容器挂载 emptyDir 卷的路径可能相同也可能不同,这些容器都可以读写 emptyDir 卷中相同的文件
(4)当 Pod 因为某些原因被从节点上删除时,emptyDir 卷中的数据也会被永久删除
(5)容器崩溃并不会导致 Pod 被从节点上移除,因此容器崩溃期间 emptyDir 卷中的数据是安全的
2、emptyDir 的一些用途
(1)缓存空间,例如基于磁盘的归并排序
(2)为耗时较长的计算任务提供检查点,以便任务能方便地从崩溃前状态恢复执行
(3)在 Web 服务器容器服务数据时,保存内容管理器容器获取的文件
3、emptyDir.medium 字段用来控制 emptyDir 卷的存储位置
(1)默认情况下,emptyDir 卷存储在该节点所使用的介质上; 此处的介质可以是磁盘、SSD 或网络存储,这取决于你的环境
(2)你可以将 emptyDir.medium 字段设置为 "Memory", 以告诉 Kubernetes 为你挂载 tmpfs(基于 RAM 的文件系统)
(3)虽然 tmpfs 速度非常快,但是要注意它与磁盘不同:tmpfs 在节点重启时会被清除,并且你所写入的所有文件都会计入容器的内存消耗,受容器内存限制约束
4、你可以通过为默认介质指定大小限制,来限制 emptyDir 卷的存储容量
(1)此存储是从节点临时存储中分配的
(2)如果来自其他来源(如日志文件或镜像分层数据)的数据占满了存储,emptyDir 可能会在达到此限制之前发生存储容量不足的问题
(3)当启用 SizeMemoryBackedVolumes 特性门控时,你可以为基于内存提供的卷指定大小,如果未指定大小,则基于内存的卷的大小为 Linux 主机上内存的 50%
hostPath
1、hostPath 卷能将主机节点文件系统上的文件或目录挂载到你的 Pod 中
(1)HostPath 卷存在许多安全风险,最佳做法是尽可能避免使用 HostPath
(2)当必须使用 HostPath 卷时,它的范围应仅限于所需的文件或目录,并以只读方式挂载
(3)如果通过 AdmissionPolicy 限制 HostPath 对特定目录的访问,则必须要求 volumeMounts 使用 readOnly 挂载以使策略生效
2、hostPath 的一些用法
(1)运行一个需要访问 Docker 内部机制的容器;可使用 hostPath 挂载 /var/lib/docker 路径
(2)在容器中运行 cAdvisor 时,以 hostPath 方式挂载 /sys
(3)允许 Pod 指定给定的 hostPath 在运行 Pod 之前是否应该存在,是否应该创建以及应该以什么方式存在
3、除了必需的 path 属性之外,你可以选择性地为 hostPath 卷指定 type
取值 | 行为 |
---|---|
空字符串(默认)用于向后兼容,这意味着在安装 hostPath 卷之前不会执行任何检查。 | |
DirectoryOrCreate | 如果在给定路径上什么都不存在,那么将根据需要创建空目录,权限设置为 0755,具有与 kubelet 相同的组和属主信息。 |
Directory | 在给定路径上必须存在的目录。 |
FileOrCreate | 如果在给定路径上什么都不存在,那么将在那里根据需要创建空文件,权限设置为 0644,具有与 kubelet 相同的组和所有权。 |
File | 在给定路径上必须存在的文件。 |
Socket | 在给定路径上必须存在的 UNIX 套接字。 |
CharDevice | 在给定路径上必须存在的字符设备。 |
BlockDevice | 在给定路径上必须存在的块设备。 |
4、谨慎使用这种类型的卷的原因
(1)HostPath 卷可能会暴露特权系统凭据(例如 Kubelet)或特权 API(例如容器运行时套接字),可用于容器逃逸或攻击集群的其他部分
(2)具有相同配置(例如基于同一 PodTemplate 创建)的多个 Pod 会由于节点上文件的不同而在不同节点上有不同的行为
(3)下层主机上创建的文件或目录只能由 root 用户写入。你需要在特权容器中以 root 身份运行进程,或者修改主机上的文件权限以便容器能够写入 hostPath 卷
nfs
1、nfs 卷能将 NFS (网络文件系统) 挂载到你的 Pod 中
(1)不像 emptyDir 那样会在删除 Pod 的同时也会被删除,nfs 卷的内容在删除 Pod 时会被保存,卷只是被卸载
(2)这意味着 nfs 卷可以被预先填充数据,并且这些数据可以在 Pod 之间共享
2、说明
(1)在使用 NFS 卷之前,你必须运行自己的 NFS 服务器并将目标 share 导出备用
(2)不能在 Pod spec 中指定 NFS 挂载可选项。可以选择设置服务端的挂载可选项,或者使用 /etc/nfsmount.conf,还可以通过允许设置挂载可选项的持久卷挂载 NFS 卷
configMap
1、configMap 卷提供了向 Pod 注入配置数据的方法
(1)ConfigMap 对象中存储的数据可以被 configMap 类型的卷引用,然后被 Pod 中运行的容器化应用使用
(2)引用 configMap 对象时,你可以在卷中通过它的名称来引用
(3)你可以自定义 ConfigMap 中特定条目所要使用的路径
2、说明
(1)在使用 ConfigMap 之前你首先要创建它
(2)容器以 subPath 卷挂载方式使用 ConfigMap 时,将无法接收 ConfigMap 的更新
(3)文本数据挂载成文件时采用 UTF-8 字符编码。如果使用其他字符编码形式,可使用 binaryData 字段
secret
1、secret 卷用来给 Pod 传递敏感信息,例如密码
(1)你可以将 Secret 存储在 Kubernetes API 服务器上,然后以文件的形式挂载到 Pod 中,无需直接与 Kubernetes 耦合
(2)secret 卷由 tmpfs(基于 RAM 的文件系统)提供存储,因此它们永远不会被写入非易失性(持久化的)存储器
2、说明
(1)使用前你必须在 Kubernetes API 中创建 Secret
(2)容器以 subPath 卷挂载方式挂载 Secret 时,将感知不到 Secret 的更新
PersistentVolume 子系统为用户和管理员提供了一组 API, 将存储如何制备的细节从其如何被使用中抽象出来。
1、持久卷(PersistentVolume,PV)是集群中的一块存储,可以由管理员事先制备, 或者使用存储类(Storage Class)来动态制备
(1)持久卷是集群资源,就像节点也是集群资源一样
(2)PV 持久卷和普通的 Volume 一样, 也是使用卷插件来实现的,只是它们拥有独立于任何使用 PV 的 Pod 的生命周期
(3)此 API 对象中记述了存储的实现细节,无论其背后是 NFS、iSCSI 还是特定于云平台的存储系统
2、持久卷申领(PersistentVolumeClaim,PVC)表达的是用户对存储的请求
(1)概念上与 Pod 类似
(2)Pod 会耗用节点资源,而 PVC 申领会耗用 PV 资源
(3)Pod 可以请求特定数量的资源(CPU 和内存);同样 PVC 申领也可以请求特定的大小和访问模式 (例如,可以要求 PV 卷能够以 ReadWriteOnce、ReadOnlyMany 或 ReadWriteMany 模式之一来挂载)
3、尽管 PersistentVolumeClaim 允许用户消耗抽象的存储资源, 常见的情况是针对不同的问题用户需要的是具有不同属性(如,性能)的 PersistentVolume 卷。集群管理员需要能够提供不同性质的 PersistentVolume,并且这些 PV 卷之间的差别不仅限于卷大小和访问模式,同时又不能将卷是如何实现的这些细节暴露给用户。为了满足这类需求,就有了存储类(StorageClass)资源
持久卷(PersistentVolume,PV)
1、PV 持久卷是用插件的形式来实现的。Kubernetes 目前支持以下插件
(1)csi - 容器存储接口 (CSI)
(2)fc - Fibre Channel (FC) 存储
(3)hostPath - HostPath 卷 (仅供单节点测试使用;不适用于多节点集群;请尝试使用 local 卷作为替代)
(4)iscsi - iSCSI (SCSI over IP) 存储
(5)local - 节点上挂载的本地存储设备
(6)nfs - 网络文件系统 (NFS) 存储
2、容量
(1)一般而言,每个 PV 卷都有确定的存储容量
(2)容量属性是使用 PV 对象的 capacity 属性来设置的
(3)目前,存储大小是可以设置和请求的唯一资源。未来可能会包含 IOPS、吞吐量等属性
3、访问模式
(1)PersistentVolume 卷可以用资源提供者所支持的任何方式挂载到宿主系统上
(2)提供者(驱动)的能力不同,每个 PV 卷的访问模式都会设置为对应卷所支持的模式值
(3)每个 PV 卷都会获得自身的访问模式集合,描述的是特定 PV 卷的能力
(4)ReadWriteOnce:卷可以被一个节点以读写方式挂载,ReadWriteOnce 访问模式也允许运行在同一节点上的多个 Pod 访问卷
(5)ReadOnlyMany:卷可以被多个节点以只读方式挂载
(6)ReadWriteMany:卷可以被多个节点以读写方式挂载
(7)ReadWriteOncePod:卷可以被单个 Pod 以读写方式挂载。如果你想确保整个集群中只有一个 Pod 可以读取或写入该 PVC,请使用 ReadWriteOncePod 访问模式。这只支持 CSI 卷以及需要 Kubernetes 1.22 以上版本
4、在命令行接口(CLI)中,访问模式也使用以下缩写形式
(1)RWO - ReadWriteOnce
(2)ROX - ReadOnlyMany
(3)RWX - ReadWriteMany
(4)RWOP - ReadWriteOncePod
5、说明
(1)Kubernetes 使用卷访问模式来匹配 PersistentVolumeClaim 和 PersistentVolume
(2)在某些场合下,卷访问模式也会限制 PersistentVolume 可以挂载的位置
(3)卷访问模式并不会在存储已经被挂载的情况下为其实施写保护。即使访问模式设置为 ReadWriteOnce、ReadOnlyMany 或 ReadWriteMany,它们也不会对卷形成限制
(4)每个卷同一时刻只能以一种访问模式挂载,即使该卷能够支持多种访问模式
6、回收策略
(1)Retain -- 手动回收
(2)Recycle -- 基本擦除 (rm -rf /thevolume/*)
(3)Delete -- 诸如 AWS EBS、GCE PD、Azure Disk 或 OpenStack Cinder 卷这类关联存储资产也被删除
(4)目前,仅 NFS 和 HostPath 支持回收(Recycle)。AWS EBS、GCE PD、Azure Disk 和 Cinder 卷都支持删除(Delete)
7、类
(1)每个 PV 可以属于某个类(Class),通过将其 storageClassName 属性设置为某个 StorageClass 的名称来指定
(2)特定类的 PV 卷只能绑定到请求该类存储卷的 PVC 申领
(3)未设置 storageClassName 的 PV 卷没有类设定,只能绑定到那些没有指定特定存储类的 PVC 申领
8、每个卷会处于以下阶段(Phase)之一
(1)Available(可用)-- 卷是一个空闲资源,尚未绑定到任何申领
(2)Bound(已绑定)-- 该卷已经绑定到某申领
(3)Released(已释放)-- 所绑定的申领已被删除,但是资源尚未被集群回收
(4)Failed(失败)-- 卷的自动回收操作失败
9、命令行接口能够显示绑定到某 PV 卷的 PVC 对象
持久卷申领(PersistentVolumeClaim,PVC)
1、访问模式:申领在请求具有特定访问模式的存储时,使用与卷相同的访问模式约定
2、资源
(1)申领和 Pod 一样,也可以请求特定数量的资源,在这个上下文中,请求的资源是存储
(2)卷和申领都使用相同的资源模型
3、选择算符
(1)申领可以设置标签选择算符来进一步过滤卷集合
(2)只有标签与选择算符相匹配的卷能够绑定到申领上
(3)选择算符包含两个字段
(4)matchLabels - 卷必须包含带有此值的标签
(5)matchExpressions - 通过设定键(key)、值列表和操作符(operator) 来构造的需求。合法的操作符有 In、NotIn、Exists 和 DoesNotExist
(6)来自 matchLabels 和 matchExpressions 的所有需求都按逻辑与的方式组合在一起。这些需求都必须被满足才被视为匹配
4、类
(1)申领可以通过为 storageClassName 属性设置 StorageClass 的名称来请求特定的存储类
(2)只有所请求的类的 PV 卷,即 storageClassName 值与 PVC 设置相同的 PV 卷,才能绑定到 PVC 申领
5、PVC 申领不必一定要请求某个类
(1)如果 PVC 的 storageClassName 属性值设置为 "",则被视为要请求的是没有设置存储类的 PV 卷,因此这一 PVC 申领只能绑定到未设置存储类的 PV 卷
(2)未设置注解或者注解值为 "" 的 PersistentVolume(PV)对象在系统中不会被删除, 因为这样做可能会引起数据丢失
(3)未设置 storageClassName 的 PVC 与此大不相同, 也会被集群作不同处理
6、具体筛查方式取决于 DefaultStorageClass 准入控制器插件是否被启用
(1)如果准入控制器插件被启用,则管理员可以设置一个默认的 StorageClass。 所有未设置 storageClassName 的 PVC 都只能绑定到隶属于默认存储类的 PV 卷。 设置默认 StorageClass 的工作是通过将对应 StorageClass 对象的注解storageclass.kubernetes.io/is-default-class 赋值为 true 来完成的
(2)如果管理员未设置默认存储类,集群对 PVC 创建的处理方式与未启用准入控制器插件时相同
(3)如果设定的默认存储类不止一个,准入控制插件会禁止所有创建 PVC 操作
(4)如果准入控制器插件被关闭,则不存在默认 StorageClass 的说法。 所有将 storageClassName 设为 "" 的 PVC 只能被绑定到也将 storageClassName 设为 "" 的 PV。 不过,只要默认的 StorageClass 可用,就可以稍后更新缺少 storageClassName 的PVC
(5)如果这个 PVC 更新了,它将不再绑定到也将 storageClassName 设为 "" 的 PV
(6)取决于安装方法,默认的 StorageClass 可能在集群安装期间由插件管理器(Addon Manager)部署到集群中
(7)当某 PVC 除了请求 StorageClass 之外还设置了 selector,则这两种需求会按逻辑与关系处理: 只有隶属于所请求类且带有所请求标签的 PV 才能绑定到 PVC
(8)目前,设置了非空 selector 的 PVC 对象无法让集群为其动态制备 PV 卷
PV 卷和 PVC 申领之间的互动遵循如下生命周期
1、制备:PV 卷的制备有两种方式,静态制备或动态制备
2、静态制备
(1)集群管理员创建若干 PV 卷
(2)这些卷对象带有真实存储的细节信息,并且对集群用户可用(可见)
(3)PV 卷对象存在于 Kubernetes API 中,可供用户消费(使用)
3、动态制备
(1)如果管理员所创建的所有静态 PV 卷都无法与用户的 PersistentVolumeClaim 匹配,集群可以尝试为该 PVC 申领动态制备一个存储卷
(2)这一制备操作是基于 StorageClass 来实现的:PVC 申领必须请求某个存储类,同时集群管理员必须已经创建并配置了该类,这样动态制备卷的动作才会发生。如果 PVC 申领指定存储类为 "",则相当于为自身禁止使用动态制备的卷
(3)为了基于存储类完成动态的存储制备,集群管理员需要在 API 服务器上启用 DefaultStorageClass 准入控制器,举例而言,可以通过保证 DefaultStorageClass 出现在 API 服务器组件的 --enable-admission-plugins 标志值中实现这点;该标志的值可以是逗号分隔的有序列表
4、绑定
用户创建一个带有特定存储容量和特定访问模式需求的 PersistentVolumeClaim 对象; 在动态制备场景下,这个 PVC 对象可能已经创建完毕。 主控节点中的控制回路监测新的 PVC 对象,寻找与之匹配的 PV 卷(如果可能的话), 并将二者绑定到一起。 如果为了新的 PVC 申领动态制备了 PV 卷,则控制回路总是将该 PV 卷绑定到这一 PVC 申领。 否则,用户总是能够获得他们所请求的资源,只是所获得的 PV 卷可能会超出所请求的配置。 一旦绑定关系建立,则 PersistentVolumeClaim 绑定就是排他性的, 无论该 PVC 申领是如何与 PV 卷建立的绑定关系。 PVC 申领与 PV 卷之间的绑定是一种一对一的映射,实现上使用 ClaimRef 来记述 PV 卷与 PVC 申领间的双向绑定关系
如果找不到匹配的 PV 卷,PVC 申领会无限期地处于未绑定状态。 当与之匹配的 PV 卷可用时,PVC 申领会被绑定。 例如,即使某集群上制备了很多 50 Gi 大小的 PV 卷,也无法与请求 100 Gi 大小的存储的 PVC 匹配。当新的 100 Gi PV 卷被加入到集群时, 该 PVC 才有可能被绑定
5、使用
(1)Pod 将 PVC 申领当做存储卷来使用
(2)集群会检视 PVC 申领,找到所绑定的卷,并为 Pod 挂载该卷
(3)对于支持多种访问模式的卷,用户要在 Pod 中以卷的形式使用申领时指定期望的访问模式
(4)一旦用户有了申领对象并且该申领已经被绑定,则所绑定的 PV 卷在用户仍然需要它期间一直属于该用户
(5)用户通过在 Pod 的 volumes 块中包含 persistentVolumeClaim 节区来调度 Pod,访问所申领的 PV 卷
6、回收(Reclaiming)
(1)当用户不再使用其存储卷时,他们可以从 API 中将 PVC 对象删除, 从而允许该资源被回收再利用
(2)PersistentVolume 对象的回收策略告诉集群, 当其被从申领中释放时如何处理该数据卷
(3)目前,数据卷可以被 Retained(保留)、Recycled(回收)或 Deleted(删除)
7、保留(Retain)
(1)回收策略 Retain 使得用户可以手动回收资源
(2)当 PersistentVolumeClaim 对象被删除时,PersistentVolume 卷仍然存在,对应的数据卷被视为"已释放(released)"
(3)由于卷上仍然存在这前一申领人的数据,该卷还不能用于其他申领。 管理员可以通过下面的步骤来手动回收该卷
(4)删除 PersistentVolume 对象。与之相关的、位于外部基础设施中的存储资产 (例如 AWS EBS、GCE PD、Azure Disk 或 Cinder 卷)在 PV 删除之后仍然存在
(5)根据情况,手动清除所关联的存储资产上的数据
(6)手动删除所关联的存储资产
(7)如果你希望重用该存储资产,可以基于存储资产的定义创建新的 PersistentVolume 卷对象
8、删除(Delete)
(1)对于支持 Delete 回收策略的卷插件,删除动作会将 PersistentVolume 对象从 Kubernetes 中移除,同时也会从外部基础设施(如 AWS EBS、GCE PD、Azure Disk 或 Cinder 卷)中移除所关联的存储资产
(2)动态制备的卷会继承其 StorageClass 中设置的回收策略, 该策略默认为 Delete
(3)管理员需要根据用户的期望来配置 StorageClass,否则 PV 卷被创建之后必须要被编辑或者修补
9、回收(Recycle)
(1)警告: 回收策略 Recycle 已被废弃。取而代之的建议方案是使用动态制备
(2)如果下层的卷插件支持,回收策略 Recycle 会在卷上执行一些基本的擦除 (rm -rf /thevolume/*)操作,之后允许该卷用于新的 PVC 申领
(3)不过,管理员可以按 参考资料 中所述,使用 Kubernetes 控制器管理器命令行参数来配置一个定制的回收器(Recycler) Pod 模板。此定制的回收器 Pod 模板必须包含一个 volumes 规约
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 微软正式发布.NET 10 Preview 1:开启下一代开发框架新篇章
· 没有源码,如何修改代码逻辑?
· PowerShell开发游戏 · 打蜜蜂
· 在鹅厂做java开发是什么体验
· WPF到Web的无缝过渡:英雄联盟客户端的OpenSilver迁移实战