使用案例

PV 的全称是 Persistent Volume , PVC 的全称是 Persistent Volume Claim . 是由k8s提供的用于屏蔽复杂持久化存储项目(比如 Ceph, GlusterFs )的两个 API 对象.

在实际项目中, 可以由运营人员维护一个具体的 PV, 配置如下

kind: PersistentVolume
apiVersion: v1
metadata:
	name: pv-volume
	labels:
		type: local
spec:
	capacity:
	storage: 10Gi
	rbd:
		monitors:
			- '10.16.154.78:6789'
			- '10.16.154.82:6789'
			- '10.16.154.83:6789'
		pool: kube
		image: foo
		fsType: ext4
		readOnly: true
		user: admin
		keyring: /etc/ceph/keyring
		imageformat: "2"
		imagefeatures: "layering"

而对于开发人员来说, 无需关系PV的定义细节, 他只需要通过 PVC 来使用 Volume 即可, 通过如下方式定义一个 PVC

kind: PersistentVolumeClaim
apiVersion: v1
metadata:
	name: pv-claim
spec:
	accessModes:
		- ReadWriteOnce  # 其他值如: ReadOnlyMany, ReadWriteMany
	volumeMode: Filesystem  # 卷模型,用于指定此卷可被用作文件系统还是裸格式的块设备;默认为“Filesystem”。
	resources:
		requests:
			storage: 1Gi
	selector: # 可选, 要匹配的PV
		matchLables:
			release: "stable"
	# volumeName: ...  # 直接指定要绑定的 PV 卷名

然后在自己的应用中声明使用这个 PVC 即可

apiVersion: v1
kind: Pod
metadata:
	name: pv-pod
spec:
	containers:
		- name: pv-container
			image: nginx
			ports:
				- containerPort: 80
					name: "http-server"
			volumeMounts:
				- mountPath: "/usr/share/nginx/html"
					name: pv-storage
	volumes:
		- name: pv-storage
			persistentVolumeClaim:  # 指定上面创建的 PVC
				claimName: pv-claim

这样就可以通过 PVC 的方式屏蔽掉了底层关于持久化存储的细节, 就避免了因为向开发者暴露过多的存储系统细节而带来的隐患。

PersistentVolumeController

在k8s中存在一个专门的控制器 PersistentVolumeController , 它会不断地查看当前每一个 PVC,是不是已经处于 Bound(已绑定)状态。如果不是,那它就会遍历所有的、可用的 PV,并尝试将其与 PVC 进行绑定。这样,Kubernetes 就可以保证用户提交的每一个 PVC,只要有合适的 PV 出现,它就能够很快进入绑定状态。

而所谓将一个 PV 与 PVC 进行“绑定”,其实就是将这个 PV 对象的名字,填在了 PVC 对象的spec.volumeName 字段上。所以,接下来 Kubernetes 只要获取到这个 PVC 对象,就一定能够找到它所绑定的 PV。

PV

PV的实现依赖于远程存储服务, 这样 PV 还能被各Node上的不同 Pod 进行挂载.而 Kubernetes 需要做的工作,就是使用这些存储服务,来为容器准备一个持久化的宿主机目录,以供将来进行绑定挂载时使用。而所谓“持久化”,指的是容器在这个目录里写入的文件,都会保存在远程存储中,从而使得这个目录具备了“持久性”。

这个准备“持久化”宿主机目录的过程,我们可以形象地称为“两阶段处理”。

在两阶段处理中, 第一阶段先将远程服务的数据作为磁盘挂载到宿主机, 然后在第二阶段再通过 mount 将磁盘挂载到对应的宿主机上 Pod 运行时的 volume 目录, 有时候也可以跳过第一阶段, 直接挂载远程服务

PV 的处理流程独立于 kubelet 的主循环流程, 通过另外两个控制循环实现

其中负责第一阶段的主要是 AttachDetachController , 它的作用是不断地检查每一个Pod 对应的 PV,和这个 Pod 所在宿主机之间挂载情况。从而决定,是否需要对这个 PV 进行Attach(或者 Dettach)操作。它运行在 Master 节点上, 是 kube-controller-manager 的一部分.

<aside> ❓ AttachDetachController 运行在宿主机上? 如何加载远程磁盘?

</aside>