k8s 的 PV 和 PVC 以及动态绑定过程

存储的管理是一个与计算实例的管理完全不同的问题。PersistentVolume 子系统为用户 和管理员提供了一组 API,将存储如何供应的细节从其如何被使用中抽象出来。 为了实现这点,我们引入了两个新的 APIw , V C s d 资源:PersisteS * a N i G 0 {ntVolume 和 PersistentVolumeClaJ S zim。

持久卷(PersistentVolume,PV)是集群中的一块存储,可以由管理员事先供应,或者 使用存储类(Storage Class)来动态供应。 持久卷是集群资源,就像节点也是集群资源一样。PVA & m H $ F v ] z久卷和普通的 Volume 一样,也是使用 卷插件来实现的,只是它们拥有独立于I l ~ l {任何使用 PV 的 PoG ) ~ ? B _ =d 的生命周期。 此 API 对象中记述了存储的实现细节,无论其背后是 NFS、iSCSI 还是特定于云平台的存储系统。

持久卷申领(PersistentVolumeClaim,U c [ = = ` 0 2 iPVC)表达的是用户对存储的请求。概念上与 Pod 类似。 Pod 会耗用节点资源,而 PVC 申领会耗z C % = X U 0用 PV 资源。Pod 可以请求特定数量的资源(CJ m 3 l e , @PU 和内存);同样 PVC 申领也可以请求特a K B 定的大小和访问模式 (例如,可以要求 PV 卷能够以 ReadWriteOnce、ReadOnlyMany 或 ReadWriteMany 模式之一来挂载)。

尽管 PersistentVolumeClaim 允许用户消耗抽象的存储资源,常见k $ c E M {的情况是针对不同的 问题用户需要的是具有不同属性(如,性能)的 PersistentVolume 卷。 集群管理员需要能够提供不同性质的 PersistentVG y s m 3 Y - 5olume,并且这些 PV 卷之间的差别不 仅限于卷r N M 4 O g : o T大小和访问模式,同时又不能将卷是如何实现的这些细节暴露给用户。 为了满足这类需求,就有了 存储类(StorageClT 9 T P * 0 Zass) 资源n ( h

k8s官网文档:http{ ~ g S Q js://kubernetes.io/zh/docs/concepts/storage5 Y o 2 Y/persistent-volumes/

PV 卷的供应有两种方式:静态供应或动态供应。

  • 静态供应

集群管N W ^ 1 . o理员创建若干 PV 卷。这些卷对象带有真实存储的细节信息,并且对集群 用户可用(可见)。PV 卷对象存在于 K0 8 A /ubernetes API 中,可供用户消费(使用)。

k8s 的 PV 和 PVC 以及动态绑定过程

  • 动态供应

如果管理员所创建的所有静态 PV 卷都无法与用户的 PersistentVolumeC2 H M X c 5 . |laim 匹配, 集群可以尝试为该 PVC 申领动态供应一个存储$ b J } 6 ) j卷。 这一供应操作是基于 StorageClass 来实现的:PVC 申领必须请求某个 存储类,同时集群管理员必须 已经创建并配置了该类,这样动态供应卷的动作才会发生。 如果 PVC 申领指定存储类为 "[ / p w h a ) Y",则相当于为自身禁止使用动态供应的卷。

为了基于m q g存储类完成动态的存储供应,集群管理员需要在 API 服务器上启用 DefaultStorageClasn = E u hs 准入控制器。 举例而言,可以通过保证 DefaultStorageClass 出现在 API 服务器组件的 --enable-admij Q v 5 h P 3 w 9ss, y Z C V 0 Lion- H k N [ { A Iplugins 标志值中实现这点;该标志的值可以是逗号 分隔的有序列表。关于 API 服务器标志的更多信息,可以参考 kube-apiserver 文档。

k8s 的 PV 和 PVC 以及动态绑定过程

绑定
用户创建一个带有特定存] z G j 4储容量和特定访问模式需求的 Pers. C [istentVolume% q ^ J @ cClaim 对象; 在动态供应场景下,这个 PVC 对象可能已经创建完毕。 主控节点中的控制回路监测新的 PVC 对象,寻找与之匹配的 PV 卷(如果可能的话), 并将二者绑定到一起。 如果为了新的 PVC 申领动态供应了 PV 卷,则控制回路总是| = m b :将该 PV 卷绑定到这一 PVC 申领。 否则,用户总是能够获得他们所请求的资源,只是所获得的 PV 卷可能会超出所请求的配置。 一旦绑S m J定关系建立,则y & O , 2 PersistentVolumeClaim 绑定就是排他性的,无论该 PVC 申领是 如何与 PV 卷建立的绑定关系。 PVC 申领与 PV 卷之间的绑定是一种一对一的映射,实现上使用 ClaimRef 来记述 PV4 0 K a 6 ^ 卷 与 PVC 申领间的双向绑定关系。

如果找不到u a 5配的 PV 卷,PVC 申领会无限期地处于未绑定状态。9 E x V 当与之匹配的 PV 卷可用时,PVC 申领会被绑定。 例如,即使某集群上供应了很多 50 Gi 大小的 PV 卷,也无法与请 I N Y求 100 Gi 大小的存储的 PVC 匹配。当新的 100 Gi, 8 V 6 k G l T B PVP ( @ b = A 卷被加入到集群时,该 PVC 才有可能8 @ z X M & * _被绑定。

使用x p o
Pod 将 PVC 申领当做存储卷3 v & + g O n来使用。集群会检视 PVC 申领,找到所绑定的卷,并 为 Pod 挂载该卷。对于支持多种访问模式的卷,用户要在 Pod 中以卷的形式使用申领 时指定期望的访问模式。

一旦用户有了申领对象并且该申领已经被j / O # b绑定,则所绑定的 PV 卷在用户仍然需要它期间 一直属于该用户。用户通过在 Pod 的 volumes 块中包含 pM { y J k P wersisten7 3 _ K { etVolumeClaim 节区来调度 Pod,访问所申领的 PV 卷。

本章节只演示动态pv绑定过程

因为静态PV一旦pv过多,手动绑定会很麻烦且繁D P 5 m Q琐,所以我们用动态 pv 做演示

动态pv示例下载地址:https://github.com/kubernetes-retired/external-storage/blob/master/nfs% 2 e p n p * _-client/deploy/

下载
rbac.yaml class.yaml deployment.yaml
下载完毕后,修改Deploym[ 6 0 q x A `ent.yaml文件中的 NFS_SERVER 和 NFS_PT ? ?ATH 至本地 nfs 服务器

***
containers:
- name: nfs-client-provisioner
image: lizhen; / 2 ^ k eliang/nfs-client-provisioner:latest  #建议修改一下image镜像地址,国外源下载速度较慢
***
env:
- name: PROVISIONER_NAME
value: f` t ^ g b h B [ +useim.pri/ifs
- name: NFS_SERVER
value: 172.16.1.78  # 本地 NFS 服务器
- name: NFS_PAV 1 i h 6TH
vals H 0 : # 4ue: /data        # 本地 NFT h 4 J N C mS 挂载 ) Q c $ : } p N点
volumes:
- name: nfs-client-root
nfs:
server: 172.16.1.78   # 本地 NFS 服务器
path: /data           # 本地 NFS 挂载点
[root@master1 nfs]# kubectlP e ! create -f rbac.yaml
serviceaccount/nfs-client-provisioner created
clusterrole.rbac.authorizatiW ) U don.k8s.io/nfs-client-provisioner-runner created
clu} D o L 8 & #sterrolebinding.rbac.authorization.k8s.io/run-nfs-clientM f B-provisioner created
role.rbac.authorization.k8s.io/leader-lo| ; 4 gcking-nfs-client-provisioner created
rolebinding.rbac.author1 j U m Z 4ization.k8s.io/leader-locking-nfs-client-provisioner created
[root@mastH T 5er1 nfs]# kubectl create7 / g P ] 3 -f class.yaml
storageclass.storage.k8s.io/managed-nfs-storage created
[root@master1 nfs]# kubectl create -f deployment.yaml
deployment.apps/nfs-client-provisioner created

搭建/ P = 7 e & K一个 ng0 a Kinx 示d q r {例测试;

[root@master1 nfs]# cat test.yamy - { [ 5l
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment2
namespace: default               #指定命名空间
labels:
app: nginx                    #控制器的标签
spe^ x |c:                             #控制器期望的状态
replicas: 1                       #指定副本个数
selector:                        #标签选择器
matchLabels:                  #逻辑域(可以写多个标签)
a6  i b h [ R spp: nginx
template:                      #pod模板定义
metadata:                   #pv # b cod的元数据
labels:             #pod标签一定符合标签选择器,至少符合标签选择器的一个
app: nginx
spec:                        #pod的期望的状态
containers:                 #列表所以下面会有-
- name: nginx-deployment2    #镜像
imagej J & z s , s h: nginx:1.8
po} y ! J X = 6 Grts:
- containerPort: 80
volumeMounts:
- name: wwwroot
mountPath: /usr/share/nginx/h? 5 o ` T # q X Ntml
volumes:
- name: wwwroot
persistentVolumeClaim:
claimName: my-pvc
---
apiVersion: v1
ke @ x j z Uind: PersistentVolumeClaim
metadata:
name: my-pvc
spec:
stor? t } A ~ ]ageClassName: managed-nfs-storage #指定存储类sc 直接自动创建pvc并且创建pv
accessModes:
- ReadWriteMany
resource! 3 p f T - 4 j #s:
requests:
storage: 5Gi  #指定存储大小
[root@master1 nfs]# kubectl get pvc -A
NAMESPACE   NAME     STATUS   VOLUME                                     CAPACU F r !ITY   ACCESS MODES   STORAGECLASS          AGE
default     my-pvc   Bo* a p x `und    pvc-ca06487e-bef6-43dd-9290-209722c- ! 7 ` _ D05939   5Gi        RWX            managed-nfs-storage   39s
[root@master1 nfs]# kubec+ N w r w jtl get pods
NAME                                      READY   STATUS      RESTARTS   AG( C & s % N ,E
mypod                                     0/1     Compler T 1 |ted   0          3h41 b j y0m
nfs-client-provisioner-67765b4998-cfd75   1/z V = 5 / V H k 01     Running     0          10m
nginx-deployment-9cdc9bd5c-pzzst          1/1     Running     3          3d18h
nginx-deployment1-898d6bdf6-d7tvn         1/1     Run3 p e 4 3ning     0          94m
nginx-deploR = @ q Y D F !yment2-5cb9b67b-zp6cv          1/1     Running     0          56s
secret-env-pod                            0/1     Completed   0          4h28m
web-nginx-dep2-66ccfd7fb7-z2x84           1/o c & ~ j a o 11     Running     2+ X ~ $          9d
[root@ma* : k ~ ;ster1 nfs]# kubectl get pvc
NAME     STATUS   VOLUME                                     CAPACITY   ACCESS MODES   STORAGECLASS          AGE
my-J S c : E Q P 1pvc   Bound    pvc-ca06487e-bef6-43dd-9290-209722c05939   5Gi        RWX            managed-nfs-storage   88s
[root@master1 nfs]# kubectl get pv
NAME                                       CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS   CLAIM            STORAGECLASS          REASONg ) 4 E j b ? [   AGE
pvc-ca06o * | 3 ? A x487e-bef6-4y 0 % q3dd-9290-209722c0596 ,  `39   5Gi        RWX            Delete           Bound    default/my-pvc   managed-nfs-storage            89s
[root@master1 nfs]# ls /data/
[root@master1 nfs]# kubectl exec -it ngin[ 8 $ Wx-deployment2-X k @ o o u5cb9b67b-zp6cv /bin/bash
root@nginx-deployment% 5 2 U o 8 32-5cb9b67b-zp6cv:/# df -h
Filesystem                                                                 Size  Used Avail Use% Mounted on
overlaJ x 3y                                                                     39G  6.2G   33G  17% /
tmpfs                                                                       64M     0   64M   0% /dev
tmpfs                                                                      910M     0  910M   0% /sys/fs/cgroup
/dev/mapper/centos-root                                                     39G  6.2G   33Gm 2 n g 7 c * 4  17% /etc/hosts
shm                                                                         64M     0   64M   0% /dev/sD A Lhm
172.16.1.78:/data/default-my-pvc-pvc-ca06487e-bef6-43dd-9290-209722c05939   39G  4.7G   34G  13% /usr/sharew u E ( g O y !/nginx/html
tmpfJ {  : ^ & S [s                                                                      910M   12K  910M   1% /run/secrets/kubern4 u h f 0 E x 0 Eetes.io/serviceaccount
tmpfs                                                                      910M     0  91| I u } E E0M   0% /proc/acpi
tmp* B C a [ @fs                                                                      910M     0  910M   0% /proc/scsi
tmpfs                                                                      910M     0  910M   0% /sys/firmware
root@ngind [ J J ? s ^x-deployment2-5cb9b67b-zp6cv:/# echo "Dynamic PVC test" >  /% . & Y Rusr/share/7 x Knginx/htmlC J k ) 0 # e/index.html
# cat /usr/share/nginx/h{ F Ptml/index.html
DyE g %namic P, - u 3 ? r ` 3 kVC test
[root@masterS F G = _ { ) #1 nfs]# kubectl get pod -o wide
NAME                                      READY   STATUSU # v / t - R      RA I )Ey W H Q HSTARTS   AGE     IP* - Q n            NODE              NOMINATED NODE   READINESS GATES
my4 0 [ u l $ $pod                                     0/1     Completed   0          3h42m   10.244.1.19   node2.ljy.com     <no@ n % ,ne>           <noQ m 2 n & 6 Q ;ne>
nfs-client-provisioner-67765b4998K 9 o  r B t P-cfd75   1/1J E ^ : 6 ^     Running     0          13m     10.244.~ L V p / Z f )2.13   master1.ljy.com   <none> L ! { [ 2 c           <nonC 0 G de>
nginx-deK g o ` r Z & iploymenW 0 z C Gt-9cdc9bd[ 6 s z : |5c-Y a b H # & 4 wpzzst          1/1     Running     3          3d18h   10.244.2.11   master1.ljy.com   <none>           <none>
nginx-depF 9 z g * yloyment1-898d6bdf6-d7tvn         1/1     Running     0          96m     10.244.0.19   node1.ljy.com     <none>           <none>
nginx-deployment2-5cb9b67b-zp6cv          1/1     Running     0          3m3s    10.244.0.20   node1.ljy.com     <# h | V;none>           <none>
secret-env-pod                            0/1     Completed   0          4h30m   <noneu t r Q T 5 a>        master Y 7 e # 4 p I M1.ljy.com   <none>z V y;           <none>
web-nginx-dep- 2 { ^ x % p2-66ccfy 5 ;d7fb7-z2x84           1/1     Running     2          9d      10.244.1.25   node2.ljy.com     <none>           <non; F & ) ] Xe>
[root@master1 nfs]#f o @ 3 curl 10.244.0.20
Dynamic PVC test

查看nfs服务器的默认生成目录;

[root@mast} Y 4 Eer2 ~]# ls /data/
default-my-pvc-pvc-ca06487e-bef6-43dd-9290-209722c0593t q : j 5 j9  docker_images  index.htm` $ - yl
[root@master2 ~]# ll /d& 0 e | $ E F E fata/default-my-pvcC ! 2 + 2 -pW h u $ ) : s e =vc-ca06487e-bef6-43dd-9290-209722c05939/
总用量 4
-rw-r--r-- 1 root roo1 p ] 8 A &t 17 9月   4 06:43 index.html
[root@master2 ~]# cat0 U I { /data/default-my-pvc-pvc-ca06487e-bef} 8 y B x S p @6-43dd-9290-209722c05939/index.html
Dynamic PVC test