Kubernetes 存储入门

发布于:2025-07-11 ⋅ 阅读:(15) ⋅ 点赞:(0)

目录

一、Volume 的概念

二、Volume 的类型

三、通过 emptyDir 共享数据

1:编写 emptyDir 的 Deployment 文件

2:部署该 Deployment

3:查看部署结果

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

5:删除此 Pod

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

1:编写 Dep1oyment 文件,实现 HostPath 挂载

2:创建此 Pod

3:测试挂载情况

4:删除

五、挂载 NFS 至容器

1:安装 NFS

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

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

4:编写 Deployment 文件,挂载 NFS

6:查看部署结果

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

六、PersistentVolume(PV,持久卷)

七、PersistentVolumeClaim(PVC,持久卷声明)

1:PVC 的概念

2:PVC 与 PV 的绑定条件

3:PVC的创建

4:PVC的使用


一、Volume 的概念

在 Kubernetes 中,容器内数据具有临时性(容器崩溃重启后数据丢失),且传统架构中存储挂载易出问题,为此抽象出 Volume 概念解决数据存储需求。

其核心特点包括:

  • 生命周期明确:与所属 Pod 一致,长于容器生命周期,可在容器重启 / 销毁后保留数据。
  • 功能更优:支持多种类型,Pod 可同时使用多个卷;相比 Docker 卷,无单卷驱动限制,能传递后端存储参数,管理更完善。
  • 使用方式:本质是挂载到容器的目录,容器可对其读写,与裸机挂载类似。通过 Pod 的 .spec.volumes 定义卷,再用 .spec.containers.volumeMounts 指定容器内挂载目录即可使用。

此外,Volume 可解决多容器文件共享问题,支持 NFS、Ceph、GlusterFS 等多种存储类型(生产环境推荐分布式存储或公有云服务,避免 NFS 单点故障)。

二、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,Emptyir 卷中的数据也将被删除,所以一般 emptyDir 用于 Pod 中不同容器共享数据,比如一个 Pod 存在两个容器 A 和容器 B,容器 A 需要使用容器 B 产生的数据,此时可以采用 emptyDir 共享数据,类似的使用如 Filebeat 收集容器内程序产生的日志。

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

1:编写 emptyDir 的 Deployment 文件

[root@k8s-master ~]#cat <EOF>nginx-empty.yam1
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
imagePul1Policy:IfNotPresent
name:nginx01
volumeMounts:
mountPath:/opt
name:share-volume
image:nginx:1.7.9
imagePul1Policy:IfNotPresent
name:nginx02
command:
工场
sh
--C
-sleep 3600
volumeMounts:
-mountPath:/mnt
name:share-volume
volumes:
name:share-volume
emptyDir:{}
#medium: Memory
EOF

备注:

  • volumeMounts:
    • mountPath:/mnt name:share-volume                                                                      ## 容器定义部分的卷挂载名称,此处的名称引用了 volumes 对应的名称
  • volumes:
    • name:share-volume              ## 共享存储卷的名称

2:部署该 Deployment

[root@k8s-master ~]#kubectl create-f nginx-empty.yam1

3:查看部署结果

[root@k8s-master ~]#kubectl get pod
NAME READY STATUS RESTARTS AGE
nginx-6fffbd7c7b-jrw7f2/2 Running 0 10s

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

[root@k8s-master~]#kubect1exec-ti nginx-6fffbd7c7b-jrw7f-cnginx01--sh

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

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

[root@k8s-master~]#kubectl exec-ti nginx-6fffbd7c7b-jrw7f-cnginx02--sh

注意
登录伤处后,此处可以使用 date 命令查看容器中的时间,会发现时间是不对的。是因为时区的问题,容器内使用的不是亚洲上海市区。导致时间不对。

5:删除此 Pod

[root@k8s-master ~]#kubectl delete -f nginx-empty.yam1

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

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

1:编写 Dep1oyment 文件,实现 HostPath 挂载

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

[root@k8s-master ~]#cat<<EOFnginx-hostPath.yam1
apiVersion:apps/v1
kind: Deployment
metadata:
1abels:
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
imagePul1Policy:IfNotPresent
name:nginx
volumeMounts:
-mountPath:/etc/1ocaltime
name: timezone-time
volumes:
-name: timezone-time
hostPath:
path:/etc/localtime
type:File
EOF

备注: 关于时区的设置是通过配置 /etc/1ocaltime 文件设置系统的时区,/etc/1ocaltime 用于配置系统时区(此文件是一个链接文件,链接自 /usr/share/zoneinfo/Asia/Shanghai)。

2:创建此 Pod

[root@k8s-master ~]#kubect1 create -f nginx-hostPath.yam1
    [root@k8s-master ~]# kubectl get pod
    NAME READY STATUS RESTARTS AGE
    nginx-5c9b77966c-jrw7f1/1 Running 0 47m
    

    3:测试挂载情况

    [root@k8s-master~]#kubectlexec-tinginx-5c9b77966c-jrw7f-nginx--sh
    #date
    

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

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

    4:删除

    [root@k8s-master ~]#kubectl delete -f nginx-hostPath.yam1
    

    五、挂载 NFS 至容器

    1:安装 NFS

    在所有的 Kubernetes 节点都要安装

    [root@k8s-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.htm1
    [root@k8s-master ~]#vim /etc/exports
    /opt/wwwroot 192.168.10.0/24(rw,sync,no_root_squash)
    

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

    [root@k8s-master ~]#systemct1 start nfs
    [root@k8s-master ~]#systemct1 start rpcbind
    

    4:编写 Deployment 文件,挂载 NFS

    [root@k8s-master ~]#cat<<EOFnginx-nfsvolume.yam1
    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
    imagePul1Policy:IfNotPresent
    name:nginx
    volumeMounts:
    mountPath:/usr/share/nginx/htm1
    name:nfs-volume
    volumes:
    -name:nfs-volume
    nfs:
    server:192.168.10.101
    path:/opt/wwwroot
    EOF
    

    5:部署此 Pod

    [root@k8s-master~]#kubectl create -f nginx-nfsvolume.yam1
    

    6:查看部署结果

    [root@k8s-master ~]#kubectl get pod
    NAME
    READY
    STATUS
    RESTARTS
    AGE
    nginx-fbd476c4c-zscq91/1
    Running
    0
    8m12s
    

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

    [root@k8s-master~]#kubectl exec-ti nginx-fbd476c4c-zscq9- nginx--bash
    

    六、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 无需提前创建。

    • PV 回收策略

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

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

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

    • ReadlMriteOnce:单路可读可写,可以被单节点以读写模式挂载,命令行中可以被缩写橙 RWO。
    • ReadOn1yMany:多路只读,可以被多节点以只读模式挂载,命令行中可以被缩写为 ROX。
    • ReadWriteMany:多路可读可写,可以被多个节点以读写模式挂载,命令行中可以被缩写为 RMX。
    • ReadwriteOncePod:单节点只读(1.22+),只能被一个 Pod 以读写的模式挂载,命令行中可以被缩写为 RWOP
    • PV 配置方式
    • 静态配置:管理员手动创建 PV,定义容量、访问模式、存储后端等属性,适用于固定存储后端(如 NFS)。
    • 动态配置:管理员配置 StorageClass 后,Kubernetes 可根据 PVC 需求自动创建匹配的 PV 并绑定,提升存储管理灵活性。

    七、PersistentVolumeClaim(PVC,持久卷声明)

    1:PVC 的概念

    PVC 是 Kubernetes 中技术人员对存储资源的申请,用于标明程序所需的后端存储类型、空间大小及访问模式等,类似于 Pod 对 CPU 和内存资源的请求。它能实现存储解耦,让用户无需了解底层存储的具体实现细节,只需通过定义 PVC 即可绑定合适的 PV 以使用存储资源。

    2:PVC 与 PV 的绑定条件

    绑定需满足多个参数匹配,包括 accessModes(访问模式)、storageClassName(存储类)、volumeMode(卷模式)需相同,且 PVC 请求的存储大小(storage)需小于等于 PV 的容量

    3:PVC的创建

    • 步骤一:确保 HostPath 类型的 PV 已创建
      • 编写 PV 配置文件:创建一个 YAML 文件,例如pv.yaml,定义 HostPath 类型的 PV。示例内容如下:
    apiVersion: v1
    kind: PersistentVolume
    metadata:
      name: my-pv
    spec:
      capacity:
        storage: 10Gi
      accessModes:
        - ReadWriteOnce
      hostPath:
        path: /data/my-pv
    

    上述配置中,name定义了 PV 的名称,capacity指定了存储容量,accessModes设置访问模式为单节点读写,hostPath.path指定了宿主机上的存储路径。

    应用 PV 配置:执行命令kubectl apply -f pv.yaml,将 PV 配置应用到 Kubernetes 集群中。可通过kubectl get pv my-pv查看 PV 是否创建成功,若状态为Available,则表示创建成功。

    • 步骤二:创建 PVC
      • 编写 PVC 配置文件:创建一个新的 YAML 文件,如pvc.yaml,用于定义 PVC。示例如下:
    apiVersion: v1
    kind: PersistentVolumeClaim
    metadata:
      name: my-pvc
    spec:
      accessModes:
        - ReadWriteOnce
      resources:
        requests:
          storage: 5Gi
      # 如果PV有指定存储类,这里需设置为相同的存储类名称,若PV未设置存储类,此处可省略
      # storageClassName: my - storage - class
    

    此配置中,name为 PVC 的名称,accessModes需与 PV 的访问模式一致,resources.requests.storage定义了请求的存储容量。

    应用 PVC 配置:运行命令kubectl apply -f pvc.yaml,将 PVC 配置应用到集群。使用kubectl get pvc my-pvc查看 PVC 状态,若状态为Bound,则表示 PVC 已成功与符合条件的 PV 绑定。

    完成上述步骤后,就成功为 HostPath 类型的 PV 创建了 PVC,后续可在 Pod 中引用该 PVC 来使用持久化存储。例如,在 Pod 的配置文件中添加如下内容:

    apiVersion: v1
    kind: Pod
    metadata:
      name: my - pod
    spec:
      volumes:
        - name: my - volume
          persistentVolumeClaim:
            claimName: my - pvc
      containers:
        - name: my - container
          image: nginx
          volumeMounts:
            - name: my - volume
              mountPath: /usr/share/nginx/html

    4:PVC的使用

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

    (1)创建pod,绑定hostpath的PV

    apiVersion: v1
    kind: PersistentVolumeClaim
    metadata:
      name: pvc-demo  # PVC名称
    spec:
      accessModes:
        - ReadWriteOnce  # 需与PV的访问模式匹配
      resources:
        requests:
          storage: 10Gi  # 请求10Gi存储(需≤PV的20Gi)
      # 若PV未指定storageClassName,PVC无需设置;若PV有存储类,此处需一致
      # storageClassName: ""  # 若PV无存储类,可显式指定为空(避免默认存储类干扰)

    应用 PVC 配置:

    kubectl apply -f pvc-demo.yaml
    

    验证 PVC 状态(状态为Bound表示已与 PV 绑定):

    kubectl get pvc pvc-demo
    # 输出示例:
    NAME        STATUS   VOLUME             CAPACITY   ACCESS MODES   STORAGECLASS   AGE
    pvc-demo    Bound    pv-hostpath-demo   20Gi       RWO                           5s

    (2)创建pod,绑定NFS的PV

    apiVersion: v1
    kind: Pod
    metadata:
      name: pod-use-pvc  # Pod名称
    spec:
      containers:
      - name: nginx-demo
        image: nginx:alpine  # 用Nginx容器示例
        ports:
        - containerPort: 80
        volumeMounts:
        - name: pvc-storage  # 与下方volumes.name对应
          mountPath: /usr/share/nginx/html  # 容器内挂载路径(Nginx默认静态文件目录)
      volumes:
      - name: pvc-storage  # 卷名称,需与volumeMounts.name一致
        persistentVolumeClaim:
          claimName: pvc-demo  # 引用的PVC名称

    应用 Pod 配置:

    kubectl apply -f pod-with-pvc.yaml
    

    验证 Pod 状态(状态为Running表示正常运行):

    kubectl get pod pod-use-pvc


    网站公告

    今日签到

    点亮在社区的每一天
    去签到