Docker K8s 10 存储管理

K8s 的存储卷(Volume) 是 Docker Volume 的升级版. 一般 Container 和 Pod 是暂时的, 会被频繁的创建销毁. 容器内部文件系统随之消失. 而且多个容器也有共享数据的需求.

存储卷生命周期独立于容器. 存储卷是一个目录, 会被挂载到 Pod 上, 相同 Pod 的多个 Container 都可以访问. 存储卷提供了多种后端类型抽象支持, 并且无需关心具体存储, 只当是本地目录.

存储卷类型

emptyDir

生命周期与 Pod 一致, 是本地主机的一个目录, 对于 Container 来说是持久的, 随着 Pod 删除消亡.

创建 Pod 的时候定义卷 .spec.volumes

1
2
3
volumes:
- name: <VOLUME_NAME>
emptyDir: {}

在容器中挂载卷到 /data 路径

1
2
3
volumeMounts:
- mountPath: /data
name: <VOLUME_NAME>

通常在主机的目录地址为: /var/lib/kubelet/pods/<pod uuid>/volumes

hostPath

一般不使用, 会增加 Pod 与系统的耦合. 使用场景一般是在 DaemonSet 访问 Docker 或者 K8s 的系统数据.

创建 Pod 的时候定义卷 .spec.volumes

1
2
3
4
volumes:
- name: <VOLUME_NAME>
hostPath:
path: # 主机系统路径

NFS

网络文件系统(Network File System), 通过局域网让不同主机共享目录文件, 通常为 C/S 模型, 将服务端大容量磁盘映射到本地. 使用此类型需要在 Node 上安装对应组件.

创建 Pod 的时候定义卷 .spec.volumes

1
2
3
4
5
volumes:
- name: <VOLUME_NAME>
nfs:
server: <SERVER_IP>
path: <SERVER_PATH> # SERVER 主机系统路径

Secret

用于保存小规模私密数据, 用户名, 密码, 密钥等. 私密卷创建独立于 Pod.

创建私密卷

1
2
3
4
5
6
7
apiVersion: v1
kind: Secret
metadata:
name: <SECRET_VOLUME_NAME>
type: Opaque
data:
# k: v 数据

也可以使用文件(或者指定文件夹下所有文件), 格式为文件名为 key, 内容为 value.
也可以手动指定

1
kubectl create secret <SECRET_VOLUME_NAME> --type=Opaque --from-file=filename --from-literal=key=value

创建 Pod 的时候挂载私密卷 .spec.volumes

1
2
3
4
volumes:
- name: <VOLUME_NAME>
secret:
secretName: <SECRET_VOLUME_NAME>

在容器中挂载卷到 /secret 路径, 设置为只读

1
2
3
4
volumeMounts:
- mountPath: /secret
name: <VOLUME_NAME>
readOnly: true

使用的时候, 直接读取名为 <key> 的文件即可得到 <value> 数据.

iSCSI

iSCSI 与 emptyDir 类似, 但是 iSCSI 是挂载整块磁盘, 不是单一目录, 而且删除 Pod 的时候不会删除 iSCSI, 只是卸载.

创建 Pod 的时候挂载卷 .spec.volumes

1
2
3
4
5
6
7
8
9
volumes:
- name: <VOLUME_NAME>
iscsi:
targetPortal: IP:PORT
partals: ['IP:PORT', ...]
iqn:
lun:
fsType: ext4
readOnly: true

持久化数据卷

存储卷在可管理性上存在一定问题. Pod 开发者使用时需要知道各种卷的实现细节, 这给运维带来非常多的不变.

持久化存储卷(Persistent Volume)的概念, 用于搭建 Pod 和 Volume 之间的桥梁. 对不同 Volume 类型进行封装, 向 Pod 提供统一的服务. Pod 使用者只需要知道需要多少资源, 如何使用资源即可, 无需知道资源如何来, 怎么实现的.

持久化数据卷有自己的生命周期

  • 提供 Provision: 系统管理员静态手动创建, 或者根据需求动态自动创建, 提供存储卷
  • 请求 Claim 普通用户根据业务需求, 在集群中发起存储资源请求, 描述需求和访问模式
  • 绑定 Bind 根据请求大小以及访问模式, 查找存储卷建立绑定关系. 一个持久化存储卷只能绑定给一个用户.
  • 使用 Use 将持久化存储卷当成普通卷使用
  • 释放 Release 使用完后, 请求删掉, 卷被标记为释放(released)状态, 准备回收
  • 回收 Recycle 根据回收策略回收释放的卷. 回收策略有 保留(retained)-不变, 回收(recycled)-删数据, 删除(deleted)-删卷

静态绑定

Pod 在使用时正常挂载

1
2
3
4
volumes:
- name: <VOLUME_NAME>
persistentVolumeClaim:
claimName: <PERSISTENT_VOLUME_CLAIM_NAME>

请求数据卷

1
2
3
4
5
6
7
8
9
10
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: <PERSISTENT_VOLUME_CLAIM_NAME>
spec:
accessMode:
- ReadWriteMany
resources:
request:
storage: 1Gi

定义持久化存储, 使用 NFS 作为实际存储卷

1
2
3
4
5
6
7
8
9
10
11
12
13
apiVersion: v1
type: PersistentVolume
metadata:
name: <PERSISTENT_VOLUME_NAME>
spec:
capacity:
storage: 2Gi
accessModes:
- ReadWriteMany
persistentVolumeReclaimPolicy: Recycle
nfs:
server: <SERVER_IP>
path: <SERVER_PATH> # SERVER 主机系统路径

查看持久化存储, 持久化存储请求, 以及持久化存储在服务中的情况

1
2
3
kubectl get pv
kubectl get pvc
kubectl describe pod <POD_NAME>

动态绑定

Pod 在使用时正常挂载

1
2
3
4
volumes:
- name: <VOLUME_NAME>
persistentVolumeClaim:
claimName: <PERSISTENT_VOLUME_CLAIM_NAME>

请求数据卷

1
2
3
4
5
6
7
8
9
10
11
12
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: <PERSISTENT_VOLUME_CLAIM_NAME>
annotations:
volume.beta.kubernetes.io/storage-class: <STORAGE_CLASS_NAME>
spec:
accessMode:
- ReadWriteMany
resources:
request:
storage: 1Gi

定义 StorageClass

1
2
3
4
5
6
7
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: <STORAGE_CLASS_NAME>
provisioner: <PROVISIONER_NAME_VALUE>
parameters:
archiveOnDelete: false

定义存储供应商

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# ...
metadata:
name: <EXTERNAL_STORAGE_NAME>
containers:
- name: ...
volumeMounts:
- name: <VOLUME_NAME>
mountPath: # 挂载的本地目录位置
env:
- name: PROVISIONER_NAME # env 环境变量, 就是 PROVISIONER_NAME
value: <PROVISIONER_NAME_VALUE> # env 环境变量值, 需要改成详细的值
- name: NFS_SERVER
value: <SERVER_IP>
- name: NFS_PATH
value: <SERVER_PATH>
volumes:
- name: <VOLUME_NAME>
nfs:
server: <SERVER_IP> # 服务器地址
path: <SERVER_PATH> # 服务器的目录位置

除此之外, 还需要创建 ServiceAccount, ClusterRole, ClusterRoleBinding, 并且给 打一个 patch 进行授权.

之后, Pod 中直接使用加载资源 持久化数据卷请求 , 即可自动创建数据卷.

数据卷回收策略

保留 Retain

用户手动回收资源

持久化数据卷请求(Persistent Volume Claim), 也可以翻译成存储卷.
持久化数据卷(Persistent Volume)

  • 删除 pod 持久化数据卷请求仍然存在, 持久化数据卷仍然存在, 文件在 NFS 磁盘仍然存在.
  • 删除持久化数据卷请求, 持久化数据卷仍然存在(Bound->Released), 文件在 NFS 磁盘仍然存在.
  • 删除持久化数据卷, 文件在 NFS 磁盘仍然存在.

这意味着, 在保留模式下, 数据的生命周期独立于所有资源. 如果需要删除需要登录 NFS 手动删除文件.

当 Pod 删除后, 持久化数据卷请求可以被其他 Pod 复用.
当持久化数据卷请求删除后, 持久化数据卷状态为 Released, 无法复用, 只能删除.
这时想要复用数据, 可以删除持久化数据卷, 重新创建持久化数据卷, 并且绑定新的持久化数据卷请求.

回收 Recycle

持久化数据卷请求删除时, 清空持久化数据卷数据, 使持久化数据卷可以重新被绑定.

以后会删除, 使用动态绑定方式替代.

删除 Delete

从集群删除持久化存储卷的同时, 删除在外部存储设施中的文件.

Donate - Support to make this site better.
捐助 - 支持我让我做得更好.