Container中的磁盘文件(生命周期)是短暂的,这在容器中运行时会给部分特殊的应用程序带来一些问题。首先,当容器崩溃时,kubelet在重新启动它,数据文件会丢失(Container会以干净的状态启动)。其次,在Pod中运行多个Container时,通常需要在这些容器之间共享文件。Kubernetes Volume(卷)抽象的解决了这两个问题。

背景

Docker也有卷的概念,虽然它有点宽松和较少管理。在Docker中,卷只是磁盘上或另一个Container中的目录。生命周期不受管理,直到最近才有本地磁盘支持的卷。 Docker现在提供了卷驱动程序,但是现在功能非常有限(例如,从Docker 1.7开始,每个Container只允许一个卷驱动程序,并且无法将参数传递给卷)。

另一方面,Kubernetes卷具有明确的生命周期:与使用它的Pod相同。因此,卷可以比Pod中运行的任何Container更长,并且可以在Container重新启动之间保留数据。当然,当Pod不再存在时,卷也将不复存在。Kubernetes支持多种类型的卷,Pod可以同时使用任意数量的卷。

从本质上讲,卷只是一个目录,可能包含一些数据,Pod中的容器可以访问它。该目录是如何形成的,支持它的介质以及它的内容由所使用的特定卷类型决定。要使用卷,Pod指定要为Pod提供的卷(.spec.volumes字段)以及将这些卷挂载到Container中的位置(.spec.containers.volumeMounts字段)。

容器中的进程可以看到由Docker镜像和卷组成的文件系统视图。Docker镜像位于文件系统层次结构的根目录下,任何卷都挂载在镜像中的指定路径上。 卷无法挂载其他卷或具有到其他卷的硬链接。Pod中的每个Container必须独立指定每个卷的挂载位置。

volumes类型

Kubernetes支持如下多种类型的Volume:

  • awsElasticBlockStore
  • azureDisk
  • azureFile
  • cephfs
  • cinder
  • configMap
  • csi
  • downwardAPI
  • emptyDir
  • fc (fibre channel)
  • flexVolume
  • flocker
  • gcePersistentDisk
  • gitRepo (deprecated)
  • glusterfs
  • hostPath
  • iscsi
  • local
  • nfs
  • persistentVolumeClaim
  • projected
  • portworxVolume
  • quobyte
  • rbd
  • scaleIO
  • secret
  • storageos
  • vsphereVolume

awsElasticBlockStore

awsElasticBlockStore卷将Amazon Web Services(AWS)EBS卷挂载到你的Pod中。与删除Pod时删除的emptyDir不同,EBS卷的内容将被保留,并且仅卸载卷。这意味着可以使用数据预先填充EBS卷,并且可以在Pod之间“切换”该数据。

注意:必须先使用aws ec2 create-volume或AWS API创建EBS卷,然后才能使用它。

使用awsElasticBlockStore卷时有一些限制:

  • 正在运行Pod的节点必须是AWS EC2实例
  • 这些实例需要与EBS卷位于同一区域和可用区域
  • EBS仅支持挂载卷的单个EC2实例

创建EBS卷

在将Pod与EBS卷一起使用之前,需要先创建它。

1
aws ec2 create-volume --availability-zone=eu-west-1a --size=10 --volume-type=gp2

确保该区域与你启动群集的区域匹配。(并检查大小和EBS卷类型是否适合你的使用!)

示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
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

azureDisk用于将Microsoft Azure数据磁盘挂载到Pod。更多详细信息可以在这里找到。

azureFile

azureFile用于将Microsoft Azure文件卷(SMB 2.1和3.0)挂载到Pod中。更多详细信息可以在这里找到。

cephfs

cephfs卷允许将现有的CephFS卷挂载到Pod中。 与删除Pod时删除的emptyDir不同,将保留cephfs卷的内容,并且仅卸载卷。这意味着可以使用数据预先填充CephFS卷,并且可以在Pod之间“切换”该数据。 CephFS可以由多个编写器同时挂载。

注意:在使用共享之前,必须运行自己的Ceph服务器并创建共享。有关更多详细信息,请参阅CephFS示例

cinder

先决条件:已配置OpenStack Cloud Provider的Kubernetes。对于cloudprovider配置,请参阅云提供商openstack

cinder用于将OpenStack Cinder Volume挂载到Pod中。

示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
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

configMap

configMap资源提供了一种将配置数据注入Pod的方法。存储在ConfigMap对象中的数据可以在configMap类型的卷中引用,然后由在Pod中运行的容器化应用程序使用。引用configMap对象时,只需在卷中提供其名称即可引用它。还可以自定义ConfigMap中特定条目的路径。例如,要将log-config ConfigMap挂载到名为configmap-pod的Pod上,可以使用下面的YAML:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
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条目中的所有内容都挂载在路径“/etc/config/log_level”的Pod中。注意,此路径派生自卷的mountPath和使用log_level键入的路径,且必须先创建ConfigMap才能使用它。

注意:使用ConfigMap作为subPath卷挂载的Container将不会收到ConfigMap更新。

downwardAPI

downwardAPI卷用于向应用程序提供downward的API数据。它挂载目录并将所请求的数据写入纯文本文件。

注意:使用downwardAPI作为subPath卷挂载的Container不会接收downwardAPI更新。

emptyDir

将Pod分配给节点时,首先会创建一个emptyDir卷,只要Pod在该节点上运行,就会存在。 顾名思义,它最初是空的。Pod中的容器都可以在emptyDir卷中读取和写入相同的文件。当从节点中删除Pod时,将永久删除emptyDir中的数据。

注意:容器崩溃不会从节点中删除Pod,因此emptyDir卷中的数据在Container崩溃中是安全的。

emptyDir的一些用途是:

  • 临时空间,例如基于磁盘的合并排序
  • 检查从崩溃中恢复的长计算
  • 保存内容管理器容器在Web服务器容器提供数据时提取的文件

默认情况下,emptyDir卷存储在支持节点的任何介质上:可能是磁盘或SSD或网络存储,具体取决于你的环境。但是,可以将emptyDir.medium字段设置为“Memory”,以告知Kubernetes挂载tmpfs(RAM支持的文件系统)。虽然tmpfs非常快,但请注意,与磁盘不同,tmpfs在节点重新启动时被清除,并且你编写的任何文件都将计入Container的内存限制。

示例Pod:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
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光纤通道

fc卷允许将现有光纤通道卷挂载在Pod中。可以使用卷配置中的参数targetWWNs指定单个或多个目标全局通用名称。如果指定了多个WWN,则targetWWN期望这些WWN来自多路径连接。

注意:你必须配置FC SAN分区以预先将这些LUN(卷)分配和屏蔽到目标WWN,以便Kubernetes主机可以访问它们。详见

flocker

Flocker是一个开源的集群Container数据卷管理器。它提供由各种存储后端支持的数据卷的管理和编排。

flocker卷允许将Flocker数据集挂载到Pod中。 如果Flocker中尚不存在数据集,则需要首先使用Flocker CLI或使用Flocker API创建数据集。 如果数据集已经存在,它将被Flocker重新附加到调度Pod的节点。这意味着可以根据需要在Pod之间“切换”数据。

注意:必须先运行自己的Flocker挂载才能使用它。有关更多详细信息,请参阅Flocker示例

gcePersistentDisk

gcePersistentDisk卷将Google Compute Engine(GCE)永久磁盘装入Pod。与删除Pod时删除的emptyDir不同,PD的内容将被保留,并且仅卸载卷。 这意味着PD可以预先填充数据,并且该数据可以在Pod之间“切换”。

注意:必须先使用gcloud或GCE API或UI创建PD,然后才能使用它。

使用gcePersistentDisk时有一些限制:

  • 运行Pod的节点必须是GCE VM
  • 这些VM需要与PD处于同一GCE项目和区域

PD的一个特征是它们可以同时由多个消费者以只读方式挂载。这意味着可以使用数据集预先填充PD,然后根据需要从多个Pod中并行提供。不幸的是,PD只能由一个消费者以读写模式挂载:不允许同时写入。

除非PD是只读的或副本计数为0或1,否则在由ReplicationController控制的Pod上使用PD将失败。

创建PD

在将GCE PD与Pod一起使用之前,需要先创建它:

1
gcloud compute disks create --size=500GB --zone=us-central1-a my-data-disk

示例Pod:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
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

手动配置区域PD PersistentVolume

使用StorageClass for GCE PD可以进行动态配置。 在创建PersistentVolume之前,先必须创建PD:

1
2
3
gcloud beta compute disks create --size=500GB my-data-disk
--region us-central1
--replica-zones us-central1-a,us-central1-b

PersistentVolume spec配置示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
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

glusterfs

glusterfs卷允许将Glusterfs(开源网络文件系统)卷挂载到Pod中。与删除Pod时删除的emptyDir不同,glusterfs卷的内容将被保留,并且仅卸载卷。 这意味着可以使用数据预先填充glusterfs卷,并且可以在Pod之间“切换”该数据。GlusterFS可以由多个编写器同时挂载。

注意:必须先运行自己的GlusterFS挂载,然后才能使用它。

有关更多详细信息,请参阅GlusterFS示例

hostPath

hostPath卷将文件或目录从主机节点的文件系统挂载到Pod中。这不是大多数Pod需要的东西,但它为某些应用程序提供了强大的用途。

例如,hostPath的一些用途是:

  • 运行需要访问Docker内部的Container; 使用/var/lib/docker的hostPath
  • 在容器中运行cAdvisor; 使用/sys的hostPath
  • 允许Pod指定在Pod运行之前是否应该存在给定的hostPath,是否应该创建它以及它应该存在的内容

除了必需的path属性之外,用户还可以选择为hostPath卷指定类型。

字段类型支持的值为:

Value Behavior
Empty string (default) is for backward compatibility, which means that no checks will be performed before mounting the hostPath volume.
DirectoryOrCreate If nothing exists at the given path, an empty directory will be created there as needed with permission set to 0755, having the same group and ownership with Kubelet.
Directory A directory must exist at the given path
FileOrCreate If nothing exists at the given path, an empty file will be created there as needed with permission set to 0644, having the same group and ownership with Kubelet.
File A file must exist at the given path
Socket A UNIX socket must exist at the given path
CharDevice A character device must exist at the given path
BlockDevice A block device must exist at the given path

请注意何时使用此类型的卷,因为:

  • 由于节点上的文件不同,具有相同配置的Pod(例如从podTemplate创建)在不同节点上的行为可能会有所不同
  • 当Kubernetes按计划添加资源调度时,它将无法考虑hostPath使用的资源
  • 在底层主机上创建的文件或目录只能由root写入。需要以特权Container中的root身份运行你的进程,或者修改主机上的文件权限以便能够写入hostPath卷

示例Pod:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
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卷允许将现有iSCSI(SCSI over IP)卷挂载到Pod中。 与删除Pod时删除的emptyDir不同,iscsi卷的内容将被保留,并且仅卸载卷。这意味着可以使用数据预先填充iscsi卷,并且可以在Pod之间“切换”该数据。

注意:必须先使用创建的卷运行自己的iSCSI服务器,然后才能使用它。

iSCSI的一个特性是它可以同时由多个消费者以只读方式挂载。这意味着你可以使用数据集预填充卷,然后根据需要从多个Pod中并行提供。 遗憾的是,iSCSI卷只能由单个用户以读写模式挂载:不允许同时写入。

有关更多详细信息,请参阅iSCSI示例

local

本地卷表示已挂载的本地存储设备,例如磁盘,分区或目录。

本地卷只能用作静态创建的PersistentVolume(持久卷)。尚不支持动态配置。

与hostPath卷相比,可以以持久且可移植的方式使用本地卷,而无需手动将Pod调度到节点,因为系统通过查看PersistentVolume上的节点关联性来了解卷的节点约束。但是,本地卷仍受基础节点可用性的限制,并不适用于所有应用程序。 如果节点变得不健康,则本地卷也将变得不可访问,并且使用它的Pod将无法运行。使用本地卷的应用程序必须能够容忍这种降低的可用性以及潜在的数据丢失,具体取决于底层磁盘的持久性特征。

以下是使用本地卷和nodeAffinity的PersistentVolume规范的示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
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

使用本地卷时需要配置PersistentVolume的nodeAffinity。 它使Kubernetes调度程序能够使用本地卷正确地将Pod调度到正确的节点。

PersistentVolume的volumeMode现在可以设置为“Block”(而不是默认值“Filesystem”),以将本地卷公开为原始块设备。volumeMode字段需要启用BlockVolume的Alpha功能。

使用本地卷时,建议创建一个将volumeBindingMode设置为WaitForFirstConsumer的StorageClass。延迟卷绑定可确保PersistentVolumeClaim绑定决策也将使用Pod可能具有的任何其他节点约束进行评估,例如节点资源要求,节点选择器,Pod关联和Pod反关联。

可以单独运行外部静态配置程序,以改进对本地卷生命周期的管理。请注意,此配置程序尚不支持动态配置。有关如何运行外部本地配置程序的示例,请参阅本地卷配置程序用户指南

注意:如果外部静态配置器未用于管理卷生命周期,则本地PersistentVolume需要用户手动清理和删除。

NFS

nfs卷允许将现有NFS(网络文件系统)共享挂载到Pod中。与删除Pod时删除的emptyDir不同,nfs仅卸载卷,卷的内容将被保留。这意味着可以使用数据预先填充NFS卷,并且可以在Pod之间“切换”该数据。NFS可以由多个编写器同时挂载。

注意:必须先使用已导出的共享运行自己的NFS服务器,然后才能使用它。

用法示例请查看

persistentVolumeClaim

persistentVolumeClaim卷(持久卷声明)用于将PersistentVolume挂载到Pod中。PersistentVolumes是用户在不知道特定云环境的详细信息的情况下“声明”持久存储(例如GCE PersistentDisk或iSCSI卷)的一种方式。

有关更多详细信息,请参阅PersistentVolumes示例

projected

projected卷将几个现有卷源映射到同一目录中。

目前,可以映射以下类型的卷源:

  • secret
  • downwardAPI
  • configMap
  • serviceAccountToken

所有源都需要与Pod在同一名称空间中。serviceAccountToken的是Kubernetes 1.11中引入的功能,并在1.12中提升为Beta。要在1.11上启用此功能,需要将TokenRequestProjection功能门显式设置为True。

示例Pod包含密钥,downwardAPI和configmap:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
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,其中设置了非默认权限模式:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
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

每个projected卷源都列在源的规范中。参数几乎相同,但有两个例外:

  • 对于secret,secretName字段已更改为name以与ConfigMap命名一致。
  • defaultMode只能在预计级别指定,而不能在每个卷源中指定。但是,如上所示,可以为每个单独的卷映射明确设置mode模式。

启用TokenRequestProjection功能后,可以将当前service account的令牌注入指定路径的Pod。 以下是一个例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
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具有包含注入的服务帐户令牌的projected卷。 例如,Pod容器可以使用此标记来访问Kubernetes API服务器。 受众群体字段包含令牌的目标受众。令牌的接收者必须使用令牌的受众中指定的标识符来标识自己,否则应拒绝该令牌。此字段是可选字段,默认为API服务器的标识符。

expirationSeconds是服务帐户令牌的预期有效期。默认为1小时,且必须至少为10分钟(600秒)。管理员还可以通过为API服务器指定–service-account-max-token-expiration选项来限制其最大值。 path字段指定投影体积的挂载点的相对路径。

同样,projected卷也不支持对shubPath的更新。

### portworxVolume

portworxVolume是一个弹性块存储层,与Kubernetes运行超融合。Portworx指纹存储在服务器中,基于功能层,并聚合多个服务器之间的容量。 Portworx在虚拟机或裸机Linux节点上运行in-guest。

portworxVolume可以通过Kubernetes动态创建,也可以在Kubernetes Pod中预先配置和引用。以下是引用预先配置的PortworxVolume的Pod示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
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>"

更多细节参考

quobyte

一个quobyte卷允许将现有的Quobyte卷挂载到Pod中。

注意:必须先使用创建的卷运行自己的Quobyte设置,然后才能使用它。

Quobyte支持容器存储接口。CSI是推荐在Kubernetes中使用Quobyte卷的插件。Quobyte的GitHub项目提供了使用CSI部署Quobyte的说明以及示例。

rbd

rbd卷允许将Rados Block Device卷挂载到Pod中。与删除Pod时删除的emptyDir不同,rbd卷的内容将被保留,并且仅卸载卷。这意味着RBD卷可以预先填充数据,并且该数据可以在Pod之间“切换”。

注意:在使用RBD之前,必须先运行自己的Ceph挂载。

RBD的一个特点是它可以同时由多个消费者以只读方式挂载。这意味着您可以使用数据集预填充卷,然后根据需要从多个Pod中并行提供。不幸的是,RBD卷只能由一个消费者以读写模式挂载 - 不允许同时写入。

有关更多详细信息,请参阅RBD示例

scaleIO

ScaleIO是一个基于软件的存储平台,可以使用现有硬件来创建可伸缩共享块网络存储的集群。scaleIO卷插件允许已部署的Pod访问现有的ScaleIO卷(或者可以为持久卷声明动态配置新卷,请参阅ScaleIO持久卷)。

注意:必须先挂载现有的ScaleIO群集,并在创建卷之前运行它们,然后才能使用它们。

以下是使用ScaleIO的Pod配置示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
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

secret卷用于将敏感信息(如密码)传递给Pod。 可以将密钥存储在Kubernetes API中,并将其作为文件挂载以供Pod使用,而无需直接耦合到Kubernetes。secret卷由tmpfs(RAM支持的文件系统)支持,因此它们永远不会写入非易失性存储。

注意:您必须先在Kubernetes API中创建一个secret,然后才能使用它。且使用Secret作为子路径卷装入的Container将不会收到Secret更新。

这里将更详细地描述secret。

storageOS

storageos卷允许将现有StorageOS卷挂载到Pod中。

StorageOS在Kubernetes环境中作为Container运行,从而可以从Kubernetes集群中的任何节点访问本地或附加存储。可以复制数据以防止节点故障。 精简配置和压缩可以提高利用率并降低成本。

StorageOS的核心是为容器提供块存储,可通过文件系统访问。

StorageOS Container需要64位Linux,并且没有其他依赖项。 提供免费的开发人员许可。

注意:必须在要访问StorageOS卷的每个节点上运行StorageOS Container,或者为池提供存储容量。有关挂载说明,请参阅StorageOS文档

vsphereVolume

先决条件:已配置vSphere Cloud Provider的Kubernetes。有关cloudprovider配置,请参阅vSphere入门指南

vsphereVolume用于将vSphere VMDK卷装入Pod。在卸载卷时,将保留卷的内容。它支持VMFS和VSAN数据存储。

注意:在使用Pod之前,必须使用以下方法之一创建VMDK。

使用示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
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

使用subPath

有时,在单个Pod中共享一个卷用于多个用途很有用。volumeMounts.subPath属性可用于指定引用卷内的子路径而不是其根。

下面是使用单个共享卷的Pod与LAMP堆栈(Linux Apache Mysql PHP)的示例。HTML内容映射到其html文件夹,数据库将存储在其mysql文件夹中:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
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

使用带有扩展环境变量的subPath

API版本:Kubernetes v1.15 beta

使用subPathExpr字段从Downward API环境变量构造subPath目录名。 在使用此功能之前,必须启用VolumeSubpathEnvExpansion功能。subPath和subPathExpr属性是互斥的。

在如下示例中,Pod使用subPathExpr使用Downward API中的pod名称在hostPath卷/var/log/pods中创建目录pod1。 主机目录/var/log/pods/pod1挂载在容器中的/logs中。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
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