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网络存储应用的更多相关文章

  1. Kubernetes 存储卷管理 PV&PVC(十)

    目录 一.emptyDir 二.hostPath 三.PV & PVC 1.NFS PersistentVolume 2.创建 PVC 3.创建 Pod 进行挂载 为了持久化保存容器的数据,可 ...

  2. k8s-数据持久化存储卷,nfs,pv/pvc

    目录 数据持久化-储存卷 官方文档 存储卷类型 1.emptyDir 2.hostpath 3.pv/pvc(推荐使用) nfs官方文档 安装测试nfs pv/pvc管理nfs 官方文档 pv/pvc ...

  3. 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 ...

  4. 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. ...

  5. k8s教程:Kubernetes集群使用网络存储NFS

    NFS存储 NFS即网络文件系统Network File System,它是一种分布式文件系统协议,最初是由Sun MicroSystems公司开发的类Unix操作系统之上的一款经典网络存储方案,其功 ...

  6. [Kubernetes]PV,PVC,StorageClass之间的关系详解

    在Kubernetes中,容器化一个应用比较麻烦的地方莫过于对其"状态"的管理,而最常见的"状态",莫过于存储状态. 在[Kubernetes]深入理解Stat ...

  7. Kubernetes Pv & Pvc

    Kubernetes PV & pvc 介绍 PersistentVolume(pv)和PersistentVolumeClaim(pvc)是k8s提供的两种API资源,用于抽象存储细节.管理 ...

  8. io.fabric8.kubernetes对pv和pvc的增删查改

    1.新建maven项目k8stest,pom.xml如下: <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns: ...

  9. kubernetes Value:将磁盘挂载到容器,PV,PVC

    6.1.介绍卷 6.1.1.卷的类型 emptyDir-用于存储临时数据的简单空目录 hostPath-用于将目录从工作节点的文件系统挂载到pod nfs-挂载到pod中的NFS共享卷. 还有其他的如 ...

随机推荐

  1. Java实现 LeetCode 27 移除元素

    27. 移除元素 给定一个数组 nums 和一个值 val,你需要原地移除所有数值等于 val 的元素,返回移除后数组的新长度. 不要使用额外的数组空间,你必须在原地修改输入数组并在使用 O(1) 额 ...

  2. Java实现网格中移动字母

    2x3=6个方格中放入ABCDE五个字母,右下角的那个格空着.如图[1.jpg]所示. 和空格子相邻的格子中的字母可以移动到空格中,比如,图中的C和E就可以移动,移动后的局面分别是: A B D E ...

  3. Linux RPM管理命令

    RPM安装 rpm -ivh 包全名,其中,-i 表示安装,-v 表示显示详细信息,-h 表示显示进度 手动安装会有很多包依赖需要解决,如果是模块依赖,可以使用rpmfind进行查询解决 RPM升级 ...

  4. 第一次使用Genymotion遇到的问题:for an unknown reson,VirtualBox DHCP has not assigned an IP address to virtual

    解决方案:http://www.aiuxian.com/article/p-554135.html

  5. 【经验心得】谈一谈我IT行业未来的方向

    随着科技的发展,越来越多的入门行业将被淘汰,其实淘汰的不仅仅是工厂.环卫工人.普工这些无技术含量的工作,有一些运维.编辑等低门槛的行业也将被淘汰,这也是我这两年看互联网发展趋势得出来的结论,人类要想发 ...

  6. SpringBoot与(Security)安全

    1.简介 应用程序的两个主要区域 认证(Authentication): 是建立一个它声明的主体的过程(一个"主体" 一般是指用户,设备或一些可以在你的应用程序中执行动作的其他系统 ...

  7. 懒羊羊找朋友(struct实现优先排序)

    4907: 懒羊羊找朋友(点击) 时间限制: 1 Sec  内存限制: 128 MB                                                           ...

  8. 设计模式系列之工厂模式三兄弟(Factory Pattern)

    说明:设计模式系列文章是读刘伟所著<设计模式的艺术之道(软件开发人员内功修炼之道)>一书的阅读笔记.个人感觉这本书讲的不错,有兴趣推荐读一读.详细内容也可以看看此书作者的博客https:/ ...

  9. 使用Apache Spark和Apache Hudi构建分析数据湖

    1. 引入 大多数现代数据湖都是基于某种分布式文件系统(DFS),如HDFS或基于云的存储,如AWS S3构建的.遵循的基本原则之一是文件的"一次写入多次读取"访问模型.这对于处理 ...

  10. IDEA Gradle项目控制台输出乱码

    idea 更新到2019.2.3没有这个选项. 可以点击 help->edit custom vm options 然后加上 -Dfile.encoding=utf-8 重启一下就好了