09 . Kubernetes之pv、pvc及使用nfs网络存储应用
PV,PVC概述
PV的全称是: PersistentVolume (持久化卷),是对底层的共享存储的一种抽象,PV由管理员进行创建和配置,它和具体的底层的共享存储技术的实现方式有关,比如Ceph、GlusterFS、NFS等,都是通过插件机制完成与共享存储的对接.
PVC的全称是: PersistenVolumeClaim (持久化卷声明),PVC是用户存储的一种声明,PVC和Pod比较类型,Pod是消耗节点,PVC消耗的是PV资源,Pod可以请求CPU的内存,而PVC可以请求特定的存储空间和访问模式。对于真正存储的用户不需要关心底层的存储实现细节,只需要直接使用PVC即可.
但是通过PVC请求一定的存储空间也很有可能不足以满足对于存储设备的各种需求,而且不同的应用程序对于存储性能的要求也能也不尽相同,比如读写速度、并发性能等,为了解决这一问题,Kubernetes又为我们引入了一个新的资源对象: StorageClass,通过StorageClass的定义,管理员可以将存储资源定义为某种类型的资源,比如快速存储、慢速存储等,用户根据StorageClass的描述就可以非常直观的知道各种存储资源特性了,这样就可以根据应用的特性去申请合适的存储资源了.
PV和PVC生命周期
PV可以看作可用的存储资源,PVC则是对存储资源的需求,PV和PVC的互相关系遵循如下图

资源供应
Kubernetes支持两种资源的供应模式:静态模式(Staic)和动态模式(Dynamic)。资源供应的结果就是创建好的PV.
静态模式: 管理员手工创建许多PV,在定义PV时需要将后端存储的特性进行设置
动态模式: 管理员无需手动创建PV,而是通过StorageClass的设置对后端存储进行描述,标记为某种"类型(Class)",此时要求PVC对存储的类型进行声明,系统将自动完成PV的创建及PVC的绑定,PVC可以声明为Class为"",说明该PVC禁止使用动态模式
资源绑定(Binding)
在用户定义好PVC后,系统将根据PVC对存储资源的请求(存储空间和访问模式)在已存在的PV中选择一个满足PVC要求的PV,一旦找到,就将PV与用户定义的PVC进行绑定,然后用户的应用就可以使用这个PVC了。如果系统中没有满足PVC要求的PV,PVC则会无限期处于Pending状态,直到等到系统管理员创建了一个符合要求的PV。PV一旦绑定在某个PVC上,就被这个PVC独占,不能再与其他PVC进行绑定了。在这种情况下,当PVC申请的存储空间比PV的少时,整个PV的空间都能够为PVC所用,可能会造成资源的浪费。如果资源供应使用的是动态模式,则系统在PVC找到合适的StorageClass后,将会自动创建PV并完成PVC的绑定
资源使用(Using)
Pod 使用volume的定义,将PVC挂载到容器内的某个路径进行使用。volume的类型为persistentVoulumeClaim,在容器应用挂载了一个PVC后,就能被持续独占使用。不过,多个Pod可以挂载同一个PVC,应用程序需要考虑多个实例共同访问一块存储空间的问题
资源释放(Releasing)
当用户对存储资源使用哪个完毕后,用户可以删除PVC,与该PVC绑定的PV将会被标记为已释放,但还不能立刻与其他PVC进行绑定。通过之前PVC写入的数据可能还留在存储设备上,只有在清除之后该PV才能继续使用.
资源回收(Reclaiming)
对于PV,管理员可以设定回收策略(Reclaim Policy)用于设置与之绑定的PVC释放资源之后,对于遗留数据如何处理。只有PV的存储空间完成回收,才能供新的PVC绑定和使用。
1 . 静态资源下,通过PV和PVC完成绑定,并供Pod使用的存储管理机制

2 . 动态资源下,通过StorageClass和PVC完成资源动态绑定(系统自动生成PV,并供Pod使用的存储管理机制

存储卷概述
由于容器本身是非持久化的,因此需要解决在容器中运行应用程序遇到的一些问题。首先,当容器崩溃时,kubelet将重新启动容器,但是写入容器的文件将会丢失,容器将会以镜像的初始状态重新开始;第二,在通过一个Pod中一起运行的容器,通常需要共享容器之间一些文件。Kubernetes通过存储卷解决上述的两个问题。
在Docker有存储卷的概念卷,但Docker中存储卷只是磁盘的或另一个容器中的目录,并没有对其生命周期进行管理。Kubernetes的存储卷有自己的生命周期,它的生命周期与使用的它Pod生命周期一致。因此,相比于在Pod中运行的容器来说,存储卷的存在时间会比的其中的任何容器都长,并且在容器重新启动时会保留数据。当然,当Pod停止存在时,存储卷也将不再存在。在Kubernetes支持多种类型的卷,而Pod可以同时使用各种类型和任意数量的存储卷。在Pod中通过指定下面的字段来使用存储卷:
spec.volumes: 通过此字段提供指定的存储卷
spec.containers.volumeMounts: 通过此字段将存储卷挂载到容器中
存储卷类型和示例
当前Kubernetes支持如下所列的存储卷类型,并以hostPath、nfs和persistentVolumeClaim类型的存储卷为例,介绍如何定义存储卷,以及如何在Pod中被使用.
* awsElasticBlockStore
* azureDisk
* azureFile
* cephfs
* configMap
* csi
* downwardAPI
* emptyDir
* fc (fibre channel)
* flocker
* gcePersistentDisk
* gitRepo
* glusterfs
* hostPath
* iscsi
* local
* nfs
* persistentVolumeClaim
* projected
* portworxVolume
* quobyte
* rbd
* scaleIO
* secret
* storageos
* vsphereVolume
xample1 EmptyDir(两个Pod目录互相挂载)
EmptyDir是一个空目录,他的生命周期和所属的Pod是完全一致的,他用处是把同一Pod内的不同容器之间共享工作过程产生的文件,
apiVersion: v1
kind: Pod
metadata:
name: test-pd
spec:
containers:
- image: gcr.io/google_containers/test-webserver
name: test-container
volumeMounts:
- mountPath: /cache
name: cache-volume
volumes:
- name: cache-volume
emptyDir: {}
mkdir /storage
cd /storage
mkdir volumes
cat pod.vol.demo.yaml
apiVersion: v1
kind: Pod
metadata:
name: pod-demo
namespace: default
labels:
app: myapp
tier: frontend
annotations:
youmen.com/created-by: "youmen admin"
spec:
containers:
- name: myapp
image: ikubernetes/myapp:v1
imagePullPolicy: IfNotPresent
ports:
- name: http
containerPort: 80
volumeMounts:
- name: html
mountPath: /usr/share/nginx/html/
- name: busybox
image: busybox:latest
imagePullPolicy: IfNotPresent
volumeMounts:
- name: html
mountPath: /data/
command: ['/bin/sh', '-c']
args:
- 'while true; do echo $(date) >> /data/index.html; sleep 3; done'
volumes:
- name: html
emptyDir: {}
curl 10.244.3.34 -s
Tue Dec 24 15:37:09 UTC 2019
Tue Dec 24 15:37:12 UTC 2019
Tue Dec 24 15:37:15 UTC 2019
Tue Dec 24 15:37:18 UTC 2019
Tue Dec 24 15:37:21 UTC 2019
Tue Dec 24 15:37:24 UTC 2019
Example2 HostPath(主机目录挂载)
依赖于node,这种会把宿主机的指定卷加载到容器之中,实现数据持久,但是如果Pod发生跨主机的重建,内容很难保证,或者Node节点宕机了
这种卷一般和DaemonSet搭配使用,用来操作主机文件,例如进行日志采集的FLK的FluentD就采用这种方式,加载主机的容器日志目录,达到收集本机所有日志的目的
# hostPath
# 将Pod里面的目录内容绑定到宿主机目录,Pod删除并不到导致宿主机删除.
# 如果指定宿主机目录不存在要不要先创建取决于type
cat pod-volhost.demo.yaml
apiVersion: v1
kind: Pod
metadata:
name: pod-vol-hostpath
namespace: default
spec:
containers:
- name: myapp
image: ikubernetes/myapp:v1
volumeMounts:
- name: html
mountPath: /usr/share/nginx/html/
volumes:
- name: html
hostPath:
path: /data/pod/volume1
type: DirectoryOrCreate
echo youmen >> /data/pod/volume1/index.html
kubectl get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
pod-vol-hostpath 1/1 Running 0 3m49s 10.244.3.35 node1 <none> <none>
curl 10.244.3.35
youmen
# 我们删除Pod,可以到Node主机查看目录,依然存在.
[root@node1 ~]# cat /data/pod/volume1/index.html
youmen
Example3(NFS共享存储)
# 找集群外的一台机器做NFS
hostnamectl set-hostname stor01
echo 172.19.0.18 stor01 >> /etc/hosts
yum -y install nfs-utils
mkdir -pv /data/volumes
echo nfs >> /data/volumes/index.html
vim /etc/exports
/data/volumes 172.19.0.0/16(rw,no_root_squash)
systemctl start nfs
# 切换到k8s集群内的节点挂载存储卷
yum -y install nfs-utils
echo 172.19.0.18 stor01 >> /etc/hosts
# 挂载测试以下,然后umount掉,待会创建Pod自动会挂载
mount -t nfs stor01:/data/volumes /mnt
cat pod-volnfs.demo.yaml
apiVersion: v1
kind: Pod
metadata:
name: pod-volnfs-demo
namespace: default
spec:
containers:
- name: myapp
image: ikubernetes/myapp:v1
volumeMounts:
- name: html
mountPath: /usr/share/nginx/html/
volumes:
- name: html
nfs:
path: /data/volumes
server: stor01
kubectl get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
pod-volnfs-demo 1/1 Running 0 20s 10.244.1.49 node2 <none> <none>
curl 10.244.1.49
nfs
# 可以删除Pod再创建数据依然存在,哪怕节点宕掉依然数据不会丢失,但是当挂载的数据,Pod多了,效果就不尽人意了
Pv和Pvc

Pv和Pvc是K8s的一种标准资源,Pvc被Pv调用后就会被绑定起来,取决于用户怎么绑,
kubectl explain explain pvc.spec
FIELDS:
accessModes <[]string>
AccessModes contains the desired access modes the volume should have. More
info:
https://kubernetes.io/docs/concepts/storage/persistent-volumes#access-modes-1
dataSource <Object>
This field requires the VolumeSnapshotDataSource alpha feature gate to be
enabled and currently VolumeSnapshot is the only supported data source. If
the provisioner can support VolumeSnapshot data source, it will create a
new volume and data will be restored to the volume at the same time. If the
provisioner does not support VolumeSnapshot data source, volume will not be
created and the failure will be reported as an event. In the future, we
plan to support more data source types and the behavior of the provisioner
may change.
resources <Object>
Resources represents the minimum resources the volume should have. More
info:
https://kubernetes.io/docs/concepts/storage/persistent-volumes#resources
selector <Object>
A label query over volumes to consider for binding.
storageClassName <string>
Name of the StorageClass required by the claim. More info:
https://kubernetes.io/docs/concepts/storage/persistent-volumes#class-1
volumeMode <string>
volumeMode defines what type of volume is required by the claim. Value of
Filesystem is implied when not included in claim spec. This is a beta
feature.
volumeName <string>
VolumeName is the binding reference to the PersistentVolume backing this
claim.
Example4(创建多个Pvc)
因为pvc属于集群资源级别的不能定义在名成空间
mkdir v{1,2,3,4,5}
exportfs -arv
exporting 172.19.0.0/16:/data/volumes/v5
exporting 172.19.0.0/16:/data/volumes/v4
exporting 172.19.0.0/16:/data/volumes/v3
exporting 172.19.0.0/16:/data/volumes/v2
exporting 172.19.0.0/16:/data/volumes/v1
showmount -e
Export list for stor01:
/data/volumes/v5 172.19.0.0/16
/data/volumes/v4 172.19.0.0/16
/data/volumes/v3 172.19.0.0/16
/data/volumes/v2 172.19.0.0/16
/data/volumes/v1 172.19.0.0/16
切换到k8s控制节点
cat pod-pv.yaml
apiVersion: v1
kind: PersistentVolume
metadata:
name: pv001
labels:
name: pv001
spec:
nfs:
path: /data/volumes/v1
server: stor01
accessModes: ["ReadWriteMany","ReadWriteOnce"]
capacity:
storage: 2Gi
---
apiVersion: v1
kind: PersistentVolume
metadata:
name: pv002
labels:
name: pv002
spec:
nfs:
path: /data/volumes/v2
server: stor01
accessModes: ["ReadWriteMany","ReadWriteOnce"]
capacity:
storage: 4Gi
---
apiVersion: v1
kind: PersistentVolume
metadata:
name: pv003
labels:
name: pv003
spec:
nfs:
path: /data/volumes/v3
server: stor01
accessModes: ["ReadWriteMany","ReadWriteOnce"]
capacity:
storage: 4Gi
kubectl apply -f pod-pvc.yaml
查看Pv
kubectl get pv
NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE
pv001 2Gi RWO,RWX Retain Available 87s
pv002 4Gi RWO,RWX Retain Available 87s
pv003 4Gi RWO,RWX Retain Available 87s
创建pvc然后绑定pv
cat pod-vol-pvc.yaml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: mypvc
namespace: default
spec:
accessModes: ["ReadWriteMany"]
resources:
requests:
storage: 2Gi
---
apiVersion: v1
kind: Pod
metadata:
name: pod-vol-pvc
namespace: default
spec:
containers:
- name: myapp
image: ikubernetes/myapp:v1
volumeMounts:
- name: html
mountPath: /usr/share/nginx/html/
volumes:
- name: html
persistentVolumeClaim:
claimName: mypvc
kubectl get pv
NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE
pv001 4Gi RWO,RWX Retain Available 43s
pv002 4Gi RWX Retain Bound default/mypvc 43s
pv003 4Gi RWO,RWX Retain Available 43s
kubectl get pvc
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE
mypvc Bound pv002 4Gi RWX 106s
pvc创建在pv之上,而且指定的空间大小不能超过pv大小,否则一直Pending挂起
NFS存储的缺点
不支持动态创建持久卷,只能手工创建
先手工创建PV,再通过PV手工创建PVC,PVC就是真正可用的持久卷PVC是和PV进行绑定的:
PVC会根据自己需求空间的大小自动选择合适的PV,比如需要一个5G的PVC,PV分别为2G,7G和10G,那么PVC会自动选择7G的,但是剩余的空间不是浪费了么?原因如下:
一个被绑定的PV只能用于一个PVC,他们是一对一绑定的,如果PVC大小只需要5G,但是所选的PV有7G,那么剩余的2G是没办法使用的,如果不想这样浪费空间只能使用动态创建的方式.
09 . Kubernetes之pv、pvc及使用nfs网络存储应用的更多相关文章
- Kubernetes 存储卷管理 PV&PVC(十)
目录 一.emptyDir 二.hostPath 三.PV & PVC 1.NFS PersistentVolume 2.创建 PVC 3.创建 Pod 进行挂载 为了持久化保存容器的数据,可 ...
- k8s-数据持久化存储卷,nfs,pv/pvc
目录 数据持久化-储存卷 官方文档 存储卷类型 1.emptyDir 2.hostpath 3.pv/pvc(推荐使用) nfs官方文档 安装测试nfs pv/pvc管理nfs 官方文档 pv/pvc ...
- 8.3 k8s部署jenkins,通过pv/pvc结合NFS服务器持久化
1.制作jenkins docker镜像 1.1 下载jenkins wget https://mirrors.tuna.tsinghua.edu.cn/jenkins/war-stable/2.30 ...
- 8.1 k8s使用PV/PVC做数据持久化运行redis服务,数据保存至NFS
1.制作redis docker镜像 1.1 准备alpine基础镜像 # 下载 docker pull alpine:3.13 # 更改tag docker tag alpine:3.13 192. ...
- k8s教程:Kubernetes集群使用网络存储NFS
NFS存储 NFS即网络文件系统Network File System,它是一种分布式文件系统协议,最初是由Sun MicroSystems公司开发的类Unix操作系统之上的一款经典网络存储方案,其功 ...
- [Kubernetes]PV,PVC,StorageClass之间的关系详解
在Kubernetes中,容器化一个应用比较麻烦的地方莫过于对其"状态"的管理,而最常见的"状态",莫过于存储状态. 在[Kubernetes]深入理解Stat ...
- Kubernetes Pv & Pvc
Kubernetes PV & pvc 介绍 PersistentVolume(pv)和PersistentVolumeClaim(pvc)是k8s提供的两种API资源,用于抽象存储细节.管理 ...
- io.fabric8.kubernetes对pv和pvc的增删查改
1.新建maven项目k8stest,pom.xml如下: <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns: ...
- kubernetes Value:将磁盘挂载到容器,PV,PVC
6.1.介绍卷 6.1.1.卷的类型 emptyDir-用于存储临时数据的简单空目录 hostPath-用于将目录从工作节点的文件系统挂载到pod nfs-挂载到pod中的NFS共享卷. 还有其他的如 ...
随机推荐
- Java实现 蓝桥杯VIP 算法训练 拦截导弹
1260:[例9.4]拦截导弹(Noip1999) 时间限制: 1000 ms 内存限制: 65536 KB 提交数: 4063 通过数: 1477 [题目描述] 某国为了防御敌国的导弹袭击,发展出一 ...
- Java实现 LeetCode 200 岛屿数量
200. 岛屿数量 给定一个由 '1'(陆地)和 '0'(水)组成的的二维网格,计算岛屿的数量.一个岛被水包围,并且它是通过水平方向或垂直方向上相邻的陆地连接而成的.你可以假设网格的四个边均被水包围. ...
- java实现巧排扑克牌
** 巧排扑克牌** 小明刚上小学,学会了第一个扑克牌"魔术",到处给人表演.魔术的内容是这样的: 他手里握着一叠扑克牌:A,2,-J,Q,K 一共13张.他先自己精心设计它们的顺 ...
- 小菜成长之路,警惕沦为 API 调用侠
小菜(化名)在某互联网公司担任运维工程师,负责公司后台业务的运维保障工作.由于自己编程经验不多,平时有不少工作需要开发协助. 听说 Python 很火,能快速开发一些运维脚本,小菜也加入 Python ...
- numpy.random.randn()与numpy.random.rand()的区别
numpy中有一些常用的用来产生随机数的函数,randn()和rand()就属于这其中. numpy.random.randn(d0, d1, …, dn)是从标准正态分布中返回一个或多个样本值. n ...
- SpringMVC+Mybatis初尝试
一个月前简单学完了SpringMVC框架和Mybatis框架,一直没有使用过,今天主要用它做了个简单的学生管理系统,不过第一次用框架,实现的功能简单,比较low. 注:这里使用的数据库是SQLServ ...
- Java StringTokenizer 类使用方法,字符串分割
Java StringTokenizer 属于 java.util 包,用于分隔字符串. StringTokenizer 构造方法: StringTokenizer(String str) :构造一个 ...
- 基于 abp vNext 和 .NET Core 开发博客项目 - Blazor 实战系列(四)
系列文章 基于 abp vNext 和 .NET Core 开发博客项目 - 使用 abp cli 搭建项目 基于 abp vNext 和 .NET Core 开发博客项目 - 给项目瘦身,让它跑起来 ...
- CSS里盒子模型中【margin垂直方向边界叠加】问题及解决方案
边界重叠是指两个或多个盒子(可能相邻也可能嵌套)的相邻边界(其间没有任何非空内容.补白.边框)重合在一起而形成一个单一边界. 两个或多个块级盒子的垂直相邻边界会重合. 如果都是正边界,结果的边界宽度是 ...
- [noi.ac省选模拟赛]第12场题解集合
题目 比赛界面. T1 数据范围明示直接\(O(n^2)\)计算,问题就在如何快速计算. 树上路径统计通常会用到差分方法.这里有两棵树,因此我们可以做"差分套差分",在 A 树上对 ...