一、PV配置示例¶
在企业内,可能存储很多不同类型的存储,比如NFS、Ceph、GlusterFS等,针对不同类型的后端存储具有不同的配置方式,这也是对集群管理员的一种挑战,因为集群管理员需要对每种存储都有所了解。接下来看一下几个常用的PV配置示例。
1.1 基于NFS的PV¶
首先我们需要安装一下NFS
1.每台机器安装NFS客户端
$ yum install nfs-utils -y
2.在k8s-node01(192.168.1.34)启动nfs
[root@k8s-node01 ~]# systemctl start nfs-server
在k8s-node01(192.168.1.34)查看nfs支持的版本
[root@k8s-node01 ~]# cat /proc/fs/nfsd/versions
-2 +3 +4 +4.1 +4.2
3.在k8s-node01(192.168.1.34)上创建一个共享目录
[root@k8s-node01 ~]# mkdir -p /data/nfs/test_nfs
4.在k8s-node01(192.168.134)编辑授权文件,这里网段根据自己主机来定,我这里网段是192.168.1.0/24
[root@k8s-node01 ~]# vim /etc/exports
/data/nfs/ 192.168.1.0/24(rw,sync,no_subtree_check,no_root_squash)
5.在k8s-node01(192.168.1.34)配置生效
[root@k8s-node01 ~]# exportfs -r
6.在k8s-node01(192.168.1.34)重新加载NFS
[root@k8s-node01 ~]# systemctl reload nfs-server
7.在k8s-master01上进行挂载测试
[root@k8s-master01 ~]# mount -t nfs 192.168.1.34:/data/nfs /mnt/
[root@k8s-master01 ~]# cd /mnt/
[root@k8s-master01 mnt]# touch test123
8.在k8s-node01(192.168.1.34)进行验证
[root@k8s-node01 ~]# cd /data/nfs/
[root@k8s-node01 nfs]# ls
test123 test_nfs
接下来,我们对上面的测试进行卸载
1.针对上诉测试进行卸载
[root@k8s-master01 ~]# umount /mnt/
最后进行NFS配置示例
1.定义一个yaml文件
[root@k8s-master01 pv]# vim pv-nfs.yaml
apiVersion: v1
kind: PersistentVolume
metadata:
name: pv-nfs
spec:
capacity:
storage: 5Gi
volumeMode: Filesystem
accessModes:
- ReadWriteOnce
persistentVolumeReclaimPolicy: Recycle
storageClassName: nfs-slow
nfs:
path: /data/nfs/test_nfs
server: 192.168.1.34
上面参数说明:
- capacity:容量配置
- volumeMode:卷的模式,目前支持Filesystem (文件系统) 和 Block(块),其中Block类型需 要后端存储支持,默认为文件系统
- accessModes:该PV的访问模式,这里设置为RWO,可以被单节点以读写模式挂载
- storageClassName:PV的类,一个特定类型的PV 只能绑定到特定类别的PVC
- persistentVolumeReclaimPolicy:回收策略
- nfs:NFS服务配置,包括以下两个选项:path:NFS上的共享目录;server:NFS的IP地址
2.部署
[root@k8s-master01 pv]# kubectl create -f pv-nfs.yaml
3.结果验证
[root@k8s-master01 pv]# kubectl get -f pv-nfs.yaml
NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE
pv-nfs 5Gi RWO Recycle Available nfs-slow 16s
1.2 基于HostPath的PV¶
当公司目前没有可靠性的存储,但是想要部署k8s集群中应用的数据不丢失,这时把宿主机目录直接挂载到Pod,Pod的数据直接落在宿主机上。接下来介绍基于HostPath的PV:
1.在master01节点上创建挂载目录
[root@k8s-master01 pv]# mkdir -p /mnt/data
2.定义一个yaml文件
[root@k8s-master01 pv]# vim pv-hostpath.yaml
apiVersion: v1
kind: PersistentVolume
metadata:
name: pv-hostpath
labels:
type: local
spec:
storageClassName: hostpath
capacity:
storage: 10Gi
accessModes:
- ReadWriteOnce
hostPath:
path: "/mnt/data"
上面参数说明:
- capacity:容量配置
- accessModes:该PV的访问模式,这里设置为RWO,可以被单节点以读写模式挂载
- storageClassName:PV的类,一个特定类型的PV 只能绑定到特定类别的PVC
- hostPath:hostPath配置,path:"/mnt/data",其中/mnt/data为宿主机的目录
3.部署
[root@k8s-master01 pv]# kubectl create -f pv-hostpath.yaml
4.结果验证
[root@k8s-master01 pv]# kubectl get -f pv-hostpath.yaml
NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE
task-pv-volume 10Gi RWO Retain Available hostpath 26s
1.3 基于Ceph RBD的PV¶
Ceph可能是目前企业内最常用的一种分布式存储之一,同时支持文件系统、块存储及对象存储,和上述NFS和HostPath相比,具有高可用性和读写高效性。接下来看一下Ceph RBD类型的PV配置:
1.定义一个yaml文件
[root@k8s-master01 pv]# vim pv-cephrbd.yaml
apiVersion: v1
kind: PersistentVolume
metadata:
name: ceph-rbd-pv
spec:
capacity:
storage: 1Gi
storageClassName: ceph-fast
accessModes:
- ReadWriteOnce
rbd:
monitors:
- 192.168.1.123:6789
- 192.168.1.124:6789
- 192.168.1.125:6789
pool: rbd
image: ceph-rbd-pv-test
user: admin
secretRef:
name: ceph-secret
fsType: ext4
readOnly: false
上面参数说明:
- monitors:Ceph的monitor节点的IP
- pool:所用Ceph Pool的名称,可以使用ceph osd pool ls查看
- image:Ceph块设备中的磁盘映像文件,可以使用rbd create POOL_NAME/IMAGE_NAME--size 1024创建,使用rbd list POOL_NAME查看
- user:Rados的用户名,默认是admin
- secretRef:用于验证Ceph身份的密钥
- fsType:文件类型,可以是Ext4、XFS等
- readOnly:是否是只读挂载
注意:Ceph的Pool和Image需要提前创建才能使用。虽然前面讲述了RBD类型的PV配置示例,但是在实际使用时,大多数Ceph存储的使用都是采用动态存储的方式,很少通过静态方式去管理。同时,Kubernetes所有的节点都需要安装ceph-common才能正常挂载Ceph.
2.部署
[root@k8s-master01 pv]# kubectl create -f pv-cephrbd.yaml
3.结果验证
[root@k8s-master01 pv]# kubectl get -f pv-cephrbd.yaml
二、PVC绑定PV¶
在工作场景中,k8s管理员会碰到两种场景:
- 场景一:k8s管理员成功创建好PV,请求开发人员申请该PV并创建PVC配置到Volumes配置一个PVC类型的存 储,并指定PVC的名字是xxx即可
- 场景二:k8s管理员成功创建好PV和PVC,请求开发人员在Volumes指定PVC的名字是xxx即可

注意:PVC和PV进行绑定的前提条件是一些参数必须匹配,比如accessModes、storageClassName、volumeMode都需要相同,并且PVC的storage需要小于等于PV的storage配置。
下面进行PVC挂载示例:
首先创建PV
1.定义一个yaml文件
[root@k8s-master01 pv]# vim pv-nfs.yaml
apiVersion: v1
kind: PersistentVolume
metadata:
name: pv-nfs
spec:
capacity:
storage: 5Gi
volumeMode: Filesystem
accessModes:
- ReadWriteOnce
persistentVolumeReclaimPolicy: Recycle
storageClassName: nfs-slow
nfs:
path: /data/nfs/test_nfs
server: 192.168.1.34
上面参数说明:
- capacity:容量配置
- volumeMode:卷的模式,目前支持Filesystem (文件系统) 和 Block(块),其中Block类型需 要后端存储支持,默认为文件系统
- accessModes:该PV的访问模式,这里设置为RWO,可以被单节点以读写模式挂载
- storageClassName:PV的类,一个特定类型的PV 只能绑定到特定类别的PVC
- persistentVolumeReclaimPolicy:回收策略
- nfs:NFS服务配置,包括以下两个选项:path:NFS上的共享目录;server:NFS的IP地址
2.部署
[root@k8s-master01 pv]# kubectl create -f pv-nfs.yaml
3.结果验证
[root@k8s-master01 pv]# kubectl get -f pv-nfs.yaml
NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE
pv-nfs 5Gi RWO Recycle Available nfs-slow 16s
其次创建PVC
1.定义一个名为pvc-nfs.yaml 的yaml文件
[root@k8s-master01 pv]# vim pvc-nfs.yaml
kind: PersistentVolumeClaim
apiVersion: v1
metadata:
name: nfs-pvc-claim
spec:
storageClassName: nfs-slow #要求PV一致
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 3Gi #小于等于PV大小
注意:PVC有命名空间限制,这里默认是default空间
2.部署
[root@k8s-master01 pv]# kubectl create -f pvc-nfs.yaml
3.结果验证,观察到状态已更改为Bound,但此时并不代表可用
[root@k8s-master01 pv]# kubectl get -f pvc-nfs.yaml
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE
nfs-pvc-claim Bound pv-nfs 5Gi RWO nfs-slow 60s
4.查看PV状态,此时PV状态由原来的Available变为Bound ,但此时并不代表可用
[root@k8s-master01 pv]# kubectl get pv pv-nfs
NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE
pv-nfs 5Gi RWO Recycle Bound default/nfs-pvc-claim nfs-slow 79m
最后,创建Pod
1.在k8s-master01上定义一个名为pvc-nfs-pod.yaml的yaml文件
[root@k8s-master01 pv]# vim pvc-nfs-pod.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app: nginx
name: nginx
namespace: default
spec:
replicas: 2
revisionHistoryLimit: 10
selector:
matchLabels:
app: nginx
strategy:
rollingUpdate:
maxSurge: 1
maxUnavailable: 0
type: RollingUpdate
template:
metadata:
creationTimestamp: null
labels:
app: nginx
spec:
volumes:
- name: task-pv-storage
persistentVolumeClaim:
claimName: nfs-pvc-claim
containers:
- env:
- name: TZ
value: Asia/Shanghai
- name: LANG
value: C.UTF-8
image: registry.cn-hangzhou.aliyuncs.com/zq-demo/nginx:1.14.2
imagePullPolicy: IfNotPresent
name: nginx
volumeMounts:
- mountPath: "/usr/share/nginx/html"
name: task-pv-storage
2.在k8s-master01上开始部署
[root@k8s-master01 pv]# kubectl create -f pvc-nfs-pod.yaml
3.在k8s-master01上查看pod状态
[root@k8s-master01 pv]# kubectl get po
NAME READY STATUS RESTARTS AGE
nginx-59fdd74bd4-2c2hk 1/1 Running 0 19s
nginx-59fdd74bd4-dlfgf 1/1 Running 0 19s
4.在k8s-master01上以容器的方式进入pod,修改文件内容,用于测试另一个Pod是否会同步
[root@k8s-master01 pv]# kubectl exec -it nginx-59fdd74bd4-2c2hk -- sh
/ # cd /usr/share/nginx/html/
/usr/share/nginx/html # echo "test_nfs" > /usr/share/nginx/html/index.html
/usr/share/nginx/html # cat /usr/share/nginx/html/index.html
test_nfs
5.继续在k8s-master01上以容器的方式进入另一个pod后,查看已经同步
[root@k8s-master01 pv]# kubectl exec nginx-59fdd74bd4-dlfgf -- cat /usr/share/nginx/html/index.html
test_nfs
三、PVC创建和挂载失败的原因¶
3.1 PVC一直Pending的原因¶
1.PVC的空间申请大小大于PV的大小 2.PVC的StorageClassName没有和PV的一致 3.PVC的accessModes和PV的不一致
3.2 挂载PVC的Pod一直处于Pending¶
1.PVC没有创建成功/PVC不存在 2.PVC和Pod不在同一个Namespace
四、常见存储分类¶
1.文件存储 一些数据可能需要被多个节点使用,比如用户的头像、用户上传的文 件等,实现方式:NFS、NAS、FTP、CephFS等。 2.块存储 一些数据只能被一个节点使用,或者是需要将一块裸盘整个挂载使用, 比如数据库、Redis等,实现方式:Ceph、GlusterFS、公有云。 3.对象存储 由程序代码直接实现的一种存储方式,云原生应用无状态化常用的实现方式,实现方式:一般是符合S3协议的云存储,比如AWS的S3存储、Minio、七牛云等。