临时卷
本文档介绍了 Kubernetes 中的临时卷。建议熟悉卷,特别是 PersistentVolumeClaim 和 PersistentVolume。
某些应用程序需要额外的存储,但并不关心这些数据是否在重启后持久保存。例如,缓存服务通常受内存大小限制,可以将不常使用的数据移动到比内存慢的存储中,对整体性能影响很小。
其他应用程序期望某些只读输入数据存在于文件中,例如配置数据或密钥。
临时卷专为这些用例而设计。由于卷遵循 Pod 的生命周期,并与 Pod 一起创建和删除,因此可以停止和重启 Pod,而不会受到某些持久卷可用性的限制。
临时卷在 Pod 规范中内联指定,这简化了应用程序部署和管理。
临时卷类型
Kubernetes 支持多种不同类型的临时卷,用于不同目的
- emptyDir:Pod 启动时为空,存储来自 kubelet 基目录(通常是根磁盘)或 RAM 的本地存储
- configMap、downwardAPI、secret:将不同类型的 Kubernetes 数据注入 Pod 中
- CSI 临时卷:类似于之前的卷类型,但由专门CSI 驱动程序提供,这些驱动程序专门支持此功能
- 通用临时卷,可以由所有也支持持久卷的存储驱动程序提供
emptyDir
、configMap
、downwardAPI
、secret
作为本地临时存储提供。它们由每个节点上的 kubelet 管理。
CSI 临时卷必须由第三方 CSI 存储驱动程序提供。
通用临时卷可以由第三方 CSI 存储驱动程序提供,也可以由任何其他支持动态配置的存储驱动程序提供。某些 CSI 驱动程序专门为 CSI 临时卷编写,不支持动态配置:因此,它们不能用于通用临时卷。
使用第三方驱动程序的优点是,它们可以提供 Kubernetes 本身不支持的功能,例如具有不同性能特性的存储(不同于 kubelet 管理的磁盘),或注入不同数据。
CSI 临时卷
Kubernetes v1.25 [稳定]
注意
CSI 临时卷仅由部分 CSI 驱动程序支持。Kubernetes CSI 驱动程序列表 显示哪些驱动程序支持临时卷。从概念上讲,CSI 临时卷类似于 configMap
、downwardAPI
和 secret
卷类型:存储在每个节点上本地管理,并在 Pod 调度到节点后与其他本地资源一起创建。在此时,Kubernetes 不会再调度 Pod。卷创建必须不太可能失败,否则 Pod 启动将卡住。特别是,存储容量感知 Pod 调度不支持这些卷。目前,它们也不受 Pod 的存储资源使用限制的约束,因为 kubelet 只能对自身管理的存储执行此限制。
以下是用 CSI 临时存储的 Pod 的示例清单
kind: Pod
apiVersion: v1
metadata:
name: my-csi-app
spec:
containers:
- name: my-frontend
image: busybox:1.28
volumeMounts:
- mountPath: "/data"
name: my-csi-inline-vol
command: [ "sleep", "1000000" ]
volumes:
- name: my-csi-inline-vol
csi:
driver: inline.storage.kubernetes.io
volumeAttributes:
foo: bar
volumeAttributes
确定驱动程序准备的卷。这些属性特定于每个驱动程序,并非标准化。有关更多说明,请参阅每个 CSI 驱动程序的文档。
CSI 驱动程序限制
CSI 临时卷允许用户在 Pod 规范中直接将 volumeAttributes
提供给 CSI 驱动程序。允许 volumeAttributes
的 CSI 驱动程序通常仅限于管理员,不适合用作内联临时卷。例如,通常在 StorageClass 中定义的参数不应通过使用内联临时卷暴露给用户。
需要限制可在 Pod 规范中用作内联卷的 CSI 驱动程序的集群管理员可以通过以下方式进行操作
- 从 CSIDriver 规范中的
volumeLifecycleModes
中删除Ephemeral
,这将阻止驱动程序用作内联临时卷。 - 使用准入 Webhook来限制此驱动程序的使用方式。
通用临时卷
Kubernetes v1.23 [稳定]
通用临时卷类似于 emptyDir
卷,它们为暂存数据提供每个 Pod 目录,这些目录通常在配置后为空。但它们可能还具有其他功能
示例
kind: Pod
apiVersion: v1
metadata:
name: my-app
spec:
containers:
- name: my-frontend
image: busybox:1.28
volumeMounts:
- mountPath: "/scratch"
name: scratch-volume
command: [ "sleep", "1000000" ]
volumes:
- name: scratch-volume
ephemeral:
volumeClaimTemplate:
metadata:
labels:
type: my-frontend-volume
spec:
accessModes: [ "ReadWriteOnce" ]
storageClassName: "scratch-storage-class"
resources:
requests:
storage: 1Gi
生命周期和 PersistentVolumeClaim
关键设计理念是,卷声明的参数允许在 Pod 的卷源中使用。支持标签、注释和 PersistentVolumeClaim 的所有字段。当这样的 Pod 被创建时,临时卷控制器将在与 Pod 相同的命名空间中创建一个实际的 PersistentVolumeClaim 对象,并确保在 Pod 被删除时 PersistentVolumeClaim 被删除。
这会触发卷绑定和/或配置,如果StorageClass 使用立即卷绑定,则立即触发,或者在 Pod 临时调度到节点上时触发(WaitForFirstConsumer
卷绑定模式)。后者建议用于通用临时卷,因为这样调度程序可以自由选择适合 Pod 的节点。使用立即绑定,调度程序被迫选择一个在卷可用后可以访问该卷的节点。
在资源所有权方面,具有通用临时存储的 Pod 是提供该临时存储的 PersistentVolumeClaim(s) 的所有者。当 Pod 被删除时,Kubernetes 垃圾收集器会删除 PVC,这通常会触发卷的删除,因为存储类的默认回收策略是删除卷。您可以使用回收策略为 retain
的 StorageClass 来创建准临时本地存储:存储会比 Pod 存活更长时间,在这种情况下,您需要确保单独执行卷清理。
虽然这些 PVC 存在,但它们可以像其他任何 PVC 一样使用。特别是,它们可以作为数据源在卷克隆或快照中引用。PVC 对象还保存卷的当前状态。
PersistentVolumeClaim 命名
自动创建的 PVC 的命名是确定性的:名称是 Pod 名称和卷名称的组合,中间用连字符 (-
) 连接。在上面的示例中,PVC 名称将为 my-app-scratch-volume
。这种确定性命名使与 PVC 的交互更加容易,因为一旦知道 Pod 名称和卷名称,就不需要搜索它。
确定性命名还会在不同的 Pod 之间(一个 Pod "pod-a" 带有卷 "scratch",另一个 Pod 的名称为 "pod",卷名为 "a-scratch",这两个 Pod 最终都具有相同的 PVC 名称 "pod-a-scratch")以及 Pod 与手动创建的 PVC 之间引入潜在冲突。
检测到此类冲突:只有为 Pod 创建的 PVC 才会用作临时卷。此检查基于所有权关系。不会覆盖或修改现有的 PVC。但这并不能解决冲突,因为如果没有正确的 PVC,Pod 无法启动。
注意
在同一命名空间中命名 Pod 和卷时要小心,以防止发生此类冲突。安全
使用通用临时卷允许用户间接创建 PVC,如果他们可以创建 Pod,即使他们没有直接创建 PVC 的权限。集群管理员必须注意这一点。如果这与他们的安全模型不符,他们应该使用准入 Webhook,拒绝包含通用临时卷的 Pod 等对象。
PVC 的正常命名空间配额仍然适用,因此,即使用户被允许使用这种新机制,他们也无法用它来绕过其他策略。
下一步
由 kubelet 管理的临时卷
请参阅本地临时存储。
CSI 临时卷
- 有关设计的更多信息,请参阅临时内联 CSI 卷 KEP。
- 有关此功能进一步开发的更多信息,请参阅增强跟踪问题 #596。
通用临时卷
- 有关设计的更多信息,请参阅通用临时内联卷 KEP。