Kubernetes存储入门

目录

简介

一、Volume的概念

Volume的本质

二、Volume的类型

三、通过emptyDir共享Pod内容器数据

示例:使用emptyDir实现容器间数据共享

emptyDir的注意事项

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

示例:挂载宿主机时区文件到Pod

HostPath的type参数

HostPath的注意事项

五、挂载NFS共享存储至容器

示例:部署NFS服务并挂载到Pod

步骤1:在NFS服务器上安装并配置NFS

步骤2:在所有Kubernetes节点安装NFS客户端

步骤3:创建Deployment配置文件挂载NFS

步骤4:部署并验证

六、PersistentVolume(PV)

PV的核心属性

示例:创建基于HostPath的PV

示例:创建基于NFS的PV

七、PersistentVolumeClaim(PVC)

示例:创建PVC并绑定PV

步骤1:为HostPath类型PV创建PVC

步骤2:为NFS类型PV创建PVC

示例:在Pod中使用PVC

总结


简介

在Kubernetes的世界里,数据持久化是一个至关重要的话题。容器的临时性意味着我们不能将关键数据存储在容器内部,而Kubernetes提供的存储解决方案正是为了解决这一难题。本文将介绍Kubernetes中的存储机制,从基础的Volume概念到高级的PV/PVC管理,全方位掌握数据持久化的实现方式。

一、Volume的概念

在Kubernetes中,容器的文件系统是临时的,当容器重启时,所有数据都会丢失。而且,一个Pod中的多个容器可能需要共享数据。为了解决这些问题,Kubernetes引入了Volume(卷)的概念。

Kubernetes Volume vs Docker Volume

  • Docker卷:功能有限,生命周期不受管理,每个容器仅允许一个卷驱动程序。
  • Kubernetes卷:与Pod具有相同的生命周期,比容器寿命更长,支持多种类型,一个Pod可同时使用多个卷。
Volume的本质

从本质上讲,Kubernetes卷在挂载后就是容器中的一个目录,容器可以像操作本地目录一样对其进行读写。使用卷只需两步:

  1. 在Pod的​.spec.volumes​字段中定义卷。
  2. 在容器的​.spec.containers.volumeMounts​字段中指定挂载目录。

二、Volume的类型

Kubernetes支持多种Volume类型,以适应不同的存储需求。常见的类型包括:

  • 网络存储:CephFS、GlusterFS、NFS等
  • 云服务存储:Cinder、EBS等
  • Kubernetes特有:ConfigMap、Secret、emptyDir、PersistentVolumeClaim等

接下来,我们将详细介绍几种常用的Volume类型及其实践方法。

三、通过emptyDir共享Pod内容器数据

emptyDir是一种简单的Volume类型,它在Pod被创建时自动创建,当Pod被删除时也会被一并删除。适合用于Pod内多个容器之间的临时数据共享。

示例:使用emptyDir实现容器间数据共享
  1. 创建Deployment配置文件

    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 # 第一个容器使用nginx镜像
    imagePullPolicy: IfNotPresent # 本地有镜像则不重新拉取
    name: nginx01
    volumeMounts: # 挂载卷到/opt目录
    - mountPath: /opt
    name: share-volume
    - image: nginx:1.7.9 # 第二个容器也使用nginx镜像
    imagePullPolicy: IfNotPresent
    name: nginx02
    command: # 让容器休眠3600秒,避免立即退出
    - sh
    - -c
    - sleep 3600
    volumeMounts: # 挂载卷到/mnt目录
    - mountPath: /mnt
    name: share-volume
    volumes: # 定义名为share-volume的emptyDir卷
    - name: share-volume
    emptyDir: {}
    # medium: Memory # 可选,设置为Memory则使用内存作为存储介质

  2. 部署Deployment

    kubectl create -f nginx-empty.yaml

此命令通过指定的配置文件创建Deployment资源,Kubernetes会根据配置创建Pod及相关容器。

  1. 查看部署结果

    kubectl get pod

该命令用于查看当前命名空间下的Pod状态,确认Pod是否正常运行(STATUS为Running)。

  1. 验证数据共享

    进入第一个容器

    kubectl exec -ti <pod名称> -c nginx01 -- sh

    在/opt目录下创建一个测试文件

    echo "hello from nginx01" > /opt/test.txt

    退出第一个容器

    exit

    进入第二个容器

    kubectl exec -ti <pod名称> -c nginx02 -- sh

    查看/mnt目录下是否存在test.txt文件并检查内容

    cat /mnt/test.txt

通过以上操作,我们可以看到在nginx01的/opt目录创建的文件,在nginx02的/mnt目录下也能看到,证明数据共享成功。

emptyDir的注意事项
  • 当Pod被删除时,emptyDir中的数据也会被删除。
  • 若设置​medium: Memory​,则使用tmpfs(内存文件系统),速度更快,但节点重启时数据会丢失,且占用容器的内存配额。

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

HostPath卷用于将宿主机上的文件或目录挂载到Pod中,实现Pod与宿主机之间的数据共享。常见用途包括挂载宿主机的时区文件、日志目录等。

示例:挂载宿主机时区文件到Pod
  1. 创建Deployment配置文件

    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: # 将时区文件挂载到容器的/etc/localtime
    - mountPath: /etc/localtime
    name: timezone-time
    volumes: # 定义hostPath卷,指向宿主机的/etc/localtime
    - name: timezone-time
    hostPath:
    path: /etc/localtime # 宿主机上的文件路径
    type: File # 指定挂载类型为文件

  2. 部署Deployment

    kubectl create -f nginx-hostPath.yaml

  3. 验证时区挂载结果

    进入容器

    kubectl exec -ti <pod名称> -- sh

    查看容器内的时间,确认是否与宿主机一致

    date

若容器内的时间与宿主机时间一致,说明时区文件挂载成功。

HostPath的type参数

HostPath的type参数用于指定挂载类型,常用值包括:

  • 空字符串(默认):挂载前不进行任何检查。
  • DirectoryOrCreate:若路径不存在,则创建一个权限为0755的目录。
  • Directory:路径必须存在且为目录。
  • FileOrCreate:若路径不存在,则创建一个权限为0644的文件。
  • File:路径必须存在且为文件。
  • Socket:路径必须存在且为UNIX套接字。
  • CharDevice:路径必须存在且为字符设备。
  • BlockDevice:路径必须存在且为块设备。
HostPath的注意事项
  • 使用HostPath时,Pod调度到不同节点可能会出现问题(如节点上不存在指定的文件/目录)。
  • 需谨慎使用,避免Pod对宿主机文件系统进行未授权的修改。

五、挂载NFS共享存储至容器

NFS(网络文件系统)是一种常用的网络存储解决方案,通过NFS卷可以实现多个节点之间的数据共享。

示例:部署NFS服务并挂载到Pod
步骤1:在NFS服务器上安装并配置NFS
复制代码
# 安装NFS服务(以CentOS为例)
yum -y install nfs-utils rpcbind

# 创建共享目录
mkdir /opt/wwwroot

# 在共享目录中创建测试文件
echo "This is my test file" > /opt/wwwroot/index.html

# 配置NFS exports文件
vim /etc/exports
# 添加以下内容,允许192.168.10.0/24网段访问该目录
/opt/wwwroot 192.168.10.0/24(rw,sync,no_root_squash)

# 启动NFS和rpcbind服务
systemctl start nfs
systemctl start rpcbind
systemctl enable nfs
systemctl enable rpcbind

​/etc/exports​​配置项说明:

  • ​rw​:允许读写
  • ​sync​:同步写入磁盘
  • ​no_root_squash​:客户端以root身份访问时,保留root权限
步骤2:在所有Kubernetes节点安装NFS客户端
复制代码
yum -y install nfs-utils

确保节点能够正常访问NFS服务器的共享目录:

复制代码
showmount -e <NFS服务器IP>
步骤3:创建Deployment配置文件挂载NFS
复制代码
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:  # 将NFS卷挂载到nginx的默认网页目录
        - mountPath: /usr/share/nginx/html
          name: nfs-volume
      volumes:  # 定义NFS卷
      - name: nfs-volume
        nfs:
          server: 192.168.10.101  # NFS服务器IP地址
          path: /opt/wwwroot  # NFS共享目录路径
步骤4:部署并验证
复制代码
# 部署Deployment
kubectl create -f nginx-nfsvolume.yaml

# 查看Pod状态
kubectl get pod

# 进入容器验证NFS挂载
kubectl exec -ti <pod名称> -- bash
# 查看nginx网页目录下的文件
cat /usr/share/nginx/html/index.html

若能看到之前创建的测试文件内容,说明NFS挂载成功。

六、PersistentVolume(PV)

虽然Volume已经能满足基本的存储需求,但在实际使用中仍存在一些问题:

  • 无法对存储的生命周期进行精细化管理。
  • 普通用户可能不了解存储的具体配置参数。

为此,Kubernetes引入了PersistentVolume(PV)和PersistentVolumeClaim(PVC)两个资源对象。

PV是由管理员配置的持久化存储,具有独立于Pod的生命周期,可以使用NFS、Ceph等多种存储后端,并支持访问模式、回收策略等高级配置。

PV的核心属性
  1. 回收策略:当PVC被删除后,PV的处理方式。
  • Retain:保留PV和数据,需手动回收。
  • Recycle:清理PV中的数据(仅NFS和HostPath支持),该策略已被弃用。
  • Delete:删除PV及数据(部分云存储支持)。
  1. 访问模式:定义PV的访问权限。
  • ReadWriteOnce(RWO):单节点读写。
  • ReadOnlyMany(ROX):多节点只读。
  • ReadWriteMany(RWX):多节点读写。
  • ReadWriteOncePod(RWOP):单Pod读写(Kubernetes 1.22+)。
  1. 配置方式
  • 静态配置:管理员手动创建PV。
  • 动态配置:根据PVC的需求自动创建PV(需配置StorageClass)。
示例:创建基于HostPath的PV
  1. 在所有节点创建目录

    mkdir /mnt/data

  2. 创建PV配置文件

    kind: PersistentVolume
    apiVersion: v1
    metadata:
    name: mypv-hostpath # PV名称
    labels:
    type: local
    spec:
    storageClassName: pv-hostpath # 存储类名称,用于匹配PVC
    capacity:
    storage: 10Gi # PV容量
    accessModes:

    • ReadWriteOnce # 访问模式:单节点读写
      hostPath:
      path: "/mnt/data" # 宿主机目录路径
  3. 创建PV

    kubectl create -f hostpath-pv.yaml

  4. 查看PV状态

    kubectl get pv

创建成功后,PV状态为Available,表示可被PVC绑定。

示例:创建基于NFS的PV
  1. 确保NFS服务已正确配置(参考前面的NFS配置步骤)

  2. 创建PV配置文件

    apiVersion: v1
    kind: PersistentVolume
    metadata:
    name: mypv-nfs # PV名称
    spec:
    capacity:
    storage: 5Gi # PV容量
    volumeMode: Filesystem # 卷模式:文件系统
    accessModes:

    • ReadWriteOnce # 访问模式
      persistentVolumeReclaimPolicy: Recycle # 回收策略
      storageClassName: pv-nfs # 存储类名称
      nfs:
      path: /opt/wwwroot # NFS共享目录
      server: 192.168.10.101 # NFS服务器IP
  3. 创建PV并查看

    kubectl create -f nfs-pv.yaml
    kubectl get pv

七、PersistentVolumeClaim(PVC)

PVC是用户对PV的请求,用户通过PVC指定所需的存储大小、访问模式等,Kubernetes会自动匹配合适的PV并进行绑定。

PVC与PV绑定的条件:

  • accessModes、storageClassName、volumeMode必须一致。
  • PVC请求的存储大小不得超过PV的容量。
示例:创建PVC并绑定PV
步骤1:为HostPath类型PV创建PVC
  1. 创建PVC配置文件

    kind: PersistentVolumeClaim
    apiVersion: v1
    metadata:
    name: mypvc-hostpath # PVC名称
    spec:
    storageClassName: pv-hostpath # 存储类名称,需与PV一致
    accessModes:

    • ReadWriteOnce # 访问模式,需与PV一致
      resources:
      requests:
      storage: 3Gi # 请求的存储大小,不超过PV容量
  2. 创建PVC并查看

    kubectl create -f pvc-hostpath.yaml
    kubectl get pvc

创建成功后,PVC状态为Bound,表示已与PV绑定。

步骤2:为NFS类型PV创建PVC
  1. 创建PVC配置文件

    kind: PersistentVolumeClaim
    apiVersion: v1
    metadata:
    name: mypvc-nfs # PVC名称
    spec:
    storageClassName: pv-nfs # 存储类名称,需与PV一致
    accessModes:

    • ReadWriteOnce # 访问模式,需与PV一致
      resources:
      requests:
      storage: 3Gi # 请求的存储大小
  2. 创建PVC并查看

    kubectl create -f pvc-nfs.yaml
    kubectl get pvc

示例:在Pod中使用PVC

PVC创建并绑定PV后,就可以在Pod中像使用普通Volume一样使用PVC了。

  1. 创建使用HostPath类型PVC的Pod

    kind: Pod
    apiVersion: v1
    metadata:
    name: hostpath-pv-pod
    spec:
    volumes:

    • name: task-pv-storage # 卷名称
      persistentVolumeClaim:
      claimName: mypvc-hostpath # 关联的PVC名称
      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 # 关联的卷名称

部署并验证:

复制代码
# 部署Pod
kubectl create -f pvc-pv-pod-hostpath.yaml

# 在宿主机的PV目录中创建文件
touch /mnt/data/aaa.txt

# 进入Pod查看文件
kubectl exec -ti hostpath-pv-pod -- bash
ls /usr/share/nginx/html/
  1. 创建使用NFS类型PVC的Pod

    kind: Pod
    apiVersion: v1
    metadata:
    name: pvc-nfs
    spec:
    volumes:

    • name: pvc-nfs01 # 卷名称
      persistentVolumeClaim:
      claimName: mypvc-nfs # 关联的PVC名称
      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 # 关联的卷名称

部署并验证:

复制代码
# 部署Pod
kubectl create -f pvc-pv-pod-nfs.yaml

# 进入Pod查看NFS共享目录中的文件
kubectl exec -ti pvc-nfs -- bash
ls /usr/share/nginx/html/

总结

本文介绍了Kubernetes中的存储解决方案,从基础的Volume类型(emptyDir、HostPath、NFS)到高级的PV/PVC机制,涵盖了从临时存储到持久化存储的各种场景。

通过学习这些知识,您可以根据实际需求选择合适的存储方式:

  • 临时共享数据:使用emptyDir。
  • 与宿主机交互:使用HostPath。
  • 跨节点共享:使用NFS。
  • 企业级持久化存储:使用PV/PVC,实现存储与应用的解耦。

掌握Kubernetes存储管理,将为构建高效、可靠的容器化应用奠定坚实的基础。在实际生产环境中,还需要根据业务需求和存储特性,选择合适的存储后端和配置方式,确保数据的安全性和可用性。