基于NFS实现pod数据持久化

PV和PVC

  

概念

  PersistentVolume(PV):是集群中由管理员配置的一段网络存储。它是集群中的资源,就像节点是集群资源一样。PV是容量插件,如Volumes,但其生命周期独立于使用PV的任何单个pod。此API对象捕获存储实现的详细信息,包括NFS,iSCSI或特定于云提供程序的存储系统。

  PersistentVolumeClaim(PVC):是由用户进行存储的请求。它类似于pod。 Pod消耗节点资源,PVC消耗PV资源。Pod可以请求特定级别的资源(CPU和内存)。声明可以请求特定的大小和访问模式(例如,可以一次读/写或多次只读)。

虽然PersistentVolumeClaims允许用户使用抽象存储资源,但是PersistentVolumes对于不同的问题,用户通常需要具有不同属性(例如性能)。群集管理员需要能够提供各种PersistentVolumes不同的方式,而不仅仅是大小和访问模式,而不会让用户了解这些卷的实现方式。对于这些需求,有StorageClass 资源。

  pvc用于实现pod和storage的解耦,修改storage的时候不需要修改pod。与NFS的区别,可以在PV和pVC层面实现对存储服务器的空间分配、存储的访问权限管理灯。

  PV是属于集群资源,pvc是属于namespace中的资源。

  StorageClass为管理员提供了一种描述他们提供的存储的“类”的方法。不同的类可能映射到服务质量级别,或备份策略,或者由群集管理员确定的任意策略。Kubernetes本身对于什么类别代表是不言而喻的。这个概念有时在其他存储系统中称为“配置文件”。

 

PV访问模式

  PersistentVolume卷可以用资源提供者所支持的任何方式挂载到宿主系统上。 如下表所示,提供者(驱动)的能力不同,每个PV卷的访问模式都会设置为对应卷所支持的模式值。例如,NFS可以支持多个读写客户,但是某个特定的 NFS PV卷可能在服务器上以只读的方式导出。每个PV卷都会获得自身的访问模式集合,描述的是特定PV卷的能力。每个卷同一时刻只能以一种访问模式挂载,即使该卷能够支持多种访问模式。

 

  accessModes 访问模式有:

root@deploy:~# kubectl explain PersistentVolume.spec.accessModes

 

ReadWriteOnce

    卷可以被一个节点以读写方式挂载。 ReadWriteOnce 访问模式也允许运行在同一节点上的多个 Pod 访问卷。

 

ReadOnlyMany

    卷可以被多个节点以只读方式挂载。

 

ReadWriteMany

    卷可以被多个节点以读写方式挂载。

 

ReadWriteOncePod

    卷可以被单个 Pod 以读写方式挂载。 如果你想确保整个集群中只有一个 Pod 可以读取或写入该 PVC, 请使用ReadWriteOncePod 访问模式。这只支持 CSI 卷以及需要 Kubernetes 1.22 以上版本。

 

在命令行接口(CLI)中,访问模式也使用以下缩写形式:

    RWO - ReadWriteOnce

    ROX - ReadOnlyMany

    RWX - ReadWriteMany

    RWOP - ReadWriteOncePo

 

  说明:

  Kubernetes 使用卷访问模式来匹配PersistentVolumeClaim和PersistentVolume。在某些场合下,卷访问模式也会限制PersistentVolume可以挂载的位置。卷访问模式并不会在存储已经被挂载的情况下为其实施写保护。即使访问模式设置为ReadWriteOnce、ReadOnlyMany或ReadWriteMany,它们也不会对卷形成限制。例如,即使某个卷创建时设置为ReadOnlyMany,也无法保证该卷是只读的。如果访问模式设置为ReadWriteOncePod,则卷会被限制起来并且只能挂载到一个Pod上。

 

 

PV阶段

每个卷会处于以下阶段(Phase)之一:

    Available(可用)-- 卷是一个空闲资源,尚未绑定到任何申领;

    Bound(已绑定)-- 该卷已经绑定到某申领;

    Released(已释放)-- 所绑定的申领已被删除,但是资源尚未被集群回收;

    Failed(失败)-- 卷的自动回收操作失败。

 

命令行接口能够显示绑定到某 PV 卷的 PVC 对象。

 

PV回收策略

       persistentVolumeReclaimPolicy目前的回收策略有:

root@deploy:~# kubectl explain PersistentVolume.spec.persistentVolumeReclaimPolicy

  

  Retain -- 手动回收,默认策略,pvc回收后,PV卷的状态为released,卷上仍然保留上一次关联的pvc信息,无法绑定给任何pvc。使用命令kubectl edit pv pvname手动清理卷上claimRef信息,删除完成后,pv可以与其他pvc绑定。

   

  Recycle -- 基本擦除 (rm -rf /thevolume/*),pvc回收后,pv的状态为Available,pv可以绑定给其他pvc,pv后端存储中数据被清空。(实际操作过程是:Kubernetes使用busybox镜像创建容器,挂载卷,并清空卷数据。)

   

  Delete -- 诸如AWS EBS、GCE PD、Azure Disk或OpenStack Cinder卷这类关联存储资产也被删除

 

  目前,仅NFS和HostPath支持回收(Recycle)。AWS EBS、GCE PD、Azure Disk和Cinder卷都支持删除(Delete)。

 

PVC与PV匹配规则

 PV的mode必须高于PVC申请的最低要求:mode优先级,可简单理解为ROX<RWO<RWX。例如,用户请求RWO模式PV,但是目前只有NFS PV(RWO+ROX+RWX),PVC将匹配NFS。

  容量满足最低要求:具有相同modes卷会被分组,然后根据size分类(由小到大)。

  pv storage classes:用于对pv进行分类,pvc可以根据storageClassName参数申请特定类型pv。如果pv设置了storageClassName,那么pvc申请资源的时候也要指定storageClassName。例如,storageClassName指定为ns1-storage,ns1中pvc申请也指定storageClassName为ns1-storage。

 

PV卷类型

       定义存储卷使用的类型:分块设备block和文件系统Filesystem。默认为文件系统

root@deploy:~# kubectl explain PersistentVolume.spec.volumeMode

 

PV挂载选项

       mountOptions附加的挂载选项列表,实现更精细的权限控制

root@deploy:~# kubectl explain PersistentVolume.spec.mountOptions

 

 

emptyDir

  默认情况下,当Pod分配到Node上时,将会创建emptyDir,只要Node上的Pod一直运行,Volume就会一直存在。当Pod(不管任何原因)从Node上

  被删除时,emptyDir也同时会删除,存储的数据也将永久删除。

 

  Pod使用示例:(2个容器在一个pod,使用emptydir)

cat pod_storage.yaml 
apiVersion: v1
kind: Pod
metadata:
  name: busybox
  labels:
    app: busybox
spec:
  volumes:
  - name: datavolume
    emptyDir: {}
  containers:
  - name: busybox1
    image: busybox
    imagePullPolicy: IfNotPresent
    command: ['sh', '-c', 'echo Hello Kubernetes! && sleep 3600']
    volumeMounts:
    - mountPath: /data
      name: datavolume
  - name: busybox2
    image: busybox
    imagePullPolicy: IfNotPresent
    command: ['sh', '-c', 'echo Hello Kubernetes! && sleep 3600']
    volumeMounts:
    - mountPath: /data
      name: datavolume

  配置说明:

  spec.volumes:定义卷,是默认卷类型。

  spec.containers.volumeMounts:引用卷

 

  hostPath

  hostPath允许Pod将Node的文件系统挂载到Pod内部。pod删除后,hostPath卷数据保留。

  Pod的hostpath示例:

cat pod-hostpath.yaml 

apiVersion: v1
kind: Pod
metadata:
  name: busybox
  labels:
    app: busybox
spec:
  volumes:
  - name: datavolume
    hostPath:
      path: /busyboxdir
  containers:
  - name: busybox1
    image: busybox
    command: ['sh', '-c', 'echo Hello Kubernetes! && sleep 3600']
    volumeMounts:
    - mountPath: /data
      name: datavolume
  - name: busybox2
    image: busybox
    command: ['sh', '-c', 'echo Hello Kubernetes! && sleep 3600']
    volumeMounts:
    - mountPath: /data
      name: datavolume
      #设置readOnly,控制读写,默认值是false,也就是读写访问。
      readOnly: false

 

NFS存储

  NFS卷允许将现有的NF挂载到容器中,且不想emptyDir会丢失数据,当删除pod时,nfs卷的内容被保留,卷仅仅是被卸载,这意味着NFS卷可以预先上传好的数据待pod启动后即可直接使用,并且网络存储可以再多个pod之间共享同一份数据,即NFS可以被多个Pod同时挂载和读写。

 

  Ubuntu准备NFS

root@harbor:~# apt install nfs-server -y
root@harbor:~# vim /etc/exports
/data/k8sdata  *(rw,sync,no_root_squash)

root@harbor:~# mkdir /data/k8sdata
root@harbor:~# exportfs -r

#k8s节点安装nfs-common
root@node1:~# apt install nfs-common -y

 

  volume示例:

       1、单卷挂载使用

root@deploy:~# cat nfs-deployment.yaml 
apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    app: web
  name: web
spec:
  replicas: 2
  selector:
    matchLabels:
      app: web
  template:
    metadata:
      labels:
        app: web
    spec:
      containers:
      - image: nginx
        name: nginx
        imagePullPolicy: IfNotPresent
        volumeMounts:
        - name: nfs
          mountPath: "/usr/share/nginx/html"
      volumes:
      - name: nfs
        nfs:
          server: 192.168.100.15
          path: "/data/k8sdata"

---
apiVersion: v1
kind: Service
metadata:
  creationTimestamp: null
  labels:
    app: web-svc
  name: web-svc
spec:
  ports:
  - port: 80
    protocol: TCP
    targetPort: 80
    nodePort: 30010
  selector:
    app: web
  type: NodePort

 

       NFS server创建站点文件

root@deploy:~# kubectl apply -f nfs-deployment.yaml
root@harbor:~# cd /data/k8sdata/
root@harbor:/data/k8sdata# echo test > index.html

 

  查看node节点容器具体挂载nfs

       2、多卷挂载使用

root@deploy:~# cat nfs-deployment.yaml 
apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    app: web
  name: web
spec:
  replicas: 2
  selector:
    matchLabels:
      app: web
  template:
    metadata:
      labels:
        app: web
    spec:
      containers:
      - image: nginx
        name: nginx
        imagePullPolicy: IfNotPresent
        volumeMounts:
        - name: nfs1
          mountPath: "/usr/share/nginx/html/data1"
        - name: nfs2
          mountPath: "/usr/share/nginx/html/data2"
      volumes:
      - name: nfs1
        nfs:
          server: 192.168.100.15
          path: "/data/k8sdata/data1"
      - name: nfs2
        nfs:
          server: 192.168.100.15
          path: "/data/k8sdata/data2"

---
apiVersion: v1
kind: Service
metadata:
  creationTimestamp: null
  labels:
    app: web-svc
  name: web-svc
spec:
  ports:
  - port: 80
    protocol: TCP
    targetPort: 80
    nodePort: 30010
  selector:
    app: web
  type: NodePort

 

       nfs添加站点文件

root@harbor:/data/k8sdata# echo "data1" >> data1/index.html
root@harbor:/data/k8sdata# echo "data2" >> data2/index.html

 

       访问测试

       查看node挂载

 

PV示例:

   注意:PV资源属于集群全局资源,不归属于某个namespace

       查看支持的卷存储类型

root@node1:~# kubectl explain deployment.spec.template.spec.volumes

 

  示例:nfs类型pv

root@deploy:~# vim pv.yaml
apiVersion: v1
kind: PersistentVolume
metadata:
  name: pv0001
  labels:
    type: nfs001
spec:
  capacity:
    storage: 10Gi
  accessModes:
    - ReadWriteOnce
  nfs:
    path: "/data/k8sdata/staticdata"
    server: 192.168.100.15

 

  NFS创建目录共享

root@harbor:/data/k8sdata# mkdir staticdata
root@harbor:/data/k8sdata# showmount -e localhost
Export list for localhost:
/data/k8sdata *

 

  创建pv

root@deploy:~# kubectl apply -f pv.yaml

 

 

PVC示例:                       

       注意:创建的pvc属于namespace下的资源,其他pod想要使用必须与pvc处于一个namespace下。

pvc创建参数:

       1accesModes:PVC访问模式

root@master1:~# kubectl explain PersistentVolumeClaim.spec.accessModes

       ReadWriteOnce

    卷可以被一个节点以读写方式挂载。 ReadWriteOnce 访问模式也允许运行在同一节点上的多个 Pod 访问卷。

 

       ReadOnlyMany

    卷可以被多个节点以只读方式挂载。

 

       ReadWriteMany

    卷可以被多个节点以读写方式挂载。

 

       2、resources定义PVC创建存储卷的大小

root@master1:~# kubectl explain PersistentVolumeClaim.spec.resources

 

       3、Selector标签选择器

root@master1:~# kubectl explain PersistentVolumeClaim.spec.selector

       matchExpressions

       使用正则表达式匹配

      

       matchLabels

       匹配标签名称

 

       4、volumeName指定要绑定的pv的名称

root@master1:~# kubectl explain PersistentVolumeClaim.spec.volumeName

 

       5、volumeMode 卷的类型,文件系统|块存储,默认为文件系统

root@master1:~# kubectl explain PersistentVolumeClaim.spec.volumeMode

 

示例:创建申请nfs的pvc

       创建pv

root@deploy:~# vim pv.yaml
apiVersion: v1
kind: PersistentVolume
metadata:
  name: pv0001
  labels:
    type: nfs001
spec:
  capacity:
    storage: 10Gi
  accessModes:
    - ReadWriteOnce
  nfs:
    path: "/data/k8sdata/staticdata"
    server: 192.168.100.15

 

       使用matchLabels指定pv

kind: PersistentVolumeClaim
apiVersion: v1
metadata:
  name: pvc-nfs
  namespace: default
spec:
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 10Gi
  selector:
    matchLabels:
      type: nfs001

 

       创建后,验证pvc对pv的绑定

root@deploy:~# kubectl get pvc -n default
root@deploy:~# kubectl get pv

  查看创建后的pvc详细信息

root@deploy:~# kubectl describe pvc pvc-nfs -n default
Name:          pvc-nfs
Namespace:     default			#所处的namespace
StorageClass:  
Status:        Bound			#pvc的状态
Volume:        pv0001			#绑定对应pv的名称
Labels:        <none>
Annotations:   pv.kubernetes.io/bind-completed: yes
               pv.kubernetes.io/bound-by-controller: yes
Finalizers:    [kubernetes.io/pvc-protection]
Capacity:      10Gi			#pvc申请的容量
Access Modes:  RWO			#pvc访问模式为RWO,允许一台节点读写
VolumeMode:    Filesystem		#卷类型为文件系统
Used By:       <none>
Events:        <none>

 

  创建deployment绑定pvc

root@deploy:~# cat nfs-deployment.yaml 
apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    app: web
  name: web
spec:
  replicas: 2
  selector:
    matchLabels:
      app: web
  template:
    metadata:
      labels:
        app: web
    spec:
      containers:
      - image: nginx
        name: nginx
        imagePullPolicy: IfNotPresent
        volumeMounts:
        - name: nfs-pvc
          mountPath: "/usr/share/nginx/html/staticdata"
      volumes:
      - name: nfs-pvc
        persistentVolumeClaim:
          claimName: pvc-nfs


---
apiVersion: v1
kind: Service
metadata:
  creationTimestamp: null
  labels:
    app: web-svc
  name: web-svc
spec:
  ports:
  - port: 80
    protocol: TCP
    targetPort: 80
    nodePort: 30111
  selector:
    app: web
  type: NodePort

 

       创建deployment

root@deploy:~# kubectl apply -f nfs-deployment.yaml

 

       确保deployment和pvc处于同一个namespace中

       NFS创建站点文件

root@harbor:/data/k8sdata/staticdata# echo "Testing pvc" >> index.html

 

       验证客户端访问:

       验证节点容器挂载卷

 

       验证pod挂载卷

posted @ 2022-08-04 17:23  PunchLinux  阅读(392)  评论(0编辑  收藏  举报