Kubernetes PV/PVC

在Kubernetes中,我们虽然可以使用volume将容器内目录挂载到宿主机目录上,但由于Pod调度的不确定性,这种数据存储方式是不牢靠的。对于有状态的应用,我们希望无论Pod被调度到哪个节点上,它们的数据总能够完整地恢复,这时候我们就不能用volume挂载了,而应该使用“网络共享存储”。PV/PVC就是用于解决问题而存在的,它们屏蔽了底层存储实现的细节,使得我们很容易上手使用。

PV

PersistentVolume(PV)是对底层网络共享存储的抽象,将共享存储定义为一种“资源”,Kubernetes支持的PV类型如下:

类型描述
AWSElasticBlockStoreAWS公有云提供的ElasticBlockStore
AzureFileAzure公有云提供的File
AzureDiskAzure公有云提供的Disk
CephFS一种开源共享存储系统
FC(Fibre Channel)光纤存储设备
FlexVolume一种插件式的存储机制
Flocker一种开源共享存储系统
GCEPersistentDiskGCE公有云提供的PersistentDisk
Glusterfs一种开源共享存储系统
HostPath宿主机目录,仅用于单机测试
iSCSIiSCSI存储设备
Local本地存储设备,从Kubernetes 1.7版本引入,到1.14版本时更新为稳定版,目前可以通过指定块(Block)设备提供Local PV,或通过社区开发的sig-storage-local-static-provisioner插件https://github.com/kubernetes-sigs/sigstorage-local-static-provisioner来管理Local PV的生命周期
NFS网络文件系统
Portworx VolumesPortworx提供的存储服务
Quobyte VolumesQuobyte提供的存储服务
RBD(Ceph Block Device)Ceph块存储
ScaleIO VolumesDellEMC的存储设备
StorageOSStorageOS提供的存储服务
VsphereVolumeVMWare提供的存储系统

举个PV配置文件例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
apiVersion: v1
kind: PersistentVolume
metadata:
name: nfs
spec:
capacity:
storage: 1Gi # 具有1Gi内存
accessModes:
- ReadWriteMany # 具有读写权限,允许被多个Node挂载
persistentVolumeReclaimPolicy: Retain # 回收策略,这里为保留
nfs: # pv类型为NFS类型
server: 192.168.33.13
path: "/nfs"

PV支持的accessModes有:

  • ReadWriteOnce(RWO):读写权限,并且只能被单个Node挂载。
  • ReadOnlyMany(ROX):只读权限,允许被多个Node挂载。
  • ReadWriteMany(RWX):读写权限,允许被多个Node挂载。

不同的存储提供者支持的accessModes:

Volume PluginReadWriteOnceReadOnlyManyReadWriteMany
AWSElasticBlockStore--
AzureFile
AzureDisk--
CephFS
Cinder--
CSIdepends on the driverdepends on the driverdepends on the driver
FC-
FlexVolumedepends on the driver
Flocker--
GCEPersistentDisk-
Glusterfs
HostPath--
iSCSI-
Quobyte
NFS
RBD-
VsphereVolume-- (works when Pods are collocated)
PortworxVolume-
ScaleIO-
StorageOS--

PV支持的persistentVolumeReclaimPolicy有:

  • Retain,不清理, 保留 Volume(需要手动清理)
  • Recycle,删除数据,(只有 NFS 和 HostPath 支持)
  • Delete,删除存储资源,比如删除 AWS EBS 卷(只有 AWS EBS, GCE PD, Azure Disk 和 Cinder 支持)

PV声明周期:

  • Available:空闲状态;
  • Bound:已经绑定到某个PVC上;
  • Released:对应的PVC已经被删除,但资源还没有被集群收回;
  • Failed:PV自动回收失败。

PVC

PersistentVolumeClaim(PVC),对存储资源的需求申请,主要包括存储空间请求、访问模式、PV选择条件和存储类别等信息的设置。只有PVC和PV相匹配,才能绑定上。

定义一个PVC配置:

1
2
3
4
5
6
7
8
9
10
kind: PersistentVolumeClaim
apiVersion: v1
metadata:
name: nfs
spec:
accessModes:
- ReadWriteMany
resources:
requests:
storage: 1Gi

该PVC声明了需要1Gi存储空间,访问模式为ReadWriteMany,刚刚定义的PV符合这个要求,所以会被绑定上。

实践

因为NFS类型存储演示起来方便,所以这里选择使用NFS作为存储提供者。

Kubeadm安装Kubernetes1.16.2集群一节中,我们曾在以下虚拟机上搭建了Kubernetes集群:

操作系统IP角色CPU核心数内存Hostname
centos7192.168.33.11master24096Mmaster
centos7192.168.33.12worker24096Mnode1
centos7192.168.33.13worker24096Mnode2

为了方便,这里就不再创建新的虚拟机安装NFS,直接在192.168.33.13节点上准备好NFS环境。

在192.168.33.13节点上执行以下bash命令:

1
2
3
4
5
6
7
8
# 创建目录
mkdir /nfs

# 修改权限
chmod 777 /nfs

# 创建exports文件
vim /etc/exports

exports内容如下所示:

1
/nfs *(rw,insecure,sync,no_subtree_check,no_root_squash)

让配置生效:

1
exportfs -r

启动NFS:

1
2
3
4
systemctl enable nfs
systemctl enable rpcbind
systemctl restart nfs
systemctl restart rpcbind

接着在master节点上,创建test-pv-pvc.yml配置文件:

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
apiVersion: v1
kind: PersistentVolume
metadata:
name: nfs-pv
spec:
capacity:
storage: 1Gi
accessModes:
- ReadWriteMany
nfs:
server: 192.168.33.13
path: "/nfs"

---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: nfs-pvc
spec:
accessModes:
- ReadWriteMany
resources:
requests:
storage: 1Gi

---
apiVersion: v1
kind: ReplicationController
metadata:
name: busybox
spec:
replicas: 1
selector:
name: busybox
template:
metadata:
labels:
name: busybox
spec:
containers:
- image: busybox
command:
- sh
- -c
- 'while true; do echo hello world > /mnt/index.html; sleep $(($RANDOM % 5 + 5)); done'
imagePullPolicy: IfNotPresent
name: busybox
volumeMounts:
- name: nfs
mountPath: "/mnt"
volumes:
- name: nfs
persistentVolumeClaim:
claimName: nfs-pvc

---
apiVersion: v1
kind: ReplicationController
metadata:
name: nginx
spec:
replicas: 1
selector:
name: nginx
template:
metadata:
labels:
name: nginx
spec:
containers:
- name: nginx
image: nginx
ports:
- name: web
containerPort: 80
volumeMounts:
- name: nfs
mountPath: "/usr/share/nginx/html"
volumes:
- name: nfs
persistentVolumeClaim:
claimName: nfs-pvc

---
kind: Service
apiVersion: v1
metadata:
name: nginx-service
spec:
ports:
- port: 80
nodePort: 30000
type: NodePort
selector:
name: nginx

上面的配置文件效果可以用下面这张图表示:

QQ截图20191125142753.png

主要过程就是busybox通过nfs-pvc绑定了nfs-pv,然后定时将hello world写到容器内部/mnt/index.html文件中,而容器内部/mnt和PV的/nfs目录挂载;nginx也通过nfs-pvc绑定了nfs-pv,将/nfs目录和容器内部/usr/share/nginx/html目录挂载;我们后续可以通过访问浏览器http://192.168.33.11:30000/地址查看效果。

创建该配置文件:

QQ截图20191125143031.png

查看192.168.33.13虚拟机/nfs目录下是否已经存在index.html文件,并查看内容:

QQ截图20191125143126.png

浏览器访问http://192.168.33.11:30000/

QQ截图20191125143416.png

说明整个流程没问题。

请作者喝瓶肥宅水~

TOP