kubernetes 持久化的存储方式

emptyDir

emptyDir类型的Volume在Pod分配到Node上时被创建,Kubernetes会在Node上自动分配一个目录,因此无需指定宿主机Node上对应的目录文件。 这个目录的初始内容为空,当Pod从Node上移除时,emptyDir中的数据会被永久删除。
注:容器的crashing事件并不会导致emptyDir中的数据被删除。

使用场景

  • 临时空间,例如基于磁盘的合并排序
  • 设置检查点以从崩溃事件中恢复未执行完毕的长计算
  • 保存内容管理器容器从Web服务器容器提供数据时所获取的文件

例子

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
apiVersion: v1
kind: Pod
metadata:
name: test-pod
spec:
containers:
- image: busybox
name: test-emptydir
command: [ "sleep", "3600" ]
volumeMounts:
- mountPath: /data
name: data-volume
volumes:
- name: data-volume
emptyDir: {}

hostPath

hostPath类型则是映射node文件系统中的文件或者目录到pod里。在使用hostPath类型的存储卷时,也可以设置type字段,支持的类型有文件、目录、File、Socket、CharDevice和BlockDevice。

使用场景

  • 当运行的容器需要访问Docker内部结构时,如使用hostPath映射/var/lib/docker到容器
  • 当在容器中运行cAdvisor时,可以使用hostPath映射/dev/cgroups到容器中

注意事项

  • 配置相同的pod(如通过podTemplate创建),可能在不同的Node上表现不同,因为不同节点上映射的文件内容不同
  • 当Kubernetes增加了资源敏感的调度程序,hostPath使用的资源不会被计算在内
  • 宿主机下创建的目录只有root有写权限。你需要让你的程序运行在privileged container上,或者修改宿主机上的文件权限

例子

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
apiVersion: v1
kind: Pod
metadata:
name: test-pod2
spec:
containers:
- image: busybox
name: test-hostpath
command: [ "sleep", "3600" ]
volumeMounts:
- mountPath: /test-data
name: test-volume
volumes:
- name: test-volume
hostPath:
# directory location on host
path: /data
# this field is optional
type: Directory

StorageClass 完整例子

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
apiVersion: v1
kind: ServiceAccount
metadata:
name: hostpath-provisioner

---
kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1beta1
metadata:
name: hostpath-provisioner
rules:
- apiGroups: [""]
resources: ["persistentvolumes"]
verbs: ["get", "list", "watch", "create", "delete"]
- apiGroups: [""]
resources: ["persistentvolumeclaims"]
verbs: ["get", "list", "watch", "update"]
- apiGroups: ["storage.k8s.io"]
resources: ["storageclasses"]
verbs: ["get", "list", "watch"]
- apiGroups: [""]
resources: ["events"]
verbs: ["list", "watch", "create", "update", "patch"]

---
kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1beta1
metadata:
name: hostpath-provisioner
subjects:
- kind: ServiceAccount
name: hostpath-provisioner
namespace: default
roleRef:
kind: ClusterRole
name: hostpath-provisioner
apiGroup: rbac.authorization.k8s.io

---
apiVersion: rbac.authorization.k8s.io/v1beta1
kind: Role
metadata:
name: hostpath-provisioner
rules:
- apiGroups: [""]
resources: ["secrets"]
verbs: ["create", "get", "delete"]

---
apiVersion: rbac.authorization.k8s.io/v1beta1
kind: RoleBinding
metadata:
name: hostpath-provisioner
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: Role
name: hostpath-provisioner
subjects:
- kind: ServiceAccount
name: hostpath-provisioner

---
# -- Create a pod in the kube-system namespace to run the host path provisioner
apiVersion: v1
kind: Pod
metadata:
name: hostpath-provisioner
spec:
serviceAccountName: hostpath-provisioner
containers:
- name: hostpath-provisioner
image: registry.cn-hangzhou.aliyuncs.com/chinaqqpub/k8s.hostpath-provisioner:latest
imagePullPolicy: "IfNotPresent"
env:
- name: NODE_NAME
valueFrom:
fieldRef:
fieldPath: spec.nodeName
- name: PV_DIR
value: /mnt/kubernetes-pv-manual
volumeMounts:
- name: pv-volume
mountPath: /mnt/kubernetes-pv-manual
volumes:
- name: pv-volume
hostPath:
path: /mnt/kubernetes-pv-manual

---
# -- Create the standard storage class for running on-node hostpath storage
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: manual
labels:
kubernetes.io/cluster-service: "true"
addonmanager.kubernetes.io/mode: EnsureExists
provisioner: hostpath

---
# 创建pvc进行测试
kind: PersistentVolumeClaim
apiVersion: v1
metadata:
name: hostpath-pvc-test
spec:
accessModes:
- ReadWriteMany
resources:
requests:
storage: 100Mi
storageClassName: manual

local volume

这是一个很新的存储类型,建议在k8s v1.10+以上的版本中使用。该local volume类型目前还只是beta版。

Local volume 允许用户通过标准PVC接口以简单且可移植的方式访问node节点的本地存储。 PV的定义中需要包含描述节点亲和性的信息,k8s系统则使用该信息将容器调度到正确的node节点。

配置要求

  • 使用local-volume插件时,要求使用到了存储设备名或路径都相对固定,不会随着系统重启或增加、减少磁盘而发生变化
  • 静态provisioner配置程序仅支持发现和管理挂载点(对于Filesystem模式存储卷)或符号链接(对于块设备模式存储卷)。 对于基于本地目录的存储卷,必须将它们通过bind-mounted的方式绑定到发现目录中

风险

local volume仍受node节点可用性方面的限制,因此并不适用于所有应用程序。 如果node节点变得不健康,则local volume也将变得不可访问,使用这个local volume的Pod也将无法运行。 使用local voluems的应用程序必须能够容忍这种降低的可用性以及潜在的数据丢失,是否会真得导致这个后果将取决于node节点底层磁盘存储与数据保护的具体实现了。

例子

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
# StorageClass
kind: StorageClass
apiVersion: storage.k8s.io/v1
metadata:
name: local-storage
provisioner: kubernetes.io/no-provisioner
volumeBindingMode: WaitForFirstConsumer

---
# PV
apiVersion: v1
kind: PersistentVolume
metadata:
name: example-pv
spec:
capacity:
storage: 100Gi
volumeMode: Filesystem
accessModes:
- ReadWriteOnce
persistentVolumeReclaimPolicy: Delete
storageClassName: local-storage
local:
path: /mnt/disks/ssd1
nodeAffinity:
required:
nodeSelectorTerms:
- matchExpressions:
- key: kubernetes.io/hostname
operator: In
values:
- example-node

参考

https://www.kubernetes.org.cn/4846.html