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上。这种方法使得存储管理更加灵活和可扩展,允许管理员在集群中动态添加、删除、和管理存储资源

相关推荐
aherhuo3 小时前
kubevirt网络
linux·云原生·容器·kubernetes
陌北v14 小时前
Docker Compose 配置指南
运维·docker·容器·docker-compose
catoop4 小时前
K8s 无头服务(Headless Service)
云原生·容器·kubernetes
阿里嘎多学长4 小时前
docker怎么部署高斯数据库
运维·数据库·docker·容器
小峰编程5 小时前
独一无二,万字详谈——Linux之文件管理
linux·运维·服务器·云原生·云计算·ai原生
小马爱打代码5 小时前
云原生服务网格Istio实战
云原生
liuxuzxx5 小时前
1.24.1-Istio安装
kubernetes·istio·service mesh
G_whang6 小时前
windos 安装docker
运维·docker·容器
道一云黑板报6 小时前
Flink集群批作业实践:七析BI批作业执行
大数据·分布式·数据分析·flink·kubernetes
运维小文6 小时前
K8S中的PV、PVC介绍和使用
docker·云原生·容器·kubernetes·存储