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未设定无法绑定
BlockBlock可以绑定
BlockFileSystem无法绑定
FileSystemFileSystem可以绑定
FileSystemBlock无法绑定
FileSystem未设定可以绑定

2.1.4 PV选择条件 (Selector)

PV选择条件 (Selector)通过Label Selector的设置,可使PVC对于系统中己存在的各种PV进行筛选。系统将根据标签选出合适的PV与该PVC进行绑定

对选择条件可以使用matchLabelsmatchExpressions进行设置,如果两个字段都已设置,则Selector的逻辑将是两组条件同时满足才能完成匹配

2.1.5 存储类别(Class)

存储类别(Class)PVC在定义时可以设定需要的后端存储的类别(通过storageClassName字段指定),以减少对后端存储特性的详细信息的依赖。只有设置了该ClassPV才能被系统选出,并与该PVC进行绑定

PVC也可以不设置 Class 需求,如果 storageClassName 字段的值被设置为空 (storageClassName=""),则表示该PVC不要求特定的Class,系统将只选择未设定ClassPV与之匹配和绑定。PVC也可以完全不设置storageClassName字段, 此时将根据系统是否启用了名为DefaultStorageClassadmission 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 APIPod名称设置为环境变量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,希望能帮助到大家,谢谢大家的阅读,本文完!

Logo

K8S/Kubernetes社区为您提供最前沿的新闻资讯和知识内容

更多推荐