第六章 将磁盘挂载到容器

1.介绍卷

1.1 什么是卷

卷就相当于一个存储,卷是Pod的一个组成部分,不属于kubernetes对象,所以不能单独创建和删除,Pod中的所有容器都可以使用卷,但是必须先将它挂载到需要访问它的容器中,在每个容器中都可以在自身文件系统的任意位置挂在卷,一个卷可以被多个容器挂载,当pod删除后,卷也将不存在

1.2创建卷并挂载到容器

apiVersion: v1
kind: Pod
metadata:
  name: pod-demo
  namespace: default
  labels:
    app: myapp
    tier: frontend
  annotations:
    magedu.com/create-by: "cluster 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/    #在容器内定义挂载存储名称和挂载路径
      readOnly: true
    command: ['/bin/sh','-c','while true;do echo $(date) >> /data/index.html;sleep 2;done']
  volumes:  #定义存储卷
  - name: html    #定义存储卷名称  
    emptyDir: {}  #定义存储卷类型

第一个容器名为myapp,运行ikubernetes/myapp:v1镜像,名为html的卷将挂载到myapp容器的/usr/share/nginx/html/

第二个容器名为 busybox, 同样挂载到html卷,并且挂载到 /data/ ,并且设置为只读

volumes 定义一个emptyDir卷

验证:

[root@master ~]# k get pods -o wide
NAME       READY   STATUS    RESTARTS   AGE     IP          NODE        NOMINATED NODE   READINESS GATES
pod-demo   2/2     Running   0          6m52s   10.40.0.2   node1.k8s   <none>           <none>

在上面,我们定义了2个容器,其中一个容器是输入日期到index.html中,然后验证访问nginx的html是否可以获取日期。以验证两个容器之间挂载的emptyDir实现共享。如下访问验证:
[root@master ~]# curl 10.40.0.2
Sat Dec 28 15:21:47 UTC 2019
Sat Dec 28 15:21:50 UTC 2019
Sat Dec 28 15:21:52 UTC 2019
Sat Dec 28 15:21:54 UTC 2019
Sat Dec 28 15:21:56 UTC 2019
Sat Dec 28 15:21:58 UTC 2019
Sat Dec 28 15:22:00 UTC 2019
Sat Dec 28 15:22:02 UTC 2019
Sat Dec 28 15:22:04 UTC 2019
Sat Dec 28 15:22:06 UTC 2019
Sat Dec 28 15:22:08 UTC 2019
Sat Dec 28 15:22:10 UTC 2019
Sat Dec 28 15:22:12 UTC 2019

1.3将卷文件储存在内存

  volumes:
  - name: html
    emptyDir: {}
      medium: Memory

1.4使用Git仓库作为储存卷

gitRepo 卷基本上也是一个emptyDir卷,它通过克隆Git仓库并在pod启动时(在创建之前)将git仓文件填充到卷

apiVersion: v1
kind: Pod
metadata: 
  name: gitrepo-volume-pod
spec:
  containers:
  - image: nginx:alpine
    name: web-server
    volumeMounts:
    - name: html
      mountPath: /usr/share/nginx/html
      readOnly: true
    ports:
    - containerPort: 80
      protocol: TCP
  volumes:
  - name: html
    gitRepo:
      repository: https://github.com/luksa/kubia-website-example.git
      revision: master
      directory: .
在创建 pod 时,首先 将卷初始 化为 一 个空目录,然后将制定的 Git 仓库克隆到其中。 如果没有将目 录设置为 .( 句点),存储库将会被克隆到 kubia-website-exampl e示例目录中,远不是我们想要的结果 。 我们预期 将 repo 克隆到卷的根目录中 。 在设置存储库 时,我们还 需要指明让 Kubemetes 切 换到 master 分支所在的版本来创建存储卷修订变更 。

注意:
pod中的卷不会自动同步git仓库内容,如果需要对pod卷更新可以建立rc资源,然后删除一个卷,重建的卷则是最新的内容

2.访问工作节点上文件系统的文件

2.1介绍hostPath卷

hostPath卷指向节点文件系统上的特定文件或目录。在同一个节点上运行并在其 hostPath 卷中使用相同路径的 pod 可以看到相同的文件

hostPath卷是一种持久性存储,并不会像emptyDir卷和gitRepo卷一样在pod被删除时被删除,如果删除一个pod,而下一个pod使用了指向主机上相同路径的hostPath卷,则新的pod将会发现上一个pod留下的数据(也就是说hostPath卷数据不会随着pod的删除而清除),前提是两个pod在同一个节点

但是hostPath卷最好不要作为储存数据库的数据目录,因为通常一个服务的多个pod不在一个节点上调度,会造成pod数据库不一致

创建hostPath:

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

验证:

[root@node1 ~]#  mkdir -p /data/pod/volume1   
[root@node1 ~]# vi /data/pod/volume1/index.html 
node1
[root@node2 ~]#  mkdir -p /data/pod/volume1
[root@node2 ~]# vi /data/pod/volume1/index.html
node2

[root@master ~]# k get po -o wide
NAME               READY   STATUS    RESTARTS   AGE     IP          NODE        NOMINATED NODE   READINESS GATES
pod-demo           2/2     Running   0          23m     10.40.0.2   node1.k8s   <none>           <none>
pod-vol-hostpath   1/1     Running   0          5m15s   10.38.0.2   node2.k8s   <none>           <none>
[root@master ~]# curl 10.38.0.2
node2.com
[root@master ~]# k delete po pod-vol-hostpath
pod "pod-vol-hostpath" deleted
[root@master ~]# k apply -f pod-hostpath.yaml 
pod/pod-vol-hostpath created
[root@master ~]# k get po
NAME               READY   STATUS    RESTARTS   AGE
pod-demo           2/2     Running   0          25m
pod-vol-hostpath   1/1     Running   0          3s
[root@master ~]# k get po -o wide
NAME               READY   STATUS    RESTARTS   AGE   IP          NODE        NOMINATED NODE   READINESS GATES
pod-demo           2/2     Running   0          25m   10.40.0.2   node1.k8s   <none>           <none>
pod-vol-hostpath   1/1     Running   0          16s   10.38.0.2   node2.k8s   <none>           <none>
[root@master ~]# curl 10.38.0.2
node2.com

# 删除Pod对hostPath无任何影响

提示:

请记住仅当需要在节点上读取或写入系统文件时才使用 hostPath, 切勿使用它们来持久化跨 pod 的数据

3.使用持久化存储

当运行在 一 个 pod 中的应用程序需要将数据保存到磁盘上, 并且即使该 pod 重新调度到另 一 个节点时也要求具有相同的数据可用。 这就不能使用到目前为止我们提到的任何卷类型, 由于这些数据需要可以从任何集群节点访问, 因此必须将其存储在某种类型的网络存储 (NAS) 中。

3.1暂时不介绍GCE和AWS,使用NFS

如果集群 是运行在自有的 一 组服务器上,那么就有大量其他可移植的选项用千在卷内挂载外部存储。例如,要挂载 一 个简单的 NFS 共享,只需指定 NFS 服务器和共享路径

# nfs 使用本地宿主机
1.安装nfs:
sudo apt-get install nfs-kernel-server
2.sudo mkdir /nfsroot
3.打开配置:vi /etc/exports 添加共享目录 /nfsroot
/nfsroot *(insecure,rw,sync,no_root_squash)
4.sudo /etc/init.d/nfs-kernel-server restart

# 创建pod nfs-pod.yaml
apiVersion: v1
kind: Pod
metadata:
  name: nfs-pod
  namespace: default
spec:
  containers:
  - name: myapp
    image: ikubernetes/myapp:v1
    volumeMounts:
    - name: html
      mountPath: /usr/share/nginx/html
  volumes:
    - name: html
      nfs:
        path: /nfsroot
        server: 1.2.3.4
5. kubectl apply -f nfs-pod.yaml

4.介绍持久卷和持久卷声明(pv和pvc)

4.1介绍

 管理存储是管理计算的一个明显问题。该PersistentVolume子系统为用户和管理员提供了一个API,用于抽象如何根据消费方式提供存储的详细信息。为此,我们引入了两个新的API资源:PersistentVolume和PersistentVolumeClaim

  PersistentVolume(PV)是集群中由管理员配置的一段网络存储。 它是集群中的资源,就像节点是集群资源一样。 PV是容量插件,如Volumes,但其生命周期独立于使用PV的任何单个pod。 此API对象捕获存储实现的详细信息,包括NFS,iSCSI或特定于云提供程序的存储系统。

  PersistentVolumeClaim(PVC)是由用户进行存储的请求。 它类似于pod。 Pod消耗节点资源,PVC消耗PV资源。Pod可以请求特定级别的资源(CPU和内存)。声明可以请求特定的大小和访问模式(例如,可以一次读/写或多次只读)。

  虽然PersistentVolumeClaims允许用户使用抽象存储资源,但是PersistentVolumes对于不同的问题,用户通常需要具有不同属性(例如性能)。群集管理员需要能够提供各种PersistentVolumes不同的方式,而不仅仅是大小和访问模式,而不会让用户了解这些卷的实现方式。对于这些需求,有StorageClass 资源。

  StorageClass为管理员提供了一种描述他们提供的存储的“类”的方法。 不同的类可能映射到服务质量级别,或备份策略,或者由群集管理员确定的任意策略。 Kubernetes本身对于什么类别代表是不言而喻的。 这个概念有时在其他存储系统中称为“配置文件”。

  PVC和PV是一一对应的。

4.2整个流程

首先管理员向Kubernetes API申请创建持久卷(PV)(申请储存空间以及储存规则),创建后pv状态为Available
其次用户创建一个持久卷声明(PVC),
再次Kubernetes寻找符合PVC的PV,如果寻找到合适的PV即将PV和该PVC绑定,绑定成功后pvc状态为bound
最后用户创建一个pod并通过卷配置来引用pvc

4.3生命周期

PV是群集中的资源。PVC是对这些资源的请求,并且还充当对资源的检查。PV和PVC之间的相互作用遵循以下生命周期:

Provisioning ——-> Binding ——–>Using——>Releasing——>Recycling

 供应准备Provisioning---通过集群外的存储系统或者云平台来提供存储持久化支持。
 - 静态提供Static:集群管理员创建多个PV。 它们携带可供集群用户使用的真实存储的详细信息。 它们存在于Kubernetes API中,可用于消费
 - 动态提供Dynamic:当管理员创建的静态PV都不匹配用户的PersistentVolumeClaim时,集群可能会尝试为PVC动态配置卷。 此配置基于StorageClasses:PVC必须请求一个类,并且管理员必须已创建并配置该类才能进行动态配置。 要求该类的声明有效地为自己禁用动态配置。
 绑定Binding---用户创建pvc并指定需要的资源和访问模式。在找到可用pv之前,pvc会保持未绑定状态。
 使用Using---用户可在pod中像volume一样使用pvc。
 释放Releasing---用户删除pvc来回收存储资源,pv将变成“released”状态。由于还保留着之前的数据,这些数据需要根据不同的策略来处理,否则这些存储资源无法被其他pvc使用。
 回收Recycling---pv可以设置三种回收策略:保留(Retain),回收(Recycle)和删除(Delete)。
 - 保留策略:允许人工处理保留的数据。
 - 删除策略:将删除pv和外部关联的存储资源,需要插件支持。
 - 回收策略:将执行清除操作,之后可以被新的pvc使用,需要插件支持。
 注:目前只有NFS和HostPath类型卷支持回收策略,AWS EBS,GCE PD,Azure Disk和Cinder支持删除(Delete)策略

4.4pv类型

 GCEPersistentDisk
 AWSElasticBlockStore
 AzureFile
 AzureDisk
 FC (Fibre Channel)
 Flexvolume
 Flocker
 NFS
 iSCSI
 RBD (Ceph Block Device)
 CephFS
 Cinder (OpenStack block storage)
 Glusterfs
 VsphereVolume
 Quobyte Volumes
 HostPath (Single node testing only – local storage is not supported in any way and WILL NOT WORK in a multi-node cluster)
 Portworx Volumes
 ScaleIO Volumes
 StorageOS

4.5pv卷阶段状态

 Available – 资源尚未被claim使用
 Bound – 卷已经被绑定到claim了
 Released – claim被删除,卷处于释放状态,但未被集群回收。
 Failed – 卷自动回收失败

4.6pv和pvc使用NFS存储

1.查看pv和pvc定义

[root@k8s-master ~]# kubectl explain pv    #查看pv的定义方式
FIELDS:
    apiVersion
    kind
    metadata
    spec
[root@k8s-master ~]# kubectl explain pv.spec    #查看pv定义的规格
spec:
  nfs(定义存储类型)
    path(定义挂载卷路径)
    server(定义服务器名称)
  accessModes(定义访问模型,有以下三种访问模型,以列表的方式存在,也就是说可以定义多个访问模式)
    ReadWriteOnce(RWO)  单节点读写
    ReadOnlyMany(ROX)  多节点只读
    ReadWriteMany(RWX)  多节点读写
  capacity(定义PV空间的大小)
    storage(指定大小)

[root@k8s-master volumes]# kubectl explain pvc   #查看PVC的定义方式
KIND:     PersistentVolumeClaim
VERSION:  v1
FIELDS:
   apiVersion   <string>
   kind <string>  
   metadata <Object>
   spec <Object>
[root@k8s-master volumes]# kubectl explain pvc.spec
spec:
  accessModes(定义访问模式,必须是PV的访问模式的子集)
  resources(定义申请资源的大小)
    requests:
      storage:

2.配置nfs存储

[root@stor01 volumes]# mkdir v{1,2,3,4,5}
[root@stor01 volumes]# vim /etc/exports
/data/volumes/v1 192.168.56.0/24(rw,no_root_squash)
/data/volumes/v2 192.168.56.0/24(rw,no_root_squash)
/data/volumes/v3 192.168.56.0/24(rw,no_root_squash)
/data/volumes/v4 192.168.56.0/24(rw,no_root_squash)
/data/volumes/v5 192.168.56.0/24(rw,no_root_squash)
[root@stor01 volumes]# exportfs -arv
exporting 192.168.56.0/24:/data/volumes/v5
exporting 192.168.56.0/24:/data/volumes/v4
exporting 192.168.56.0/24:/data/volumes/v3
exporting 192.168.56.0/24:/data/volumes/v2
exporting 192.168.56.0/24:/data/volumes/v1
[root@stor01 volumes]# showmount -e
Export list for stor01:
/data/volumes/v5 192.168.56.0/24
/data/volumes/v4 192.168.56.0/24
/data/volumes/v3 192.168.56.0/24
/data/volumes/v2 192.168.56.0/24
/data/volumes/v1 192.168.56.0/24

3.定义PV

[root@k8s-master volumes]# kubectl explain pv
[root@k8s-master volumes]# kubectl explain pv.spec.nfs
[root@k8s-master volumes]# vim pv-demo.yaml
apiVersion: v1
kind: PersistentVolume
metadata:
  name: pv001
  labels:
    name: pv001
spec:
  nfs:
    path: /data/volumes/v1
    server: stor01
  accessModes: ["ReadWriteMany","ReadWriteOnce"]
  capacity:
    storage: 1Gi
---
apiVersion: v1
kind: PersistentVolume
metadata:
  name: pv002
  labels:
    name: pv002
spec:
  nfs:
    path: /data/volumes/v2
    server: stor01
  accessModes: ["ReadWriteOnce"]
  capacity:
    storage: 2Gi
---
apiVersion: v1
kind: PersistentVolume
metadata:
  name: pv003
  labels:
    name: pv003
spec:
  nfs:
    path: /data/volumes/v3
    server: stor01
  accessModes: ["ReadWriteMany","ReadWriteOnce"]
  capacity:
    storage: 2Gi
---
apiVersion: v1
kind: PersistentVolume
metadata:
  name: pv004
  labels:
    name: pv004
spec:
  nfs:
    path: /data/volumes/v4
    server: stor01
  accessModes: ["ReadWriteMany","ReadWriteOnce"]
  capacity:
    storage: 4Gi
---
apiVersion: v1
kind: PersistentVolume
metadata:
  name: pv005
  labels:
    name: pv005
spec:
  nfs:
    path: /data/volumes/v5
    server: stor01
  accessModes: ["ReadWriteMany","ReadWriteOnce"]
  capacity:
    storage: 5Gi
[root@k8s-master volumes]# kubectl apply -f pv-demo.yaml 
persistentvolume/pv001 created
persistentvolume/pv002 created
persistentvolume/pv003 created
persistentvolume/pv004 created
persistentvolume/pv005 created
[root@k8s-master volumes]# kubectl get pv
NAME      CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS      CLAIM     STORAGECLASS   REASON    AGE
pv001     1Gi        RWO,RWX        Retain           Available                                      7s
pv002     2Gi        RWO            Retain           Available                                      7s
pv003     2Gi        RWO,RWX        Retain           Available                                      7s
pv004     4Gi        RWO,RWX        Retain           Available                                      7s
pv005     5Gi        RWO,RWX        Retain           Available                                      7s

4.定义PVC

[root@k8s-master volumes ~]# vim 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
[root@k8s-master volumes]# kubectl apply -f pod-vol-pvc.yaml 
persistentvolumeclaim/mypvc created
pod/pod-vol-pvc created
[root@k8s-master volumes]# kubectl get pv
NAME      CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS      CLAIM           STORAGECLASS   REASON    AGE
pv001     1Gi        RWO,RWX        Retain           Available                                            19m
pv002     2Gi        RWO            Retain           Available                                            19m
pv003     2Gi        RWO,RWX        Retain           Bound       default/mypvc                            19m
pv004     4Gi        RWO,RWX        Retain           Available                                            19m
pv005     5Gi        RWO,RWX        Retain           Available                                            19m
[root@k8s-master volumes]# kubectl get pvc
NAME      STATUS    VOLUME    CAPACITY   ACCESS MODES   STORAGECLASS   AGE
mypvc     Bound     pv003     2Gi        RWO,RWX                       22s

5.测试访问

[root@stor01 volumes]# cd v3/
[root@stor01 v3]# echo "welcome to use pv3" > index.html
[root@k8s-master volumes]# kubectl get pods -o wide
pod-vol-pvc             1/1       Running   0          3m        10.244.2.39   k8s-node02
[root@k8s-master volumes]# curl  10.244.2.39
welcome to use pv3

5.使用StorageClass

1存储类介绍

Kubernetes集群管理员通过提供不同的存储类,可以满足用户不同的服务质量级别、备份策略和任意策略要求的存储需求。动态存储卷供应使用StorageClass进行实现,其允许存储卷按需被创建。如果没有动态存储供应,Kubernetes集群的管理员将不得不通过手工的方式类创建新的存储卷。通过动态存储卷,Kubernetes将能够按照用户的需要,自动创建其需要的存储。

工作流程如下:

1)集群管理员预先创建存储类(StorageClass);

2)用户创建使用存储类的持久化存储声明(PVC:PersistentVolumeClaim);

3)存储持久化声明通知系统,它需要一个持久化存储(PV: PersistentVolume);

4)系统读取存储类的信息;

5)系统基于存储类的信息,在后台自动创建PVC需要的PV;

6)用户创建一个使用PVC的Pod;

7)Pod中的应用通过PVC进行数据的持久化;

8)而PVC使用PV进行数据的最终持久化处理。

2.定义存储类

每一个存储类都包含provisioner、parameters和reclaimPolicy这三个参数域,当一个属于某个类的PersistentVolume需要被动态提供时,将会使用上述的参数域。

存储类对象的名称非常重要,用户通过名称类请求特定的存储类。管理员创建存储类对象时,会设置类的名称和其它的参数,存储类的对象一旦被创建,将不能被更新。管理员能够为PVC指定一个默认的存储类。

kind: StorageClass
apiVersion: storage.k8s.io/v1
metadata:
  name: standard
# 指定存储类的供应者
provisioner: kubernetes.io/aws-ebs
parameters:
  type: gp2
# 指定回收策略
reclaimPolicy: Retain
mountOptions:
  - debug

2.1 provisinoer:

AWSElasticBlockStore    ✓   AWS
AzureFile   ✓   Azure File
AzureDisk   ✓   Azure Disk
CephFS  –   –
Cinder  ✓   OpenStack Cinder
FC  –   –
FlexVolume  –   –
Flocker ✓   –
GCEPersistentDisk   ✓   GCE
Glusterfs   ✓   Glusterfs
iSCSI   –   –
PhotonPersistentDisk    ✓   –
Quobyte ✓   Quobyte
NFS –   –
RBD ✓   Ceph RBD
VsphereVolume   ✓   vSphere
PortworxVolume  ✓   Portworx Volume
ScaleIO ✓   ScaleIO
StorageOS   ✓   StorageOS
Local   –   Local

Kubernetes的存储类并不局限于表中的“interneal”供应者,“interneal”供应者的名称带有“kubernetes.io”前缀;也可以允许和指定外部的供应者,外部供应者通过独立的程序进行实现。外部供应者的作者对代码在何处生存、如何供应、如何运行、使用什么卷插件(包括Flex)等有充分的判断权,kubernetes-incubator/external-storage仓库中存在编写外部提供者的类库。例如,NFS不是内部的供应者,但也是可以使用。在kubernetes-incubator/external-storage仓库中以列表的形式展示了一些外部的供应者,一些第三方供应商也提供了他们自己的外部供应者。

2.2 提供者的参数

存储类存在很多描述存储卷的参数,依赖不同的提供者可能有不同的参数。例如,对于type参数,它的值可能为io1。当一个参数被省略,则使用默认的值

2.3 回收策略

通过存储类创建的持久化存储卷通过reclaimPolicy参数来指定,它的值可以是Delete或者Retain,默认为Delete。对于通过手工创建的,并使用存储类进行管理的持久化存储卷,将使用任何在创建时指定的存储卷。

2.4 挂接选项

通过存储类动态创建的持久化存储卷,会存在一个通过mountOptions参数指定的挂接选择。如果存储卷插件不支持指定的挂接选项,这提供存储供应就会失败,在存储类或者PV中都不会对挂接选项进行验证,因此需要在设置时进行确认。

3使用存储类

动态存储卷供应基于StorageClass的API对象的来实现,集群管理员能够按需定义StorageClass对象,每一个StorageClass对象能够指定一个存储卷插件(即供应者)。集群管理员能够在一个集群中定义各种存储卷供应,用户不需要了解存储的细节和复杂性,就能够选择符合自己要求的存储。

3.1启动动态供应

为了启用动态供应,集群管理员需要预先为用户创建一个或者多个存储类对象。存储类对象定义了使用哪个供应者,以及供应者相关的参数。下面是存储类的一个示例,它创建一个名称为slow的存储类,使用gce供应者:

apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: slow
provisioner: kubernetes.io/gce-pd
parameters:
  type: pd-standard

下面创建了一个名为“fast”的存储类,其提供类似固态磁盘的存储卷磁盘:

apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: fast
provisioner: kubernetes.io/gce-pd
parameters:
  type: pd-ssd

3.2使用动态供应

用户通过在PersistentVolumeClaim中包含一个存储类,来请求动态供应存储。在Kubernetes v1.6之前的版本,通过volume.beta.kubernetes.io/storage-class注释类请求动态供应存储;在v1.6版本之后,用户应该使用PersistentVolumeClaim对象的storageClassName参数来请求动态存储

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: claim1
spec:
  accessModes:
    - ReadWriteOnce
# 指定所使用的存储类,此存储类将会自动创建符合要求的PV
 storageClassName: fast
 resources:
    requests:
      storage: 30Gi

此声明将使用类似于固态存储磁盘,当持久化存储卷声明被删除后,存储卷也将会被销毁。

4.NFS存储类示例

4.1 部署nfs-provisioner

为nfs-provisioner实例选择存储状态和数据的存储卷,并将存储卷挂接到容器的/export 命令。

...
 volumeMounts:
    - name: export-volume
      mountPath: /export
volumes:
  - name: export-volume
    hostPath:
      path: /tmp/nfs-provisioner
...

为StorageClass选择一个供应者名称,并在deploy/kubernetes/deployment.yaml进行设置

args:
  - "-provisioner=example.com/nfs"
...

完整的deployment.yaml

kind: Service
apiVersion: v1
metadata:
  name: nfs-provisioner
  labels:
    app: nfs-provisioner
spec:
  ports:
    - name: nfs
      port: 2049
    - name: mountd
      port: 20048
    - name: rpcbind
      port: 111
    - name: rpcbind-udp
      port: 111
      protocol: UDP
  selector:
    app: nfs-provisioner
---

apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: nfs-provisioner
spec:
  replicas: 1
  strategy:
    type: Recreate
  template:
    metadata:
      labels:
        app: nfs-provisioner
    spec:
      containers:
        - name: nfs-provisioner
          image: quay.io/kubernetes_incubator/nfs-provisioner:v1.0.8
          ports:
            - name: nfs
              containerPort: 2049
            - name: mountd
              containerPort: 20048
            - name: rpcbind
              containerPort: 111
            - name: rpcbind-udp
              containerPort: 111
              protocol: UDP
          securityContext:
            capabilities:
              add:
                - DAC_READ_SEARCH
                - SYS_RESOURCE
          args:
            # 定义提供者的名称,存储类通过此名称指定提供者
            - "-provisioner=nfs-provisioner"
          env:
            - name: POD_IP
              valueFrom:
                fieldRef:
                  fieldPath: status.podIP
            - name: SERVICE_NAME
              value: nfs-provisioner
            - name: POD_NAMESPACE
              valueFrom:
                fieldRef:
                  fieldPath: metadata.namespace
          imagePullPolicy: "IfNotPresent"
          volumeMounts:
            - name: export-volume
              mountPath: /export
      volumes:
        - name: export-volume
          hostPath:
            path: /srv

在设置好deploy/kubernetes/deployment.yaml文件后,通过kubectl create命令在Kubernetes集群中部署nfs-provisioner。

$ kubectl create -f {path}/deployment.yaml

4.2创建StorageClass

下面是example-nfs的StorageClass配置文件,此配置文件定义了一个名称为nfs-storageclass的存储类,此存储类的提供者为nfs-provisioner。

apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: nfs-storageclass
  provisioner: nfs-provisioner

通过kubectl create -f命令使用上面的配置文件创建:

$ kubectl create -f deploy/kubernetes/class.yaml

在存储类被正确创建后,就可以创建PersistenetVolumeClaim来请求StorageClass,而StorageClass将会为PersistenetVolumeClaim自动创建一个可用PersistentVolume。

4.3 创建PersistenetVolumeClaim

PersistenetVolumeClaim是对PersistenetVolume的声明,即PersistenetVolume为存储的提供者,而PersistenetVolumeClaim为存储的消费者。下面是PersistentVolumeClaim的YAML配置文件,此配置文件通过spec.storageClassName字段指定所使用的存储储类。

在此配置文件中,使用nfs-storageclass存储类为PersistenetVolumeClaim创建PersistenetVolume,所要求的PersistenetVolume存储空间大小为1Mi,可以被多个容器进行读取和写入操作。

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: nfs-pvc
spec:
  accessModes:
  - ReadWriteMany
  storageClassName: nfs-storageclass
  resources:
    requests:
      storage: 1Mi

通过kubectl create命令创建上述的持久化存储卷声明:

$ kubectl create -f {path}/claim.yaml

4.4 创建使用PersistenVolumeClaim的部署

在这里定义名为busybox-deployment的部署YAML配置文件,使用的镜像为busybox。基于busybox镜像的容器需要对/mnt目录下的数据进行持久化,在YAML文件指定使用名称为nfs的PersistenVolumeClaim对容器的数据进行持久化。

# This mounts the nfs volume claim into /mnt and continuously
# overwrites /mnt/index.html with the time and hostname of the pod. 
apiVersion: v1
kind: Deployment
metadata:  
  name: busybox-deployment
spec:  
  replicas: 2  
  selector:    
    name: busybox-deployment
  template:    
    metadata:      
      labels:        
        name: busybox-deployment    
    spec:      
      containers:      
      - image: busybox        
        command:          
        - sh          
        - -c          
        - 'while true; do date > /mnt/index.html; hostname >> /mnt/index.html; sleep $(($RANDOM % 5 + 5)); done'        
        imagePullPolicy: IfNotPresent        
        name: busybox        
        volumeMounts:          
        # name must match the volume name below          
        - name: nfs            
          mountPath: "/mnt"     
     # 
     volumes:      
     - name: nfs        
       persistentVolumeClaim:          
         claimName: nfs-pvc

通过kubectl create创建busy-deployment部署:

$ kubectl create -f {path}/nfs-busybox-deployment.yaml

猜你喜欢

转载自www.cnblogs.com/limengchun/p/12161641.html