Volume补

Local Persistent Volume

Kubernetes 能够直接使用宿主机上的本地磁盘目录,而不依赖于远程存储服务,来提供“持久化”的容器 Volume

比于正常的 PV,一旦这些节点宕机且不能恢复时,Local Persistent Volume 的数据就可能丢失,使用 Local Persistent Volume 的应用必须具备数据备份和恢复的能力,允许你把这些数据定时备份在其他位置。

难点:

  1. 如何把本地磁盘抽象成 PV ()
  2. 保证 Pod 始终能被正确地调度到它所请求的 Local Persistent Volume 所在的节点上

不应该把一个宿主机上的目录当作 PV 使用。这种本地目录的存储行为完全不可控,它所在的磁盘随时都可能被应用写满,甚至造成整个宿主机宕机. 最好一块额外挂载在宿主机的磁盘或者块设备。(“一个 PV 一块盘”)

调度器就必须能够知道所有节点与 Local Persistent Volume 对应的磁盘的关联关系,然后根据这个信息来调度 Pod。(“在调度的时候考虑 Volume 分布”)

示例

  1. 在名叫 node-1 的宿主机上创建一个挂载点,比如 /mnt/disks;然后,用几个 RAM Disk 来模拟本地磁盘
1
2
3
4
5
6
7

# 在node-1上执行
$ mkdir /mnt/disks
$ for vol in vol1 vol2 vol3; do
mkdir /mnt/disks/$vol
mount -t tmpfs $vol /mnt/disks/$vol
done
  1. 为这些本地磁盘定义对应的 PV

    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: PersistentVolume
    metadata:
    name: example-pv
    spec:
    capacity:
    storage: 5Gi
    volumeMode: Filesystem
    accessModes:
    - ReadWriteOnce
    persistentVolumeReclaimPolicy: Delete
    storageClassName: local-storage # 对应
    local:
    path: /mnt/disks/vol1
    nodeAffinity:
    required:
    nodeSelectorTerms:
    - matchExpressions:
    - key: kubernetes.io/hostname
    operator: In
    values:
    - node-1
  2. 创建一个 StorageClass 来描述这个 PV

1
2
3
4
5
6
kind: StorageClass
apiVersion: storage.k8s.io/v1
metadata:
name: local-storage # 对应
provisioner: kubernetes.io/no-provisioner # Local Persistent Volume 目前尚不支持 Dynamic Provisioning
volumeBindingMode: WaitForFirstConsumer # 延迟绑定 原本实时发生的 PVC 和 PV 的绑定过程,就被延迟到了 Pod 第一次调度的时候在调度器中进行
  1. 创建 PVC,apply 后还不会绑定 ,pending 状态

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12

    kind: PersistentVolumeClaim
    apiVersion: v1
    metadata:
    name: example-local-claim
    spec:
    accessModes:
    - ReadWriteOnce
    resources:
    requests:
    storage: 5Gi
    storageClassName: local-storage # 对应
  2. 编写一个 Pod 来声明使用这个 PVC

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19

    kind: Pod
    apiVersion: v1
    metadata:
    name: example-pv-pod
    spec:
    volumes:
    - name: example-pv-storage
    persistentVolumeClaim:
    claimName: example-local-claim # pvc name
    containers:
    - name: example-pv-container
    image: nginx
    ports:
    - containerPort: 80
    name: "http-server"
    volumeMounts:
    - mountPath: "/usr/share/nginx/html"
    name: example-pv-storage

删除流程:

  1. 删除使用这个 PV 的 Pod
  2. 从宿主机移除本地磁盘(比如,umount 它)
  3. 删除 PVC
  4. 删除 PV

如果不按照这个流程的话,这个 PV 的删除就会失败

csi

CSI 的设计思想,把插件的职责从“两阶段处理”,扩展成了 ProvisionAttachMount 三个阶段。

  1. Provision 等价于“创建磁盘”
  2. Attach 等价于“挂载磁盘到虚拟机”
  3. Mount 等价于“将该磁盘格式化后,挂载在 Volume 的宿主机目录上”。
1
2
3
4
5
6
7
8
kind: StorageClass
apiVersion: storage.k8s.io/v1
metadata:
name: do-block-storage
namespace: kube-system
annotations:
storageclass.kubernetes.io/is-default-class: "true" # 使用这个 StorageClass 作为默认的持久化存储提供者
provisioner: com.digitalocean.csi.dobs # 使用 com.digitalocean.csi.dobs 的 CSI 插件处理这个 StorageClass 相关的所有操作

具体用到了再看吧