当前位置: 首页 > 工具软件 > K8STARS > 使用案例 >

【云原生 | Kubernetes 实战】13、K8s 常见的存储方案及具体应用场景分析(中)

漆雕昊天
2023-12-01

目录

k8s 持久化存储:PVC

一、k8s PV 是什么?

二、k8s PVC 是什么?

三、k8s PVC 和 PV 工作原理

3.1 pv 的配置方式

3.2 绑定

3.3 使用

3.4 回收策略

四、创建 pod ,使用 pvc 作为持久化存储卷

4.1 创建 nfs 共享目录

4.2  编写 pv 的资源清单文件

4.3 创建 pvc 与符合条件的 pv 绑定

五、清理 pv

5.1 清理 pv 步骤:

​​​​​​​5.2 演示 pv 用 Delete 回收策略


k8s 持久化存储:PVC

一、k8s PV 是什么?

        持久卷(PersistentVolume,PV)是群集中的一块存储,由管理员配置或使用存储类动态配置。 它是集群中的资源,就像 pod 是 k8s 集群资源一样。 PV 是容量插件,如 Volumes,其生命周期独立于使用 PV 的任何单个 pod。

二、k8s PVC 是什么?

        持久卷申领(PersistentVolumeClaim,PVC) 是一个持久化存储卷,我们在创建 pod 时可以定义这个类型的存储卷。 它类似于一个 pod。 Pod 消耗节点资源,PVC 消耗 PV 资源。 Pod 可以请求特定级别的资源(CPU 和内存)。 pvc 在申请 pv 的时候也可以请求特定的大小和访问模式(例如,可以一次读写或多次只读)。

三、k8s PVC 和 PV 工作原理

        PV 卷是集群中的资源。PVC 申领是对这些资源的请求,也被用来执行对资源的申领检查。 PV 卷和 PVC 申领之间的互动遵循如下生命周期:

3.1 pv 的配置方式

可以通过两种方式配置PV:静态或动态。

  • 静态配置:

        集群管理员创建了许多 PV。它们包含可供群集用户使用的实际存储的详细信息。它们存在于Kubernetes API 中,可供使用。

  • 动态配置:

        当管理员创建的静态 PV 都不匹配用户的 PersistentVolumeClaim 时,群集可能会尝试为 PVC 专门动态配置卷。此配置基于 StorageClasses,PVC 必须请求存储类,管理员必须创建并配置该类,以便进行动态配置。

3.2 绑定

用户创建 pvc 并指定需要的资源和访问模式。在找到可用 pv 之前,pvc 会保持未绑定状态。

3.3 使用

  1. 需要找一个存储服务器,把它划分成多个存储空间;
  2. k8s 管理员可以把这些存储空间定义成多个 pv;
  3. 在 pod 中使用 pvc 类型的存储卷之前需要先创建 pvc,通过定义需要使用的 pv 的大小和对应的访问模式,找到合适的 pv;
  4. pvc 被创建之后,就可以当成存储卷来使用了,我们在定义 pod 时就可以使用这个 pvc 的存储卷
  5. pvc 和 pv 它们是一一对应的关系,pv 如果被 pvc 绑定了,就不能被其他 pvc 使用了;
  6. 我们在创建 pvc 的时候,应该确保和底下的 pv 能绑定,如果没有合适的 pv,那么 pvc 就会处于pending 状态。

3.4 回收策略

        当我们创建 pod 时如果使用 pvc 做为存储卷,那么它会和 pv 绑定,当删除 pod,pvc 和 pv 绑定就会解除,解除之后和 pvc 绑定的 pv 卷里的数据需要怎么处理呢?目前,卷可以保留,回收或删除:Retain、Recycle (不推荐使用,1.15可能被废弃了)、Delete。

  • Retain

        当删除 pvc 的时候,pv 仍然存在,处于 released 状态,但是它不能被其他 pvc 绑定使用,里面的数据还是存在的,当我们下次再使用的时候,数据还是存在的,这个是默认的回收策略。

  • Delete

删除 pvc 时即会从 Kubernetes 中移除 PV,也会从相关的外部设施中删除存储资产。

PV 官方参考文档:持久卷 | Kubernetes 

四、创建 pod ,使用 pvc 作为持久化存储卷

4.1 创建 nfs 共享目录

# 创建十个目录
[root@k8s-master01 volumes]# mkdir /data/volume_test/v{1,2,3,4,5,6,7,8,9,10} -pv

# 配置 nfs 共享宿主机上的 /data/volume_test/v1..v10 目录
[root@k8s-master01 volumes]# vim /etc/exports
/data/volumes *(rw,no_root_squash)
/data/volume_test/v1 *(rw,no_root_squash)
/data/volume_test/v2 *(rw,no_root_squash)
/data/volume_test/v3 *(rw,no_root_squash)
/data/volume_test/v4 *(rw,no_root_squash)
/data/volume_test/v5 *(rw,no_root_squash)
/data/volume_test/v6 *(rw,no_root_squash)
/data/volume_test/v7 *(rw,no_root_squash)
/data/volume_test/v8 *(rw,no_root_squash)
/data/volume_test/v9 *(rw,no_root_squash)

# 重新加载配置,使配置成效
[root@k8s-master01 volumes]# exportfs -arv

4.2  编写 pv 的资源清单文件

# 查看定义 pv 需要的字段
[root@k8s-master01 ~]# kubectl explain pv
[root@k8s-master01 ~]# kubectl explain pv.spec
[root@k8s-master01 ~]# kubectl explain pv.spec.nfs
[root@k8s-master01 ~]# kubectl explain pv.spec.accessModes
[root@k8s-master01 ~]# kubectl explain pv.spec.capacity

# 编写 pv 资源文件,创建三种类型的 pv
[root@k8s-master01 volumes]# vim pv.yaml
apiVersion: v1
kind: PersistentVolume
metadata:
  name: v1
  labels:
    app: v1
spec: 
  nfs:
    server: 192.168.78.133
    path: /data/volume_test/v1
  accessModes: ["ReadWriteOnce"]    # 卷可以被一个节点以读写方式挂载。 ReadWriteOnce 访问模式也允许运行在同一节点上的多个 Pod 访问卷。
  capacity:
    storage: 1Gi
---
apiVersion: v1
kind: PersistentVolume
metadata:
  name: v2
  labels:
    app: v2
spec: 
  nfs:
    server: 192.168.78.133
    path: /data/volume_test/v2
  accessModes: ["ReadOnlyMany"]    # 卷可以被多个节点以只读方式挂载。
  capacity:
    storage: 2Gi
---
apiVersion: v1
kind: PersistentVolume
metadata:
  name: v3
  labels:
    app: v3
spec: 
  nfs:
    server: 192.168.78.133
    path: /data/volume_test/v3
  accessModes: ["ReadWriteMany"]    # 卷可以被多个节点以读写方式挂载。
  capacity:
    storage: 3Gi

[root@k8s-master01 volumes]# kubectl apply -f pv.yaml 
persistentvolume/v1 created
persistentvolume/v2 created
persistentvolume/v3 created

# 输出结果显示该 PersistentVolume 的状态(STATUS)为 Available。 这意味着它还没有被绑定给 PersistentVolumeClaim。
[root@k8s-master01 volumes]# kubectl get pv 
NAME   CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS      CLAIM   STORAGECLASS   REASON   AGE
v1     1Gi        RWO            Retain           Available                                   25s
v2     2Gi        ROX            Retain           Available                                   25s
v3     3Gi        RWX            Retain           Available                                   25s

ACCESS MODES 说明:

  • RWO:readwariteonce,单路读写,允许同一个node节点上的pod访问
  • ROX:readonlymany,多路只读,允许不通node节点的pod以只读方式访问
  • RWX:readwritemany,多路读写,允许不同的node节点的pod以读写方式访问

pv.spec.accessModes(访问模式)官方参考文档:持久卷 | Kubernetes

pv.spec.capacity(容量)官方参考文档:持久卷 | Kubernetes

创建 pv 官方参考文档:配置 Pod 以使用 PersistentVolume 作为存储 | Kubernetes

4.3 创建 pvc 与符合条件的 pv 绑定

# 查看 pvc 字段帮助命令
[root@k8s-master01 ~]# kubectl explain pvc
[root@k8s-master01 ~]# kubectl explain pvc.spec.accessModes
[root@k8s-master01 ~]# kubectl explain pvc.spec.selector
[root@k8s-master01 ~]# kubectl explain pvc.spec.selector.matchLabels
[root@k8s-master01 ~]# kubectl explain pvc.spec.resources

# 编写 pvc 资源文件,创建三种类型的 pvc 请求对应的 pv
[root@k8s-master01 volumes]# vim pvc.yaml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: pvc-v1
spec:
  accessModes: ["ReadWriteOnce"]
  selector:
    matchLabels:
      app: v1
  resources:
    requests: 
      storage: 1Gi
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: pvc-v2
spec:
  accessModes: ["ReadOnlyMany"]
  selector:
    matchLabels:
      app: v2
  resources:
    requests: 
      storage: 2Gi
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: pvc-v3
spec:
  accessModes: ["ReadWriteMany"]
  selector:
    matchLabels:
      app: v3
  resources:
    requests: 
      storage: 3Gi

[root@k8s-master01 volumes]# kubectl apply -f pvc.yaml 
persistentvolumeclaim/pvc-v1 created
persistentvolumeclaim/pvc-v2 created
persistentvolumeclaim/pvc-v3 created

# 看到 pvc 的 status 都是 bound 状态,就说明 pvc 跟 pv 已经绑定了
[root@k8s-master01 volumes]# kubectl get pvc
NAME     STATUS   VOLUME   CAPACITY   ACCESS MODES   STORAGECLASS   AGE
pvc-v1   Bound    v1       1Gi        RWO                           20s
pvc-v2   Bound    v2       2Gi        ROX                           20s
pvc-v3   Bound    v3       3Gi        RWX                           20s

创建 pvc 资源官方参考文档:配置 Pod 以使用 PersistentVolume 作为存储 | Kubernetes

4.4 创建 pod 挂载 pvc 

建一个使用 PersistentVolumeClaim 作为存储卷的 Pod。

[root@k8s-master01 volumes]# vim pod_pvc.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: pvc-test
spec:
  replicas: 3
  selector:
    matchLabels:
      cunchu: pvc
  template: 
    metadata:
      labels:
        cunchu: pvc
    spec:
      containers:
      - name: test-pvc
        image: nginx
        imagePullPolicy: IfNotPresent
        ports:
        - containerPort: 80
          protocol: TCP
        volumeMounts:
        - name: nginx-html
          mountPath: /usr/share/nginx/html
      volumes:
      - persistentVolumeClaim:
          claimName: pvc-v1        # 指定需要挂载的 pvc 类型
        name: nginx-html

# 创建 Pod:
[root@k8s-master01 volumes]# kubectl apply -f pod_pvc.yaml 
deployment.apps/pvc-test created

# 检查 Pod 中的容器是否运行正常:
[root@k8s-master01 volumes]# kubectl get pods -o wide 
NAME                        READY   STATUS    RESTARTS   AGE   IP               NODE        NOMINATED NODE   READINESS GATES
pvc-test-76c9c959b4-hsrtc   1/1     Running   0          6s    10.244.36.73     k8s-node1   <none>           <none>
pvc-test-76c9c959b4-k5klk   1/1     Running   0          6s    10.244.169.163   k8s-node2   <none>           <none>
pvc-test-76c9c959b4-sf4s5   1/1     Running   0          6s    10.244.169.164   k8s-node2   <none>           <none>

# 打开一个 Shell 访问 Pod 中的容器:
[root@k8s-master01 volumes]# kubectl exec -it pvc-test-76c9c959b4-hsrtc -- bash
root@pvc-test-76c9c959b4-hsrtc:/# cd /usr/share/nginx/html/
root@pvc-test-76c9c959b4-hsrtc:/usr/share/nginx/html# echo "hello sky" > index.html
root@pvc-test-76c9c959b4-hsrtc:/usr/share/nginx/html# ls
index.html
root@pvc-test-76c9c959b4-hsrtc:/usr/share/nginx/html# cat index.html 
hello sky

# 查看宿主机挂载的目录是否有生成文件
[root@k8s-master01 ~]# cat /data/volume_test/v1/index.html 
hello sky

        如果你看到“hello sky”消息,则证明你已经成功地配置了 Pod 使用 PersistentVolumeClaim 的存储。反过来,你在宿主机挂载的目录下创建文件,也会同步到三个 pod中。

创建 pod 挂载 pvc官方参考文档:配置 Pod 以使用 PersistentVolume 作为存储 | Kubernetes 

五、清理 pv

注:使用 pvc 和 pv 的注意事项

  1. 我们每次创建 pvc 的时候,需要事先有划分好的 pv,这样可能不方便,那么可以在创建 pvc 的时候直接动态创建一个 pv 这个存储类,pv 事先是不存在的。
  2. pvc 和 pv 绑定,如果使用默认的回收策略 retain,那么删除 pvc 之后,pv 会处于 released 状态,我们想要继续使用这个 pv,需要手动删除 pv,kubectl delete pv pv_name。删除 pv,不会删除 pv 里的数据,当我们重新创建 pvc 时还会和这个最匹配的 pv 绑定,数据还是原来数据,不会丢失。

5.1 清理 pv 步骤:

# 如果先删除 pvc 或者 pv,都不能删除成功,因为有 pod 在使用
[root@k8s-master01 volumes]# kubectl delete -f pvc.yaml

# 显示 Terminating 状态
[root@k8s-master01 ~]# kubectl get pvc
NAME     STATUS        VOLUME   CAPACITY   ACCESS MODES   STORAGECLASS   AGE
pvc-v1   Terminating   v1       1Gi        RWO                           37m

# 所以因先删除使用中的 pod,再删除 pvc
[root@k8s-master01 volumes]# kubectl delete -f pod_pvc.yaml
[root@k8s-master01 ~]# kubectl delete pvc pvc-v1
persistentvolumeclaim "pvc-v1" deleted
[root@k8s-master01 volumes]# kubectl get pvc
NAME     STATUS   VOLUME   CAPACITY   ACCESS MODES   STORAGECLASS   AGE
pvc-v2   Bound    v2       2Gi        ROX                           95s
pvc-v3   Bound    v3       3Gi        RWX                           95s

# 删除 pv
[root@k8s-master01 volumes]# kubectl delete pv v1 
persistentvolume "v1" deleted

[root@k8s-master01 volumes]# kubectl get pv
NAME   CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS   CLAIM            STORAGECLASS   REASON   AGE
v2     2Gi        ROX            Retain           Bound    default/pvc-v2                           4m22s
v3     3Gi        RWX            Retain           Bound    default/pvc-v3                           4m22s

# 查看宿主机挂载目录数据是否被删除
[root@k8s-master01 volumes]# ls /data/volume_test/v1
index.html

# 重新创建 pv pvc pod 进入 容器内部查看,数据还在

删除 pv 官方参考文档:配置 Pod 以使用 PersistentVolume 作为存储 | Kubernetes 

​​​​​​​​​​​​​​5.2 演示 pv 用 Delete 回收策略

# 新创建一个 pv
[root@k8s-master01 volumes]# cp pv.yaml pv-delete.yaml
[root@k8s-master01 volumes]# vim pv-delete.yaml 
apiVersion: v1
kind: PersistentVolume
metadata:
  name: v4
  labels:
    app: v4
spec:
  nfs:
    server: 192.168.78.133
    path: /data/volume_test/v4
  accessModes: ["ReadWriteOnce"]
  capacity:
    storage: 1Gi
  persistentVolumeReclaimPolicy: Delete

[root@k8s-master01 volumes]# kubectl apply -f pv-delete.yaml 
persistentvolume/v4 created

# 新创建一个 pvc
[root@k8s-master01 volumes]# cp pvc.yaml pvc-delete.yaml
[root@k8s-master01 volumes]# vim pvc-delete.yaml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: pvc-v4
spec:
  accessModes: ["ReadWriteOnce"]
  selector:
    matchLabels:
      app: v4
  resources:
    requests:
      storage: 1Gi
[root@k8s-master01 volumes]# kubectl apply -f pvc-delete.yaml 
persistentvolumeclaim/pvc-v4 created

[root@k8s-master01 volumes]# kubectl get pvc | grep v4
pvc-v4   Bound    v4       1Gi        RWO                           26s

# 新创建一个 pod
[root@k8s-master01 volumes]# cp pod_pvc.yaml pod-delete.yaml
您在 /var/spool/mail/root 中有新邮件
[root@k8s-master01 volumes]# vim pod-delete.yam
apiVersion: apps/v1
kind: Deployment
metadata:
  name: pvc-test-1
spec:
  replicas: 3
  selector:
    matchLabels:
      cunchu: pvc-1
  template:
    metadata:
      labels:
        cunchu: pvc-1
    spec:
      containers:
      - name: test-pvc
        image: nginx
        imagePullPolicy: IfNotPresent
        ports:
        - containerPort: 80
          protocol: TCP
        volumeMounts:
        - name: nginx-html
          mountPath: /usr/share/nginx/html
      volumes:
      - persistentVolumeClaim:
          claimName: pvc-v4
        name: nginx-html

[root@k8s-master01 volumes]# kubectl apply -f pod-delete.yaml 
deployment.apps/pvc-test-1 created

# 在宿主机挂载目录创建文件
[root@k8s-master01 volumes]# cd /data/volume_test/v4/
[root@k8s-master01 v4]# echo "hello sky" > index.html

# 可以在 pod 里看到
[root@k8s-master01 ~]# kubectl exec -it pvc-test-1-d546f478f-57kkz -- bash
root@pvc-test-1-d546f478f-57kkz:/# cat /usr/share/nginx/html/index.html 
hello sky

# 删除
[root@k8s-master01 volumes]# kubectl delete -f pod-delete.yaml 
deployment.apps "pvc-test-1" deleted
[root@k8s-master01 volumes]# kubectl delete pvc pvc-v4
persistentvolumeclaim "pvc-v4" deleted
[root@k8s-master01 volumes]# kubectl get pv
NAME   CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS   CLAIM            STORAGECLASS   REASON   AGE
v2     2Gi        ROX            Retain           Bound    default/pvc-v2                           22m
v3     3Gi        RWX            Retain           Bound    default/pvc-v3                           22m
v4     1Gi        RWO            Delete           Failed   default/pvc-v4                           9m4s
[root@k8s-master01 volumes]# kubectl delete pv v4

# 宿主机挂载目录数据还在
[root@k8s-master01 volumes]# ls /data/volume_test/v4/
index.html

# 数据恢复
[root@k8s-master01 volumes]# kubectl apply -f pv-delete.yaml 
persistentvolume/v4 created
[root@k8s-master01 volumes]# kubectl apply -f pvc-delete.yaml 
persistentvolumeclaim/pvc-v4 created
[root@k8s-master01 volumes]# kubectl apply -f pod-delete.yaml 
deployment.apps/pvc-test-1 created
[root@k8s-master01 volumes]# kubectl get pods 
NAME                         READY   STATUS    RESTARTS   AGE
pvc-test-1-d546f478f-7zpht   1/1     Running   0          8s
pvc-test-1-d546f478f-llvcn   1/1     Running   0          8s
pvc-test-1-d546f478f-qnpsr   1/1     Running   0          8s 
[root@k8s-master01 volumes]# kubectl exec -it pvc-test-1-d546f478f-7zpht -- bash
root@pvc-test-1-d546f478f-7zpht:/# cat /usr/share/nginx/html/index.html 
hello sky

经过测试,如果回收策略是retain、Delete ,删除 pv pv 后端存储的数据也不会被删除

 上一篇文章:【云原生 | Kubernetes 实战】13、K8s 常见的存储方案及具体应用场景分析(上)_Stars.Sky的博客-CSDN博客

下一篇文章:【云原生 | Kubernetes 实战】13、K8s 常见的存储方案及具体应用场景分析(下)_Stars.Sky的博客-CSDN博客

 类似资料: