容器中的文件在磁盘上是临时存放的,这给容器中运行的特殊应用程序带来一些问题。
首先,当容器崩溃时,kubelet 将重新启动容器,容器中的文件将会丢失——因为容器会以干净的状态重建。
其次,当在一个 Pod
中同时运行多个容器时,常常需要在这些容器之间共享文件。
Kubernetes 抽象出 Volume
对象来解决这两个问题。
阅读本文前建议您熟悉一下 Pods。
Docker 也有 Volume 的概念,但对它只有少量且松散的管理。 在 Docker 中,Volume 是磁盘上或者另外一个容器内的一个目录。 直到最近,Docker 才支持对基于本地磁盘的 Volume 的生存期进行管理。 虽然 Docker 现在也能提供 Volume 驱动程序,但是目前功能还非常有限(例如,截至 Docker 1.7,每个容器只允许有一个 Volume 驱动程序,并且无法将参数传递给卷)。
另一方面,Kubernetes 卷具有明确的生命周期——与包裹它的 Pod 相同。 因此,卷比 Pod 中运行的任何容器的存活期都长,在容器重新启动时数据也会得到保留。 当然,当一个 Pod 不再存在时,卷也将不再存在。也许更重要的是,Kubernetes 可以支持许多类型的卷,Pod 也能同时使用任意数量的卷。
卷的核心是包含一些数据的目录,Pod 中的容器可以访问该目录。 特定的卷类型可以决定这个目录如何形成的,并能决定它支持何种介质,以及目录中存放什么内容。
使用卷时, Pod 声明中需要提供卷的类型 (.spec.volumes
字段)和卷挂载的位置 (.spec.containers.volumeMounts
字段).
容器中的进程能看到由它们的 Docker 镜像和卷组成的文件系统视图。 Docker 镜像 位于文件系统层次结构的根部,并且任何 Volume 都挂载在镜像内的指定路径上。 卷不能挂载到其他卷,也不能与其他卷有硬链接。 Pod 中的每个容器必须独立地指定每个卷的挂载位置。
Kubernetes 支持下列类型的卷:
我们欢迎大家贡献其他的卷类型支持。
awsElasticBlockStore
卷将 Amazon Web服务(AWS)EBS 卷 挂载到您的 Pod 中。
与 emptyDir
在删除 Pod 时会被删除不同,EBS 卷的内容在删除 Pod 时会被保留,卷只是被卸载掉了。
这意味着 EBS 卷可以预先填充数据,并且可以在 Pod 之间传递数据。
警告:您在使用 EBS 卷之前必须先创建它,可以使用
aws ec2 create-volume
命令进行创建;也可以使用 AWS API 进行创建。
使用 awsElasticBlockStore
卷时有一些限制:
在将 EBS 卷用到 Pod 上之前,您首先要创建它。
aws ec2 create-volume --availability-zone=eu-west-1a --size=10 --volume-type=gp2
确保该区域与您的群集所在的区域相匹配。(也要检查卷的大小和 EBS 卷类型都适合您的用途!)
apiVersion: v1
kind: Pod
metadata:
name: test-ebs
spec:
containers:
- image: k8s.gcr.io/test-webserver
name: test-container
volumeMounts:
- mountPath: /test-ebs
name: test-volume
volumes:
- name: test-volume
# This AWS EBS volume must already exist.
awsElasticBlockStore:
volumeID: <volume-id>
fsType: ext4
azureDisk
用来在 Pod 上挂载 Microsoft Azure 数据盘(Data Disk) .
更多详情请参考这里。
Kubernetes v1.15
alpha启用azureDisk的CSI迁移功能后,它会将所有插件操作从现有的内建插件填添加disk.csi.azure.com容器存储接口(CSI)驱动程序中。
为了使用此功能,必须在群集上安装 Azure磁盘CSI驱动程序,
并且 CSIMigration
和 CSIMigrationAzureDisk
Alpha功能 必须启用。
azureFile
用来在 Pod 上挂载 Microsoft Azure 文件卷(File Volume) (SMB 2.1 和 3.0)。
更多详情请参考这里。
Kubernetes v1.15
alpha启用azureFile的CSI迁移功能后,它会将所有插件操作从现有的内建插件填添加file.csi.azure.com容器存储接口(CSI)驱动程序中。
为了使用此功能,必须在群集上安装 Azure文件CSI驱动程序,
并且 CSIMigration
和 CSIMigrationAzureFile
Alpha功能 必须启用。
cephfs
允许您将现存的 CephFS 卷挂载到 Pod 中。不像 emptyDir
那样会在删除 Pod 的同时也会被删除,cephfs
卷的内容在删除 Pod 时会被保留,卷只是被卸载掉了。
这意味着 CephFS 卷可以被预先填充数据,并且这些数据可以在 Pod 之间”传递”。CephFS 卷可同时被多个写者挂载。
警告:在您使用 Ceph 卷之前,您的 Ceph 服务器必须正常运行并且要使用的 share 被导出(exported)。
更多信息请参考 CephFS 示例。
注意:先决条件:配置了OpenStack Cloud Provider 的 Kubernetes。 有关 cloudprovider 配置,请参考 cloud provider openstack。
cinder
用于将 OpenStack Cinder 卷安装到 Pod 中。
apiVersion: v1
kind: Pod
metadata:
name: test-cinder
spec:
containers:
- image: k8s.gcr.io/test-webserver
name: test-cinder-container
volumeMounts:
- mountPath: /test-cinder
name: test-volume
volumes:
- name: test-volume
# This OpenStack volume must already exist.
cinder:
volumeID: <volume-id>
fsType: ext4
Kubernetes v1.14
alpha启用Cinder的CSI迁移功能后,它会将所有插件操作从现有的内建插件填添加 cinder.csi.openstack.org
容器存储接口(CSI)驱动程序中。
为了使用此功能,必须在群集上安装 Openstack Cinder CSI驱动程序,
并且 CSIMigration
和 CSIMigrationOpenStack
Alpha功能 必须启用。
configMap
资源提供了向 Pod 注入配置数据的方法。
ConfigMap
对象中存储的数据可以被 configMap
类型的卷引用,然后被应用到 Pod 中运行的容器化应用。
当引用 configMap
对象时,你可以简单的在 Volume 中通过它名称来引用。
还可以自定义 ConfigMap 中特定条目所要使用的路径。
例如,要将名为 log-config
的 ConfigMap 挂载到名为 configmap-pod
的 Pod 中,您可以使用下面的 YAML:
apiVersion: v1
kind: Pod
metadata:
name: configmap-pod
spec:
containers:
- name: test
image: busybox
volumeMounts:
- name: config-vol
mountPath: /etc/config
volumes:
- name: config-vol
configMap:
name: log-config
items:
- key: log_level
path: log_level
log-config
ConfigMap 是以卷的形式挂载的,
存储在 log_level
条目中的所有内容都被挂载到 Pod 的 “/etc/config/log_level
” 路径下。
请注意,这个路径来源于 Volume 的 mountPath
和 log_level
键对应的 path
。
警告:在使用 ConfigMap 之前您首先要创建它。
注意:容器以 subPath 卷挂载方式使用 ConfigMap 时,将无法接收 ConfigMap 的更新。
downwardAPI
卷用于使 downward API 数据对应用程序可用。
这种卷类型挂载一个目录并在纯文本文件中写入请求的数据。
注意:容器以挂载 subPath 卷的方式使用 downwardAPI 时,将不能接收到它的更新。
更多详细信息请参考 downwardAPI
卷示例。
当 Pod 指定到某个节点上时,首先创建的是一个 emptyDir
卷,并且只要 Pod 在该节点上运行,卷就一直存在。
就像它的名称表示的那样,卷最初是空的。
尽管 Pod 中的容器挂载 emptyDir
卷的路径可能相同也可能不同,但是这些容器都可以读写 emptyDir
卷中相同的文件。
当 Pod 因为某些原因被从节点上删除时,emptyDir
卷中的数据也会永久删除。
注意:容器崩溃并不会导致 Pod 被从节点上移除,因此容器崩溃时
emptyDir
卷中的数据是安全的。
emptyDir
的一些用途:
默认情况下, emptyDir
卷存储在支持该节点所使用的介质上;这里的介质可以是磁盘或 SSD 或网络存储,这取决于您的环境。
但是,您可以将 emptyDir.medium
字段设置为 "Memory"
,以告诉 Kubernetes 为您安装 tmpfs(基于 RAM 的文件系统)。
虽然 tmpfs 速度非常快,但是要注意它与磁盘不同。
tmpfs 在节点重启时会被清除,并且您所写入的所有文件都会计入容器的内存消耗,受容器内存限制约束。
apiVersion: v1
kind: Pod
metadata:
name: test-pd
spec:
containers:
- image: k8s.gcr.io/test-webserver
name: test-container
volumeMounts:
- mountPath: /cache
name: cache-volume
volumes:
- name: cache-volume
emptyDir: {}
fc
卷允许将现有的光纤通道卷挂载到 Pod 中。
可以使用卷配置中的参数 targetWWNs
来指定单个或多个目标 WWN。
如果指定多个 WWN,targetWWNs 期望这些 WWN 来自多路径连接。
警告:您必须配置 FC SAN Zoning,以便预先向目标 WWN 分配和屏蔽这些 LUN(卷),这样 Kubernetes 主机才可以访问它们。
更多详情请参考 FC 示例。
Flocker 是一个开源的、集群化的容器数据卷管理器。 Flocker 提供了由各种存储后备支持的数据卷的管理和编排。
flocker
卷允许将一个 Flocker 数据集挂载到 Pod 中。
如果数据集在 Flocker 中不存在,则需要首先使用 Flocker CLI 或 Flocker API 创建数据集。
如果数据集已经存在,那么 Flocker 将把它重新附加到 Pod 被调度的节点。
这意味着数据可以根据需要在 Pod 之间 “传递”。
警告:您在使用 Flocker 之前必须先安装运行自己的 Flocker。
更多详情请参考 Flocker 示例。
gcePersistentDisk
卷能将谷歌计算引擎 (GCE) 持久盘(PD) 挂载到您的 Pod 中。
不像 emptyDir
那样会在删除 Pod 的同时也会被删除,持久盘卷的内容在删除 Pod 时会被保留,卷只是被卸载掉了。
这意味着持久盘卷可以被预先填充数据,并且这些数据可以在 Pod 之间”传递”。
警告:您在使用 PD 前,必须使用
gcloud
或者 GCE API 或 UI 创建它。
使用 gcePersistentDisk
时有一些限制:
PD 的一个特点是它们可以同时被多个消费者以只读方式挂载。 这意味着您可以用数据集预先填充 PD,然后根据需要并行地在尽可能多的 Pod 中提供该数据集。 不幸的是,PD 只能由单个使用者以读写模式挂载——即不允许同时写入。
在由 ReplicationController 所管理的 Pod 上使用 PD 将会失败,除非 PD 是只读模式或者副本的数量是 0 或 1。
在 Pod 中使用 GCE 持久盘之前,您首先要创建它。
gcloud compute disks create --size=500GB --zone=us-central1-a my-data-disk
apiVersion: v1
kind: Pod
metadata:
name: test-pd
spec:
containers:
- image: k8s.gcr.io/test-webserver
name: test-container
volumeMounts:
- mountPath: /test-pd
name: test-volume
volumes:
- name: test-volume
# This GCE PD must already exist.
gcePersistentDisk:
pdName: my-data-disk
fsType: ext4
Kubernetes v1.10
beta区域持久盘 功能允许您创建能在同一区域的两个可用区中使用的持久盘。 要使用这个功能,必须以持久盘的方式提供卷;Pod 不支持直接引用这种卷。
使用 为 GCE PD 定义的存储类 也可以动态供应。 在创建 PersistentVolume 之前,您首先要创建 PD。
gcloud beta compute disks create --size=500GB my-data-disk
--region us-central1
--replica-zones us-central1-a,us-central1-b
PersistentVolume 示例:
apiVersion: v1
kind: PersistentVolume
metadata:
name: test-volume
labels:
failure-domain.beta.kubernetes.io/zone: us-central1-a__us-central1-b
spec:
capacity:
storage: 400Gi
accessModes:
- ReadWriteOnce
gcePersistentDisk:
pdName: my-data-disk
fsType: ext4
Kubernetes v1.14
alpha启用 GCE PD 的 CSI 迁移功能后,它会将所有插件操作从现有的内建插件填添加 pd.csi.storage.gke.io
容器存储接口( CSI )驱动程序中。
为了使用此功能,必须在群集上安装 GCE PD CSI驱动程序,
并且 CSIMigration
和 CSIMigrationGCE
Alpha功能 必须启用。
gitRepo
卷是一个卷插件的例子。
该卷类型挂载了一个空目录,并将一个 Git 代码仓库克隆到这个目录中供您使用。
将来,这种卷可能被移动到一个更加解耦的模型中,而不是针对每个应用案例扩展 Kubernetes API。
下面给出一个 gitRepo 卷的示例:
apiVersion: v1
kind: Pod
metadata:
name: server
spec:
containers:
- image: nginx
name: nginx
volumeMounts:
- mountPath: /mypath
name: git-volume
volumes:
- name: git-volume
gitRepo:
repository: "git@somewhere:me/my-git-repository.git"
revision: "22f1d8406d464b0c0874075539c1f2e96c253775"
glusterfs
卷能将 Glusterfs (一个开源的网络文件系统) 挂载到您的 Pod 中。
不像 emptyDir
那样会在删除 Pod 的同时也会被删除,glusterfs
卷的内容在删除 Pod 时会被保存,卷只是被卸载掉了。
这意味着 glusterfs
卷可以被预先填充数据,并且这些数据可以在 Pod 之间”传递”。GlusterFS 可以被多个写者同时挂载。
警告:在使用前您必须先安装运行自己的 GlusterFS。
更多详情请参考 GlusterFS 示例。
hostPath
卷能将主机节点文件系统上的文件或目录挂载到您的 Pod 中。
虽然这不是大多数 Pod 需要的,但是它为一些应用程序提供了强大的逃生舱。
例如,hostPath
的一些用法有:
hostPath
挂载 /var/lib/docker
路径。hostPath
方式挂载 /sys
。hostPath
在运行 Pod 之前是否应该存在,是否应该创建以及应该以什么方式存在。除了必需的 path
属性之外,用户可以选择性地为 hostPath
卷指定 type
。
支持的 type
值如下:
取值 | 行为 |
---|---|
空字符串(默认)用于向后兼容,这意味着在安装 hostPath 卷之前不会执行任何检查。 | |
DirectoryOrCreate | 如果在给定路径上什么都不存在,那么将根据需要创建空目录,权限设置为 0755,具有与 Kubelet 相同的组和所有权。 |
Directory | 在给定路径上必须存在的目录。 |
FileOrCreate | 如果在给定路径上什么都不存在,那么将在那里根据需要创建空文件,权限设置为 0644,具有与 Kubelet 相同的组和所有权。 |
File | 在给定路径上必须存在的文件。 |
Socket | 在给定路径上必须存在的 UNIX 套接字。 |
CharDevice | 在给定路径上必须存在的字符设备。 |
BlockDevice | 在给定路径上必须存在的块设备。 |
当使用这种类型的卷时要小心,因为:
hostPath
使用的资源。hostPath
卷。apiVersion: v1
kind: Pod
metadata:
name: test-pd
spec:
containers:
- image: k8s.gcr.io/test-webserver
name: test-container
volumeMounts:
- mountPath: /test-pd
name: test-volume
volumes:
- name: test-volume
hostPath:
# directory location on host
path: /data
# this field is optional
type: Directory
iscsi
卷能将 iSCSI (基于 IP 的 SCSI) 挂载到您的 Pod 中。
不像 emptyDir
那样会在删除 Pod 的同时也会被删除,持久盘 卷的内容在删除 Pod 时会被保存,卷只是被卸载掉了。
这意味着 iscsi
卷可以被预先填充数据,并且这些数据可以在 Pod 之间”传递”。
警告:在您使用 iSCSI 卷之前,您必须拥有自己的 iSCSI 服务器,并在上面创建卷。
iSCSI 的一个特点是它可以同时被多个用户以只读方式挂载。 这意味着您可以用数据集预先填充卷,然后根据需要在尽可能多的 Pod 上提供它。不幸的是,iSCSI 卷只能由单个使用者以读写模式挂载——不允许同时写入。
更多详情请参考 iSCSI 示例。
注意:alpha 版本的 PersistentVolume NodeAffinity 注释已被取消,将在将来的版本中废弃。 用户必须更新现有的使用该注解的 PersistentVolume,以使用新的 PersistentVolume
NodeAffinity
字段。
local
卷指的是所挂载的某个本地存储设备,例如磁盘、分区或者目录。
local
卷只能用作静态创建的持久卷。尚不支持动态配置。
相比 hostPath
卷,local
卷可以以持久和可移植的方式使用,而无需手动将 Pod 调度到节点,因为系统通过查看 PersistentVolume 所属节点的亲和性配置,就能了解卷的节点约束。
然而,local
卷仍然取决于底层节点的可用性,并不是适合所有应用程序。
如果节点变得不健康,那么local
卷也将变得不可访问,并且使用它的 Pod 将不能运行。
使用 local
卷的应用程序必须能够容忍这种可用性的降低,以及因底层磁盘的耐用性特征而带来的潜在的数据丢失风险。
下面是一个使用 local
卷和 nodeAffinity
的持久卷示例:
apiVersion: v1
kind: PersistentVolume
metadata:
name: example-pv
spec:
capacity:
storage: 100Gi
# volumeMode field requires BlockVolume Alpha feature gate to be enabled.
volumeMode: Filesystem
accessModes:
- ReadWriteOnce
persistentVolumeReclaimPolicy: Delete
storageClassName: local-storage
local:
path: /mnt/disks/ssd1
nodeAffinity:
required:
nodeSelectorTerms:
- matchExpressions:
- key: kubernetes.io/hostname
operator: In
values:
- example-node
使用 local
卷时,需要使用 PersistentVolume 对象的 nodeAffinity
字段。
它使 Kubernetes 调度器能够将使用 local
卷的 Pod 正确地调度到合适的节点。
现在,可以将 PersistentVolume 对象的 volumeMode
字段设置为 “Block”(而不是默认值 “Filesystem”),以将 local
卷作为原始块设备暴露出来。
volumeMode
字段需要启用 Alpha 功能 BlockVolume
。
当使用 local
卷时,建议创建一个 StorageClass,将 volumeBindingMode
设置为 WaitForFirstConsumer
。
请参考 示例。
延迟卷绑定操作可以确保 Kubernetes 在为 PersistentVolumeClaim 作出绑定决策时,会评估 Pod 可能具有的其他节点约束,例如:如节点资源需求、节点选择器、Pod 亲和性和 Pod 反亲和性。
您可以在 Kubernetes 之外单独运行静态驱动以改进对 local 卷的生命周期管理。
请注意,此驱动不支持动态配置。
有关如何运行外部 local
卷驱动的示例,请参考
local 卷驱动用户指南。
注意:如果不使用外部静态驱动来管理卷的生命周期,则用户需要手动清理和删除 local 类型的持久卷。
nfs
卷能将 NFS (网络文件系统) 挂载到您的 Pod 中。
不像 emptyDir
那样会在删除 Pod 的同时也会被删除,nfs
卷的内容在删除 Pod 时会被保存,卷只是被卸载掉了。
这意味着 nfs
卷可以被预先填充数据,并且这些数据可以在 Pod 之间”传递”。
警告:在您使用 NFS 卷之前,必须运行自己的 NFS 服务器并将目标 share 导出备用。
要了解更多详情请参考 NFS 示例。
persistentVolumeClaim
卷用来将持久卷(PersistentVolume)挂载到 Pod 中。
持久卷是用户在不知道特定云环境细节的情况下”申领”持久存储(例如 GCE PersistentDisk 或者 iSCSI 卷)的一种方法。
更多详情请参考持久卷示例
projected
卷类型能将若干现有的卷来源映射到同一目录上。
目前,可以映射的卷来源类型如下:
secret
downwardAPI
configMap
serviceAccountToken
所有的卷来源需要和 Pod 处于相同的命名空间。 更多详情请参考一体化卷设计文档。
服务帐户令牌的映射是 Kubernetes 1.11 版本中引入的一个功能,并在 1.12 版本中被提升为 Beta 功能。
若要在 1.11 版本中启用此特性,需要显式设置 TokenRequestProjection
功能开关 为 True。
apiVersion: v1
kind: Pod
metadata:
name: volume-test
spec:
containers:
- name: container-test
image: busybox
volumeMounts:
- name: all-in-one
mountPath: "/projected-volume"
readOnly: true
volumes:
- name: all-in-one
projected:
sources:
- secret:
name: mysecret
items:
- key: username
path: my-group/my-username
- downwardAPI:
items:
- path: "labels"
fieldRef:
fieldPath: metadata.labels
- path: "cpu_limit"
resourceFieldRef:
containerName: container-test
resource: limits.cpu
- configMap:
name: myconfigmap
items:
- key: config
path: my-group/my-config
带有非默认许可模式设置的多个 secret 的 Pod 示例如下:
apiVersion: v1
kind: Pod
metadata:
name: volume-test
spec:
containers:
- name: container-test
image: busybox
volumeMounts:
- name: all-in-one
mountPath: "/projected-volume"
readOnly: true
volumes:
- name: all-in-one
projected:
sources:
- secret:
name: mysecret
items:
- key: username
path: my-group/my-username
- secret:
name: mysecret2
items:
- key: password
path: my-group/my-password
mode: 511
每个被投射的卷来源都在 spec 中的 sources
内列出。
参数几乎相同,除了两处例外:
secretName
字段已被变更为 name
以便与 ConfigMap 命名一致。defaultMode
只能根据投射级别指定,而不是针对每个卷来源指定。不过,如上所述,您可以显式地为每个投射项设置 mode
值。当开启 TokenRequestProjection
功能时,可以将当前 服务帐户的令牌注入 Pod 中的指定路径。
下面是一个例子:
apiVersion: v1
kind: Pod
metadata:
name: sa-token-test
spec:
containers:
- name: container-test
image: busybox
volumeMounts:
- name: token-vol
mountPath: "/service-account"
readOnly: true
volumes:
- name: token-vol
projected:
sources:
- serviceAccountToken:
audience: api
expirationSeconds: 3600
path: token
示例 Pod 具有包含注入服务帐户令牌的映射卷。
例如,这个令牌可以被 Pod 容器用来访问 Kubernetes API服务器。
audience
字段包含令牌的预期受众。
令牌的接收者必须使用令牌的受众中指定的标识符来标识自己,否则应拒绝令牌。
此字段是可选的,默认值是 API 服务器的标识符。
expirationSeconds
是服务帐户令牌的有效期。
默认值为 1 小时,必须至少 10 分钟(600 秒)。
管理员还可以通过指定 API 服务器的 --service-account-max-token-expiration
选项来限制其最大值。
path
字段指定相对于映射卷的挂载点的相对路径。
注意:使用投射卷源作为 subPath 卷挂载的容器将不会接收这些卷源的更新。
portworxVolume
是一个可伸缩的块存储层,能够以超聚合(hyperconverged)的方式与 Kubernetes 一起运行。
Portworx 支持对服务器上存储的指纹处理、基于存储能力进行分层以及跨多个服务器整合存储容量。
Portworx 可以以 in-guest 方式在虚拟机中运行,也可以在裸金属 Linux 节点上运行。
portworxVolume
类型的卷可以通过 Kubernetes 动态创建,也可以在 Kubernetes Pod 内预先供应和引用。
下面是一个引用预先配置的 PortworxVolume 的示例 Pod:
apiVersion: v1
kind: Pod
metadata:
name: test-portworx-volume-pod
spec:
containers:
- image: k8s.gcr.io/test-webserver
name: test-container
volumeMounts:
- mountPath: /mnt
name: pxvol
volumes:
- name: pxvol
# This Portworx volume must already exist.
portworxVolume:
volumeID: "pxvol"
fsType: "<fs-type>"
警告:在 Pod 中使用 portworxVolume 之前,请确保有一个名为
pxvol
的 PortworxVolume 存在。
更多详情和示例可以在这里找到。
quobyte
卷允许将现有的 Quobyte 卷挂载到您的 Pod 中。
警告:在使用 Quobyte 卷之前,您首先要进行安装并创建好卷。
Quobyte 支持容器存储接口容器存储接口 (CSI)定义了存储系统暴露给容器的标准接口。 。 推荐使用 CSI 插件以在 Kubernetes 中使用 Quobyte 卷。 Quobyte 的 GitHub 项目具有[说明(https://github.com/quobyte/quobyte/quobyte-csi#quobyte-csi)以及使用示例来部署 CSI 的 Quobyte。
rbd
卷允许将 Rados 块设备 卷挂载到您的 Pod 中.
不像 emptyDir
那样会在删除 Pod 的同时也会被删除,rbd
卷的内容在删除 Pod 时会被保存,卷只是被卸载掉了。
这意味着 rbd
卷可以被预先填充数据,并且这些数据可以在 Pod 之间”传递”。
警告:在使用 RBD 之前,您必须安装运行 Ceph。
RBD 的一个特点是它可以同时被多个用户以只读方式挂载。 这意味着您可以用数据集预先填充卷,然后根据需要从尽可能多的 Pod 中并行地提供卷。 不幸的是,RBD 卷只能由单个使用者以读写模式安装——不允许同时写入。
更多详情请参考 RBD 示例。
ScaleIO 是基于软件的存储平台,可以使用现有硬件来创建可伸缩的、共享的而且是网络化的块存储集群。
scaleIO
卷插件允许部署的 Pod 访问现有的 ScaleIO 卷(或者它可以动态地为持久卷申领提供新的卷,参见ScaleIO 持久卷)。
警告:在使用前,您必须有个安装完毕且运行正常的 ScaleIO 集群,并且创建好了存储卷。
下面是配置了 ScaleIO 的 Pod 示例:
apiVersion: v1
kind: Pod
metadata:
name: pod-0
spec:
containers:
- image: k8s.gcr.io/test-webserver
name: pod-0
volumeMounts:
- mountPath: /test-pd
name: vol-0
volumes:
- name: vol-0
scaleIO:
gateway: https://localhost:443/api
system: scaleio
protectionDomain: sd0
storagePool: sp1
volumeName: vol-0
secretRef:
name: sio-secret
fsType: xfs
更多详情,请参考 ScaleIO 示例。
secret
卷用来给 Pod 传递敏感信息,例如密码。您可以将 secret 存储在 Kubernetes API 服务器上,然后以文件的形式挂在到 Pod 中,无需直接与 Kubernetes 耦合。
secret
卷由 tmpfs(基于 RAM 的文件系统)提供存储,因此它们永远不会被写入非易失性(持久化的)存储器。
警告:使用前您必须在 Kubernetes API 中创建 secret。
注意:容器以 subPath 卷的方式挂载 Secret 时,它将感知不到 Secret 的更新。
Secret 的更多详情请参考这里。
storageos
卷允许将现有的 StorageOS 卷挂载到您的 Pod 中。
StorageOS 在 Kubernetes 环境中以容器的形式运行,这使得应用能够从 Kubernetes 集群中的任何节点访问本地或关联的存储。 为应对节点失效状况,可以复制数据。 若需提高利用率和降低成本,可以考虑瘦配置(Thin Provisioning)和数据压缩。
作为其核心能力之一,StorageOS 为容器提供了可以通过文件系统访问的块存储。
StorageOS 容器需要 64 位的 Linux,并且没有其他的依赖关系。 StorageOS 提供免费的开发者授权许可。
警告:您必须在每个希望访问 StorageOS 卷的或者将向存储资源池贡献存储容量的节点上运行 StorageOS 容器。 有关安装说明,请参阅 StorageOS 文档。
apiVersion: v1
kind: Pod
metadata:
labels:
name: redis
role: master
name: test-storageos-redis
spec:
containers:
- name: master
image: kubernetes/redis:v1
env:
- name: MASTER
value: "true"
ports:
- containerPort: 6379
volumeMounts:
- mountPath: /redis-master-data
name: redis-data
volumes:
- name: redis-data
storageos:
# The `redis-vol01` volume must already exist within StorageOS in the `default` namespace.
volumeName: redis-vol01
fsType: ext4
更多关于动态供应和持久卷申领的信息请参考 StorageOS 示例。
注意:前提条件:配备了 vSphere 云驱动的 Kubernetes。云驱动的配置方法请参考 vSphere 使用指南。
vsphereVolume
用来将 vSphere VMDK 卷挂载到您的 Pod 中。
在卸载卷时,卷的内容会被保留。
vSphereVolume 卷类型支持 VMFS 和 VSAN 数据仓库。
警告:在挂载到 Pod 之前,您必须用下列方式之一创建 VMDK。
选择下列方式之一创建 VMDK。
apiVersion: v1
kind: Pod
metadata:
name: test-vmdk
spec:
containers:
- image: k8s.gcr.io/test-webserver
name: test-container
volumeMounts:
- mountPath: /test-vmdk
name: test-volume
volumes:
- name: test-volume
# This VMDK volume must already exist.
vsphereVolume:
volumePath: "[DatastoreName] volumes/myDisk"
fsType: ext4
更多示例可以在这里找到。
有时,在单个 Pod 中共享卷以供多方使用是很有用的。
volumeMounts.subPath
属性可用于指定所引用的卷内的子路径,而不是其根路径。
下面是一个使用同一共享卷的、内含 LAMP 栈(Linux Apache Mysql PHP)的 Pod 的示例。
HTML 内容被映射到卷的 html
文件夹,数据库将被存储在卷的 mysql
文件夹中:
apiVersion: v1
kind: Pod
metadata:
name: my-lamp-site
spec:
containers:
- name: mysql
image: mysql
env:
- name: MYSQL_ROOT_PASSWORD
value: "rootpasswd"
volumeMounts:
- mountPath: /var/lib/mysql
name: site-data
subPath: mysql
- name: php
image: php:7.0-apache
volumeMounts:
- mountPath: /var/www/html
name: site-data
subPath: html
volumes:
- name: site-data
persistentVolumeClaim:
claimName: my-lamp-site-data
Kubernetes v1.15
beta使用 subPathExpr
字段从 Downward API 环境变量构造 subPath
目录名。
在使用此特性之前,必须启用 VolumeSubpathEnvExpansion
功能开关。
subPath
和 subPathExpr
属性是互斥的。
在这个示例中,Pod 基于 Downward API 中的 Pod 名称,使用 subPathExpr
在 hostPath 卷 /var/log/pods
中创建目录 pod1
。
主机目录 /var/log/pods/pod1
挂载到了容器的 /logs
中。
apiVersion: v1
kind: Pod
metadata:
name: pod1
spec:
containers:
- name: container1
env:
- name: POD_NAME
valueFrom:
fieldRef:
apiVersion: v1
fieldPath: metadata.name
image: busybox
command: [ "sh", "-c", "while [ true ]; do echo 'Hello'; sleep 10; done | tee -a /logs/hello.txt" ]
volumeMounts:
- name: workdir1
mountPath: /logs
subPathExpr: $(POD_NAME)
restartPolicy: Never
volumes:
- name: workdir1
hostPath:
path: /var/log/pods
emptyDir
卷的存储介质(磁盘、SSD 等)是由保存 kubelet 根目录(通常是 /var/lib/kubelet
)的文件系统的介质确定。
emptyDir
卷或者 hostPath
卷可以消耗的空间没有限制,容器之间或 Pod 之间也没有隔离。
将来,我们希望 emptyDir
卷和 hostPath
卷能够使用 resource 规范来请求一定量的空间,并且能够为具有多种介质类型的集群选择要使用的介质类型。
Out-of-Tree 卷插件包括容器存储接口(CSI)和 FlexVolume。 它们使存储供应商能够创建自定义存储插件,而无需将它们添加到 Kubernetes 代码仓库。
在引入 CSI 和 FlexVolume 之前,所有卷插件(如上面列出的卷类型)都是 “in-tree” 的,这意味着它们是与 Kubernetes 的核心组件一同构建、链接、编译和交付的,并且这些插件都扩展了 Kubernetes 的核心 API。 这意味着向 Kubernetes 添加新的存储系统(卷插件)需要将代码合并到 Kubernetes 核心代码库中。
CSI 和 FlexVolume 都允许独立于 Kubernetes 代码库开发卷插件,并作为扩展部署(安装)在 Kubernetes 集群上。
对于希望创建 out-of-tree 卷插件的存储供应商,请参考这个 FAQ。
Kubernetes v1.10
beta容器存储接口 (CSI) 为容器编排系统(如 Kubernetes)定义标准接口,以将任意存储系统暴露给它们的容器工作负载。
更多详情请阅读 CSI 设计方案。
CSI 的支持在 Kubernetes v1.9 中作为 alpha 特性引入,在 Kubernetes v1.10 中转为 beta 特性,并在 Kubernetes v1.13 正式 GA。
注意:
Kubernetes v1.13中不支持 CSI 规范版本0.2和0.3,并将在以后的版本中删除。
注意:CSI驱动程序可能并非在所有Kubernetes版本中都兼容。 请查看特定CSI驱动程序的文档,以获取每个 Kubernetes 版本所支持的部署步骤以及兼容性列表。
一旦在 Kubernetes 集群上部署了 CSI 兼容卷驱动程序,用户就可以使用 csi
卷类型来关联、挂载 CSI 驱动程序暴露出来的卷。
csi
卷类型不支持来自 Pod 的直接引用,只能通过 PersistentVolumeClaim
对象在 Pod 中引用。
存储管理员可以使用以下字段来配置 CSI 持久卷:
driver
:指定要使用的卷驱动程序名称的字符串值。
这个值必须与 CSI 驱动程序在 GetPluginInfoResponse
中返回的值相对应;该接口定义在 CSI 规范中。
Kubernetes 使用所给的值来标识要调用的 CSI 驱动程序;CSI 驱动程序也使用该值来辨识哪些 PV 对象属于该 CSI 驱动程序。volumeHandle
:唯一标识卷的字符串值。
该值必须与CSI 驱动程序在 CreateVolumeResponse
的 volume_id
字段中返回的值相对应;接口定义在 CSI spec 中。
在所有对 CSI 卷驱动程序的调用中,引用该 CSI 卷时都使用此值作为 volume_id
参数。readOnly
:一个可选的布尔值,指示通过 ControllerPublished
关联该卷时是否设置该卷为只读。
默认值是 false。
该值通过 ControllerPublishVolumeRequest
中的 readonly
字段传递给 CSI 驱动程序。fsType
:如果 PV 的 VolumeMode
为 Filesystem
,那么此字段指定挂载卷时应该使用的文件系统。
如果卷尚未格式化,并且支持格式化,此值将用于格式化卷。
此值可以通过 ControllerPublishVolumeRequest
、NodeStageVolumeRequest
和
NodePublishVolumeRequest
的 VolumeCapability
字段传递给 CSI 驱动。volumeAttributes
:一个字符串到字符串的映射表,用来设置卷的静态属性。
该映射必须与 CSI 驱动程序返回的 CreateVolumeResponse
中的 volume.attributes
字段的映射相对应;CSI 规范 中有相应的定义。
该映射通过ControllerPublishVolumeRequest
、NodeStageVolumeRequest
、和 NodePublishVolumeRequest
中的 volume_attributes
字段传递给 CSI 驱动。controllerPublishSecretRef
:对包含敏感信息的 secret 对象的引用;该敏感信息会被传递给 CSI 驱动来完成 CSI ControllerPublishVolume
和 ControllerUnpublishVolume
调用。
此字段是可选的;在不需要 secret 时可以是空的。
如果 secret 对象包含多个 secret,则所有的 secret 都会被传递。nodeStageSecretRef
:对包含敏感信息的 secret 对象的引用,以传递给 CSI 驱动来完成 CSI NodeStageVolume
调用。
此字段是可选的,如果不需要 secret,则可能是空的。
如果 secret 对象包含多个 secret,则传递所有 secret。nodePublishSecretRef
:对包含敏感信息的 secret 对象的引用,以传递给 CSI 驱动来完成 CSI `NodePublishVolume
调用。
此字段是可选的,如果不需要 secret,则可能是空的。
如果 secret 对象包含多个 secret,则传递所有 secret。Kubernetes v1.14
beta从 1.11 版本开始,CSI 引入了对原始块卷的支持。该特性依赖于在 Kubernetes 的之前版本中引入的原始块卷(Raw Block Volume)功能。 该特性将使具有外部 CSI 驱动程序的供应商能够在 Kubernetes 工作负载中实现原始块卷支持。
CSI块卷支持功能已启用,但默认情况下启用。必须为此功能启用的两个功能是“ BlockVolume”和“ CSIBlockVolume”。
--feature-gates=BlockVolume=true,CSIBlockVolume=true
学习怎样安装您的带有块卷支持的 PV/PVC。
Kubernetes v1.16
beta此功能使 CSI 卷可以直接嵌入 Pod 规范中,而不是 PersistentVolume 中。 以这种方式指定的卷是临时的,不会在 Pod 重新启动后持续存在。
实例:
kind: Pod
apiVersion: v1
metadata:
name: my-csi-app
spec:
containers:
- name: my-frontend
image: busybox
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
此功能需要启用 CSIInlineVolume 功能门。 从Kubernetes 1.16开始默认启用它。
CSI 临时卷仅由一部分 CSI 驱动程序支持。 请在此处查看 CSI 驱动程序列表。
#开发人员资源 有关如何开发 CSI 驱动程序的更多信息,请参考kubernetes-csi文档
Kubernetes v1.14
alpha启用 CSI 迁移功能后,会将针对现有 in-tree 插件的操作定向到相应的 CSI 插件(应安装和配置)。 该功能实现了必要的转换逻辑和填充以无缝方式重新路由操作。 因此,操作员在过渡到取代树内插件的CSI驱动程序时,无需对现有存储类,PV 或 PVC(指 in-tree 插件)进行任何配置更改。 在 Alpha 状态下,受支持的操作和功能包括供应/删除,附加/分离,安装/卸载和调整卷大小。 上面的 “卷类型” 部分列出了支持 CSI 迁移并已实现相应 CSI 驱动程序的树内插件。
FlexVolume 是一个自 1.2 版本(在 CSI 之前)以来在 Kubernetes 中一直存在的 out-of-tree 插件接口。 它使用基于 exec 的模型来与驱动程序对接。 用户必须在每个节点(在某些情况下是主节点)上的预定义卷插件路径中安装 FlexVolume 驱动程序可执行文件。
Pod 通过 flexvolume
in-tree 插件与 Flexvolume 驱动程序交互。
更多详情请参考这里。
挂载卷的传播能力允许将容器安装的卷共享到同一 Pod 中的其他容器,甚至共享到同一节点上的其他 Pod。
卷的挂载传播特性由 Container.volumeMounts 中的 mountPropagation
字段控制。
它的值包括:
None
- 此卷挂载将不会感知到主机后续在此卷或其任何子目录上执行的挂载变化。
类似的,容器所创建的卷挂载在主机上是不可见的。这是默认模式。
该模式等同于 Linux 内核文档中描述的 private
挂载传播选项。HostToContainer
- 此卷挂载将会感知到主机后续针对此卷或其任何子目录的挂载操作。换句话说,如果主机在此挂载卷中挂载任何内容,容器将能看到它被挂载在那里。
类似的,配置了 Bidirectional
挂载传播选项的 Pod 如果在同一卷上挂载了内容,挂载传播设置为 HostToContainer
的容器都将能看到这一变化。
该模式等同于 Linux 内核文档 中描述的 rslave
挂载传播选项。
Bidirectional
- 这种卷挂载和 HostToContainer
挂载表现相同。另外,容器创建的卷挂载将被传播回至主机和使用同一卷的所有 Pod 的所有容器。
该模式等同于 Linux 内核文档 中描述的 rshared
挂载传播选项。
警告:
Bidirectional
形式的挂载传播可能比较危险。 它可以破坏主机操作系统,因此它只被允许在特权容器中使用。 强烈建议您熟悉 Linux 内核行为。 此外,由 Pod 中的容器创建的任何卷挂载必须在终止时由容器销毁(卸载)。
在某些部署环境中,挂载传播正常工作前,必须在 Docker 中正确配置挂载共享(mount share),如下所示。
编辑您的 Docker systemd
服务文件,按下面的方法设置 MountFlags
:
MountFlags=shared
或者,如果存在 MountFlags=slave
就删除掉。然后重启 Docker 守护进程:
sudo systemctl daemon-reload
sudo systemctl restart docker
此页是否对您有帮助?
感谢反馈。如果您有一个关于如何使用 Kubernetes 的特定的、需要答案的问题,可以访问 Stack Overflow. 在 GitHub 仓库上登记新的问题 报告问题 或者 提出改进建议.