Kubernetes持久化储存

1、K8s持久化储存介绍

​ 之前接触hostpath、emptyDir的是本地储存,缺陷数据不能做到和其他机器共享

​ 容器内部的的存储在生命周期是短暂的,会随着容器环境的销毁而销毁,具有不稳定性,在k8s里将对容器应用所需的存储资源抽象为存储卷(Volume)概念来解决这些问题。

K8s目前支持的Volume类型包括k8s的内部资源对象类型,开源共享存储类型和公有云存储等。分类如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#K8s特定的资源对象
configMap:储存配置文件 (配置中心:nacos)
Secret:储存加密数据,证书文件
ServiceAccountToken:储存token数据


#本地储存:pod起在哪,数据就在哪个机器
EmptDir:临时储存(宿主机随机生成一个储存目录)
HostPath:宿主机目录


#网络共享储存
CephFS:开源共享储存系统(现在用的比较多一些)
ClusterFS:开源共享储存系统 FastDFS
NFS:开源共享储存 (这个是单点,写脚本会卡主)


#PV共享存储:
PersishtenVolumeClain:

2、本地储存——EmptyDir类型的挂载方式

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
1、编写Deployment控制器的资源清单
[root@master01 kubernetes]# vim nginx-emptDir.yml
apiVersion: "apps/v1"
kind: "Deployment"
metadata:
name: nginx-dp
namespace: default
spec:
replicas: 1
selector:
matchLabels:
app: mysql-dp
template:
metadata:
name: nginx-dp-pod
namespace: default
labels:
app: mysql-dp
spec:
volumes:
- name: mysql-emptydir
emptyDir: {}
containers:
- name: mysql-container
image: mysql:5.7
imagePullPolicy: IfNotPresent
env:
- name: MYSQL_ROOT_PASSWORD
value: '123'
volumeMounts:
- name: mysql-emptydir
mountPath: /var/lib/mysql

2、运行并查看
[root@master01 kubernetes]# kubectl apply -f nginx-emptDir.yml
[root@master01 kubernetes]# kubectl get pod -owide
NAME READY STATUS RESTARTS AGE IP NODE
nginx-dp-67b5bd5fdc-kvjqh 1/1 Running 0 18s 10.2.3.119 node03

3、node03查看挂载的数据
[root@node03 ~]# docker inspect fb799f13d7e9
[root@node03 ~]# ll /var/lib/kubelet/pods/9be94529-0040-4185-91c8-91b4b271d387/volumes/kubernetes.io~empty-dir/mysql-emptydir
-rw-r----- 1 polkitd input 56 Sep 28 11:53 auto.cnf
-rw------- 1 polkitd input 1680 Sep 28 11:53 ca-key.pem
-rw-r--r-- 1 polkitd input 1112 Sep 28 11:53 ca.pem
-rw-r--r-- 1 polkitd input 1112 Sep 28 11:53 client-cert.pem
-rw------- 1 polkitd input 1680 Sep 28 11:53 client-key.pem
-rw-r----- 1 polkitd input 1318 Sep 28 11:53 ib_buffer_pool
-rw-r----- 1 polkitd input 79691776 Sep 28 11:53 ibdata1
-rw-r----- 1 polkitd input 50331648 Sep 28 11:53 ib_logfile0
-rw-r----- 1 polkitd input 50331648 Sep 28 11:53 ib_logfile1
-rw-r----- 1 polkitd input 12582912 Sep 28 11:53 ibtmp1
drwxr-x--- 2 polkitd input 4096 Sep 28 11:53 mysql
lrwxrwxrwx 1 polkitd input 27 Sep 28 11:53 mysql.sock -> /var/run/mysqld/mysqld.sock
drwxr-x--- 2 polkitd input 8192 Sep 28 11:53 performance_schema
-rw------- 1 polkitd input 1680 Sep 28 11:53 private_key.pem
-rw-r--r-- 1 polkitd input 452 Sep 28 11:53 public_key.pem
-rw-r--r-- 1 polkitd input 1112 Sep 28 11:53 server-cert.pem
-rw------- 1 polkitd input 1680 Sep 28 11:53 server-key.pem
drwxr-x--- 2 polkitd input 8192 Sep 28 11:53 sys

3、本地储存——hostpath类型

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
1、编写控制器的资源清单
[root@master01 kubernetes]# vim nginx-hostpath.yml
apiVersion: "apps/v1"
kind: "Deployment"
metadata:
name: nginx-dp
namespace: default
spec:
replicas: 1
selector:
matchLabels:
app: mysql-dp
template:
metadata:
name: nginx-dp-pod
namespace: default
labels:
app: mysql-dp
spec:
volumes:
- name: mysql-emptydir
emptyDir: {}
- name: mysql-hostpath
hostPath:
path: /opt/mysql
containers:
- name: mysql-container
image: mysql:5.7
imagePullPolicy: IfNotPresent
env:
- name: MYSQL_ROOT_PASSWORD
value: '123'
volumeMounts:
- name: mysql-hostpath
mountPath: /var/lib/mysql


[root@master01 kubernetes]# kubectl apply -f nginx-hostpath.yml

4、共享储存——NFS类型

image-20240928175642454

1、部署NFS

环境准备

主机名 ip 角色
nfs 10.0.0.31 / 172.16.1.31
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#NFS服务器不能起在Pod里的,储存类的几乎不会用pod去起的

1、NFS服务安装NFS
[root@nfs ~]# yum -y install nfs-utils

2、node节点要挂载过去,所有node节点安装nfs
[root@node01 ~]# yum -y install nfs-utils
[root@node02 ~]# yum -y install nfs-utils
[root@node03 ~]# yum -y install nfs-utils

3、修改nfs服务器的配置文件
[root@nfs ~]# vim /etc/exports
/data/wp 172.16.1.0/24(rw,sync,all_squash)

4、创建挂载目录,并授权,启动服务
[root@nfs ~]# mkdir -p /data/wp
[root@nfs ~]# chown -R nfsnobody.nfsnobody /data/wp
[root@nfs ~]# systemctl start nfs && systemctl enable nfs

5、验证生效
[root@nfs ~]# cat /var/lib/nfs/etab
/data/wp 172.16.1.0/24(rw,sync,wdelay,hide,nocrossmnt,secure,root_squash,all_squash,no_subtree_check,secure_locks,acl,no_pnfs,anonuid=65534,anongid=65534,sec=sys,rw,secure,root_squash,all_squash)

2、master编写wp挂载nfs的资源清单

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
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
1、编写wp的Deployment资源清单
[root@master01 kubernetes]# vim wp-dp-v1.yml
apiVersion: "apps/v1"
kind: "Deployment"
metadata:
name: wp-dp
namespace: default
spec:
#起2个,数据也是2个,除非把数据分开
replicas: 2
selector:
matchLabels:
app: wp
template:
metadata:
name: wp-pod
namespace: default
labels:
app: wp
spec:
volumes:
- name: wp-data
hostPath:
path: /data/wp

#-----------------挂载nfs的写法---------------------
#最后一行挂载的名字要改一下
# mount -t nfs 172.16.1.31:/data/wordpress /var/www/html
- name: wp-nfs
nfs:
#nfs服务器配置文件写的共享目录
path: /data/wp
readOnly: false
#server就是nfs服务的ip
server: 172.16.1.31

containers:
- name: wp-container
image: wordpress
imagePullPolicy: IfNotPresent
#livenessProbe:
# tcpSocket:
# port: 80
# initialDelaySeconds: 10
# periodSeconds: 3
# timeoutSeconds: 3
# failureThreshold: 3
#readinessProbe:
# tcpSocket:
# host: mysql-svc
# port: 3306
# initialDelaySeconds: 3
# timeoutSeconds: 1
# periodSeconds: 2
# successThreshold: 3
# failureThreshold: 3
env:
- name: WORDPRESS_DB_HOST
value: 'mysql-svc'
- name: WORDPRESS_DB_USER
value: 'wp_user'
- name: WORDPRESS_DB_PASSWORD
value: '123'
- name: WORDPRESS_DB_NAME
value: 'wp_db'

volumeMounts:
- name: wp-nfs
mountPath: /var/www/html/

[root@master01 kubernetes]# kubectl apply -f wp-dp-v1.yml


2、编写wp的Service资源
[root@master01 kubernetes]# vim wp-svc.yml
apiVersion: v1
kind: Service
metadata:
name: wordpress-svc
namespace: default
spec:
selector:
app: wp
ports:
- name: http
port: 80
protocol: TCP
#这里临时为了测试,所以临时使用NodePort
targetPort: 80
nodePort: 30002
type: NodePort

[root@master01 kubernetes]# kubectl apply -f wp-svc.yml
[root@master01 kubernetes]# kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S)
wordpress-svc NodePort 10.1.84.160 <none> 80:30002/TCP

3、编写mysql的Deployment资源
[root@master01 kubernetes]# vim mysql-dp.yml
apiVersion: "apps/v1"
kind: "Deployment"
metadata:
name: mysql-dp
namespace: default
spec:
replicas: 1
selector:
matchLabels:
app: mysql-dp
template:
metadata:
name: mysql-pod
namespace: default
labels:
app: mysql-dp
spec:
volumes:
- name: mysql-emptydir
emptyDir: {}
- name: mysql-hostpath
hostPath:
path: /opt/mysql

containers:
- name: mysql-container
image: mysql:5.7.44
imagePullPolicy: IfNotPresent
env:
- name: MYSQL_ROOT_PASSWORD
value: "123"
- name: MYSQL_DATABASE
value: "wp_db"
- name: MYSQL_USER
value: "wp_user"
- name: MYSQL_PASSWORD
value: "123"

volumeMounts:
- name: mysql-hostpath
mountPath: /var/lib/mysql

[root@master01 kubernetes]# kubectl apply -f mysql-dp.yml

4、编写mysql的Service资源
[root@master01 kubernetes]# vim mysql-svc.yml
apiVersion: v1
kind: Service
metadata:
name: mysql-svc
namespace: default
spec:
selector:
app: mysql-dp
ports:
- name: mysql
port: 3306
protocol: TCP
targetPort: 3306
type: ClusterIP

[root@master01 kubernetes]# kubectl apply -f mysql-svc.yml
[root@master01 kubernetes]# kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
mysql-svc ClusterIP 10.1.47.161 <none> 3306/TCP 52s
wordpress-svc NodePort 10.1.84.160 <none> 80:30002/TCP 15h

3、到nfs验证是否挂载成功
[root@nfs ~]# ll /data/wp/
-rw-r--r-- 1 nfsnobody nfsnobody 405 Feb 6 2020 index.php
-rw-r--r-- 1 nfsnobody nfsnobody 19915 Jan 1 2024 ...
-rw-r--r-- 1 nfsnobody nfsnobody 3246 Mar 2 2024 xmlrpc.php

4、浏览器访问
k8s集群中随便一个节点都可以访问,上面说过,和kube-proxy有关
10.0.0.200:30002

image-20240928141216598

发布文章上传图片

image-20240928142403213

nfs机器里面查看图片是否上传到挂载目录

1
2
3
4
5
6
7
[root@nfs ~]# ll /data/wp/wp-content/uploads/2024/09/
total 512
-rw-r--r-- 1 nfsnobody nfsnobody 74163 Sep 28 14:21 12-1024x758.jpg
-rw-r--r-- 1 nfsnobody nfsnobody 6000 Sep 28 14:21 12-150x150.jpg
-rw-r--r-- 1 nfsnobody nfsnobody 13125 Sep 28 14:21 12-300x222.jpg
-rw-r--r-- 1 nfsnobody nfsnobody 50103 Sep 28 14:21 12-768x568.jpg
-rw-r--r-- 1 nfsnobody nfsnobody 367277 Sep 28 14:21 12.jpg

5、PV和PVC的介绍

PV是对底层网络共享存储的抽象,将共享存储定义为一种“资源”
PV由管理员创建和配置
PVC则是用户对存储资源的一个“申请”就像Pod消费Node的资源一样,
PVC能够"消费"PV资源PVC可以申请特定的存储空间和访问模式

1
2
3
4
5
6
7
就目前而言,挂载那台NFS主机磁盘有多大,就能储存多大,对占用没有做限制,

PV,可以理解为nfs储存,一共20G,PV就是划分磁盘空间的东西,给储存资源划分空间,划分2G一块,3G一块...

PVC,这个储存是一个大的园区,开发商把园区开发成房子,PVC就是购买别墅的人,想要多大,就申请多大(申请PV划分的资源空间),

PV划分储存,PVC绑定PV,pod使用指定的PVC

pv和PVC的生命周期

image-20240925102733528

PV和PVC需要注意的地方

1
2
3
4
5
6
在PV的整个生命周期中,可能会处于4种不同的阶段:

Avaliable(可用):表示可用状态,还未被任何PVC绑定
Bound(被绑定的):表示PV已经被PVC绑定
Released(已释放):PVC被删除,但是资源还未被集群重新声明,被释放了,里面还有数据在,需要把数据删除或者备份,再把这个pv删除,重启起来,就会变成Avaliable状态
Failed(失败):表示该PV的自动回收失败

PVC绑定PV的条件如下:

创建PVC之后,k8s就会去查找满足我们声明要求的PV比如storageClassName,accessModes以及容是这些是否满足要求,如果满足要求就将PV和PVC绑定在一起。

1
2
3
1、storageClassName
2、accessModes
3、size

需要注意的是目前PV和PVC之间是一对一绑定的关系,也就是说一个PV只能被一个PVC绑定。>

image-20240925103145263

6、PV、PVC的资源清单

PV资源关键参数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
capacity: PV存储的容量
capacity: 5Gi #划分磁盘空间5G

accessModes: 访问模式,k8s支持的访问模式如下
------------------------------------------------------
ReadWriteOnce(RWO): 读写权限,并且只能被单个Node挂载
ReadOnlyMany(ROX): 只读权限,允许被多个Node挂载
ReadWriteMany(RWX): 读写权限,允许被多个Node挂载
------------------------------------------------------



persistentVolumeReclaimPolicy: 资源回收策略,pvc删之后数据是否回收的策略
------------------------------------------------------
Retain: 保留数据,需要手工处理
Recycle: 简单清除文件的操作(例如运行rm -rf /dada/* 命令),如果删除pvc,pv的资源就会被删除释放掉
Delete: 如果把PVC删了,PV也会被一起删除,数据也会被清掉(很少用)
目前只有NFS和HostPath两种类型的PV支持Recycle策略。
------------------------------------------------------

storageClassName: 存储类别
具有特定类别的PV只能与请求了该类别的PVC绑定。未指定类型的PV则只能对与不请求任何类别的PVC绑定。

编写PV资源清单

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
1 mib =1024 kib
1 gib = 1024 mib

1、编写PV资源清单,划分5G
[root@master01 kubernetes]# vim pv01.yml
apiVersion: "v1"
kind: "PersistentVolume"
metadata:
name: pv01
spec:
capacity:
#PV申请磁盘空间的大小5G
storage: 5Gi
#访问模式:读写权限,并且只能被单个Node挂载
accessModes:
- ReadWriteOnce
#回收策略
persistentVolumeReclaimPolicy: Recycle
storageClassName: pv01-nfs
nfs:
path: /data/wp1
server: 172.16.1.31


2、编写PV资源清单,划分3G
[root@master01 kubernetes]# vim pv02.yml
apiVersion: "v1"
kind: "PersistentVolume"
metadata:
name: pv02
spec:
capacity:
#PV申请磁盘空间的大小5G
storage: 4Gi
#访问模式:只读权限,允许被多个Node挂载
accessModes:
- ReadOnlyMany
#回收策略
persistentVolumeReclaimPolicy: Recycle
storageClassName: pv02-nfs
nfs:
path: /data/wp2
server: 172.16.1.31

3、编写PV资源清单,划分5G
[root@master01 kubernetes]# vim pv03.yml
apiVersion: "v1"
kind: "PersistentVolume"
metadata:
name: pv03
spec:
capacity:
#PV申请磁盘空间的大小5G
storage: 3Gi
#访问模式:(RWX): 读写权限,允许被多个Node挂载
accessModes:
- ReadWriteMany
#回收策略
persistentVolumeReclaimPolicy: Recycle
storageClassName: pv03-nfs
nfs:
path: /data/wp3
server: 172.16.1.31

4、运行
[root@master01 kubernetes]# kubectl apply -f pv01.yml
[root@master01 kubernetes]# kubectl apply -f pv02.yml
[root@master01 kubernetes]# kubectl apply -f pv03.yml
[root@master01 kubernetes]# kubectl get pv
NAME CAPACITY(#pvc绑定的条件) ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGEC
pv01 5Gi RWO Recycle Available pv01-nfs
pv02 4Gi ROX Recycle Available pv02-nfs
pv03 3Gi RWX Recycle Available pv03-nfs

编写PVC资源清单

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
1、编写PVC资源清单
[root@master01 kubernetes]# vim pvc01.yml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: pvc01
#spec里面的内容就是要去匹配PV的
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 4Gi
storageClassName: pv01-nfs


2、运行
[root@master01 kubernetes]# kubectl apply -f pvc01.yml

3、查看PVC已经绑定了pv01
[root@master01 kubernetes]# kubectl get pvc
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE
pvc01 Bound pv01 5Gi RWO pv01-nfs 4m5s

4、pv已经显示被绑定
[root@master01 kubernetes]# kubectl get pv
NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLA
pv01 5Gi RWO Recycle Bound default/pvc01 pv01-nfs
pv02 4Gi ROX Recycle Available pv02-nfs
pv03 3Gi RWX Recycle Available pv03-nfs

7、Pod关联PVC

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
1、创建wordpress-Deployment资源
[root@master01 kubernetes]# vim wp-dp-v2.yml
apiVersion: "apps/v1"
kind: "Deployment"
metadata:
name: wp-dp
namespace: default
spec:
#起2个,数据也是2个,除非把数据分开
replicas: 2
selector:
matchLabels:
app: wp
template:
metadata:
name: wp-pod
namespace: default
labels:
app: wp
spec:
#最后一行挂载点的名字鸡蛋更改 nfs被pv和pvc绑定了,所以pod自己用pvc资源
volumes:
- name: wp-pvc
persistentVolumeClaim:
#这个是pvc的名字
claimName: pvc01


containers:
- name: wp-container
image: wordpress
imagePullPolicy: IfNotPresent
#livenessProbe:
# tcpSocket:
# port: 80
# initialDelaySeconds: 10
# periodSeconds: 3
# timeoutSeconds: 3
# failureThreshold: 3
#readinessProbe:
# tcpSocket:
# host: mysql-svc
# port: 3306
# initialDelaySeconds: 3
# timeoutSeconds: 1
# periodSeconds: 2
# successThreshold: 3
# failureThreshold: 3
env:
- name: WORDPRESS_DB_HOST
value: 'mysql-svc'
- name: WORDPRESS_DB_USER
value: 'wp_user'
- name: WORDPRESS_DB_PASSWORD
value: '123'
- name: WORDPRESS_DB_NAME
value: 'wp_db'

volumeMounts:
- name: wp-pvc
mountPath: /var/www/html/

2、运行
[root@master01 kubernetes]# kubectl apply -f wp-dp-v2.yml

3、到nfs机器查看挂载成功
[root@nfs ~]# ll /data/wp1/
-rw-r--r-- 1 nfsnobody nfsnobody 405 Feb 6 2020 index.php
-rw-r--r-- 1 nfsnobody nfsnobody 19915 Jan 1 2024 license.txt
...

image-20240928181611313