K8S使用持久化卷存储到NFS(NAS盘)

news2025/1/15 6:54:27

参考文章:K8S-v1.20中使用PVC持久卷 - 知乎

Persistent Volumes:PV是持久化卷,系统管理员设置的存储,它是群集的一部分,是一种资源,所以它有独立于Pod的生命周期

Persistent Volume Claim:PVC是用户存储的请求。它与Pod相似,Pod消耗节点的CPU和内存资源,PVC则消耗PV资源,可以声明特定的容量大小和访问模式。

部署模式:

NFS(NAS)  ==》PV  ==》PVC

1、概念:

1.1 基础概念

容器本身是非持久化的,首先当容器崩溃,kubelet将重新启动容器,容器将会以镜像的初始状态重新开始在通过一个Pod中一起运行的容器,此时之前写入容器的文件将会丢失,另外容器之间通常需要共享容文件。Kubernetes通过Volum卷解决上述的两个问题。

Docker中存储卷只是磁盘的或另一个容器中的目录,并没有对其生命周期进行管理。Kubernetes的存储卷有自己的生命周期,它的生命周期与使用的它Pod生命周期一致。相比于在Pod中运行的容器来说,存储卷的存在时间会比的其中的任何容器都长,并且在容器重新启动时会保留数据。当然,当Pod停止存在时,存储卷也将不再存在。

在Pod中通过指定下面的字段来使用存储卷:

        spec.volumes:通过此字段提供指定的存储卷

        spec.containers.volumeMounts:通过此字段将存储卷挂接到容器中

1.2 PV的配置

1.2.1 静态PV配置

        管理员人为的创建静态一些PV。

1.2.2 动态PV配置

        系统自动创建的PV。可以通过storageClass来动态的产生PV。当管理员创建的静态 PV 都不匹配用户的 PersistentVolumeClaim 时,集群可能会尝试动态地为 PVC 创建卷。此配置基于 StorageClasses:PVC 必须请求存储类,并且管理员必须创建并配置该类才能进行动态创建。声明该类为 "" 可以有效地禁用其动态配置。要启用基于存储级别的动态存储配置,集群管理员需要启用 API server 上的 DefaultStorageClass 准入控制器。例如,通过确保 DefaultStorageClass 位于 API server 组件的 --admission-control 标志,使用逗号分隔的有序值列表中,可以完成此操作。有关 API server 命令行标志的更多信息,请检查 kube-apiserver 文档。

1.2.3 PVC与PV的绑定

        一旦用户创建或已经创建了具有特定存储量的 PersistentVolumeClaim 以及某些访问模式。Kubernetes控制器会监视到新的 PVC,并寻找匹配的 PV,并将它们绑定在一起。 PVC 跟 PV 绑定是一对一的映射。        

1.2.4 PVC及PV的使用

        Pod 使用PVC作为卷,集群检查PVC以查找绑定的卷并为集群挂载该卷。对于支持多种访问模式的卷,用户指定在使用声明作为容器中的卷时所需的模式(读写、只读)

2 部署PV及PVC

2.1 所有K8S机器都需要安装NFS程序

yum -y install nfs-utils rpcbind

2.2 仅针对需要暴露文件服务的机器开启NFS服务

        作为最终保存数据的linux服务器需要开启NSF服务,或者使用NAS盘的开启NSF服务即可。

        2.2.1 Linux为例开启NFS服务对外暴露服务目录

# 先创建一个对外共享的目录
mkdir -p /share/
chmod 777 /share/
 
echo "/share 192.168.10.0/24(rw,sync,no_root_squash)" >>/etc/exports

# 声明对外暴露
exportfs -rv

# 设置开机启动NFS服务并正式启动
systemctl enable rpcbind
systemctl enable nfs
systemctl enable nfs-lock
systemctl enable nfs-idmap
 
systemctl start rpcbind
systemctl start nfs
systemctl start nfs-lock
systemctl start nfs-idmap
#在需要成为NFS文件服务器上执行如上4行,可以对192.168.10.X网段暴露/share目录的读写

在实际需要暴露NFS的机器上执行如上命令,代表该机器对192.168.10.X网端内的机器对/share目录共享存储。rw支持读写、sync代表同步写入到NFS才算写成功、async代表写入到NFS机器的缓冲区就算成功。no_root_squash登入 NFS 主机使用分享目录的使用者,如果是 root 的话,那么对于这个分享的目录来说,他就具有 root 的权限!这个项目『极不安全』,不建议使用!root_squash:在登入 NFS 主机使用分享之目录的使用者如果是 root 时,那么这个使用者的权限将被压缩成为匿名使用者,通常他的 UID 与 GID 都会变成 nobody 那个系统账号的身份。

        2.2.2   群晖NAS盘为例开启NFS服务对外暴露共享目录

1、开启群晖NFS服务

2、创建共享文件、并设置NFS权限。

2.3 在需要挂载NFS服务的机器上执行挂载目录

假定NFS服务启动在192.168.10.31机器上

showmount -e 192.168.10.31   # 执行该命令可以看到该NFS服务器下对外暴露的目录

#### 下面是展示结果
Export list for 192.168.10.31:
/volume1/development *         # 代表允许所有机器访问
/volume1/test 192.168.10.80    # 代表仅允许80机器访问

将远程NFS服务器的某个目录挂载到本机上,例如把远程development目录挂载到本机的/root/nfs上

showmount -e 192.168.10.31 # 可以先查看下远程NFS服务器有哪些目录暴露出来

mkdir /root/nfs

chmod 777 /root/nfs

mount -t nfs 192.168.10.31:/volume1/development /root/nfs

# 可以执行如下命令查看挂载的结果
df -h

可以看下面的结果
192.168.10.31:/volume1/development nfs        14T  690G   14T    5% /root/nfs

1.3.4 取消挂载

umount /root/nfs
或强制取消挂载
umount -l /root/nfs

2.4 执行如下命令,创建PV及PVC

apiVersion: v1
kind: PersistentVolume
metadata:
  name: pv-nfs
  namespace: zo-dev
  labels:
    type: nfs
spec:
  capacity:
    storage: 100Gi
  accessModes:
    - ReadWriteMany
  persistentVolumeReclaimPolicy: Retain   #Recycle会清除数据,自动回收;Retain需要手动清理回收;Delete:云存储专用的回收空间使用命令
  storageClassName: nfs
  nfs:
    path: "/volume1/development"
    server: 192.168.10.31  #nfs服务器地址
    readOnly: false
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: pvc-nfs
  namespace: zo-dev
spec:
  accessModes:
    - ReadWriteMany
  resources:
    requests:
      storage: 20Gi
  storageClassName: nfs

3、在部署时使用PVC

 volumeMounts:
          - mountPath: /etc/nginx/nginx.conf
            name: nginx-php74
            subPath: nginx.conf
          - mountPath: "/var/www/html" ##挂载容器中的目录到pvc nfs中的目录
            name: storage    ##增加storage
      volumes:
      - name: nginx-php74
        configMap:
          name: nginx-php-configmap
          items:
           - key: nginx_php_conf
             path: nginx.conf
      - name: storage   ##与前面对应
        persistentVolumeClaim:  ##pvc声明
          claimName: pvc-nfs   ##创建好的pvc lab name

4、PV及PVC更高阶的用法

我们可以相信到一个大型的系统中会存在非常的PV及PVC的要求,挂载不同的目录,不同的容量大小,不同的NFS服务器、高速的SSD、低速的。因此如何管理好PV、PVC,最好是能依据PVC的声明要求,能做到自动分配PV岂不是很爽?

4.1 什么是StorageClass

参考这篇文章:k8s-1.22.3版本部署持久化存储之StorageClass+NFS_k8s 部署storageclass_归海听雪的博客-CSDN博客

StatefulSet是为了解决有状态服务的问题(对应Deployments和ReplicaSets是为无状态服务而设计),其应用场景包括:

稳定的持久化存储,即Pod重新调度后还是能访问到相同的持久化数据,基于PVC来实现
稳定的网络标志,即Pod重新调度后其PodName和HostName不变,基于Headless Service(即没有Cluster IP的Service)来实现
有序部署,有序扩展,即Pod是有顺序的,在部署或者扩展的时候要依据定义的顺序依次依次进行(即从0到N-1,在下一个Pod运行之前所有之前的Pod必须都是Running和Ready状态),基于init containers来实现
有序收缩,有序删除(即从N-1到0)
从上面的应用场景可以发现,StatefulSet由以下几个部分组成:

用于定义网络标志(DNS domain)的Headless Service
用于创建PersistentVolumes的volumeClaimTemplates
定义具体应用的StatefulSet
StatefulSet中每个Pod的DNS格式为statefulSetName-{0..N-1}.serviceName.namespace.svc.cluster.local,其中

serviceName为Headless Service的名字
0..N-1为Pod所在的序号,从0开始到N-1
statefulSetName为StatefulSet的名字
namespace为服务所在的namespace,Headless Servic和StatefulSet必须在相同的namespace
.cluster.local为Cluster Domain

在一个大规模的Kubernetes集群里,可能有成千上万个PVC,这就意味着运维人员必须实现创建出这个多个PV,此外,随着项目的需要,会有新的PVC不断被提交,那么运维人员就需要不断的添加新的,满足要求的PV,否则新的Pod就会因为PVC绑定不到PV而导致创建失败.而且通过 PVC 请求到一定的存储空间也很有可能不足以满足应用对于存储设备的各种需求,而且不同的应用程序对于存储性能的要求可能也不尽相同,比如读写速度、并发性能等,为了解决这一问题,Kubernetes 又为我们引入了一个新的资源对象:StorageClass,通过 StorageClass 的定义,管理员可以将存储资源定义为某种类型的资源,比如快速存储、慢速存储等,用户根据 StorageClass 的描述就可以非常直观的知道各种存储资源的具体特性了,这样就可以根据应用的特性去申请合适的存储资源了。

要使用 StorageClass,我们就得安装对应的自动配置程序,比如我们这里存储后端使用的是 nfs,那么我们就需要使用到一个 nfs-client 的自动配置程序,我们也叫它 Provisioner,这个程序使用我们已经配置好的 nfs 服务器,来自动创建持久卷,也就是自动帮我们创建 PV

搭建StorageClass+NFS,大致有以下几个步骤:

1.创建一个可用的NFS Serve
2.创建Service Account.这是用来管控NFS provisioner在k8s集群中运行的权限
3.创建StorageClass.负责建立PVC并调用NFS provisioner进行预定的工作,并让PV与PVC建立管理
4.创建NFS provisioner.有两个功能,一个是在NFS共享目录下创建挂载点(volume),另一个则是建了PV并将PV与NFS的挂载点建立关联 。

4.2 构建能自动分配PV的storageClass

执行如下部署后,然后创建PVC执行会自动产生PV卷,相当于按照PVC的声明要求,从storageClass中分配一个存储卷给到PVC。

# 如下创建storageClass,用于自动创建存储卷,原因是大规模集群中,很多的应用在不断的通过PVC申请PV,运维人员需要不断的依据PVC创建PV,另外PVC要求快速存储、慢速存储类型不一致
####################################### nfs-rbac.yaml
apiVersion: v1
kind: ServiceAccount
metadata:
  name: nfs-client-provisioner
  # replace with namespace where provisioner is deployed
  namespace: zo-dev        #根据实际环境设定namespace,下面类同
---
kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  namespace: zo-dev
  name: nfs-client-provisioner-runner
rules:
  - apiGroups: [""]
    resources: ["persistentvolumes"]
    verbs: ["get", "list", "watch", "create", "delete"]
  - apiGroups: [""]
    resources: ["persistentvolumeclaims"]
    verbs: ["get", "list", "watch", "update"]
  - apiGroups: ["storage.k8s.io"]
    resources: ["storageclasses"]
    verbs: ["get", "list", "watch"]
  - apiGroups: [""]
    resources: ["events"]
    verbs: ["create", "update", "patch"]
---
kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  name: run-nfs-client-provisioner
  namespace: zo-dev
subjects:
  - kind: ServiceAccount
    name: nfs-client-provisioner
    # replace with namespace where provisioner is deployed
    namespace: zo-dev
roleRef:
  kind: ClusterRole
  name: nfs-client-provisioner-runner
  apiGroup: rbac.authorization.k8s.io
---
kind: Role
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  name: leader-locking-nfs-client-provisioner
  # replace with namespace where provisioner is deployed
  namespace: zo-dev
rules:
  - apiGroups: [""]
    resources: ["endpoints"]
    verbs: ["get", "list", "watch", "create", "update", "patch"]
---
kind: RoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  name: leader-locking-nfs-client-provisioner
  namespace: zo-dev
subjects:
  - kind: ServiceAccount
    name: nfs-client-provisioner
    # replace with namespace where provisioner is deployed
    namespace: zo-dev
roleRef:
  kind: Role
  name: leader-locking-nfs-client-provisioner
  apiGroup: rbac.authorization.k8s.io
---
########################################## nfs-provisioner.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nfs-client-provisioner
  labels:
    app: nfs-client-provisioner
  # replace with namespace where provisioner is deployed
  namespace: zo-dev  #与RBAC文件中的namespace保持一致
spec:
  replicas: 1
  selector:
    matchLabels:
      app: nfs-client-provisioner
  strategy:
    type: Recreate
  template:
    metadata:
      labels:
        app: nfs-client-provisioner
    spec:
      serviceAccountName: nfs-client-provisioner
      containers:
        - name: nfs-client-provisioner
          #image: quay.io/external_storage/nfs-client-provisioner:latest
          #这里特别注意,在k8s-1.20以后版本中使用上面提供的包,并不好用,这里我折腾了好久,才解决,后来在官方的github上,别人提的问题中建议使用下面这个包才解决的,我这里是下载后,传到我自已的仓库里
          #easzlab/nfs-subdir-external-provisioner:v4.0.1
          image: easzlab/nfs-subdir-external-provisioner:v4.0.2
          volumeMounts:
            - name: nfs-client-root
              mountPath: /root/zo-nfs   # 宿主机该目录挂载到NFS上
          env:
            - name: PROVISIONER_NAME
              value: zo-nfs-storage  #provisioner名称,请确保该名称与 nfs-StorageClass.yaml文件中的provisioner名称保持一致
            - name: NFS_SERVER
              value: 192.168.10.31   #NFS Server IP地址
            - name: NFS_PATH
              value: "/volume1/development"    #NFS挂载卷
      volumes:
        - name: nfs-client-root
          nfs:
            server: 192.168.10.31  #NFS Server IP地址
            path: "/volume1/development"     #NFS 挂载卷
---
###################################### nfs-storageClass.yaml
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: managed-nfs-storage  #无须指定namespace,所有空间都能使用
provisioner: zo-nfs-storage #这里的名称要和nfs-provisioner.yaml配置文件中的环境变量ENV中的PROVISIONER_NAME保持一致
parameters:
  #  archiveOnDelete: "false"
  archiveOnDelete: "true"
reclaimPolicy: Retain  ## 文件需要手动删除

然后加入创建一个PVC的时候,此时会自动产生一个PV,例如

kind: PersistentVolumeClaim
apiVersion: v1
metadata:
  name: test-claim
  namespace: zo-dev
  annotations:
    #与nfs-storageClass.yaml metadata.name保持一致
    volume.beta.kubernetes.io/storage-class: "managed-nfs-storage"
spec:
  storageClassName: "managed-nfs-storage"
  accessModes:
    - ReadWriteMany
    #- ReadWriteOnce
  resources:
    requests:
      storage: 10Gi

此时PVC test-claim被自动创建,同时PV也会自动创建并被绑定。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/435772.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

抽象同步队列AbstractQueuedSynchronizer(AQS)简要理解

抽象同步队列AbstractQueuedSynchronizer AQS 简要理解 1 什么是AQS2 AQS结构2.1 同步状态2.2 CLH队列2.3 Node 3 AQS流程 https://zhuanlan.zhihu.com/p/370501087 1 什么是AQS AQS(AbstractQueuedSynchronizer)是 Java 中实现锁和同步器的基础设施&am…

el-input-number中添加单位(css版)

优点: 通过css添加,非常便捷和简单 例如此处,需要添加一个分钟单位 <el-input-number class"input-number" v-model"value" :step"5" :min"30" ></el-input-number> //css <style lang"scss"> .input-nu…

node项目(一) koa脚手架的搭建

一、koa 安装 // 安装koa npm install -g koa-generator // 创建项目 koa2 项目名称 当出现这个框的时候安装完毕 之后就是进入目录文件&#xff0c;根据package.json执行即可 二、出现问题 汇总 问题一&#xff1a;koa-generator安装失败 没有出现koa-generator安装成功 …

分类预测 | MATLAB实现BO-CNN-GRU贝叶斯优化卷积门控循环单元多输入分类预测

分类预测 | MATLAB实现BO-CNN-GRU贝叶斯优化卷积门控循环单元多输入分类预测 目录 分类预测 | MATLAB实现BO-CNN-GRU贝叶斯优化卷积门控循环单元多输入分类预测效果一览基本介绍模型描述程序设计参考资料 效果一览 基本介绍 基于贝叶斯(bayes)优化卷积神经网络-门控循环单元(CN…

4月第2周榜单丨飞瓜数据B站UP主排行榜(哔哩哔哩平台)发布!

飞瓜轻数发布2023年4月10日-4月16日飞瓜数据UP主排行榜&#xff08;B站平台&#xff09;&#xff0c;通过充电数、涨粉数、成长指数三个维度来体现UP主账号成长的情况&#xff0c;为用户提供B站号综合价值的数据参考&#xff0c;根据UP主成长情况用户能够快速找到运营能力强的B…

Linux进程概念——其一

目录 冯诺依曼体系结构 操作系统(Operator System) 概念 设计OS的目的 定位 如何理解 "管理" 总结 系统调用和库函数概念 进程 基本概念 描述进程-PCB task_struct-PCB的一种 task_ struct内容分类 组织进程 查看进程 通过系统调用获取进程标示符 通…

Docker Desktop 占用过多C盘存储空间的一种解决办法——在其他磁盘分区添加访问路径

一、问题背景 Docker Desktop默认是安装到C盘中的。但随着Docker的使用&#xff0c;其占用的空间也越来越大&#xff0c;Docker占用C盘空间过大成了个令人头疼的问题。恰好最近腾出了一个空的磁盘分区&#xff0c;因此可以使用“在其他磁盘分区添加访问路径”的方式&#xff0c…

03-Mybatis的基本使用-注解配置文件+xml配置文件

目录 1、环境准备 2、注解配置文件 基础操作01-通过ID删除数据 基础操作02-插入数据 基础操作03-更新数据 基础操作04-根据ID查询数据 基础操作05-条件查询数据 3、xml配置文件 1、环境准备 1. 创建数据库数据表 -- 部门管理 create table dept(id int unsigned prim…

【数据篇】SpringBoot 整合 MyBatis 组合 Redis 作为数据源缓存

写在最前 MyBatis 是常见的 Java 数据库访问层框架。在日常工作中&#xff0c;开发人员多数情况下是使用 MyBatis 的默认缓存配置&#xff0c;但是 MyBatis 缓存机制有一些不足之处&#xff0c;在使用中容易引起脏数据&#xff0c;形成一些潜在的隐患。 本文介绍的是 Redis 组…

版本控制工具之git安装

作为软件开发者的必备工具——版本控制工具&#xff0c;git无疑深受欢迎。 业界常用的版本控制工具主要有两种&#xff1a;SVN和Git SVN 传统的版本控制工具&#xff0c;特点为集中式分布。 使用一台专用的服务器存储所有资料。 缺点是所有的动作都必须依赖于中央服务器&#x…

FPGA配置方式的基本知识?

FPGA配置粗略可以分为主动和被动两种。主动加载是指由FPGA控制配置流程&#xff0c;被动加载是指FPGA仅仅被动接收配置数据。 最常见的被动配置模式就是JTAG下载bit文件。此模式下&#xff0c;主动发起操作的设备是计算机&#xff0c;数据通路是JTAG&#xff0c;FPGA会被动接收…

STM32F103基于HAL库I2C/SPI硬件接口+DMA驱动 SSD1306 Oled

STM32F103基于HAL库I2C/SPI硬件接口DMA驱动 SSD1306 Oled ✨由于手上只有I2C接口的SSD1306 OLED屏幕&#xff0c;仅测试了硬件I2C驱动显示功能&#xff0c;实际测试的FPS帧率在37或38变化。 &#x1f4e2;本项目从Github开源项目中移植过来&#xff0c;开源地址&#xff1a;htt…

JDBC之API详解

DriverManager可以注册驱动&#xff0c;就是创建接口的实现类对象。 Class.forName可以将Driver类加载进内存&#xff0c;Driver类中存在静态代码块&#xff0c;随着类的加载静态代码块执行&#xff0c;通过 DriverManager.registerDriver的方式注册好驱动。 获取与数据库的链…

Android Java 播放音频 AudioTrack

【很多同学读 Android 系统的源码时感觉比较费力&#xff0c;一定会觉得是自己水平不够见识有限认知水平不足&#xff0c;觉得自己需要多学习多努力多下功夫&#xff0c;但 Android 系统源码质量之烂简直超乎想象。尽管 Android 系统确实实现了很多功能、特性&#xff0c;提供了…

【面试】你在项目中遇到过慢查询问题吗?你是怎么做SQL优化的?

文章目录 前言一、找出有问题的SQL1、系统层面2、SQL语句层面 二、查看SQL执行计划三、SQL优化案例慢查询优化步骤 SQL优化小结 前言 我在面试的时候很喜欢问候选人这样一个问题&#xff1a;“你在项目中遇到过慢查询问题吗&#xff1f;你是怎么做SQL优化的&#xff1f;” 很多…

含分布式电源的配电网可靠性评估研究(Matlab代码实现)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…

Windows服务搭建web网站,使用cpolar内网穿透实现公网访问

文章目录 概述1. 搭建一个静态Web站点2. 本地浏览测试站点是否正常3. 本地站点发布公网可访问3.1 安装cpolar内网穿透3.2 创建隧道映射公网地址3.3 获取公网URL地址 4. 公网远程访问内网web站点5. 配置固定二级子域名5.1 保留二级子域名5.2 配置二级子域名 6. 测试访问二级子域…

Activiti7 工作流非原流程终止

背景 正常工作流&#xff0c;需要经过 node1、node2 才能结束。 现在要求已经开启的流程&#xff0c;目前停留在 node1&#xff0c;可以提前终止。 方案 一般根据实际需要&#xff0c;可以有几种做法&#xff1a; 新绘制流程图&#xff0c;新增 node1 结束的流程分支&#x…

基于 JESD204B 协议ARM+FPGA+AD多板卡多通道同步采集实现方法

0 引言 随着数字化信号处理技术的不断进步&#xff0c;对数字信号 的处理已经成为当前大多数工程应用的基本方法。由于 模拟信号才是现实生活中的原始信号&#xff0c;为了工程研究实 现的可能&#xff0c;需将模拟信号转换为数字信号才能在工程中 处理&#xff0c;AD 转换…

独立按键控制LED移位

1.这就是LED移位的原理 2. #include <REGX52.H> void Delay(unsigned int xms);unsigned char LEDNum;//LEDNum为0000 0000void main() {P2~0x01; //上电默认LED1点亮while(1){if(P3_10) //如果K1按键按下&#xff0c;LED灯往右依次亮起{Delay(20);while(P3_10);//消…