k8s之挂载NFS到POD中

news2024/11/16 1:53:28

写在前面

在k8s之挂载本地磁盘到POD中 一文中我们看了如何将POD中的数据写到本地磁盘中,这种方式要求POD只能在指定的Node上,一旦POD更换Node,数据依然会丢失,所以本文看下如何通过将数据写到NFS中来解决这个问题。下面我们就开始吧!

1:NFS

1.1:什么是NFS

NFS全称network file system,是一种允许我们像使用本地磁盘一样,使用远端某机器的磁盘的一种技术,采用cs架构,所以其本质上可以看做是一种数据存储解决方案。

1.2:安装server

1.2.1:安装服务器

sudo apt -y install nfs-kernel-server

1.2.2:创建服务器写文件目录

mkdir -p /tmp/nfs

注意,这里的目录仅仅用于测试,生产环境还是要使用专门的目录来做,例如创建专门的data目录,并挂载一块专门的盘。

1.2.3:配置访问规则

编辑/etc/exports文件添加如下内容:

/tmp/nfs 192.168.64.132(rw,sync,no_subtree_check,no_root_squash,insecure)

这里的IP地址注意改成你自己的,也支持配置多条,或者配置网段,根据具体情况设置即可。配置完毕后还需要将修改通知到nfs server,通过如下命令:

sudo exportfs -ra
sudo exportfs -v

1.2.4:启动服务

sudo systemctl start  nfs-server
sudo systemctl enable nfs-server
sudo systemctl status nfs-server

其中sudo systemctl status nfs-server如果输出如下信息则说明启动成功了:

dongyunqi@mongodaddy:/tmp/nfs/1g-pv$ sudo systemctl status nfs-server
......
1月 19 13:01:59 mongodaddy systemd[1]: Starting NFS server and services...
1月 19 13:02:00 mongodaddy systemd[1]: Finished NFS server and services.

我们也可以通过如下命令查看nfs server配置的挂载信息:

dongyunqi@mongodaddy:/tmp/nfs/1g-pv$ showmount -e 127.0.0.1
Export list for 127.0.0.1:
/tmp/nfs 192.168.64.132

/tmp/nfs 192.168.64.132意思是允许IP地址192.168.64.132的机器挂载到nfs server的/tmp/nfs目录。

1.3:安装client

执行如下命令:

sudo apt -y install nfs-common
dongyunqi@mongomongo:~/nfslocal$ showmount -e 192.168.64.131 # 注意这里的IP是nfs server的地址
Export list for 192.168.64.131:
/tmp/nfs 192.168.64.132

然后通过如下命令挂载目录:

sudo mount -t nfs 192.168.64.131:/tmp/nfs /home/dongyunqi/nfslocal

这样当我们在本地/home/dongyunqi/nfslocal目录中创建的文件就会同步到nfs server,即192.168.64.131的/tmp/nfs目录。如下测试:

在nfs client /home/dongyunqi/nfslocal操作:
    dongyunqi@mongomongo:~/nfslocal$ pwd
    /home/dongyunqi/nfslocal
    dongyunqi@mongomongo:~/nfslocal$ sudo tee /home/dongyunqi/nfslocal/ntf-pod.yml <<-'EOF'
    > apiVersion: v1
    > EOF
    [sudo] password for dongyunqi: 
    apiVersion: v1
在nfs server查看:
    dongyunqi@mongodaddy:/tmp/nfs$ pwd 
    /tmp/nfs
    dongyunqi@mongodaddy:/tmp/nfs$ cat ntf-pod.yml 
    apiVersion: v1

到这里nfs就安装成功了,接下来看下如何在POD中使用。

2:在POD中使用NFS

2.1:定义PV

首先我们来定义代表NFS的PV,yaml如下:

dongyunqi@mongodaddy:~/k8s$ cat ntf-1g.yml 
apiVersion: v1
kind: PersistentVolume
metadata:
  name: nfs-1g-pv

spec:
  storageClassName: nfs
  accessModes:
    - ReadWriteMany
  capacity:
    storage: 1Gi

  nfs:
    path: /tmp/nfs/1g-pv
    server: 192.168.64.131

这里accessModes设置为ReadWriteMany,因为NFS是基于网络来存储数据的,所以可以被多个POD读写多次,path: /tmp/nfs/1g-pv代表nfs server要写入的目录是/tmp/nfs/1g-pv,因为C端不能直接操作S端来创建目录,所以该目录一定要提前创建好,server是nfs server的IP地址,apply:

kubectl apply -f nfs-static-pv.yml

在这里插入图片描述

2.2:定义PVC

定义PVC来使用PV,yaml如下:

dongyunqi@mongodaddy:~/k8s$ cat ntf-pvc.yml 
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: nfs-static-pvc

spec:
  storageClassName: nfs
  accessModes:
    - ReadWriteMany

  resources:
    requests:
      storage: 1Gi

这里从storage class为nfs的PV中申请1g的空间,这样就会找到我们已经定义的PVnfs-1g-pv,apply,pvc使用pv后二者就会绑定在一起了,如下:

dongyunqi@mongodaddy:~/k8s$ kubectl get pv
NAME        CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS   CLAIM                    STORAGECLASS   REASON   AGE
nfs-1g-pv   1Gi        RWX            Retain           Bound    default/nfs-static-pvc   nfs                     40h
dongyunqi@mongodaddy:~/k8s$ kubectl get pvc
NAME             STATUS   VOLUME      CAPACITY   ACCESS MODES   STORAGECLASS   AGE
nfs-static-pvc   Bound    nfs-1g-pv   1Gi        RWX            nfs            40h

2.2:在POD中使用

yaml如下:

dongyunqi@mongodaddy:~/k8s$ cat ntf-pod.yml 
apiVersion: v1
kind: Pod
metadata:
  name: nfs-static-pod

spec:
  volumes:
  - name: nfs-pvc-vol
    persistentVolumeClaim:
      claimName: nfs-static-pvc

  containers:
    - name: nfs-pvc-test
      image: nginx:alpine
      ports:
      - containerPort: 80

      volumeMounts:
        - name: nfs-pvc-vol
          mountPath: /tmp

首先将PVC定义为volume卷,然后挂载到容器中的/tmp目录,这样在POD中的/tmp目录创建的文件就会同步到nfs server的/tmp/nfs/1g-pv目录了,apply后进入到容器中测试如下:

dongyunqi@mongodaddy:~/k8s$ kubectl get pod
NAME             READY   STATUS    RESTARTS   AGE
nfs-static-pod   1/1     Running   0          40h
dongyunqi@mongodaddy:~/k8s$ kubectl exec -it nfs-static-pod -- sh
/tmp # cd /tmp/
/tmp # touch hello.txt
/tmp # echo "hello from pod" > hello.txt 
/tmp # cat hello.txt 
hello from pod

到这里在POD中使用NFS就分享完了,最后再看下pv,pvc,pod,nfs server之间的关系图:

在这里插入图片描述

以上的PV我们都是手动定义的,接下来继续看下如何使用自动的方式来创建PV。

3:NFS provisoner

3.1:定义动态存储卷

这种方式我们叫做是动态存储卷,那么之前手动定义PV的方式我们就可以叫做是静态存储卷。

一种存储设备对应一种provisoner,想要使用某种存储介质,只需要创建其对应的相关资源即可,比如我们这里的NFS对应的provisoner的项目就在这里 ,我们需要其中的三个yaml文件,rbac.yaml、class.yaml 和 deployment.yaml,如下是我本地修改后的:
rbac.yaml

apiVersion: v1
kind: ServiceAccount
metadata:
  name: nfs-client-provisioner
  # replace with namespace where provisioner is deployed
  namespace: kube-system
---
kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  name: nfs-client-provisioner-runner
rules:
  - apiGroups: [""]
    resources: ["nodes"]
    verbs: ["get", "list", "watch"]
  - 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
subjects:
  - kind: ServiceAccount
    name: nfs-client-provisioner
    # replace with namespace where provisioner is deployed
    namespace: kube-system
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: kube-system
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
  # replace with namespace where provisioner is deployed
  namespace: kube-system
subjects:
  - kind: ServiceAccount
    name: nfs-client-provisioner
    # replace with namespace where provisioner is deployed
    namespace: kube-system
roleRef:
  kind: Role
  name: leader-locking-nfs-client-provisioner

class.yaml

apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: nfs-client
provisioner: k8s-sigs.io/nfs-subdir-external-provisioner # or choose another name, must match deployment's env PROVISIONER_NAME'
parameters:
  archiveOnDelete: "false"

deployment.yaml

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nfs-client-provisioner
  labels:
    app: nfs-client-provisioner
  # replace with namespace where provisioner is deployed
  namespace:  kube-system
spec:
  replicas: 1
  strategy:
    type: Recreate
  selector:
    matchLabels:
      app: nfs-client-provisioner
  template:
    metadata:
      labels:
        app: nfs-client-provisioner
    spec:
      serviceAccountName: nfs-client-provisioner
      containers:
        - name: nfs-client-provisioner
          image: chronolaw/nfs-subdir-external-provisioner:v4.0.2
          volumeMounts:
            - name: nfs-client-root
              mountPath: /persistentvolumes
          env:
            - name: PROVISIONER_NAME
              value: k8s-sigs.io/nfs-subdir-external-provisioner
            - name: NFS_SERVER
              value: 192.168.64.131
            - name: NFS_PATH
              value: /tmp/nfs
      volumes:
        - name: nfs-client-root
          nfs:
            server: 192.168.64.131
            path: /tmp/nfs

分别apply后查看:

dongyunqi@mongodaddy:~/k8s$ kubectl get deploy -n kube-system
NAME                     READY   UP-TO-DATE   AVAILABLE   AGE
coredns                  2/2     2            2           5d1h
nfs-client-provisioner   1/1     1            1           5h38m=]
dongyunqi@mongodaddy:~/k8s$ kubectl get pod -n kube-system -l app=nfs-client-provisioner
NAME                                      READY   STATUS    RESTARTS   AGE
nfs-client-provisioner-6b7bd59ccf-76xmb   1/1     Running   0          5h39m

这样PV定义好了,接下来就需要定义storage class对动态PV进行分类了。

3.2:storage class

比较简单,yaml如下:

dongyunqi@mongodaddy:~/k8s$ cat dynamic_class.yml 
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: nfs-client-retained

provisioner: k8s-sigs.io/nfs-subdir-external-provisioner
parameters:
  onDelete: "retain"

这里不仅仅定义了class的名称还通过参数进行了相关的设置。

3.3:定义PVC

接下来就能定义PVC来使用动态PV了,yaml如下:

dongyunqi@mongodaddy:~/k8s$ cat  dynamic_pvc.yml 
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: nfs-dyn-10m-pvc

spec:
  storageClassName: nfs-client
  accessModes:
    - ReadWriteMany

  resources:
    requests:
      storage: 10Mi

这里从storage class为nfs-client的PV中查找大小满足10M的存储设备,apply后会和自动创建的PV进行绑定,如下:

dongyunqi@mongodaddy:~/k8s$ kubectl get pv
NAME                                       CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS        CLAIM                     STORAGECLASS   REASON   AGE
pvc-d45bca08-34a6-4c32-9382-6abac724c842   10Mi       RWX            Delete           Bound         default/nfs-dyn-10m-pvc   nfs-client              15h
dongyunqi@mongodaddy:~/k8s$ kubectl get pvc
NAME              STATUS   VOLUME                                     CAPACITY   ACCESS MODES   STORAGECLASS   AGE
nfs-dyn-10m-pvc   Bound    pvc-d45bca08-34a6-4c32-9382-6abac724c842   10Mi       RWX            nfs-client     15h

可以看到PV已经自动创建了,名字是pvc-d45bca08-34a6-4c32-9382-6abac724c842,但不知道为什么前缀是pvc而不是pv,我想可能是手误吧!不过这都不重要。

3.4:在POD中使用

yaml如下:

dongyunqi@mongodaddy:~/k8s$ cat dynamic_pod.yml 
apiVersion: v1
kind: Pod
metadata:
  name: nfs-dyn-pod

spec:
  volumes:
  - name: nfs-dyn-10m-vol
    persistentVolumeClaim:
      claimName: nfs-dyn-10m-pvc

  containers:
    - name: nfs-dyn-test
      image: nginx:alpine
      ports:
      - containerPort: 80

      volumeMounts:
        - name: nfs-dyn-10m-vol
          mountPath: /tmp

这里我们将NFS共享目录挂载到POD的/tmp目录,apply后将会在NFS server创建共享目录,如下:

dongyunqi@mongodaddy:/tmp/nfs/default-nfs-dyn-10m-pvc-pvc-d45bca08-34a6-4c32-9382-6abac724c842$ pwd
/tmp/nfs/default-nfs-dyn-10m-pvc-pvc-d45bca08-34a6-4c32-9382-6abac724c842

此时我们在POD的/tmp目录创建文件的话将会自动同步到该NFS共享目录:

操作POD:
    dongyunqi@mongodaddy:~$ kubectl get pod
    NAME          READY   STATUS    RESTARTS   AGE
    nfs-dyn-pod   1/1     Running   0          15h
    dongyunqi@mongodaddy:~$ kubectl exec -it nfs-dyn-pod -- sh
    / # cd /tmp/
    /tmp # pwd
    /tmp
    /tmp # touch hello.txt
    /tmp # echo "helloooooo" > hello.txt 
    /tmp #
共享目录查看:
    dongyunqi@mongodaddy:~$ cat /tmp/nfs/default-nfs-dyn-10m-pvc-pvc-d45bca08-34a6-4c32-9382-6abac724c842/hello.txt 
    helloooooo

写在后面

小结

本文分析了如何挂载NFS server到POD中,并一起看了如何使用provisoner来实现自动创建PV的工作,减少手工重复劳动。希望本文能够帮助到你。

参考文章列表

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

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

相关文章

sklearn数据降维之字典学习

文章目录字典学习简介构造函数实战Step1 制作实验数据Step2 小批字典学习Step 3 参数调整字典学习简介 如果把降维理解成压缩的话&#xff0c;那么字典学习的本质是编码&#xff0c;其目的是找到少量的原子&#xff0c;用以描述或构建原始样本。举个一维的例子&#xff0c;以a…

程序员护眼指南

前言 前言&#xff1a;脱发和近视是当代年轻人的两大痛点&#xff0c;今天来聊聊如何护眼。 文章目录前言一、护眼的核心二、调节睫状肌的方法1. 眨眼2. 望远3. 睡觉4. 促进血液循环5. 吃补剂6. 好的屏幕一、护眼的核心 护眼的核心就是保护睫状肌。 睫状肌是眼内的一种平滑肌…

一起自学SLAM算法:7.7 典型SLAM算法

连载文章&#xff0c;长期更新&#xff0c;欢迎关注&#xff1a; 针对式&#xff08;7-38&#xff09;所述的在线SLAM系统&#xff0c;以扩展卡尔曼滤波&#xff08;EKF&#xff09;为代表的滤波方法&#xff0c;是求解该状态估计问题最典型的方法&#xff0c;在7.4节中已经详细…

GY-US42超声波传感器模块介绍

GY-US42超声波传感器模块简介GY-US42 是一款低成本高品质测距传感器模块。工作电压 3-5v&#xff0c;功耗小&#xff0c;体积小&#xff0c;安装方便。其工作原理是&#xff0c;探头发射超声波&#xff0c;照射到被测物体后&#xff0c;探头接收返回声波&#xff0c;利用时间差…

学人工智能电脑主机八大件配置选择指南

来源&#xff1a;深度之眼 作者&#xff1a;frank 编辑&#xff1a;学姐 本篇主要是帮助大家构建高性能、高性价比的AI开发的硬件平台。如何不把钱浪费到不必要的硬件上&#xff0c;并合理搭配硬件配置节省预算是本文想要去讨论的问题。如果预算充足&#xff0c;笔者建议购买一…

【JavaSE专栏1】Java的介绍、特点和历史

作者主页&#xff1a;Designer 小郑 作者简介&#xff1a;Java全栈软件工程师一枚&#xff0c;来自浙江宁波&#xff0c;负责开发管理公司OA项目&#xff0c;专注软件前后端开发&#xff08;Vue、SpringBoot和微信小程序&#xff09;、系统定制、远程技术指导。CSDN学院、蓝桥云…

Python ·保险理赔分析:数据分析

介绍 提示&#xff1a;这里可以添加系列文章的所有文章的目录&#xff0c;目录需要自己手动添加 在本笔记本中&#xff0c;我们将仔细研究保险索赔&#xff0c;并弄清一些有关血压、BMI、糖尿病、吸烟、年龄和性别等条件如何影响索赔价值的事实。 我们将使用散点图、饼图、直…

IDEA必装插件-Gyro

前言用SpringBootTest运行单测的时候&#xff0c;是不是每运行都需要重新启动Spring容器&#xff1f;大型应用启动一次会浪费大量的时间&#xff0c;导致效率比较低。Gyro插件可以解决你的问题。Gyro介绍它是一个IDEA插件&#xff0c;安装之后&#xff0c;用Gyro Debug运行你的…

一起自学SLAM算法:7.4 基于贝叶斯网络的状态估计

连载文章&#xff0c;长期更新&#xff0c;欢迎关注&#xff1a; 在7.2.4节中&#xff0c;讨论了表示机器人观测与运动之间依赖关系的概率图模型&#xff0c;主要是贝叶斯网络&#xff08;实际应用在机器人中的是动态贝叶斯网络&#xff09;和马尔可夫网络&#xff08;实际应用…

fpga实操训练(lcd字符显示)

【 声明:版权所有,欢迎转载,请勿用于商业用途。 联系信箱:feixiaoxing @163.com】 用fpga编写屏幕显示,和c语言编写有很大的不同。用c语言开发,很大程度上是遵循soc ip提供的规范进行编写。而用fpga开发的话,则需要考虑不同信号的时序关系。但是,用fpga开发也有…

c++ 优先级队列priority_queue的使用

c priority_queue是对其他容器元素顺序的调整包装; 堆的原理 1.定义 priority_queue<Type, Container, Functional> q; 其中&#xff0c;Type是数据类型&#xff0c;Container是低层容器&#xff0c;如vector, stack, deque等. Functional是比较函数&#xff1b;默认可…

day25-类加载器反射

1.类加载器 1.1类加载器【理解】 作用 负责将.class文件&#xff08;存储的物理文件&#xff09;加载在到内存中 1.2类加载的过程【理解】 类加载时机 创建类的实例&#xff08;对象&#xff09;调用类的类方法访问类或者接口的类变量&#xff0c;或者为该类变量赋值使用反…

NodeJS 之 HTTP 模块(实现一个基本的 HTTP 服务器)

NodeJS 之 HTTP 模块&#xff08;实现一个基本的 HTTP 服务器&#xff09;参考描述HTTP 模块搭建 HTTP 服务器http.createServer()监听检测服务器端口是否被占用终端Error Code超时处理处理客户端的请求request 事件http.IncomingMessagehttp.ServerResponse中文乱码问题问题解…

Java EE之线程编(进阶版)

这些锁策略能适用于很多中语言&#xff0c;博主是学Java的&#xff0c;所以下面的代码会用Java去写&#xff0c;请大家见谅&#xff0c;但是处理的方法是大差不差的。 一、常见锁和锁策略&#xff1a; (一)、乐观锁和悲观锁 1、何为乐观锁和悲观锁呢&#xff1f; 答&#…

Linux服务器常见运维性能测试(3)CPU测试super_pi、sysbench

Linux服务器常见运维性能测试&#xff08;3&#xff09;CPU测试常见性能测试软件CPU测试&#xff1a;super_pi &#xff08;计算圆周率&#xff09;CPU测试&#xff1a;sysbench&#xff08;CPU功能测试部分&#xff09;下载安装sysbench综合测试功能执行CPU测试最近需要测试一…

Java面试题含答案,最新面试题(1)

Java 中 InvokeDynamic指令是干什么的&#xff1f; JVM字节码指令集一直比较稳定&#xff0c;一直到Java7中才增加了一个InvokeDynamic 指令&#xff0c;这是JAVA为了实现『动态类型语言』支持而做的一种改进&#xff1b;但是在Java7中并没有提供直接生成InvokeDynamic 指令的…

自定义类型:结构体,枚举,联合

目录一、结构体内存对齐二、位段2.1 什么是位段2.2 位段内存分配规则2.3 位段的跨平台问题三、枚举四、联合体4.1 联合类型的定义4.2联合的特点4.3 联合大小的计算4.4 练习一、结构体内存对齐 struct s {char c1;int i;char c2; }; int main() {printf("%d\n", size…

【Hadoop】HDFS体系结构分析

文章目录1. NameNode2. Secondary NameNode3. DataNodeHDFS主要包含NameNode、Secondary NameNode和DataNode三部分&#xff0c;且这三部分在分布式文件系统中分属不同的机器&#xff0c;其中Secondary NameNode不是必须的&#xff0c;在HA架构中Standby NameNode可以替代它。 …

【深度学习】详解 SimCLR

目录 摘要 一、引言 二、方法 2.1 The Contrastive Learning Framework 2.2. Training with Large Batch Size 2.3. Evaluation Protocol 三、用于对比表示学习的数据增广 3.1 Composition of data augmentation operations is crucial for learning good representa…

5-2中央处理器-指令周期的数据流

文章目录一.指令周期二.数据流向1.取指周期2.间址周期3.执行周期4.中断周期三.指令执行方案1.单指令周期2.多指令周期3.流水线方案一.指令周期 指令周期&#xff1a;CPU从主存中每取出并执行一条指令所需的全部时间。 此处&#xff1a;取指周期取指令指令译码 指令周期常用若…