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 的方式屏蔽掉了底层关于持久化存储的细节, 就避免了因为向开发者暴露过多的存储系统细节而带来的隐患。
在k8s中存在一个专门的控制器 PersistentVolumeController
, 它会不断地查看当前每一个 PVC,是不是已经处于 Bound(已绑定)状态。如果不是,那它就会遍历所有的、可用的 PV,并尝试将其与 PVC 进行绑定。这样,Kubernetes 就可以保证用户提交的每一个 PVC,只要有合适的 PV 出现,它就能够很快进入绑定状态。
而所谓将一个 PV 与 PVC 进行“绑定”,其实就是将这个 PV 对象的名字,填在了 PVC 对象的spec.volumeName 字段上。所以,接下来 Kubernetes 只要获取到这个 PVC 对象,就一定能够找到它所绑定的 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>