k8s数据持久化(存储卷)

Posted givenchy_yzl

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了k8s数据持久化(存储卷)相关的知识,希望对你有一定的参考价值。

数据持久化

我们知道,Pod是由容器组成的,而容器宕机或停止之后,数据就随之丢了,那么这也就意味着我们在做Kubernetes集群的时候就不得不考虑存储的问题,而存储卷就是为了Pod保存数据而生的。存储卷的类型有很多,我们常用到一般有四种:**emptyDir,hostPath,NFS以及云存储(ceph, glasterfs…)**等。

emptyDir(容器与容器的数据共享)

emptyDir类型的volume在pod分配到node上时被创建,kubernetes会在node上自动分配 一个目录,因此无需指定宿主机node上对应的目录文件。这个目录的初始内容为空,当Pod从node上移除时,emptyDir中的数据会被永久删除。emptyDir Volume主要用于某些应用程序无需永久保存的临时目录,多个pod之间的临时数据共享
示例:

kind: Deployment
apiVersion: apps/v1
metadata:
  name: emptydir
spec:
  selector:
    matchLabels:
      app: emptydir
  template:
    metadata:
      labels:
        app: emptydir
    spec:
      containers:
        - name: nginx
          image: nginx
          volumeMounts:
            - mountPath: /data/
              name: emptydir-name
        - name: php
          image: registry.cn-hangzhou.aliyuncs.com/k8sos/web:discuz-php-v1
          volumeMounts:
            - mountPath: /opt/
              name: emptydir-name
      volumes:
        - name: emptydir-name
          emptyDir: {}

#部署
kubectl apply -f empty.yaml

#进入容器



#创建在nginx容器创建文件后,php容器也存在同样的文件,即为数据共享成功

hostPath(容器与节点的数据共享)

hostPath类型则是映射node文件系统中的文件或者目录到pod里。在使用hostPath类型的存储卷时,也可以设置type字段,支持的类型有文件、目录、File、Socket、CharDevice和BlockDevice。
例:

apiVersion: v1
kind: Pod
metadata:
  name: vol-hostpath
  namespace: default
spec:
  volumes:
  - name: html
    hostPath:
      path: /data/pod/volume1/
      type: DirectoryOrCreate
  containers:
  - name: myapp
    image: nginx
    volumeMounts:
    - name: html
      mountPath: /usr/share/nginx/html/

hostPath可供挂载的文件类型(参数)

参数参数释义
Directory如果在给定路径上什么都不存在,那么将根据需要创建空目录,权限设置为 0755,具有与 kubelet 相同的组和属主信息。
Directory在给定路径上必须存在的目录。 不存在,容器会阻塞在原地
FileOrCreate如果在给定路径上什么都不存在,那么将在那里根据需要创建空文件,权限设置为 0644,具有与 kubelet 相同的组和所有权。
File在给定路径上必须存在的文件。 不存在,容器会阻塞在原地
Socket在给定路径上必须存在的 UNIX 套接字文件。
CharDevice在给定路径上必须存在的字符设备。
BlockDevice在给定路径上必须存在的块设备。

pv和pvc

pv是集群级资源,pvc是命名空间级资源,所以pvc需要指定命名空间
pv是将外部的硬盘资源变成集群内部的资源,方便k8s管理
PersistentVolume(PV)是集群中已由管理员配置的一段网络存储。 集群中的资源就像一个节点是一个集群资源。 PV是诸如卷之类的卷插件,但是具有独立于使用PV的任何单个pod的生命周期。 该API对象捕获存储的实现细节,即NFS,iSCSI或云提供商特定的存储系统。

PersistentVolumeClaim(PVC)是用户存储的请求。PVC的使用逻辑:在pod中定义一个存储卷(该存储卷类型为PVC),定义的时候直接指定大小,pvc必须与对应的pv建立关系,pvc会根据定义去pv申请,而pv是由存储空间创建出来的。pv和pvc是kubernetes抽象出来的一种存储资源。
PV 的访问模式(accessModes)

PV 的访问模式(accessModes)

模式解释
ReadWriteOnce(RWO)可读可写,但只支持被单个节点挂载。
ReadOnlyMany(ROX)只读,可以被多个节点挂载。
ReadWriteMany(RWX)多路可读可写。这种存储可以以读写的方式被多个节点共享。不是每一种存储都支持这三种方式,像共享方式,目前支持的还比较少,比较常用的是 NFS。在 PVC 绑定 PV 时通常根据两个条件来绑定,一个是存储的大小,另一个就是访问模式

PV 的回收策略(persistentVolumeReclaimPolicy)

策略解释
Retain不清理, 保留 Volume(需要手动清理)
Recycle删除数据,即 rm -rf /thevolume/*(只有 NFS 和 HostPath 支持)
Delete删除存储资源,比如删除 AWS EBS卷(只有AWS EBS GCE PD,Azure Disk 和Cinder)

PV 的状态

状态解释
Available可用
Bound已经分配给PVC
ReleasedPVC解绑但未执行回收策略
Failed发生错误

示例:创建pv

[root@kubernetes-master-01 ~]# cat pv.yaml 
[root@k8s-master-01 ~]# cat pv.yaml 
kind: PersistentVolume
apiVersion: v1
metadata:
  name: pv001
  labels:
    app: pv001
spec:
  nfs:
    #挂载的路径
    path: /nfs/v2
    server: 192.168.13.13
  accessModes:
    - "ReadWriteMany"
    - "ReadWriteOnce"
  capacity:
    storage: 2Gi
---
kind: PersistentVolume
apiVersion: v1
metadata:
  name: pv002
  labels:
    app: pv002
spec:
  nfs:
    path: /nfs/v3
    server: 192.168.13.13
  accessModes:
    - "ReadWriteMany"
    - "ReadWriteOnce"
  capacity:
    storage: 5Gi
  persistentVolumeReclaimPolicy: Delete
---
kind: PersistentVolume
apiVersion: v1
metadata:
  name: pv003
  labels:
    app: pv003
spec:
  nfs:
    path: /nfs/v4
    server: 192.168.13.13
  accessModes:
    - "ReadWriteMany"
    - "ReadWriteOnce"
  capacity:
    storage: 10Gi
---
kind: PersistentVolume
apiVersion: v1
metadata:
  name: pv004
  labels:
    app: pv004
spec:
  nfs:
    path: /nfs/v5
    server: 192.168.13.13
  accessModes:
    - "ReadWriteMany"
    - "ReadWriteOnce"
  capacity:
    storage: 20Gi

#获取pv状态
[root@k8s-master-01 ~]# kubectl get pv
NAME    CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS      CLAIM   STORAGECLASS   REASON   AGE
pv001   2Gi        RWO,RWX        Retain           Available                                   5m31s
pv002   5Gi        RWO,RWX        Delete           Available                                   5m31s
pv003   10Gi       RWO,RWX        Retain           Available                                   5m31s
pv004   20Gi       RWO,RWX        Retain           Available                                   5m31s

使用pv

示例:

[root@k8s-master-01 ~]# cat pvc.yaml 
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: pvc
  namespace: default
spec:
  accessModes:
    - "ReadWriteMany"
  resources:
    requests:
      storage: "6Gi"
---
kind: Deployment
apiVersion: apps/v1
metadata:
  name: nfs
  namespace: default
spec:
  replicas: 1
  selector:
    matchLabels:
      app: nfs
  template:
    metadata:
      labels:
        app: nfs
    spec:
      containers:
        - name: nginx
          imagePullPolicy: IfNotPresent
          image: nginx
          volumeMounts:
            - name: html
              mountPath: /usr/share/nginx/html/
      volumes:
        - name: html
          persistentVolumeClaim:
            claimName: pvc

[root@k8s-master-01 ~]# kubectl get pvc,pv
NAME                             STATUS    VOLUME                                     CAPACITY   ACCESS MODES   STORAGECLASS       AGE
persistentvolumeclaim/pvc        Bound     pv003                                      10Gi       RWO,RWX                           2m6s
persistentvolumeclaim/test-nfs   Bound     pvc-2d84c2da-51ad-48fc-b661-5f3a7aef59d7   8Gi        RWX            nfs-client         <invalid>
persistentvolumeclaim/test-sc    Pending                                                                        nfs-storageclass   14m

NAME                                                        CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS      CLAIM              STORAGECLASS   REASON   AGE
persistentvolume/pv001                                      2Gi        RWO,RWX        Retain           Available                                              3m24s
persistentvolume/pv002                                      5Gi        RWO,RWX        Delete           Available                                              3m24s
persistentvolume/pv003                                      10Gi       RWO,RWX        Retain           Bound       default/pvc                                3m24s
persistentvolume/pv004                                      20Gi       RWO,RWX        Retain           Available                                              3m24s
persistentvolume/pvc-2d84c2da-51ad-48fc-b661-5f3a7aef59d7   8Gi        RWX            Retain           Bound       default/test-nfs   nfs-client              <invalid>

NFS

nfs使得我们可以挂载已经存在的共享到我们的Pod中,和emptyDir不同的是,当Pod被删除时,emptyDir也会被删除。但是nfs不会被删除,仅仅是解除挂在状态而已,这就意味着NFS能够允许我们提前对数据进行处理,而且这些数据可以在Pod之间相互传递,并且nfs可以同时被多个pod挂在并进行读写
示例:

#在所有节点上安装nfs
yum install nfs-utils rpcbind -y

# 配置nfs
[root@k8s-master-01 ~]# mkdir -p /nfs/v{1..9}
[root@k8s-master-01 ~]# cat > /etc/exports <<EOF
/nfs/v1 192.168.13.0/24(rw,sync,all_squash)
/nfs/v2 192.168.13.0/24(rw,sync,all_squash)
/nfs/v3 192.168.13.0/24(rw,sync,all_squash)
/nfs/v4 192.168.13.0/24(rw,sync,all_squash)
/nfs/v5 192.168.13.0/24(rw,sync,all_squash)
/nfs/v6 192.168.13.0/24(rw,sync,all_squash)
/nfs/v7 192.168.13.0/24(rw,sync,all_squash)
/nfs/v8 192.168.13.0/24(rw,sync,all_squash)

# 查看nfs是否创建成功
[root@k8s-master-01 ~]# showmount -e
Export list for k8s-master-01:
/nfs/v8 192.168.13.0/24
/nfs/v7 192.168.13.0/24
/nfs/v6 192.168.13.0/24
/nfs/v5 192.168.13.0/24
/nfs/v4 192.168.13.0/24
/nfs/v3 192.168.13.0/24
/nfs/v2 192.168.13.0/24
/nfs/v1 192.168.13.0/24

# 编辑nfs配置文件
[root@k8s-master-01 ~]# cat > nfs.yaml <<EOF
kind: Deployment
apiVersion: apps/v1
metadata:
  name: nginx 
spec:
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
        - name: nginx
          image: nginx
          volumeMounts:
            - mountPath: /usr/share/nginx/html/
              name: nfs
      volumes:
        - name: nfs
          nfs:
            path: /nfs/v1
            server: 192.168.13.11
[root@k8s-master-01 ~]# kubectl get pods -l app=nginx
NAME                     READY   STATUS    RESTARTS   AGE
nginx-5c66c68478-hjn6d   1/1     Running   0          115s

#检查nfs成功与否
[root@k8s-master-01 ~]# echo "index" > /nfs/v1/index.html
[root@k8s-master-01 ~]# kubectl exec -it nginx-5c66c68478-hjn6d -- bash
root@nginx-5c66c68478-hjn6d:/# cd /usr/share/nginx/html/
root@nginx-5c66c68478-hjn6d:/usr/share/nginx/html# ls
default-test-nfs-pvc-2d84c2da-51ad-48fc-b661-5f3a7aef59d7  index.html
root@nginx-5c66c68478-hjn6d:/usr/share/nginx/html# cat index.html 
index

StorageClass

在一个大规模的Kubernetes集群里,可能有成千上万个PVC,这就意味着运维人员必须实现创建出这个多个PV,此外,随着项目的需要,会有新的PVC不断被提交,那么运维人员就需要不断的添加新的,满足要求的PV,否则新的Pod就会因为PVC绑定不到PV而导致创建失败。而且通过 PVC 请求到一定的存储空间也很有可能不足以满足应用对于存储设备的各种需求,而且不同的应用程序对于存储性能的要求可能也不尽相同,比如读写速度、并发性能等,为了解决这一问题,Kubernetes 又为我们引入了一个新的资源对象:StorageClass,通过 StorageClass 的定义,管理员可以将存储资源定义为某种类型的资源,比如快速存储、慢速存储等,kubernetes根据 StorageClass 的描述就可以非常直观的知道各种存储资源的具体特性了,这样就可以根据应用的特性去申请合适的存储资源了。

环境准备

每一个存储类都包含provisioner、parameters和reclaimPolicy这三个参数域,当一个属于某个类的PersistentVolume需要被动态提供时,将会使用上述的参数域。

这里我们引入一个新的工具—>helm是一个安装包工具,类似于yum

# 下载helm并安装
wget https://git.helm.sh/helm-v3.3.4-linux-amd64.tar.gz

# 解压
tar xf helm-v3.3.4-linux-amd64.tar.gz

# 安装
mv linux-amd64/helm /usr/local/bin/

# 验证
helm version

# 添加镜像仓库
helm repo add ckotzbauer https://ckotzbauer.github.io/helm-charts

#拓展
helm repo remove [仓库名称]     #删除仓库
helm repo list          #查看仓库列表
#搜索压缩包
[root@k8s-master-01 opt]# helm search repo redis
NAME               	CHART VERSION	APP VERSION	DESCRIPTION                                       
ali-stable/redis   	1.1.15       	4.0.8      	Open source, advanced key-value store. It is of...
ali-stable/redis-ha	2.0.1        	           	Highly available Redis cluster with multiple se...
ali-stable/sensu   	0.2.0        	           	Sensu monitoring framework backed by the Redis ...
# 下载安装包nfs
helm pull stable/nfs-client-provisioner

#下载成功解压后编辑配置文件
[root@k8s-master-01 opt]# vim nfs-client-provisioner/values.yaml 
详细内容见下图:

# 编辑成功后安装nfs-client
helm install nfs ./

#示例:
[root@k8s-master-01 ~]# cat test-nfs.yaml 
kind: PersistentVolumeClaim
apiVersion: v1
metadata:
  name: test-sc
spec:
  storageClassName: nfs-storageclass
  accessModes:
    - "ReadWriteMany"
  resources:
    requests:
      storage: "6Gi"
---
kind: Deployment
apiVersion: apps/v1
metadata:
  name: test-sc
spec:
  selector:
    matchLabels:
      app: test-sc
  template:
    metadata:
      labels:
        app: test-sc
    spec:
      containers:
        - name: nginx
          imagePullPolicy: IfNotPresent
          image: nginx
          volumeMounts:
            - mountPath: /data/
              name: test-sc-name
      volumes:
        - name: test-sc-name
          persistentVolumeClaim:
            claimName: test-sc

# 


[root@k8s-master-01 ~]# vim test-nfs.yaml 
kind: PersistentVolumeClaim
apiVersion: v1
metadata:
  name: test-sc
spec:
  storageClassName: nfs-storageclass
  accessModes:
    - "ReadWriteMany"
  resources:
    requests:
      storage: "6Gi"
---
kind: Deployment
apiVersion: apps/v1
metadata:
  name: test-sc
spec:
  selector:
    matchLabels:
      app: test-sc
  template:
    metadata:
      labels:
        app: test-sc
    spec:
      containers:
        - name: nginx
          imagePullPolicy: IfNotPresent
          image: nginx
          volumeMounts:
            - mountPath: /data/
              name: test-sc-name
      volumes:
        - name: test-sc-name
          persistentVolumeClaim:
            claimName: test-sc

# 查看部署详情
[root@k8s-master-01 ~]# kubectl apply -f test-nfs.yaml 
persistentvolumeclaim/test-sc created
deployment.apps/test-sc created

[root@k8s-master-01 ~]# kubectl get pv,pvc
NAME                                                        CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS      CLAIM              STORAGEC
persistentvolume/pv003                                      10Gi       RWO,RWX        Retain           Bound       default/pvc 
persistentvolume/pvc-2d84c2da-51ad-48fc-b661-5f3a7aef59d7   8Gi        RWX            Retain           Bound       default/test-nfs   nfs-client              12h

NAME                             STATUS    VOLUME                                     CAPACITY   ACCESS MODES   STORAGECLASS       AGE
persistentvolumeclaim/pvc        Bound     pv003                                      10Gi       RWO,RWX                           13h
persistentvolumeclaim/test-nfs   Bound     pvc-2d84c2da-51ad-48fc-b661-5f3a7aef59d7   8Gi        RWX            nfs-client         13h

问题: Warning FailedScheduling 46m default-scheduler 0/4 nodes are available: 2 node(s) had taint {node-role.kubernetes.io/master: }, tachable: }, that the pod didn’t tolerate

问题分析:使用kubeadm初始化的集群,出于安全考虑Pod不会被调度到Master Node上,不参与工作负载。因此将pod布在master节点上冲突

问题解决:允许master节点部署pod即可解决问题,命令如下:
kubectl taint nodes --all node-role.kubernetes.io/master-

补充:(禁止master部署pod命令):
kubectl taint nodes k8s node-role.kubernetes.io/master=true:NoSchedule

以上是关于k8s数据持久化(存储卷)的主要内容,如果未能解决你的问题,请参考以下文章

k8s之存储卷及pvc

Kubernetes核心概念之Volume存储数据卷详解

从零开始入门 K8s | 应用存储和持久化数据卷:核心知识

k8s之存储

k8s实践:存储卷和数据持久化(Volumes and Persistent Storage)

k8s存储数据持久化,emptyDir,hostPath,基于Nfs服务的PV,PVC