• K8S常见的持久化(存储)方案用法详解



    在k8s中为什么要做持久化存储?
    在k8s中部署的应用都是以pod容器的形式运行的,假如我们部署MySQL、Redis等数据库,
    需要对这些数据库产生的数据做备份。因为Pod是有生命周期的,如果pod不挂载数据卷,
    那pod被删除或重启后这些数据会随之消失,如果想要长久的保留这些数据就要用到pod数据持久化存储。
    常用的存储如下:
    emptyDir
    hostPath
    nfs
    persistentVolumeClaim
    glusterfs
    cephfs
    configMap
    secret

    创建docker时,一般也要持久化存储

    1、k8s持久化存储:emptyDir 临时存储方案

    #查看k8s支持哪些存储:

    [root@master01 ~ ]#kubectl explain pods.spec.volumes
    
    KIND:     Pod
    VERSION:  v1
    RESOURCE: volumes <[]Object>
    DESCRIPTION:
         List of volumes that can be mounted by containers belonging to the pod.
         More info: https://kubernetes.io/docs/concepts/storage/volumes
         Volume represents a named volume in a pod that may be accessed by any
         container in the pod.
    FIELDS:
       awsElasticBlockStore	<Object>
       azureDisk	<Object>
       azureFile	<Object>
       cephfs	<Object>
       cinder	<Object>
       configMap	<Object>
       csi	<Object>
       downwardAPI	<Object>
       emptyDir	<Object>
       ephemeral	<Object>
       fc	<Object>
       flexVolume	<Object>
       flocker	<Object>
       gcePersistentDisk	<Object>
       gitRepo	<Object>
       glusterfs	<Object>
       hostPath	<Object>
       iscsi	<Object>
       name	<string> -required-
       nfs	<Object>
       persistentVolumeClaim	<Object>
       photonPersistentDisk	<Object>
       portworxVolume	<Object>
       projected	<Object>
       quobyte	<Object>
       rbd	<Object>
       scaleIO	<Object>
       secret	<Object>
       storageos	<Object>
       vsphereVolume	<Object>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41

    我们想要使用存储卷,需要经历如下步骤
    1、定义pod的volume,这个volume指明它要关联到哪个存储上的
    2、在容器中要使用volumemounts挂载对应的存储

    经过以上两步才能正确的使用存储卷

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

    #创建一个pod,挂载临时目录emptyDir

    容器挂载volumes解释:

    [root@master01 volumes ]#kubectl explain pods.spec.containers.volumeMounts
    KIND:     Pod
    VERSION:  v1
    
    RESOURCE: volumeMounts <[]Object>
    
    DESCRIPTION:
         Pod volumes to mount into the container's filesystem. Cannot be updated.
    
         VolumeMount describes a mounting of a Volume within a container.
    
    FIELDS:
       mountPath	 -required-
         Path within the container at which the volume should be mounted. Must not
         contain ':'.
    
       mountPropagation	
         mountPropagation determines how mounts are propagated from the host to
         container and the other way around. When not set, MountPropagationNone is
         used. This field is beta in 1.10.
    
       name	 -required-
         This must match the Name of a Volume.
    
       readOnly	
         Mounted read-only if true, read-write otherwise (false or unspecified).
         Defaults to false.
    
       subPath	
         Path within the volume from which the container's volume should be mounted.
         Defaults to "" (volume's root).
    
       subPathExpr	
         Expanded path within the volume from which the container's volume should be
         mounted. Behaves similarly to SubPath but environment variable references
         $(VAR_NAME) are expanded using the container's environment. Defaults to ""
         (volume's root). SubPathExpr and SubPath are mutually exclusive.
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37

    创建一个emptydir的yaml文件

    [root@master01 volumes ]#cat emptydir.yaml 
    apiVersion: v1
    kind: Pod
    metadata:
      name: pod-empty
    spec:
      containers:
      - name: container-empty
        image: nginx
        imagePullPolicy: IfNotPresent
        volumeMounts:
        - mountPath: /cache
          name: cache-volume
      volumes:
      - emptyDir: {}
        name: cache-volume  临时目录的名字
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    [root@master01 volumes ]#kubectl apply -f emptydir.yaml 
    pod/pod-empty created
    
    • 1
    • 2

    查看本机临时目录存在的位置,可用如下方法:
    #查看pod调度到哪个节点

    [root@master01 volumes ]#kubectl get pods  -owide
    NAME        READY   STATUS    RESTARTS   AGE   IP             NODE     NOMINATED NODE   READINESS GATES
    pod-empty   1/1     Running   0          46s   172.29.55.10   node01   <none>           <none>
    
    • 1
    • 2
    • 3

    #查看pod的uid

    [root@master01 volumes ]#kubectl get pods -oyaml|grep -i uid
        uid: 95ebf93e-c8ad-4bc6-965f-5f289d8b351e
    
    • 1
    • 2

    #登录到node01上
    每创建一个pod。都会有一个UID
    根据uid查看volume位置,默认情况下pod的存储位置在/var/lib/kubelet/pods/下面根据UID找到对应的pod

    [root@node01 ~ ]#tree /var/lib/kubelet/pods/95ebf93e-c8ad-4bc6-965f-5f289d8b351e
    /var/lib/kubelet/pods/95ebf93e-c8ad-4bc6-965f-5f289d8b351e
    ├── containers
    │   └── container-empty
    │       └── 96789484
    ├── etc-hosts
    ├── plugins
    │   └── kubernetes.io~empty-dir
    │       ├── cache-volume
    │       │   └── ready
    │       └── wrapped_kube-api-access-6bggs
    │           └── ready
    └── volumes
        ├── kubernetes.io~empty-dir
        │   └── cache-volume
        └── kubernetes.io~projected
            └── kube-api-access-6bggs
                ├── ca.crt -> ..data/ca.crt
                ├── namespace -> ..data/namespace
                └── token -> ..data/token
    
    11 directories, 7 files
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22

    由上可知,临时目录在本地的 /var/lib/kubelet/pods/95ebf93e-c8ad-4bc6-965f-5f289d8b351e/volumes/kubernetes.io~empty-dir/cache-volume

    进容器中看看:

    [root@node01 ~ ]#docker exec -it a8dec08364e7 /bin/bash
    root@pod-empty:/# ls -l
    total 12
    drwxr-xr-x   2 root root 4096 Sep 12 00:00 bin
    drwxr-xr-x   2 root root    6 Sep  3 12:10 boot
    drwxrwxrwx   2 root root    6 Sep 21 02:22 cache
    drwxr-xr-x   5 root root  360 Sep 21 02:22 dev
    drwxr-xr-x   1 root root   41 Sep 13 06:29 docker-entrypoint.d
    -rwxrwxr-x   1 root root 1202 Sep 13 06:29 docker-entrypoint.sh
    drwxr-xr-x   1 root root   19 Sep 21 02:22 etc
    drwxr-xr-x   2 root root    6 Sep  3 12:10 home
    drwxr-xr-x   1 root root   45 Sep 12 00:00 lib
    drwxr-xr-x   2 root root   34 Sep 12 00:00 lib64
    drwxr-xr-x   2 root root    6 Sep 12 00:00 media
    drwxr-xr-x   2 root root    6 Sep 12 00:00 mnt
    drwxr-xr-x   2 root root    6 Sep 12 00:00 opt
    dr-xr-xr-x 227 root root    0 Sep 21 02:22 proc
    drwx------   2 root root   37 Sep 12 00:00 root
    drwxr-xr-x   1 root root   38 Sep 21 02:22 run
    drwxr-xr-x   2 root root 4096 Sep 12 00:00 sbin
    drwxr-xr-x   2 root root    6 Sep 12 00:00 srv
    dr-xr-xr-x  13 root root    0 Sep 21 02:22 sys
    drwxrwxrwt   1 root root    6 Sep 13 06:29 tmp
    drwxr-xr-x   1 root root   66 Sep 12 00:00 usr
    drwxr-xr-x   1 root root   19 Sep 12 00:00 var
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    root@pod-empty:/cache# df -h
    Filesystem           Size  Used Avail Use% Mounted on
    overlay               38G  4.5G   33G  13% /
    tmpfs                 64M     0   64M   0% /dev
    tmpfs                1.5G     0  1.5G   0% /sys/fs/cgroup
    /dev/mapper/cl-root   38G  4.5G   33G  13% /cache
    shm                   64M     0   64M   0% /dev/shm
    tmpfs                2.8G   12K  2.8G   1% /run/secrets/kubernetes.io/serviceaccount
    tmpfs                1.5G     0  1.5G   0% /proc/acpi
    tmpfs                1.5G     0  1.5G   0% /proc/scsi
    tmpfs                1.5G     0  1.5G   0% /sys/firmware
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    在容器里面挂载目录下创建文件

    root@pod-empty:/cache# pwd
    /cache

    root@pod-empty:/cache# touch 123
    root@pod-empty:/cache# ls -l
    total 0
    -rw-r–r-- 1 root root 0 Sep 21 02:42 123

    退出容器,在宿主机目录下查看:

    [root@node01 cache-volume ]#pwd
    /var/lib/kubelet/pods/95ebf93e-c8ad-4bc6-965f-5f289d8b351e/volumes/kubernetes.io~empty-dir/cache-volume
    
    • 1
    • 2

    [root@node01 cache-volume ]#ll
    total 0
    -rw-r–r-- 1 root root 0 Sep 21 10:42 123

    可见在宿主机对应目录下也创建了文件

    pod如果被删除,临时目录也就没了,pod的UID所在目录没了

    也可以直接用kubectl进去pod中查看:

    [root@master01 volumes ]#kubectl exec -it pod-empty – /bin/bash

    root@pod-empty:/# cd cache/
    root@pod-empty:/cache# ls
    123

    2、k8s持久化存储:hostPath

    hostPath Volume是指Pod挂载宿主机上的目录或文件。 hostPath Volume使得容器可以使用宿主机的文件系统进行存储,
    hostpath(宿主机路径):节点级别的存储卷,在pod被删除,这个存储卷还是存在的,不会被删除,
    所以只要同一个pod被调度到同一个节点上来,在pod被删除重新被调度到这个节点之后,对应的数据依然是存在的。

    #查看hostPath存储卷的用法

    [root@master01 volumes ]#kubectl explain pods.spec.volumes.hostPath
    KIND:     Pod
    VERSION:  v1
    
    RESOURCE: hostPath <Object>
    
    DESCRIPTION:
         HostPath represents a pre-existing file or directory on the host machine
         that is directly exposed to the container. This is generally used for
         system agents or other privileged things that are allowed to see the host
         machine. Most containers will NOT need this. More info:
         https://kubernetes.io/docs/concepts/storage/volumes#hostpath
    
         Represents a host path mapped into a pod. Host path volumes do not support
         ownership management or SELinux relabeling.
    
    FIELDS:
       path	<string> -required-
         Path of the directory on the host. If the path is a symlink, it will follow
         the link to the real path. More info:
         https://kubernetes.io/docs/concepts/storage/volumes#hostpath
    
       type	<string>
         Type for HostPath Volume Defaults to "" More info:
         https://kubernetes.io/docs/concepts/storage/volumes#hostpath
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25

    支持的 type 值如下:

    取值 行为
    空字符串(默认)用于向后兼容,这意味着在安装 hostPath 卷之前不会执行任何检查。
    DirectoryOrCreate 如果在给定路径上什么都不存在,那么将根据需要创建空目录,权限设置为 0755,具有与 Kubelet 相同的组和所有权。
    Directory 在给定路径上必须存在的目录。
    FileOrCreate 如果在给定路径上什么都不存在,那么将在那里根据需要创建空文件,权限设置为 0644,具有与 Kubelet 相同的组和所有权。
    File 在给定路径上必须存在的文件。
    Socket 在给定路径上必须存在的 UNIX 套接字。
    CharDevice 在给定路径上必须存在的字符设备。
    BlockDevice 在给定路径上必须存在的块设备。

    #把tomcat.tar.gz上传到node01上,手动解压:

    [root@node01 volumes ]#docker load -i tomcat.tar.gz

    #创建一个pod,挂载hostPath存储卷

    [root@master01 volumes ]#cat hostpath.yaml 
    apiVersion: v1
    kind: Pod
    metadata:
      name: test-hostpath
    spec:
      containers:
      - image: nginx
        imagePullPolicy: IfNotPresent
        name: test-nginx
        volumeMounts:
        - mountPath: /test-nginx
          name: test-volume
      - image: tomcat:8.5-jre8-alpine
        imagePullPolicy: IfNotPresent
        name: test-tomcat
        volumeMounts:
        - mountPath: /test-tomcat
          name: test-volume
      volumes:
      - name: test-volume
        hostPath:
          path: /data1
          type: DirectoryOrCreate 
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24

    #查看pod调度到了哪个物理节点

    [root@master01 volumes ]#kubectl get pods -o wide | grep hostpath
    test-hostpath                      2/2     Running   0              11m   172.29.55.31   node01   <none>           <none>
    
    • 1
    • 2

    #由上面可以知道pod调度到了node01上,登录到node01机器,查看是否在这台机器创建了存储目录

    [root@node01 volumes ]#ll /data1/
    total 0

    #上面可以看到已经创建了存储目录/data1,这个/data1会作为pod的持久化存储目录

    #在node01上的/data1下创建一个目录

    [root@node01 volumes ]#cd /data1/
    [root@node01 data1 ]#ll
    total 0
    [root@node01 data1 ]#mkdir aa
    [root@node01 data1 ]#ll
    total 0
    drwxr-xr-x 2 root root 6 Sep 22 11:20 aa

    #测试存储卷是否可以正常使用,登录到nginx容器,查看共享目录下是否创建了aa

    [root@master01 volumes ]#kubectl exec -it test-hostpath -c test-nginx – /bin/bash

    root@test-hostpath:/# cd /test-nginx/

    root@test-hostpath:/test-nginx# ls
    aa

    #测试存储卷是否可以正常使用,登录到tomcat容器

    [root@master01 volumes ]#kubectl exec -it test-hostpath -c test-tomcat – /bin/bash

    bash-4.4# cd /test-tomcat/
    bash-4.4# ls -l
    total 0
    drwxr-xr-x 2 root root 6 Sep 22 03:20 aa

    #通过上面测试可以看到,同一个pod里的test-nginx和test-tomcat这两个容器是共享存储卷的。

    hostpath存储卷缺点:
    单节点
    pod删除之后重新创建必须调度到同一个node节点,数据才不会丢失

    可以用分布式存储:
    nfs,cephfs,glusterfs

    3、k8s持久化存储:nfs

    上节说的hostPath存储,存在单点故障,pod挂载hostPath时,只有调度到同一个节点,数据才不会丢失。那可以使用nfs作为持久化存储。

    1、搭建nfs服务

    以k8s的控制节点作为NFS服务端

    #在宿主机创建NFS需要的共享目录

    [root@master01 data ]#vim /etc/exports
    /data/v1 10.10.0.0/24(rw,no_root_squash)
    /data/volumes 10.10.0.0/24(rw,no_root_squash)
    
    • 1
    • 2
    • 3

    在node01上手动挂载试试:

    [root@node01 ~ ]#mkdir /test

    [root@node01 ~ ]#mount.nfs 10.10.0.10:/data/volumes /test/

    [root@node01 ~ ]#df -h
    
    10.10.0.10:/data/volumes                                                                      38G  5.8G   32G  16% /test
    
    • 1
    • 2
    • 3

    #nfs可以被正常挂载
    #手动卸载:
    [root@node01 ~ ]#umount /test

    2.创建Pod,挂载NFS共享出来的目录

    [root@master01 volumes ]#cat nfs.yaml 
    apiVersion: v1
    kind: Pod
    metadata:
     name: test-nfs-volume
    spec:
     containers:
     - name: test-nfs
       image: nginx
       imagePullPolicy: IfNotPresent
       ports:
       - containerPort: 80
         protocol: TCP
       volumeMounts:
       - name: nfs-volumes
         mountPath: /usr/share/nginx/html
     volumes:
     - name: nfs-volumes
       nfs:
        path: /data/volumes
        server: 10.10.0.10
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    [root@master01 volumes ]#kubectl get pods
    NAME                               READY   STATUS    RESTARTS        AGE
    counter                            1/1     Running   0               3h11m
    nfs-provisioner-685d4995b6-m56f8   1/1     Running   2 (4h30m ago)   17h
    test-hostpath                      2/2     Running   0               137m
    test-nfs-volume                    1/1     Running   0               9s
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    [root@master01 volumes ]#

    #登录到nfs服务器,在共享目录创建一个index.html

    [root@master01 volumes ]#vim index.html
    Hello.Everyone!
    My name is jingtian
    My Chat is little
    
    • 1
    • 2
    • 3
    • 4

    3.请求pod,看结果

    [root@master01 volumes ]#kubectl get pods -owide
    NAME                               READY   STATUS    RESTARTS        AGE     IP             NODE     NOMINATED NODE   READINESS GATES
    counter                            1/1     Running   0               3h14m   172.29.55.29   node01   <none>           <none>
    nfs-provisioner-685d4995b6-m56f8   1/1     Running   2 (4h33m ago)   17h     172.29.55.25   node01   <none>           <none>
    test-hostpath                      2/2     Running   0               140m    172.29.55.31   node01   <none>           <none>
    test-nfs-volume                    1/1     Running   0               3m5s    172.29.55.32   node01   <none>           <none>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    [root@master01 volumes ]#curl 172.29.55.32
    Hello.Everyone!
    My name is jingtian
    My Chat is little
    
    • 1
    • 2
    • 3
    • 4

    #通过上面可以看到,在共享目录创建的index.html已经被pod挂载了

    #登录到pod验证下

    [root@master01 volumes ]#kubectl exec -it test-nfs-volume – /bin/bash
    root@test-nfs-volume:/#

    root@test-nfs-volume:/# cat /usr/share/nginx/html/index.html 
    Hello.Everyone!
    My name is jingtian
    My Chat is little
    
    • 1
    • 2
    • 3
    • 4

    #上面说明挂载nfs存储卷成功了,nfs支持多个客户端挂载,
    可以创建多个pod,挂载同一个nfs服务器共享出来的目录;
    但是nfs如果宕机了,数据也就丢失了,所以需要使用分布式存储,
    常见的分布式存储有glusterfs和cephfs

    4、k8s持久化存储: PVC

    4.1.1 k8s PV是什么?

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

    4.1.2 k8s PVC是什么?

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

    4.1.3 k8s PVC和PV工作原理

    PV是群集中的资源。 PVC是对这些资源的请求。
    PV和PVC之间的相互作用遵循以下生命周期:

    (1)pv的供应方式

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

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

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

    (2)绑定

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

    (3)使用

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

    (4)回收策略

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

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

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

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

    1、创建nfs共享目录

    #在宿主机创建NFS需要的共享目录

    [root@master01 data ]#mkdir -p volumes_test/v{1…10}

    #配置nfs共享宿主机上的/data/volume_test/v1…v10目录

    [root@master01 volumes ]#vim /etc/exports
    /data/v1 10.10.0.0/24(rw,no_root_squash)
    /data/volumes 10.10.0.0/24(rw,no_root_squash)
    /data/volumes_test/v1 10.10.0.0/24(rw,no_root_squash)
    /data/volumes_test/v2 10.10.0.0/24(rw,no_root_squash)
    /data/volumes_test/v3 10.10.0.0/24(rw,no_root_squash)
    /data/volumes_test/v4 10.10.0.0/24(rw,no_root_squash)
    /data/volumes_test/v5 10.10.0.0/24(rw,no_root_squash)
    /data/volumes_test/v6 10.10.0.0/24(rw,no_root_squash)
    /data/volumes_test/v7 10.10.0.0/24(rw,no_root_squash)
    /data/volumes_test/v8 10.10.0.0/24(rw,no_root_squash)
    /data/volumes_test/v9 10.10.0.0/24(rw,no_root_squash)
    /data/volumes_test/v10 10.10.0.0/24(rw,no_root_squash)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    [root@master01 volumes ]#exportfs -arv
    exporting 10.10.0.0/24:/data/volumes_test/v10
    exporting 10.10.0.0/24:/data/volumes_test/v9
    exporting 10.10.0.0/24:/data/volumes_test/v8
    exporting 10.10.0.0/24:/data/volumes_test/v7
    exporting 10.10.0.0/24:/data/volumes_test/v6
    exporting 10.10.0.0/24:/data/volumes_test/v5
    exporting 10.10.0.0/24:/data/volumes_test/v4
    exporting 10.10.0.0/24:/data/volumes_test/v3
    exporting 10.10.0.0/24:/data/volumes_test/v2
    exporting 10.10.0.0/24:/data/volumes_test/v1
    exporting 10.10.0.0/24:/data/volumes
    exporting 10.10.0.0/24:/data/v1
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    2、如何编写pv的资源清单文件

    #查看定义pv需要的字段

    [root@master01 volumes ]#kubectl explain pv.spec.nfs
    KIND:     PersistentVolume
    VERSION:  v1
    
    RESOURCE: nfs <Object>
    
    DESCRIPTION:
         NFS represents an NFS mount on the host. Provisioned by an admin. More
         info: https://kubernetes.io/docs/concepts/storage/volumes#nfs
    
         Represents an NFS mount that lasts the lifetime of a pod. NFS volumes do
         not support ownership management or SELinux relabeling.
    
    FIELDS:
       path	<string> -required-
         Path that is exported by the NFS server. More info:
         https://kubernetes.io/docs/concepts/storage/volumes#nfs
    
       readOnly	<boolean>
         ReadOnly here will force the NFS export to be mounted with read-only
         permissions. Defaults to false. More info:
         https://kubernetes.io/docs/concepts/storage/volumes#nfs
    
       server	<string> -required-
         Server is the hostname or IP address of the NFS server. More info:
         https://kubernetes.io/docs/concepts/storage/volumes#nfs
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26

    访问模式(accessModes)
    ReadWriteOnce——该卷可以被单个节点以读/写模式挂载

    ReadOnlyMany——该卷可以被多个节点以只读模式挂载

    ReadWriteMany——该卷可以被多个节点以读/写模式挂载

    在命令行中,访问模式缩写为:

    ​ RWO - ReadWriteOnce
    ​ ROX - ReadOnlyMany
    ​ RWX - ReadWriteMany

    3、创建pv

    [root@master01 volumes ]#cat pv.yaml 
    apiVersion: v1
    kind: PersistentVolume
    metadata:
      name:  v1
    spec:
      capacity:
        storage: 1Gi  #pv的存储空间容量
      accessModes: ["ReadWriteOnce"]
      nfs:
        path: /data/volumes_test/v1 #把nfs的存储空间创建成pv
        server: 10.10.0.10     #nfs服务器的地址
    ---
    apiVersion: v1
    kind: PersistentVolume
    metadata:
      name:  v2
    spec:
      persistentVolumeReclaimPolicy: Delete
      capacity:
          storage: 2Gi
      accessModes: ["ReadWriteMany"]
      nfs:
        path: /data/volumes_test/v2
        server: 10.10.0.10
    ---
    apiVersion: v1
    kind: PersistentVolume
    metadata:
      name:  v3
    spec:
      capacity:
          storage: 3Gi
      accessModes: ["ReadOnlyMany"]
      nfs:
        path: /data/volumes_test/v3
        server: 10.10.0.10
    ---
    apiVersion: v1
    kind: PersistentVolume
    metadata:
      name:  v4
    spec:
      capacity:
          storage: 4Gi
      accessModes: ["ReadWriteOnce","ReadWriteMany"]
      nfs:
        path: /data/volumes_test/v4
        server: 10.10.0.10
    ---
    apiVersion: v1
    kind: PersistentVolume
    metadata:
      name:  v5
    spec:
      capacity:
          storage: 5Gi
      accessModes: ["ReadWriteOnce","ReadWriteMany"]
      nfs:
        path: /data/volumes_test/v5
        server: 10.10.0.10
    ---
    apiVersion: v1
    kind: PersistentVolume
    metadata:
      name:  v6
    spec:
      capacity:
          storage: 6Gi
      accessModes: ["ReadWriteOnce","ReadWriteMany"]
      nfs:
        path: /data/volumes_test/v6
        server: 10.10.0.10
    ---
    apiVersion: v1
    kind: PersistentVolume
    metadata:
      name:  v7
    spec:
      capacity:
          storage: 7Gi
      accessModes: ["ReadWriteOnce","ReadWriteMany"]
      nfs:
        path: /data/volumes_test/v7
        server: 10.10.0.10
    ---
    apiVersion: v1
    kind: PersistentVolume
    metadata:
      name:  v8
    spec:
      capacity:
          storage: 8Gi
      accessModes: ["ReadWriteOnce","ReadWriteMany"]
      nfs:
        path: /data/volumes_test/v8
        server: 10.10.0.10
    ---
    apiVersion: v1
    kind: PersistentVolume
    metadata:
      name:  v9
    spec:
      capacity:
          storage: 9Gi
      accessModes: ["ReadWriteOnce","ReadWriteMany"]
      nfs:
        path: /data/volumes_test/v9
        server: 10.10.0.10
    ---
    apiVersion: v1
    kind: PersistentVolume
    metadata:
      name:  v10
    spec:
      capacity:     
          storage: 10Gi
      accessModes: ["ReadWriteOnce","ReadWriteMany"]
      nfs:
        path: /data/volumes_test/v10  
        server: 10.10.0.10
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121

    #更新资源清单文件

    [root@master01 volumes ]#kubectl apply -f pv.yaml 
    persistentvolume/v1 created
    persistentvolume/v2 created
    persistentvolume/v3 created
    persistentvolume/v4 created
    persistentvolume/v5 created
    persistentvolume/v6 created
    persistentvolume/v7 created
    persistentvolume/v8 created
    persistentvolume/v9 created
    persistentvolume/v10 created
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    #查看pv资源

    [root@master01 volumes ]#kubectl get pv
    NAME                                       CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS      CLAIM                            STORAGECLASS       REASON   AGE
    v1                                         1Gi        RWO            Retain           Available                                                                28s
    v10                                        10Gi       RWO,RWX        Retain           Available                                                                28s
    v2                                         2Gi        RWX            Delete           Available                                                                28s
    v3                                         3Gi        ROX            Retain           Available                                                                28s
    v4                                         4Gi        RWO,RWX        Retain           Available                                                                28s
    v5                                         5Gi        RWO,RWX        Retain           Available                                                                28s
    v6                                         6Gi        RWO,RWX        Retain           Available                                                                28s
    v7                                         7Gi        RWO,RWX        Retain           Available                                                                28s
    v8                                         8Gi        RWO,RWX        Retain           Available                                                                28s
    v9                                         9Gi        RWO,RWX        Retain           Available                                                                28s
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    #STATUS是Available,表示pv是可用的

    4、创建pvc,和符合条件的pv绑定,会自动匹配大小相同的PV

    [root@master01 volumes ]#cat pvc.yaml 
    apiVersion: v1
    kind: PersistentVolumeClaim
    metadata:
      name: my-pvc
    spec:
      accessModes: ["ReadWriteMany"]
      resources:
        requests:
          storage: 2Gi
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    #查看pv和pvc

    [root@master01 volumes ]#kubectl get pv
    NAME                                       CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS      CLAIM                            STORAGECLASS       REASON   AGE
    v1                                         1Gi        RWO            Retain           Available                                                                3m29s
    v10                                        10Gi       RWO,RWX        Retain           Available                                                                3m29s
    v2                                         2Gi        RWX            Delete           Bound       default/my-pvc                                               3m29s
    v3                                         3Gi        ROX            Retain           Available                                                                3m29s
    v4                                         4Gi        RWO,RWX        Retain           Available                                                                3m29s
    v5                                         5Gi        RWO,RWX        Retain           Available                                                                3m29s
    v6                                         6Gi        RWO,RWX        Retain           Available                                                                3m29s
    v7                                         7Gi        RWO,RWX        Retain           Available                                                                3m29s
    v8                                         8Gi        RWO,RWX        Retain           Available                                                                3m29s
    v9                                         9Gi        RWO,RWX        Retain           Available                                                                3m29s
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    [root@master01 volumes ]#kubectl get pvc
    NAME     STATUS   VOLUME   CAPACITY   ACCESS MODES   STORAGECLASS   AGE
    my-pvc   Bound    v2       2Gi        RWX                           5s
    
    • 1
    • 2
    • 3

    #STATUS是Bound,表示这个pv已经被my-pvc绑定了

    pvc的名字-绑定到pv-绑定的是v2这个pv-pvc可使用的容量是2G

    5、创建pod,挂载pvc

    [root@master01 volumes ]#cat pod_pvc.yaml 
    apiVersion: v1
    kind: Pod
    metadata:
      name: pod-pvc
    spec:
      containers:
      - name: nginx
        image: nginx
        imagePullPolicy: IfNotPresent
        volumeMounts:
        - name: nginx-html
          mountPath: /usr/share/nginx/html
      volumes:
      - name: nginx-html
        persistentVolumeClaim:
          claimName: my-pvc
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    [root@master01 volumes ]#kubectl apply -f pod_pvc.yaml 
    pod/pod-pvc created
    
    • 1
    • 2
    [root@master01 volumes ]#kubectl get pods
    NAME                               READY   STATUS    RESTARTS      AGE
    counter                            1/1     Running   1 (18m ago)   4h10m
    nfs-provisioner-685d4995b6-m56f8   1/1     Running   3 (19m ago)   18h
    pod-pvc                            1/1     Running   0             6s
    test-hostpath                      2/2     Running   2 (19m ago)   3h16m
    test-nfs-volume                    1/1     Running   1 (19m ago)   59m
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    注:使用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绑定,数据还是原来数据,不会丢失。

  • 相关阅读:
    项目实践《小说网站数据爬取》
    数据结构-----红黑树的删除操作
    Java 24 Design Pattern 之 建造者模式
    宿舍管理系统的设计与实现/学生宿舍管理系统
    Java程序设计复习提纲(上:入门语法)
    从初级软件测试,到高级软件测试的必经之路
    PEG化金纳米棒,CAS:7440-57-5
    Java字母异位词分组leetcode_49
    .Net Core Aop之IResourceFilter
    quartz笔记
  • 原文地址:https://blog.csdn.net/littlefun591/article/details/136343761