一、部署nfs服务端

1、需在 k8s-master 节点上搭建了一个 NFS 服务器,目录为 /nfsdata:

yum install -y nfs-utils rpcbind
vim /etc/exports
/nfsdata *(rw,no_root_squash,no_all_squash,sync)

2、保存配置文件后,执行如下操作:

  在服务端创建对应的目录和赋予权限:

 mkdir /nfsdata
chmod 777 /nfsdata

3、启动rpcbind和nfs服务:

systemctl start rpcbind && systemctl enable rpcbind
systemctl start nfs && systemctl enable nfs

4、每个node安装nfs工具

 yum install -y nfs-utils 

5、每个node查询NFS服务器

showmount -e nfs-ip

二、 NFS PersistentVolume

1、创建PV

(1)下面创建一个PV mypv1,配置文件nfs-pv1.yml如下:

[root@ren7 yaml]# cat nfs-pv1.yml
apiVersion: v1
kind: PersistentVolume
metadata:
name: mypv1
spec:
capacity:
storage: 1Gi
accessModes:
- ReadWriteOnce
persistentVolumeReclaimPolicy: Recycle
storageClassName: nfs
nfs:
path: /nfsdata/pv1 #需要创建pv1目录,否则pod起不来
server: 192.168.11.7

  ① capacity 指定 PV 的容量为 1G。

  ② accessModes 指定访问模式为 ReadWriteOnce,支持的访问模式有:

  ReadWriteOnce – PV 能以 read-write 模式 mount 到单个节点。

  ReadOnlyMany – PV 能以 read-only 模式 mount 到多个节点。

  ReadWriteMany – PV 能以 read-write 模式 mount 到多个节点。

  ③ persistentVolumeReclaimPolicy 指定当 PV 的回收策略为 Recycle,支持的策略有:
  Retain – 需要管理员手工回收。
  Recycle – 清除 PV 中的数据,效果相当于执行 rm -rf /thevolume/*
  Delete – 删除 Storage Provider 上的对应存储资源,例如 AWS EBS、GCE PD、Azure Disk、OpenStack Cinder Volume 等。

  ④ storageClassName 指定 PV 的 class 为 nfs。相当于为 PV 设置了一个分类,PVC 可以指定 class 申请相应 class 的 PV。

  ⑤ 指定 PV 在 NFS 服务器上对应的目录。

  注意要做storage-provider段要提前建好文件夹

[root@ren7 nfsdata]# pwd
/nfsdata
[root@ren7 nfsdata]# mkdir pv1
[root@ren7 nfsdata]# ls
pv1

(2)创建 mypv1:

[root@ren7 yaml]# kubectl apply -f nfs-pv1.yml
persistentvolume/mypv1 created
[root@ren7 yaml]# kubectl get pv
NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE
mypv1 1Gi RWO Recycle Available nfs 9s

  STATUS 为 Available,表示 mypv1 就绪,可以被 PVC 申请。

2、创建PVC

(1)接下来创建 PVC mypvc1,配置文件 nfs-pvc1.yml 如下:

  注意:

  1)storageClassName需要与上面定义的pv保持一致!

  2)各个节点都需要下载nfs-utils

[root@ren7 yaml]# cat nfs-pvc1.yml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: mypvc1
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 1Gi
storageClassName: nfs

  PVC 就很简单了,只需要指定 PV 的容量,访问模式和 class。

(2)创建 mypvc1:

[root@ren7 yaml]# kubectl apply -f nfs-pvc1.yml
persistentvolumeclaim/mypvc1 created
[root@ren7 yaml]# kubectl get pvc
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE
mypvc1 Bound mypv1 1Gi RWO nfs 10s
[root@ren7 yaml]#
[root@ren7 yaml]# kubectl get pv
NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE
mypv1 1Gi RWO Recycle Bound default/mypvc1 nfs 161m

  从 kubectl get pvc 和 kubectl get pv 的输出可以看到 mypvc1 已经 Bound 到 mypv1,申请成功。

3、pod使用PVC

(1)接下来就可以在 Pod 中使用存储了,Pod 配置文件 pod1.yml 如下:

[root@ren7 yaml]# cat pod1.yml
apiVersion: v1
kind: Pod
metadata:
name: mypod1
spec:
containers:
- name: mypod1
image: reg.yunwei.com/learn/busybox:latest
args:
- /bin/sh
- -c
- sleep 30000
volumeMounts:
- mountPath: "/mydata"
name: mydata
volumes:
- name: mydata
persistentVolumeClaim:
claimName: mypvc1

  与使用普通 Volume 的格式类似,在 volumes 中通过 persistentVolumeClaim 指定使用 mypvc1 申请的 Volume。

(2)创建 mypod1:

[root@ren7 yaml]# kubectl apply -f pod1.yml
pod/mypod1 created
[root@ren7 yaml]# kubectl get pod -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
mypod1 1/1 Running 0 12s 172.20.72.157 192.168.11.5 <none> <none>

(3)验证 pv 是否可用:

[root@ren7 yaml]# kubectl exec mypod1 touch /mydata/hello
[root@ren7 yaml]# cd /nfsdata/
[root@ren7 nfsdata]# ls
pv1
[root@ren7 nfsdata]# ls pv1/
hello

  可见,在 Pod 中创建的文件 /mydata/hello 确实已经保存到了 NFS 服务器目录 /nfsdata/pv1 中。

  如果不再需要使用 pv,可用删除PVC 回收 pv。

三、回收 PV:

1、当 PV 不再需要时,可通过删除 PVC 回收。

[root@ren7 yaml]# kubectl delete -f nfs-pvc1.yml
persistentvolumeclaim "mypvc1" deleted
[root@ren7 yaml]# kubectl get pod -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
mypod1 1/1 Running 0 3h46m 172.20.72.157 192.168.11.5 <none> <none>

  当 PVC mypvc1 被删除后,我们发现 Kubernetes 启动了一个新 Pod这个 Pod 的作用就是清除 PV mypv1 的数据。这个时候我们再看 NFS 服务器目录 /nfsdata/pv1 中已经没有数据了。

[root@ren7 nfsdata]# ls
pv1
[root@ren7 nfsdata]# ls pv1/
[root@ren7 nfsdata]#
[root@ren7 nfsdata]#

2、当数据清除完毕,mypv1 的状态重新变为 Available,此时则可以被新的 PVC 申请。

[root@ren7 yaml]# kubectl get pv
NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE
mypv1 1Gi RWO Recycle Available nfs 3h52m

3、因为 PV 的回收策略设置为 Recycle,所以数据会被清除,但这可能不是我们想要的结果。如果我们希望保留数据,可以将策略设置为 Retain。

apiVersion: v1
kind: PersistentVolume
metadata:
name: mypv1
spec:
capacity:
storage: 1Gi
accessModes:
- ReadWriteOnce
persistentVolumeReclaimPolicy: Retain
storageClassName: nfs
nfs:
path: /nfsdata/pv1
server: 192.168.11.7

4、通过kubectl apply 更新PV:

[root@ren7 yaml]# kubectl apply -f nfs-pv1.yml
persistentvolume/mypv1 configured
[root@ren7 yaml]# kubectl get pv
NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE
mypv1 1Gi RWO Retain Available nfs 14s

5、回收策略已经变为 Retain,通过下面步骤验证其效果:

[root@ren7 yaml]# kubectl apply -f nfs-pvc1.yml
persistentvolumeclaim/mypvc1 created
[root@ren7 yaml]#
[root@ren7 yaml]# kubectl get pod
No resources found.
[root@ren7 yaml]# kubectl apply -f pod1.yml
pod/mypod1 created
[root@ren7 yaml]# kubectl get pod -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
mypod1 1/1 Running 0 10s 172.20.72.159 192.168.11.5 <none> <none>
[root@ren7 yaml]# kubectl exec mypod1 touch /mydata/nihao
[root@ren7 yaml]# kubectl delete pod mypod1
pod "mypod1" deleted
[root@ren7 yaml]# kubectl delete pvc mypvc1
persistentvolumeclaim "mypvc1" deleted
[root@ren7 yaml]# kubectl get pv
NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE
mypv1 1Gi RWO Retain Released default/mypvc1 nfs 6m51s

[root@ren7 yaml]# kubectl get pvc
  No resources found.
  [root@ren7 yaml]# kubectl get pod
  No resources found.

  ① 重新创建 mypvc1。

  ② 在 mypv1 中创建文件 nihao。

  ③ mypv1 状态变为 Released。

  ④ Kubernetes 并没有启动 Pod recycler-for-mypv1。

  ⑤ PV 中的数据被完整保留。

(6)我们再看 NFS 服务器目录 /nfsdata/pv1 中数据还保留。

[root@ren7 nfsdata]# ls
pv1
[root@ren7 nfsdata]# ls pv1/
nihao

(7)虽然 mypv1 中的数据得到了保留,但其 PV 状态会一直处于 Released,不能被其他 PVC 申请。

[root@ren7 yaml]# kubectl get pv
NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE
mypv1 1Gi RWO Retain Released default/mypvc1 nfs 10m

(8)为了重新使用存储资源,可以删除并重新创建 mypv1。删除操作只是删除了 PV 对象,存储空间中的数据并不会被删除。

  新建的 mypv1 状态为 Available,已经可以被 PVC 申请。

[root@ren7 yaml]# kubectl delete pv mypv1
persistentvolume "mypv1" deleted
[root@ren7 yaml]# kubectl apply -f nfs-pv1.yml
persistentvolume/mypv1 created
[root@ren7 yaml]# kubectl get pv
NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE
mypv1 1Gi RWO Retain Available nfs 6s

  PV 还支持 Delete 的回收策略,会删除 PV 在 Storage Provider 上对应存储空间。NFS 的 PV 不支持 Delete,支持 Delete 的 Provider 有 AWS EBS、GCE PD、Azure Disk、OpenStack Cinder Volume 等。

四、PV的动态供给

1、pv的供给方式

  前面的例子中,我们提前创建了 PV,然后通过 PVC 申请 PV 并在 Pod 中使用,这种方式叫做静态供给(Static Provision)。

  与之对应的是动态供给(Dynamical Provision),即如果没有满足 PVC 条件的 PV,会动态创建 PV。相比静态供给,动态供给有明显的优势:不需要提前创建 PV,减少了管理员的工作量,效率高。

  动态供给是通过 StorageClass 实现的,StorageClass 定义了如何创建 PV

2、pv动态供给举例

  StorageClass standard:

  StorageClass slow:

  这两个 StorageClass 都会动态创建 AWS EBS,不同在于 standard 创建的是 gp2 类型的 EBS,而 slow 创建的是 io1 类型的 EBS。不同类型的 EBS 支持的参数可参考 AWS 官方文档。

  StorageClass 支持 Delete 和 Retain 两种 reclaimPolicy,默认是 Delete。

  与之前一样,PVC 在申请 PV 时,只需要指定 StorageClass 和容量以及访问模式,比如:

  除了 AWS EBS,Kubernetes 支持其他多种动态供给 PV 的 Provisioner,完整列表请参考 https://kubernetes.io/docs/concepts/storage/storage-classes/#provisioner

五、pv、pvc无法删除问题

   一般的删除步骤为:先删除pod再删除pvc最后删除pv。

  但是遇到pv始终处于“Terminating”状态,而且delete不掉。

解决办法:

  直接删除k8s中的记录:

kubectl patch pv xxx -p '{"metadata":{"finalizers":null}}'

  参考信息:

This happens when persistent volume is protected. You should be able to cross verify this:
Command:
kubectl describe pvc PVC_NAME | grep Finalizers
Output:
Finalizers: [kubernetes.io/pvc-protection]
You can fix this by setting finalizers to null using kubectl patch:
kubectl patch pvc PVC_NAME -p '{"metadata":{"finalizers": []}}' --type=merge

NFS PersistentVolume(11)的更多相关文章

  1. NFS PersistentVolume(8)

    一.部署nfs服务端: k8s-master 节点上搭建了 NFS 服务器 (1)安装nfs服务: yum install -y nfs-utils rpcbind vim /etc/exports ...

  2. Netruon 理解(11):使用 NAT 将 Linux network namespace 连接外网

    学习 Neutron 系列文章: (1)Neutron 所实现的虚拟化网络 (2)Neutron OpenvSwitch + VLAN 虚拟网络 (3)Neutron OpenvSwitch + GR ...

  3. 基于MVC4+EasyUI的Web开发框架经验总结(11)--使用Bundles处理简化页面代码

    在Web开发的时候,我们很多时候,需要引用很多CSS文件.JS文件,随着使用更多的插件或者独立样式文件,可能我们的Web界面代码会越来越臃肿,看起来也很累赘,在MVC里面提供了一个Bundle的对象, ...

  4. Python的平凡之路(11)

    一. rabbitmq 1 进程Queue:  父进程与子进程进行交互,或者同属于同一父进程下多个子进程进行交互 2 队列通信:   send1.py #!/usr/bin/env python#Au ...

  5. spring 第一篇(1-1):让java开发变得更简单(下)转

    spring 第一篇(1-1):让java开发变得更简单(下) 这个波主虽然只发了几篇,但是写的很好 上面一篇文章写的很好,其中提及到了Spring的jdbcTemplate,templet方式我之前 ...

  6. Web 在线文件管理器学习笔记与总结(11)获取文件夹信息 (12)返回上一级操作

    (11)获取文件夹信息 文件夹没有修改操作. index.php: <?php require 'dir.func.php'; require 'file.func.php'; require ...

  7. MS CRM 2011的自定义和开发(11)——插件(plugin)开发(三)

    http://www.cnblogs.com/StoneGarden/archive/2012/02/06/2340661.html MS CRM 2011的自定义和开发(11)——插件(plugin ...

  8. MS CRM 2011的自定义和开发(11)——插件(plugin)开发(四)

    http://www.cnblogs.com/StoneGarden/archive/2012/02/08/2343294.html MS CRM 2011的自定义和开发(11)——插件(plugin ...

  9. MS CRM 2011的自定义和开发(11)——插件(plugin)开发(一)

    http://www.cnblogs.com/StoneGarden/archive/2012/02/02/2336147.html MS CRM 2011的自定义和开发(11)——插件(plugin ...

随机推荐

  1. 使用 nodejs 中的 http 模块实现几个超实用的工具

    nodejs 方便了我们前端开发者进行一些服务端上的操作,可以进行无缝地衔接.像其他一些后端语言,如 php, golang, java 等,都需要一定的学习成本,而 nodejs 则就是为前端开发者 ...

  2. 软工案例分析之OJ

    项目 内容 这个作业属于哪个课程 2021春季计算机学院软件工程(罗杰 任健) 这个作业的要求在哪里 案例分析作业要求 我在这个课程的目标是 和我的团队开发一个真正的软件,一起提升开发与合作的能力 这 ...

  3. Web协议详解与抓包实战,高效解决网络难题

    无论你是前后端工程师,还是运维测试,如果想面试更高的职位,或者要站在更高的角度去理解技术业务架构,并能在问题出现时快速.高效地解决问题,Web 协议一定是你绕不过去的一道坎. 旨在帮助你对各种常用 W ...

  4. 宝塔linux7.4.2/windows6.8 的版本中的安全随笔

    在2020/8.23宝塔官方发布了一条关于宝塔linux7.4.2和Windows6.8版本中存在的重大的安全隐患 通知来源https://www.bt.cn/bbs/thread-54644-1-1 ...

  5. 中小型前端团队代码规范工程化最佳实践 - ESLint

    前言 There are a thousand Hamlets in a thousand people's eyes. 一千个程序员,就有一千种代码风格.在前端开发中,有几个至今还在争论的代码风格差 ...

  6. python中栈的实现

    栈是一种线性数据结构,用先进后出或者是后进先出的方式存储数据,栈中数据的插入删除操作都是在栈顶端进行,常见栈的函数操作包括 empty() – 返回栈是否为空 – Time Complexity : ...

  7. Java(65-80)【方法、数组】

    1.方法的三种调用:单独调用.打印调用.赋值调用 单独调用就是调用方法并不进行输出: 打印调用就是对方法进行输出 赋值调用就是将结果赋值给一个变量再进行输出 void是没有返回值的,因此只能进行赋值单 ...

  8. electron项目踩坑--A JavaScript error occurred in the main process:document is not defined

    前言 记录electron-vue项目开发中遇到的一个错误,运行时报错如图: 控制台报错如下: ReferenceError: document is not defined at Object.&l ...

  9. ML.NET 示例:图像分类模型训练-首选API(基于原生TensorFlow迁移学习)

    ML.NET 版本 API 类型 状态 应用程序类型 数据类型 场景 机器学习任务 算法 Microsoft.ML 1.5.0 动态API 最新 控制台应用程序和Web应用程序 图片文件 图像分类 基 ...

  10. 【SpringBoot】SpringBoot 处理后端返回的小数(全局配置 + 定制化配置)

    一.抛出问题: 现在的项目中,存在这样的几个问题: 问题一.数据库存的数据类型是BigDecimal,或者代码中计算需要返回BigDecimal的值,由于BigDecimal返回给前端可能存在精度丢失 ...