文章目录
- 01 引言
- 02 PVC详解
- 2.1 参数配置
- 2.1.1 资源请求(Resources)
- 2.1.2 访问模式 (Access Modes)
- 2.1.3 存储卷模式(Volume Modes)
- 2.1.4 PV选择条件 (Selector)
- 2.1.5 存储类别(Class)
- 03 Pod使用PVC
- 3.1 举例
- 3.1.1 举例:默认模式 (Filesystem)
- 3.1.2 举例:存储卷模式为块设备(Block)
- 04 文末
01 引言
声明:本文为《Kubernetes权威指南:从Docker到Kubernetes实践全接触(第5版)》的读书笔记
在上一篇博客《k8s教程(Volume篇)-PV详解》,我们了解了持久卷的工作原理,本文继续深入学习PVC。
02 PVC详解
PVC
作为用户对存储资源的需求申请,主要涉及存储空间请求、访问模式、 PV选择条件和存储类别等信息的设置。
2.1 参数配置
下例声明的PVC具有如下属性:申请8GiB存储空间,访问模式为ReadWriteOnce,PV选择条件为包含release=stable标签并且包含条件为environment In[dev]的标签,存储类别为“slow”(要求在系统中已存在名为slow的StorageClass):
apiVersion: v1
kind: PersistentVolumeclaim
metadata:
name: myclaim
spec:
accessModes:
- ReadWriteOnce
volumeMode: Filesystem
resources:
requests:
storage: 8Gi
storageClassName: slow
selector:
matchLabels:
release: "stable"
matchExpressions:
- {key: environment, operator: In, values: [dev]}
对PVC的关键配置参数说明如下:
2.1.1 资源请求(Resources)
资源请求(Resources):描述对存储资源的请求,通过 resources.requests.storage字段设置需要的存储空间大小。
2.1.2 访问模式 (Access Modes)
访问模式 (Access Modes):PVC也可以设置访问模式,用于描述用户应用对存储资源的访问权限。其三种访问模式的设置与PV的设置相同。
2.1.3 存储卷模式(Volume Modes)
存储卷模式(Volume Modes):PVC也可以设置存储卷模式,用于描述希望使用的PV存储卷模式,包括文件系统(Filesystem)和块设备 (Block) 。
PVC设置的存储卷模式应该与PV存储卷模式相同,以实现绑定,如果不同,则可能出现不同的绑定结果。在各种组合模式下是否可以绑定的结果如下图所示:
PV的存储卷模式 | PVC的存储卷模式 | 是否可以绑定 |
未设定 | 未设定 | 可以绑定 |
未设定 | Block | 无法绑定 |
未设定 | FileSystem | 可以绑定 |
Block | 未设定 | 无法绑定 |
Block | Block | 可以绑定 |
Block | FileSystem | 无法绑定 |
FileSystem | FileSystem | 可以绑定 |
FileSystem | Block | 无法绑定 |
FileSystem | 未设定 | 可以绑定 |
2.1.4 PV选择条件 (Selector)
PV选择条件 (Selector):通过Label Selector
的设置,可使PVC
对于系统中己存在的各种PV
进行筛选。系统将根据标签选出合适的PV
与该PVC
进行绑定。
对选择条件可以使用matchLabels
和matchExpressions
进行设置,如果两个字段都已设置,则Selector
的逻辑将是两组条件同时满足才能完成匹配。
2.1.5 存储类别(Class)
存储类别(Class):PVC在定义时可以设定需要的后端存储的类别(通过storageClassName字段指定),以减少对后端存储特性的详细信息的依赖。只有设置了该Class
的PV
才能被系统选出,并与该PVC
进行绑定。
PVC
也可以不设置Class
需求,如果storageClassName
字段的值被设置为空 (storageClassName=""
),则表示该PVC
不要求特定的Class
,系统将只选择未设定Class
的PV
与之匹配和绑定。PVC
也可以完全不设置storageClassName
字段, 此时将根据系统是否启用了名为DefaultStorageClass
的admission controller
进行相应的操作。
启用DefaultStorageClass:要求集群管理员己定义默认的StorageClass。
- 如果在系统中不存在默认的StorageClass,则等效于不启用DefaultStorageClass的情况;
- 如果存在默认的StorageClass,则系统将自动为PVC创建一个PV (使用默认StorageClass的后端存储),并将它们进行绑定;
- 集群管理员设置默认 StorageClass 时,会在 StorageClass 的定义中加上一个 annotation“storageclass.kubernetes.io/is-default-class=true”;
- 如果管理员将多个StorageClass都定义为default,则由于不唯一,系统将无法创建PVC。
未启用DefaultStorageClass:等效于PVC设置storageClassName的值为空(storageClassName=“),即只能选择未设定Class的PV与之匹配和绑定。
- 当Selector和Class都进行了设置时,系统将选择两个条件同时满足的PV与之匹配。
另外,如果PVC设置了Selector,则系统无法使用动态供给模式为其分配PV。
03 Pod使用PVC
在PVC
创建成功之后,Pod
就可以以存储卷(Volume
)的方式使用PVC
的存储资源了。
PVC受限于命名空间,Pod在使用PVC时必须与PVC处于同一个命名空间。
Kubernetes为Pod挂载PVC的过程如下:系统在Pod所在的命名空间中找到其配置的PVC,然后找到PVC绑定的后端PV,将PV存储挂载到Pod所在Node的目录下,最后将Node的目录挂载到Pod的容器内。
3.1 举例
3.1.1 举例:默认模式 (Filesystem)
在Pod中使用PVC时,需要在YAML配置中设置PVC类型的Volume,然后在容器中通过volumeMounts.mountPath设置容器内的挂载目录,示例如下:
apiversion: v1
kind: Pod
metadata:
name: mypod
spec:
containers:
- name: myfrontend
image: nginx
volumeMounts:
- mountPath: "/var/www/html"
name: mypd
volumes:
- name: mypd
persistentVolumeClaim:
claimName: myclaim
3.1.2 举例:存储卷模式为块设备(Block)
如果存储卷模式为块设备(Block),则PVC的配置与默认模式 (Filesystem)略有不同,下面对如何使用裸块设备 (Raw Block Device) 进行说明。
假设使用裸块设备的PV已创建,例如:
apiVersion: V1
kind: PersistentVolume
metadata:
name: block-pv
spec:
capacity:
storage: 10Gi
accessModes:
- ReadwriteOnce
volumeMode: Block
persistentVolumeReclaimPolicy: Retain
fc:
targetWwNs: ["50060e801049cfa1"]
lun: 0
readOnly: false
PVC的YAML配置示例如下:
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: block-pvc
spec:
accessModes:
- ReadWriteOnce
volumeMode: Block
resources:
requests:
storage: 10Gi
使用裸块设备PVC的Pod定义如下:
与文件系统模式PVC的用法不同,容器不使用volumeMounts设置挂载目录,而是通过volumeDevices字段设置块设备的路径devicePath
apiVersion: v1
kind: Pod
metadata:
name: pod-with-block-volume
spec:
containers:
- name: fc-container
image: fedora:26
conmand: ["/bin/sh", "-c"]
args: ["tail -f /dev/nul1"]
volumeDevices:
- name: data
devicePath: /dev/xvda
volumes:
- name: data
persistentVolumeClaim:
claimName: block-pvc
在某些应用场景中,同一个Volume可能会被多个Pod或者一个Pod中的多个容器共享,此时可能存在各应用程序需要使用不同子目录的需求。这可以通过Pod 的volumeMounts定义的subPath字段进行设置。通过对subPath的设置,在容器中将以subPath设置的目录而不是在Volume中提供的默认根目录作为根目录使用。
下面的两个容器共享同一个PVC(及后端PV),但是各自在Volume中可以访问的根目录由subPath进行区分,mysql容器使用Volume中的mysql子目录作为根目录,php容器使用Volume中的html子目录作为根目录:
apiVersion: v1
kind: Pod
metadata:
name: mysql
spec:
containers:
- name: mysql
image: mysql
env:
name: MY_SQL_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
suoPath: html
volumes:
- name: site-data
persistentVolumeClain:
claimName: site-data-pvc
注意,subPath
中的路径名称不能以“/
”开头,需要用相对路径的形式。
在一些应用场景中,如果希望通过环境变量来设置
subPath
路径,例如使用Pod
名称作为子目录的名称,则可以通过subPathExpr
字段提供支持。subPathExpr
字段用于将Downward API
的环境变量设置为存储卷的子目录。需要注意的是,subPathExpr
字段和subPath
字段是互斥的,不能同时使用。
下面的例子通过Downward API
将Pod
名称设置为环境变量POD_NAME
,然后在挂载存储卷时设置subPathExpr=$ (POD_NAME)
子目录:
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 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
04 文末
本文主要讲解了PVC,以及Pod使用PVC,希望能帮助到大家,谢谢大家的阅读,本文完!