Kubernetes存储Volume

数据是一个企业的发展核心,他涉及到数据存储和数据交换的内容。在生产环境中尤为重要的一部分,在 Kubernetes 中另一个重要的概念就是数据持久化 Volume。

一、Volume的概念

对于大多数的项目而言,数据文件的存储是非常常见的需求,比如存储用户上传的头像、文件以及数据库的数据。在 Kubernetes 中,由于应用的部署具有高度的可扩展性和编排能力(不像传统架构部署在固定的位置),因此把数据存放在容器中是非常不可取的,这样也无法保障数据的安全。

我们应该把有状态的应用变成无状态的应用,意思是指把数据从应用中剥离出来,把产生的数据文件或者宦岑的信息都放在云端,比如常用的NFS(生产环境中不建议使用,因为存在单点故障,推荐使用分布式的存储或者公有云的 NAS 服务)、ceph、GlusterFs、Minio 等。

在传统的架构中,如果要使用这些存储,需要提前在宿主机挂载,然后程序才能访问,在实际使用时,经常碰到新加节点忘记挂载存储导致的一系列问题。而 Kubernetes 在设计之初就考虑了这些问题,并抽象出 Volume 的概念用于解决数据存储的问题。

在容器中的磁盘文件是短暂的,当容器崩溃时,Kubect1 会重新启动容器,但是容器运行时产生的数据文件都会丢失,之后容器会以干净的状态启动。另外,当一个Pod 运行多个容器时,各个容器可能需要共享一些文件,诸如此类的需求都可以使用 Volume 解决。

Docker 也有卷的概念,但是在 Docker 中,卷只是磁盘上或另一个容器中的目录,其生命周期不受管理。虽然 Docker 已经提供了卷驱动程序,但是功能非常有限,例如从 Docker1.7版本开始,每个容器只允许一个卷驱动程序,并且无法将一些特殊的参数传递给后端存储。

另一方面,Kubernetes 卷具有明确的生命周期,与使用他的 Pod 相同,因此在 Kubernetes 中的卷可以比 Pod 中运行的任何容器的生命周期都长,并且可以在容器重启或者销毁之后保留数据。Kubernetes支持多种类型的卷,并且 Pod 可以同时使用任意数量的卷。

从本质上讲,和虚拟机或者物理机一样,卷被挂载后,在容器中也只是一个目录,可能包含一些数据Pod 中的容器也可以对其进行增删改査操作,使用方式和裸机挂载几乎没有区别。要使用卷也非常简单,和其他参数类似,Pod 只需要通过.spec.volumes 字段指定为Pod 提供的卷,然后在容器中配置块,使用.spec.containers.volumeMounts字段指定卷的挂载目录即可。

二、Volume的类型

在传统架构中,企业内可能有自己的存储平台,比如 NFS、Ceph、GlusterFs、Minio 等。如果所在的环境在公有云,也可以使用公有云提供的 NAS、对象存储等。在 Kubernetes 中,Volume 也支持配置这些存储,用于挂载到 Pod 中实现数据的持久化。Kubernetes Volume 支持的卷的类型有很多。

以下为常见的卷:

  • CephFS
  • GlusterFs
  • ISCSI
  • Cinder
  • NFS
  • RBD
  • HostPath

当然也支持一些 Kubernetes 独有的类型:

  • ConfigMap:用于存储配置文件
  • Secret:用于存储敏感数据
  • EmptyDir:用于一个 Pod 内多个容器的数据共享
  • PersistentVolumeclaim:对PersistentVolume的申请

三、通过emptyDir共享数据

emptyDir 是一个特殊的 Volume 类型,与上述 Volume 不同的是,如果删除 Pod,EmptyDir 卷中的数据也将被删除,所以一般 emptyDir 用于 Pod 中不同容器共享数据,比如一个 Pod 存在两个容器A和容器 B,容器A需要使用容器B产生的数据,此时可以采用 emptyDir 共享数据,类似的使用如 Filebeat收集容器内程序产生的日志。

使用 emptyDir 卷时,直接指定 emptyDir 为{}即可

1.编写emptyDir 的 Deployment 文件

vim nginx-empty.yaml

apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    app: nginx
  name: nginx
  namespace: default
spec:
  replicas: 1
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - image: nginx:1.7.9
        imagePullPolicy: IfNotPresent
        name: nginx01
        volumeMounts:
        - mountPath: /opt
          name: share-volume
      - image: nginx:1.7.9
        imagePullPolicy: IfNotPresent
        name: nginx02
        command:
        - sh
        - -c
        - sleep 3600
        volumeMounts:
        - mountPath: /mnt
          name: share-volume
      volumes:
      - name: share-volume
        emptyDir: {}
          #medium: Memory

备注:

volumeMounts:

  • mountPath: /mnt

name: share-volume##容器定义部分的卷挂载名称,此处的名称引用了 volumes 对应的名称

volumes :

-name:share-volume ##共享存储卷的名称

此案例会将 nginx01 中/opt 中的数据,共享给 nginx02 中的/mnt 日录

此部署文件创建一个 Deployment,采用 spec.volume 字段配置了一个名字为 share-volume、类型为 emptyDir 的 volume,同时里面包含两个容器 nginx01和 nginx02,并将该 volume 挂载到了/opt 和/mnt 目录下,此时/opt 和/mnt 目录的数据就实现了共享。

默认情况下,emptyDir 支持节点上的任何介质,可以使 SSD、磁盘或是网络存储,具体取决于自身环境。可以将 emptyDir.medium 字段设置为 Memory,让 Kubernetes 使用 tmpfs(内存支持的文件系统),虽然 tmpfs 非常快,但是在节点重启时,数据同样会被清除,并且设置的大小会被记入 Container 的内存限制中。

2.部署该 Deployment

[root@master ~]# ku create -f nginx-empty.yaml 
deployment.apps/nginx created

3.查看部署结果

[root@master ~]# ku get pod
NAME                    READY   STATUS    RESTARTS   AGE
nginx-8f8dcfd8c-l57qg   2/2     Running   0          22s

4.登录Pod中的第一个容器

[root@master ~]# ku exec -it nginx-8f8dcfd8c-l57qg -c nginx01 -- bash
root@nginx-8f8dcfd8c-l57qg:/# cd /opt/
root@nginx-8f8dcfd8c-l57qg:/opt# touch aa
root@nginx-8f8dcfd8c-l57qg:/opt# touch bb
root@nginx-8f8dcfd8c-l57qg:/opt# touch cc
root@nginx-8f8dcfd8c-l57qg:/opt# exit
exit

备注:

在该容器中的/opt 下创建一个文件,并到第二个容器中査看,是否是共享的目录

5.登录第 Pod 中的第二个容器查看/mnt 下的文件

[root@master ~]# ku exec -it nginx-8f8dcfd8c-l57qg -c nginx02 -- bash
root@nginx-8f8dcfd8c-l57qg:/# cd /mnt/
root@nginx-8f8dcfd8c-l57qg:/mnt# ls
aa  bb	cc

6.删除此Pod

[root@master ~]# ku delete -f nginx-empty.yaml 
deployment.apps "nginx" deleted

四、使用 HostPath 挂载宿主机文件

HostPath 卷可以将节点上的文件或目录挂载到 Pod 上,用于实现 Pod 和宿主机之间的数据共享,常用的示例有挂载宿主机的时区至 Pod,或者将 Pod 的日志文件挂载到宿主机等。

1.编写 Deployment 文件,实现 HostPath 挂载

以下为使用 HostPath 卷的示例,实现将主机的/etc/localtime 文件挂载到 Pod 的/etc/localtime

 vim nginx-hostPath.yaml

apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    app: nginx
  name: nginx
  namespace: default
spec:
  replicas: 1
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - image: nginx:1.7.9
        imagePullPolicy: IfNotPresent
        name: nginx
        volumeMounts:
        - mountPath: /etc/localtime
          name: timezone-time


      volumes:
      - name: timezone-time
        hostPath:
          path: /etc/localtime
          type: File

备注:

关于时区的设置

通过配置/etc/localtime 文件设置系统的时区/etc/localtime用于配置系统时区(此文件是一个链接文件,!链接自/usr/share/zoneinfo/Asia/Shanghai)

2.创建此 Pod

[root@master ~]# ku create -f nginx-hostPath.yaml 
deployment.apps/nginx created

3.查看创建结果

[root@master ~]# ku get pod
NAME                     READY   STATUS    RESTARTS   AGE
nginx-59f95c99b5-jt7x9   1/1     Running   0          54s

4.测试挂载情况

[root@master ~]# ku exec -it nginx-59f95c99b5-jt7x9 -- bash
root@nginx-59f95c99b5-jt7x9:/# date
Mon Aug 26 09:31:25 CST 2024

在配置 HostPath 时,有一个 type 参数,用于表达不同的挂载类型,HostPath 卷常用的类型有:

  • type 为空字符串:默认选项,在挂载 HostPath 卷之前不会有任何检査
  • Directoryorcreate:如果给定的 path 不存在任何东西,那么将根据需要创建一个权限为 0755 的空目录,和 kubelet 具有相同的组和权限
  • Directory:目录必须存在于给定的路径下
  • FileorCreate:如果给定的路径不存在任何内容,则会根据需要创建一个空文件,权限设置为 8644,和 kubelet 具有相同的组和所有权
  • File:文件,必须存在于给定的路径中
  • Socket:UNIX套接字,必须存在于给定的路径中
  • CharDevice:字符设备,必须存在于给定的路径中
  • BlockDevice:块设备,必须存在于给定的路径中

5.删除

[root@master ~]# ku delete -f nginx-hostPath.yaml 
deployment.apps "nginx" deleted

五、挂载NFS至容器

1.安装NFS

在所有的Kubernets节点都要安装

[root@master ~]# yum -y install nfs-utils

2.设置共享目录(在NFS服务器上)

[root@k8s-master ~]# mkdir /opt/wwwroot
[root@k8s-master ~]# echo "This is my test file">/opt/wwwroot/index.html

3.开启 nfs(在 NFS 服务器上)

[root@master ~]# systemctl start nfs
[root@master ~]# systemctl start rpcbind

4.编写 Deployment 文件,挂载 NFS

 vim nginx-nfsVolume.yaml 

apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    app: nginx
  name: nginx
  namespace: default
spec:
  replicas: 1
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - image: nginx:1.7.9
        imagePullPolicy: IfNotPresent
        name: nginx
        volumeMounts:
        - mountPath: /usr/share/nginx/html
          name: nfs-volume
      volumes:
      - name: nfs-volume
        nfs:
          server: 192.168.10.101
          path: /opt/wwwroot

5.部署此Pod

[root@master ~]# ku create -f nginx-nfsVolume.yaml 
deployment.apps/nginx created

6.查看部署结果

[root@master ~]# ku get pod
NAME                     READY   STATUS    RESTARTS   AGE
nginx-7bf6df4679-nx8j2   1/1     Running   0          6s

7.登录容器查看挂载结果

[root@master ~]# ku exec -it nginx-7bf6df4679-nx8j2  -c nginx -- bash
root@nginx-7bf6df4679-nx8j2:/# cat index.html
cat: index.html: No such file or directory
root@nginx-7bf6df4679-nx8j2:/# cd /usr/share/nginx/html/
root@nginx-7bf6df4679-nx8j2:/usr/share/nginx/html# cat index.html
This is my test file

六、PersistentVolume(PV,持久卷)

虽然 volume 已经可以接入大部分存储后端,但是实际使用时还有诸多的问题。比如:

  • 当某个数据卷不再被挂载使用时,里面的数据如何处理?
  • 如果想要实现只读挂载,要如何处理?
  • 如果想要只能有一个 Pod 挂载,要如何处理?

如上所述,对于很多复杂的需求,volume 可能难以实现,并且无法对存储的生命周期进行管理。另一个很大的问题是,在企业内使用 kubernetes 的不仅仅是 kubernetes 管理员,可能还有开发人员、测试人员以及初学 kubernetes 的技术人员,对于 kubernetes 的 volume 或者相关存储平台的配置参数并不了解,所以无法自行完成存储的配置。

为此,kubernetes 引入了两个新的 API 资源:PersistentVolume(持久卷,简称 PV)和PersistentVolumeclaim(持久卷声明,简称PVC)。

PV 是 kubernetes 管理员设置的存储,PVC是对 PV的请求,标识需要什么类型的 PV。他们同样是集群中的一类资源,但其生命周期比较独立,管理员可以单独对 PV 进行增删改査,不受 Pod 的影响,生命周期可能比挂载它的其他资源还要长。如果一个 kubernetes 集群的使用者并非只有 kubernetes 管理员那么可以通过提前创建 PV,用以解决对存储概念不是很了解的技术人员对存储的需求。和单独配置 volume类似,PV 也可以使用 NFS、GFS、CEPH 等常见的存储后端,并且可以提供更为高级的配置,比如访问模式、空间大小以及回收策略等。目前 PV的提供方式有两种:静态或动态。静态 PV 由管理员提前创建,动态PV 无需提前创建。

1.PV 回收策略

当用户使用完卷时,可以从 API 中删除 PVC 对象,从而允许回收资源。回收策略会告诉 PV 如何处理改卷。目前回收策略可以设置为 Retain、Recycle 和 Delete。默认的为 delete

  • Retain:保留,该策略允许手动回收资源,当删除 PVC 时,PV仍然存在,PV 中的数据也存在。volume被视为已释放,管理员可以手动回收卷。
  • Recycle:回收,如果 volume 插件支持,Recycle 策略会对卷执行rm -rf 清理该 PV,卷中的数据已经没了,但卷还在,使其可用于下一个新的 PVC,但是本策略将会被弃用,目前只有 NFS 和 HostPath支持该策略。
  • Delete:删除,如果 volume 插件支持,删除 PVC 时会同时删除 PV,PV 中的数据自然也就没了。动态卷默认为 Delete,目前支持 Delete 的存储后端包括 AWS EBS、GCE PD、Azure Disk、OpenstackCinder 等。

2.PV 访问策略

在实际使用 PV 时,可能针对不同的应用会有不同的访问策略,比如某类 Pod 可以读写,某类 Pod 只能读,或者需要配置是否可以被多个不同的 Pod 同时读写等,此时可以使用 PV 的访问策略进行简单控制,目前支持的访问策略如下:

  • Readwrite0nce:单路可读可写,可以被单节点以读写模式挂载,命令行中可以被缩写橙
  • RWO.ReadonlyMany:多路只读,可以被多节点以只读模式挂载,命令行中可以被缩写为
  • ROX.ReadwriteMany:多路可读可写,可以被多个节点以读写模式挂载,命令行中可以被缩写为 RWX。
  • Readwrite0ncePod:单节点只读(1.22+),只能被一个 Pod 以读写的模式挂载,命令行中可以被缩写为 RWOP。
    • Readwriteonce:表示具有读写权限,但是只能被一个node 挂载一次
    • ReadonlyMany:表示具有只读权限,可以被多个node 多次挂载
    • ReadwriteMany:表示具有读写权限,可以被多个node 多次挂载
    • Readwrite0ncePod:表示具有读写权限,只能被一个 Pod 挂载

虽然 PV在创建时可以指定不同的访问策略,但是也要后端的存储支持才行。比如一般情况下,大部分块存储是不支持 ReadwriteMany 的。

在企业内,可能存储很多不同类型的存储,比如 NFS、Ceph、GlusterFs等,针对不同类型的后端存储具有不同的配置方式,这也是对集群管理员的一种挑战,因为集群管理员需要对每种存储都要有所了解。

3.PV 的配置方式

(1)静态配置

静态配置是手动创建 PV 并定义其属性,例如容量、访问模式、存储后端等。在这种情况下,Kubernetes管理员负责管理和配置 PV,然后应用程序可以使用这些 PV。静态配置通常用于一些固定的存储后端,如NFS.

(2)动态配置

动态配置允许 Kubernetes 集群根据 PVC 的需求自动创建 PV,在这种情况下,管理员只需为存储后端配置 storageclass,然后应用程序就可以通过 PVC 请求存储。Kubernetes 将自动创建与 PVC 匹配的PV,并将其绑定到 PVC上。这种方法使得存储管理更加灵活和可扩展,允许管理员在集群中动态添加、删除、和管理存储资源

4.基于HostPath 的 PV

可以创建一个基于 HostPath 的 PV,和配置 NFS 的PV 类似,只需要配置 hostPath 字段即可,其它配置基本一致。

(1)在所有 node 节点创建主机目录
[root@master ~]# mkdir /mnt/data
(2)编辑hostpath的yaml文件
[root@master ~]# vim hostpath-pv.yaml 

kind: PersistentVolume
apiVersion: v1
metadata:
  name: mypv-hostpath
  labels:
    type: local
spec:
  storageClassName: pv-hostpath
  capacity:
    storage: 10Gi
  accessModes:
    - ReadWriteOnce
  hostPath:
    path: "/mnt/data"

备注:

hostPath:宿主机的路径

使用 hostPath 类型需要固定 Pod 所在的节点,防止 Pod 漂移造成数据丢失。

[root@master ~]# ku create -f hostpath-pv.yaml 
persistentvolume/mypv-hostpath created
[root@master ~]# ku get pv
NAME            CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS      CLAIM   STORAGECLASS   REASON   AGE
mypv-hostpath   10Gi       RWO            Retain           Available           pv-hostpath             5s

5.基于NFS的pv

(1)提前安装好 nfs 服务

可以使用上一个案例中安装好的 NFS。或重新安装一台,步骤如下:

提前安装好 nfs 服务,192.168.10.101是 nfs 服务器,也可以是任意一台提供了 NFS 服务的主机客户端需要在所有的 Kubernetes 节点安装

(2)创建一个基于 NFS 的 PV

PV 目前没有 NameSpace 隔离,不需要指定命名空间,在任意命名空间下创建的 PV 均可以在其他NameSpace 使用

[root@master ~]# vim nfs-pv.yaml 

apiVersion: v1
kind: PersistentVolume
metadata:
  name: mypv-nfs
spec:
  capacity:
    storage: 5Gi
  volumeMode: Filesystem
  accessModes:
    - ReadWriteOnce
  persistentVolumeReclaimPolicy: Recycle
  storageClassName: pvc-nfs
  mountOptions:
    - hard
    - nfsvers=4.1
  nfs:
    path: /opt/wwwroot/
    server: 192.168.10.101

备注:

  • capacity:容量配置
  • volumeMode:卷的模式,目前支持 Filesystem(文件系统)和 Block(块),其中 Block 类型需要后端存储支持,默认为文件系统
  • accessModes:该PV的访问模式
  • storageclassName:Pv 的类,一个特定类型的PV 只能绑定到特定类别的 PVC
  • persistentVolumeReclaimPolicy:收策略
  • mountoption:非必要,新版本中已经弃用
  • nfs:NFS 服务配置,包括以下两个选项
    • path:NFS 上的共享目录

    • server:NFs的IP地址

创建PV:

[root@master ~]# ku create -f nfs-pv.yaml 
persistentvolume/mypv-nfs created

查看PV创建结果:

[root@master ~]# ku get pv
NAME            CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS      CLAIM   STORAGECLASS   REASON   AGE
mypv-hostpath   10Gi       RWO            Retain           Available           pv-hostpath             4m22s
mypv-nfs        5Gi        RWO            Recycle          Available           pvc-nfs                 4s

七、PersistentVolumeclaim(PVc,持久卷声明)

当 kubernetes 管理员提前创建好了 PV,我们又应该如何使用它呢?

这里介绍 kubernetes 的另一个概念 PersistentVolumeclaim(简称PVC)。PVC 是其他技术人员在 kubernetes 上对存储的申请,他可以标明一个程序需要用到什么样的后端存储、多大的空间以及什么访问模式进行挂载。这一点和 Pod 的 Qos 配置类似,Pod 消耗节点资源,PVC 消耗 PV 资源,Pod 可以请求特定级别的资源(CPU和内存),PVC可以请求特定的大小和访问模式的PV。例如申请一个大小为5G且只能被一个 Pod 只读访问的存储。

在实际使用时,虽然用户通过 PVC获取存储支持,但是用户可能需要具有不同性质的 PV 来解决不同的问题,比如使用 SSD 硬盘来提高性能。所以集群管理员需要根据不同的存储后端来提供各种 PV,而不仅仅是大小和访问模式的区别,并且无须让用户了解这些卷的具体实现方式和存储类型,打扫了存储的解耦,降低了存储使用的复杂度。

接下来我们来看看如何让 PVC 和前面创建的 PV 绑定。PVC和 PV进行绑定的前提条件是一些参数必须匹配,比如 accessModes、storageclassName、volumeMode 都需要相同,并且 PVc 的 storage 需要小于等于 PV 的 storage 配置。

1.PVC 的创建

(1)为 hostpath 类型的 PV 创建 PVC
[root@master ~]# vim pvc-hostpath.yaml 

kind: PersistentVolumeClaim
apiVersion: v1
metadata:
  name: mypvc-hostpath
spec:
  storageClassName: pv-hostpath
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 3Gi

注意:

storageClassName:存储类名称需要和对应的 PV 中的名称一致,PV 和 PVC 进行绑定并非是名字相同,而是 StorageclassName 相同且其他参数一致才可以进行绑定

[root@master ~]# ku create -f pvc-hostpath.yaml 
persistentvolumeclaim/mypvc-hostpath created
[root@master ~]# ku get pvc
NAME             STATUS   VOLUME          CAPACITY   ACCESS MODES   STORAGECLASS   AGE
mypvc-hostpath   Bound    mypv-hostpath   10Gi       RWO            pv-hostpath    9s
(2)为NFS类型的PV创建PVC
[root@master ~]# vim pvc-nfs.yaml 

kind: PersistentVolumeClaim
apiVersion: v1
metadata:
  name: mypvc-nfs
spec:
  storageClassName: pvc-nfs
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 3Gi

注意:

storageclassName:存储类名称需要和对应的 PV 中的名称一致

[root@master ~]# ku create -f pvc-nfs.yaml 
persistentvolumeclaim/mypvc-nfs created
[root@master ~]# ku get pvc
NAME             STATUS   VOLUME          CAPACITY   ACCESS MODES   STORAGECLASS   AGE
mypvc-hostpath   Bound    mypv-hostpath   10Gi       RWO            pv-hostpath    23m
mypvc-nfs        Bound    mypv-nfs        5Gi        RWO            pvc-nfs        18s

从上述两个简单的例子可以看出,PVC的定义和后端存储并没有关系。对于有存储需求的技术人员,直接定义 PVC即可绑定一块 PV,之后就可以供 Pod使用,而不用去关心具体的实现细节大大降低了存储的复杂度。接下来我们看一下 PVC 如何提供给 Pod 使用。

2.PVC的使用

上述创建了PV,并使用 PVC与其绑定,现在还差一步就能让程序使用这块存储,那就是将 PVC 挂载到 Pod。和之前的挂载方式类似,PVC 的挂载也是通过 volumes 字段进行配置的,只不过之前需要根据不同的存储后端填写很多复杂的参数'而使用 PVC进行挂载时,只填写 PVC的名字即可,不需要再关心任何的存储细节,这样即使不是 Kubemetes 管理员,不懂存储的其他技术人员想要使用存储,也可以非常简单地进行配置和使用。比如我们将之前创建的 hostPath 类型的 PVC 挂载到 Pod 中,可以看到只需要配置-个PersistentVolumeclaim 类型的 volumes,claimName 配置为 PVC 的名称即可:

(1)创建 pod,绑定 hostpath 的PV
[root@master ~]# vim pvc-pv-pod-hostpath.yaml 

kind: Pod
apiVersion: v1
metadata:
  name: hostpath-pv-pod
spec:
  volumes:
    - name: task-pv-storage
      persistentVolumeClaim:
       claimName: mypvc-hostpath
  containers:
    - name: task-pv-container
      image: nginx:1.7.9
      ports:
        - containerPort: 80
          name: "http-server"
      volumeMounts:
        - mountPath: "/usr/share/nginx/html"
          name: task-pv-storage

备注:

claimName: mypvc-hostpath 是基于 hastpath 创建的 PVC 的名字

(2)创建 pod,绑定 NFS 的 PV
[root@master ~]# ku create -f pvc-pv-pod-hostpath.yaml 
pod/hostpath-pv-pod created
[root@master ~]# ku get pod -o wide
NAME                     READY   STATUS    RESTARTS   AGE     IP               NODE    NOMINATED NODE   READINESS GATES
hostpath-pv-pod          1/1     Running   0          3m11s   10.244.166.136   node1   <none>           <none>
nginx-7bf6df4679-nx8j2   1/1     Running   0          60m     10.244.104.9     node2   <none>           <none>

[root@master ~]# ku exec -it hostpath-pv-pod -- bash
root@hostpath-pv-pod:/# cd /usr/share/nginx/html/
root@hostpath-pv-pod:/usr/share/nginx/html# ls
aa  bb	cc

[root@node1 ~]# cd /mnt/data/
[root@node1 data]# touch aa
[root@node1 data]# touch bb
[root@node1 data]# touch cc

[root@master ~]# vim pvc-pv-pod-nfs.yaml 

kind: Pod
apiVersion: v1
metadata:
  name: pvc-nfs
spec:
  volumes:
    - name: pvc-nfs01
      persistentVolumeClaim:
       claimName: mypvc-nfs
  containers:
    - name: task-pv-container
      image: nginx:1.7.9
      ports:
        - containerPort: 80
          name: "http-server"
      volumeMounts:
        - mountPath: "/usr/share/nginx/html"
          name: pvc-nfs01

备注:

claimName:mypvc-nfs 是基于NFS创建的PVC的名字

[root@master ~]# ku create -f pvc-pv-pod-nfs.yaml 
pod/pvc-nfs created
[root@master ~]# ku get pod
NAME                     READY   STATUS    RESTARTS   AGE
hostpath-pv-pod          1/1     Running   0          10m
nginx-7bf6df4679-nx8j2   1/1     Running   0          68m
pvc-nfs                  1/1     Running   0          4s

[root@master ~]# ku exec -it pvc-nfs -- bash
root@pvc-nfs:/# cd /usr/share/nginx/html/
root@pvc-nfs:/usr/share/nginx/html# ls
index.html
root@pvc-nfs:/usr/share/nginx/html# touch aa
root@pvc-nfs:/usr/share/nginx/html# exit
exit
[root@master ~]# cd /opt/wwwroot/
[root@master wwwroot]# ls
aa  index.html
相关推荐
昌sit!6 小时前
K8S node节点没有相应的pod镜像运行故障处理办法
云原生·容器·kubernetes
A ?Charis9 小时前
Gitlab-runner running on Kubernetes - hostAliases
容器·kubernetes·gitlab
wclass-zhengge9 小时前
Docker篇(Docker Compose)
运维·docker·容器
茶馆大橘9 小时前
微服务系列五:避免雪崩问题的限流、隔离、熔断措施
java·jmeter·spring cloud·微服务·云原生·架构·sentinel
北漂IT民工_程序员_ZG10 小时前
k8s集群安装(minikube)
云原生·容器·kubernetes
coding侠客10 小时前
揭秘!微服务架构下,Apollo 配置中心凭啥扮演关键角色?
微服务·云原生·架构
梦魇梦狸º13 小时前
腾讯轻量云服务器docker拉取不到镜像的问题:拉取超时
docker·容器·github
南猿北者15 小时前
docker镜像仓库常用命令
运维·docker·容器
2301_8061313616 小时前
Kubernetes的基本构建块和最小可调度单元pod-0
云原生·容器·kubernetes
SilentCodeY17 小时前
containerd配置私有仓库registry
容器·kubernetes·containerd·镜像·crictl