k8s 持久化存储 PV 和 PVC 的简单使用

概述

Kubernetes 对于有状态的容器应用或者对数据需要持久化的应用,可以通过 hostPath 或者 emptyDir 的方式来持久化我们的数据,但是我们需要更加可靠的存储来保存应用的持久化数据。不过存储资源和 CPU 资源以及内存资源有很大不同,为了屏蔽底层的技术实现细节,让用户更加方便的使用,Kubernetes 便引入了 PV 和 PVC 两个重要的资源对象来实现对存储的管理。

概念

PV (PersistentVolume) 是对底层网络共享存储的抽象,将共享存储定义为一种 “资源”。PV 一般由K8S的管理员所创建和配置,它和具体的底层的共享存储技术的实现方式有关,比如 Ceph、GlusterFS、NFS 等,都是通过插件机制完成与共享存储的对接。

PVC (PersistentVolumeClaim) 是用户对存储资源的一个 “申请”。就像 Pod消费 Node 资源一样,PVC 能够消费 PV 的资源。Pod 可以请求节点的CPU和内存,而 PVC 可以请求特定的存储空间和访问模式。对于用户来说,不需要关心底层的存储实现细节,只需要直接使用 PVC 即可。

实战:基于NFS共享存储创建PV和PVC

示例:基于NFS存储来创建PV和PVC

本次共享存储资源选择本地自建的NFS,关于搭建NFS的教程参考之前写的博文:centos7搭建NFS服务

试验环境如下,注意所有k8s节点都要安装nfs,yum install -y nfs-tools:

主机名hostname IP地址 说明
master 192.168.18.10 k8s主节点
node1 192.168.18.11 k8s的node1节点
node2 192.168.18.12 k8snode2节点
db 192.168.18.7 NFS服务器,共享目录/data/nfs/test-pv

PV

PV 作为存储资源,主要包括存储能力、访问模式、存储类型、回收策略、后端存储类型等关键信息的设置。PV 是没有名称空间的隔离性的。下面来创建一个PV 资源对象:

apiVersion: v1
kind: PersistentVolume
metadata:
  name:  pv001
spec:
  capacity:
    storage: 5Gi
  accessModes:
  - ReadWriteMany
  persistentVolumeReclaimPolicy: Recycle
  storageClassName: nfs-slow
  nfs:
    path: /data/nfs/test-pv
    server: 192.168.18.7

上面yaml文件表明:创建了一个名字是pv001的PV,使用NFS类型的后端存储,声明5G的存储空间,访问模式是 ReadWriteMany ,回收策略为 Recyle。有了yaml文件后,直接创建即可。

# 创建pv
[root@master k8s-yaml]# kubectl create -f pv.yaml
# 查看pv
[root@master k8s-yaml]# kubectl get pv
NAME    CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS      CLAIM   STORAGECLASS   REASON   AGE
pv001   5Gi        RWX            Recycle          Available           nfs-slow                5s

PV的常用配置参数

1. 存储能力(Capacity)

一个 PV 对象一般都要指定一个存储能力,通过 PV 的 capacity 属性来设置的,比如这里的 storage: 5Gi,目前只支持对存储空间的设置,未来可能加入IOIPS、吞吐量等指标的设置。

2. 访问模式(Access Modes)

对 PV 进行访问模式的设置,用于描述用户的应用对存储资源的访问权限。分为三种:

  • ReadWriteOnce:读写权限,并且只能被单个 Node 挂载;
  • ReadOnlyMany:只读权限,允许被多个 Node 挂载;
  • ReadWriteMany:读写权限,允许被多个 Node 挂载

一些 PV 可能支持多种访问模式,但是在挂载的时候只能使用一种访问模式,多种访问模式是不会生效的。

3. 存储类别(Class)

PV 可以设定其存储的类别,通过 storageClassName 参数指定一个 StorageClass 资源对象的名称。具有特定类别的 PV 只能与请求了该类别的 PVC 进行绑定。未设定类别的 PV 则只能与不请求任何类别的 PVC 进行绑定。

4. 回收策略

回收策略是通过 persistentVolumeReclaimPolicy 参数进行设置,可选性如下:

  • Retain:保留,需要手动清理数据
  • Recycle:回收,清楚PV中的数据,相当于 rm -rf /thevolume/* 命令
  • Delete:删除,与 PV 相连的后端存储完成volume的删除操作,删除 PVC 后,PV也会被删掉。这一类的PV,需要支持删除功能,是动态存储的默认方式。

PV 的生命周期

一个 PV 在生命周期可能处于下面四个阶段之一:

  • Available:可用状态,还没有于某个PVC进行绑定
  • Bound:已跟某个PVC绑定
  • Released:绑定的PVC已经删除,资源已经释放,但是没有被集群回收
  • Failed:自动资源回收失败

上面创建了PV之后,由于还没有任何PVC跟PV绑定,所以PV的状态还是 Available。

PVC

PVC 作为用户对存储资源的需求申请,主要包括存储空间请求、访问模式、PV选择条件和存储类别的信息的设置。如下,新建一个PVC,跟上面创建的PV进行绑定。

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: myclaim
spec:
  accessModes:
    - ReadWriteMany
  resources:
    requests:
      storage: 3Gi
  storageClassName: nfs-slow

该PVC申请了与存储类别名称为 nfs-slow 的 PV 进行绑定,请求3G的存储容量,访问模式是 ReadWriteMany,创建该PVC:

[root@master k8s-yaml]# kubectl create -f pvc.yaml

# 查看default名称空间下的PVC
[root@master k8s-yaml]# kubectl get pvc
NAME      STATUS   VOLUME   CAPACITY   ACCESS MODES   STORAGECLASS   AGE
myclaim   Bound    pv001    5Gi        RWX            nfs-slow       6s

# 注意,PVC有名称空间的隔离性
[root@master k8s-yaml]# kubectl get pvc -n kube-system
No resources found in kube-system namespace.

# 查看PV状态
[root@master k8s-yaml]# kubectl get pv
NAME    CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS   CLAIM             STORAGECLASS   REASON   AGE
pv001   5Gi        RWX            Recycle          Bound    default/myclaim   nfs-slow                3h29m

可以看到,在PVC与PV进行绑定之后,PV的状态变成了 Bound。但是从上面也看出,我的 PVC 里面声明的容量是3G,而PV里面声明的容量是5G,结果创建出来的PVC容量却是5G,说明,PV的容量是多少,PVC的容量就是多少。

如果PVC里面设置的容量超过PV里面定义的容量,那么PVC是创建不成功的,会一直处于Pending状态。

使用PVC

上面创建了PV和PVC,接下来就可以使用它们了,使用下面nginx-pvc.yaml 进行测试:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-pvc
spec:
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:1.18.0
        imagePullPolicy: IfNotPresent
        ports:
        - containerPort: 80
        volumeMounts:
        - mountPath: /usr/share/nginx/html
          name: my-pvc-volume

      volumes:
      - name: my-pvc-volume
        persistentVolumeClaim:
          claimName: myclaim

然后在nfs的共享目录里面创建个html文件:

[root@db ]# cd /data/nfs/test-pv/
[root@db test-pv]# echo "hello k8s pvc" > index.html

创建Deployment

[root@master k8s-yaml]# kubectl create -f nginx-pvc.yaml 

查看Pod:

[root@master k8s-yaml]# kubectl get pods -o wide
NAME                        READY   STATUS    RESTARTS   AGE   IP               NODE    NOMINATED NODE   READINESS GATES
nginx-pvc-78c9859d7-94lxn   1/1     Running   0          38s   10.244.166.165   node1   <none>           <none>

访问Pod:

[root@master k8s-yaml]# curl 10.244.166.165
hello k8s pvc

可以看到,Pod内部的容器已经成功挂载nfs的后端存储。

参考资料

posted @ 2021-06-17 15:24  syushin  阅读(2825)  评论(0)    收藏  举报