Kubernetes存储入门

在 Kubernetes 中,Volume 是一种用于持久化存储和共享数据的机制。Volume 提供了一种在容器中使用存储的方式,确保数据在容器重启或重建时不会丢失。

一. 基本概念

  • Volume 的生命周期:Volume 的生命周期与 Pod 的生命周期相关联,而不是与容器的生命周期相关联。这意味着即使容器崩溃或重新启动,Volume 中的数据仍然保留。
  • 数据持久性:Volume 提供了一种将数据存储在容器外部的方式,这样数据可以在容器重建后继续使用。

二.volume的类型

在Kubernetes中,volume支持Kubernetes特有的存储卷类型,也支持传统的存储卷类型。

Kubernetes独有的类型:

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

常见的卷:

  • CephFS
  • GlusterFS
  • ISCSI
  • Cinder
  • NFS
  • RBD
  • HostPath

三.通过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 #指定容器内的路径 /mnt,Volume 将挂载到这里

name: share-volume #指明要挂载的 Volume 的名称,必须与 volumes 部分的名称匹配。

volumes: #定义了 Volume 的来源

  • name: share-volume #指定 Volume 的名称,容器中的挂载名称必须与此匹配。

emptyDir: {} #表示一个临时目录 Volume,数据存储在 Pod 的本地磁盘上,当 Pod 被删除时数据也会丢失。

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

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

2.部署gaiDeployment

复制代码
ku create -f nginx-empty.yaml

3.查看部署结果

复制代码
[root@k8s-master ~]# ku get pod
NAME                    READY   STATUS    RESTARTS   AGE
nginx-8f8dcfd8c-4dj6h   2/2     Running   0          8s

4.登录Pod中的容器,并查看测试结果

复制代码
[root@k8s-master ~]# ku get pod
NAME                    READY   STATUS    RESTARTS   AGE
nginx-8f8dcfd8c-4dj6h   2/2     Running   0          8s

[root@k8s-master ~]# ku exec -it nginx-8f8dcfd8c-4dj6h -c nginx01 -- bash
root@nginx-8f8dcfd8c-4dj6h:/# cd opt/
root@nginx-8f8dcfd8c-4dj6h:/opt# touch aaa
root@nginx-8f8dcfd8c-4dj6h:/opt# exit
exit

[root@k8s-master ~]# ku exec -it nginx-8f8dcfd8c-4dj6h -c nginx02 -- bash
root@nginx-8f8dcfd8c-4dj6h:/# cd /mnt
root@nginx-8f8dcfd8c-4dj6h:/mnt# ls
aaa

四.使用HostyoPath挂载宿主机文件

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

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

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

复制代码
[root@k8s-master ~]# 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@k8s-master ~]# ku create -f nginx-hostPath.yaml 
deployment.apps/nginx created

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

3.登录测试

复制代码
[root@k8s-master ~]# ku exec -it nginx-59f95c99b5-ld58v -- bash
root@nginx-59f95c99b5-ld58v:/# date
Mon Aug 26 12:31:25 CST 2024

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

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

五.挂载NFS共享目录至容器

1.安装nfs(所有节点)

复制代码
[root@k8s-master ~]# yum -y install nfs-utils

2.设置共享目录(nfs服务器)

(1)创建共享目录

复制代码
mkdir /henan/xiaoman

(2)设置共享的网段

复制代码
[root@k8s-master ~]# vim /etc/exports

/henan/xiaoman 192.168.10.0/24(rw,sync,no_root_squash)

配置中的各部分

  1. /henan/xiaoman:这是 NFS 服务器上要共享的目录路径。客户端将能够访问这个目录及其内容。

  2. 192.168.10.0/24 :这是允许访问这个共享目录的客户端 IP 地址范围。192.168.10.0/24 表示子网掩码为 255.255.255.0 的网络,允许这个子网中的所有主机访问共享目录。

  3. (rw,sync,no_root_squash)

    • 这是一组 NFS 导出选项,用于控制访问权限和行为:

    • rw:表示客户端可以读写这个目录。客户端不仅可以读取目录中的文件,还可以向其中写入数据。

    • sync:表示所有写入操作都将同步到磁盘,这样可以确保数据的一致性和可靠性,但可能会稍微降低性能。

    • no_root_squash :表示 NFS 服务器不将客户端的 root 用户映射为匿名用户(nobody)。如果使用 root_squash,root 用户的权限会被映射成匿名用户的权限,增加了安全性。

3.开启nfs

复制代码
[root@k8s-master ~]# systemctl start nfs
[root@k8s-master ~]# systemctl start rpcbind

4.编写Doployment文件,挂载NFS

复制代码
[root@k8s-master ~]# 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: /henan/xiaoman

5.部署此pod

复制代码
[root@k8s-master ~]# ku create -f nginx-nfsVolume.yaml 

6.在共享目录下放东西

复制代码
[root@k8s-master ~]# echo "my name is henanxiaoman">/henan/xiaoman/index.html

7.访问或登录查看

复制代码
[root@k8s-master ~]# ku get pod -o wide
NAME                     READY   STATUS    RESTARTS   AGE    IP              NODE     NOMINATED NODE   READINESS GATES
nginx-5c94b6fc6b-bsmns   1/1     Running   0          115s   10.244.140.72   node02   <none>           <none>

[root@k8s-master ~]# curl 10.244.140.72 
my name is henanxiaoman

复制代码
[root@k8s-master ~]# ku exec -it nginx-5c94b6fc6b-bsmns -c nginx -- bash

root@nginx-5c94b6fc6b-bsmns:/# cd /usr/share/nginx/html/

root@nginx-5c94b6fc6b-bsmns:/usr/share/nginx/html# ls

index.html

[root@nginx-5c94b6fc6b-bsmns:/usr/share/nginx/html# cat index.html 
my name is henanxiaoman

六.peristentVolume(PV,持久化)

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

PV是kubernetes管理员设置的存储,PVC是对PV的请求,标识需要什么类型的PV。他们同样是集群中的一类资源,但其生命周期比较独立,管理员可以单独对PV进行增删改查,不受Pod的影响,生命周期可能比挂载它的其他资源还要长。如果一个kubernetes集群的使用者并非只有kubernetes管理员,那么可以通过提前创建PV,用以解决对存储概念不是很了解的技术人员对存储的需求。和单独配置vo1ume类似,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的存储后端包括ASEBS、GCEPD、AzureDisk、OpenStackCinder等。

2.PV访问策略

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

  • ReadWriteonce:单路可读可写,可以被单节点以读写模式挂载,命令行中可以被写橙RWO
  • ReadonlyMany多路只读,可以被多节点以只读模式挂载,命令行中可以被缩写为ROX
  • ReadWriteMany:多路可读可写,可以被多个节点以读写模式挂载,命令行中可以被缩写为RNX
  • ReadWriteOncePod:单节点只读(1.22+),只能被一个Pod以读写的模式挂载,命令行中可以被缩写为RWOP。

使用场景

  • ReadWriteonce: 表示具有读写权限,但是只能被一个node挂载一次
  • ReadOnlyMany:表示具有只读权限,可以被多个node多次挂载
  • ReadWriterany:表示具有读写权限,可以被多个node多次挂载
  • ReadWriteOncePod:表示具有读写权限,只能被一个Pod挂载

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

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

3.PV的配置方式

(1)静态配置

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

(2)动态配置

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

相关推荐
rocksun40 分钟前
为何云原生基础设施对于GenAI而言不可或缺
人工智能·云原生
葟雪儿2 小时前
Docker常用命令
linux·服务器·spring cloud·docker·微服务·容器
AutoMQ3 小时前
吉利汽车采用 EMQX 与AutoMQ联合方案构建公私有云一体化的车联网核心架构
云原生·架构·云计算·汽车
爬台阶的蚂蚁4 小时前
搭建docker registry私服,并且支持https推送
docker·容器·https
小小她爹5 小时前
dify新版本1.1.3的一些问题
云原生·eureka
张家宝68375 小时前
Containerd学习
后端·容器
会游泳的石头5 小时前
探索现代网络技术:从负载均衡到 Kubernetes
运维·kubernetes·负载均衡
容器魔方6 小时前
KubeEdge边缘设备管理系列(五):Mapper-Framework设备数据写入
云原生·容器·云计算
穷儒公羊7 小时前
第一部分——Docker篇 第一章 Docker容器
运维·docker·云原生·容器
飞猪~8 小时前
docker相关命令
运维·docker·容器