12.实践篇:pv、pvc和sc,你们都是做什么的?

12.实践篇:pv、pvc和sc,你们都是做什么的?

1.Volume定义

        在容器的生命周期里,位于磁盘上的文件,它的生命周期是很短暂的,docker里面如此,kubernetes里亦然。
        数据很可能因为各种不可抗因素丢失,比如pod被迫下线时,它会根据rs控制器的数量定义,重新生成一个干净状态的新pod。
Volume的引入不但解决里数据稳定性的问题,也解决了同一个pod内,多个containers数据共享的需求;

和docker里不同的是:
1)kubernetes中内置封装了很多存储类型,pod也可以选择性的使用一个或多个。
2)当pod被删除时,Volume才可能会被清理,并且数据是否丢失和删除取决于Volume的具体类型和其回收策略

2.Volume分类

kubernetes内置封装了很多存储类型,大致可分为以下七大部分:

我已经整理好了官方配置文档,大家可以直接按需阅读,如何使用和配置。

存储类型 存储组件 官网文档
云存储 awsElasticBlockStore awsElasticBlockStore
云存储 azureDisk azureDisk
云存储 azureFile azureFile
云存储 gcePersistentDisk gcePersistentDisk
云存储 vsphereVolume vsphereVolume
分布式存储 cephfs cephfs
分布式存储 glusterfs glusterfs
分布式存储 rbd rbd
网络存储 nfs nfs
网络存储 fc fc
网络存储 iscsi iscsi
临时存储 emptyDir emptyDir
本地存储 hostPath hostPath
特殊存储 configMap configMap
特殊存储 downwardAPI downwardAPI
特殊存储 secret secret
自定义存储 csi csi
持久卷申请 persistentVolumeClaim persistentVolumeClaim

3.PV的生命周期

pv(持久卷)和pod资源一样,拥有生命周期,共分为以下四种:

Provisioning: 正在申明
Binding: 正在绑定
using: 正在使用
Reclaiming: 正在回收

4.PV的回收策略

当pod资源被删除时,其相关pv和数据如何操作?该删除还是保留呢?
kubernetes通过persistentVolumeReclaimPolicy字段进行设置:

Delete: 数据和pv都会删除
Recyle: (已废弃)
Retain: 数据和pv都不动

5.PV的申明类型

PV的申明类型可分为以下两种:

Static(静态):

管理员根据使用情况,人为预先进行配置

Dynamic(动态):

基于已创建的StorageClasses(简称SC)存储类,起到动态申请和创建的作用
API server需要增加一个参数配置:--enable-admission-plugins,具体类型参考:
storage-classes

6.pv、pvc和sc的关系

定义:

PVC:描述使用者(Pod)想要使用的持久化属性,比如存储大小、读写权限等
PV:描述一个具体的Volume属性,比如Volume的类型、挂载目录、远程存储服务器地址等
SC:运维人员根据pv特征,可能是性能、质量级别、备份策略等进行定义的抽象存储类,通过接收pvc请求,从而启到动态实例化pv的效果

你可能还有一点茫然,我来举个例子:

PVC:好比接口,使用者只需要知道这个接口如何使用即可,比如该传哪些参数,哪些是必传的等等,他并不需要了解接口是如何实现的
PV:就是这些接口的实现,内部是用nfs,还是ceph的存储系统等等
SC:则是这些接口根据一系列规则所进行的抽象类,通过接收pvc请求,从而启到动态实例化pv的效果

另外,还有2点是非常重要的:

1.pv没有namespace名称空间概念,而pvc有namespace名称空间的概念
2.pv和pvc一一对应绑定

7.查询命令

#pv的API字段配置说明
[root@centos-1 mainfasts]# kubectl explain pods.spec.volumes
KIND:     Pod
VERSION:  v1
RESOURCE: volumes <[]Object>

#pvc的API字段配置说明      
[root@centos-1 dingqishi]# kubectl explain pods.spec.volumes.persistentVolumeClaim
KIND:     Pod
VERSION:  v1
RESOURCE: persistentVolumeClaim <Object>

#sc的API字段配置说明 
[root@k8s-etcd-mater01 fault-injection]# kubectl explain sc
KIND:     StorageClass
VERSION:  storage.k8s.io/v1

至此,本章节的知识点也已经全部讲完了,你是否已经明白了呢?

8.实战:基于nfs的静态pv/pvc

首先你要先准备好nfs的挂载配置,我这里的配置如下所示:

角色 ip 备注
server 192.168.0.114 共享目录:/home/nfstestdir
client 192.168.0.111 挂载点:/mnt

1)首先编辑pv.yaml的配置文件,正确填写nfs服务端的配置信息,并使用apply -f命令生成

apiVersion: v1
kind: PersistentVolume
metadata:
  name: nfs-pv
spec:
  capacity:
    storage: 100Mi
  accessModes:
    - ReadWriteMany
  nfs:
    # FIXME: use the right IP
    server: 192.168.0.114
    path: "/home/nfstestdir"

注意:pv是没有名称空间概念的,要记住!!!

2)编辑pvc.yaml,需要指定刚才创建的pv的名字,并apply -f生成

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: nfs-pvc
  namespace: pv-test 
spec:
  accessModes:
    - ReadWriteMany
  resources:
    requests:
      storage: 90Mi

3)此时你可以通过以下命令查看到pv和pvc的状态了,此时pv和pvc的绑定已经完成了

[root@k8s-etcd-mater01 aaron]# kubectl get pvc -n pv-test
NAME      STATUS   VOLUME   CAPACITY   ACCESS MODES   STORAGECLASS   AGE
nfs-pvc   Bound    nfs-pv   100Mi      RWX                           17s

[root@k8s-etcd-mater01 aaron]# kubectl get pv
NAME     CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS   CLAIM             STORAGECLASS   REASON   AGE
nfs-pv   100Mi      RWX            Retain           Bound    pv-test/nfs-pvc                           53s

4)接下来我们要部署一个pod,让他使用pvc资源

apiVersion: v1
kind: Pod
metadata:
  name: nginx-volume-pvc
  namespace: pv-test
spec:
  containers:
  - name: nginx-pvc
    image: nginx
    ports:
    - containerPort: 80
    volumeMounts:
    - name: html-pvc         #自定义名的引用
      mountPath: /usr/share/nginx/html/
  volumes:               #这里是选择volume的类型
  - name: html-pvc           #自定义名
    persistentVolumeClaim:
      claimName: nfs-pvc     #我们刚才定义的pvc名

注意:pvc是有名称空间的,需要使用pvc的话,需要和pvc在同一个名称空间里!

5)此时pvc的状态已经是Bound了,

[root@k8s-etcd-mater01 aaron]# kubectl get pod -n pv-test
NAME               READY   STATUS    RESTARTS   AGE
nginx-volume-pvc   1/1     Running   0          7m1s

[root@k8s-etcd-mater01 aaron]# kubectl get pvc -n pv-test
NAME      STATUS   VOLUME   CAPACITY   ACCESS MODES   STORAGECLASS   AGE
nfs-pvc   Bound    nfs-pv   100Mi      RWX                           21m

[root@k8s-etcd-mater01 aaron]# kubectl get pv
NAME     CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS   CLAIM             STORAGECLASS   REASON   AGE
nfs-pv   100Mi      RWX            Retain           Bound    pv-test/nfs-pvc                           22m

9.实战:基于nfs的动态Provisioner

上面我们使用了基于nfs静态配置的方法,来给pod资源提供存储容量,这个方式的缺点显而易见。
需要我们作为管理员,预先配置好存储容量:要几个pv,并且容量多少!

这种协作方式一般不太可取,后面我将以NFS Provisioner为例,来讲述动态供给的例子。

9.1.NFS Provisioner介绍

NFS Provisioner是一个自动配置卷程序,它使用现有的和已配置的 NFS 服务器来支持通过持久卷声明动态配置Kubernetes持久卷。
你可以在Github-NFS Provisioner上找到他的项目。

9.2.NFS环境准备

这里我就沿用上面的环境了,不再另行配置

角色 ip 备注
server 192.168.0.114 共享目录:/home/nfstestdir
client 192.168.0.111 挂载点:/mnt

9.3.部署方式

NFS Provisioner的部署方式可以分为两种:
helm和手工的方式。

1)helm的方式较为简单,命令如下:
如果你对helm还不熟悉却想使用这种部署方式,请先阅读Helm基础。

helm install stable/nfs-client-provisioner --set nfs.server=nfs_serverip --set nfs.path=nfs_server_path

2)手工方式:
本章将展示如何以手工方式部署安装。

9.4.创建SA

首先我们需要创建一个serviceaccount,并使用RoleBinding绑定到leader-locking-nfs-client-provisioner上面。

这里会有一些超纲,涉及RBAC策略,我们后面会讲~

kind: ServiceAccount
apiVersion: v1
metadata:
  name: nfs-client-provisioner
---
kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  name: nfs-client-provisioner-runner
rules:
  - apiGroups: [""]
    resources: ["persistentvolumes"]
    verbs: ["get", "list", "watch", "create", "delete"]
  - apiGroups: [""]
    resources: ["persistentvolumeclaims"]
    verbs: ["get", "list", "watch", "update"]
  - apiGroups: ["storage.k8s.io"]
    resources: ["storageclasses"]
    verbs: ["get", "list", "watch"]
  - apiGroups: [""]
    resources: ["events"]
    verbs: ["create", "update", "patch"]
---
kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  name: run-nfs-client-provisioner
subjects:
  - kind: ServiceAccount
    name: nfs-client-provisioner
    namespace: default
roleRef:
  kind: ClusterRole
  name: nfs-client-provisioner-runner
  apiGroup: rbac.authorization.k8s.io
---
kind: Role
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  name: leader-locking-nfs-client-provisioner
rules:
  - apiGroups: [""]
    resources: ["endpoints"]
    verbs: ["get", "list", "watch", "create", "update", "patch"]
---
kind: RoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  name: leader-locking-nfs-client-provisioner
subjects:
  - kind: ServiceAccount
    name: nfs-client-provisioner
    # replace with namespace where provisioner is deployed
    namespace: default
roleRef:
  kind: Role
  name: leader-locking-nfs-client-provisioner
  apiGroup: rbac.authorization.k8s.io

kubectl apply -f rbac.yaml

9.5.创建nfs-client

将nfs配置成storageclass,安装对应的自动配置程序nfs-client,可以自动创建持久卷(pv)。
每当创建storageclass时,就会在kubernetes里面自动创建pv,nfs目录下自动创建文件夹,省去手动创建的繁琐。

kind: Deployment
apiVersion: extensions/v1beta1
metadata:
  name: nfs-client-provisioner
spec:
  replicas: 1
  strategy:
    type: Recreate
  template:
    metadata:
      labels:
        app: nfs-client-provisioner
    spec:
      serviceAccountName: nfs-client-provisioner
      containers:
        - name: nfs-client-provisioner
          image: quay.io/external_storage/nfs-client-provisioner:latest
          volumeMounts:
            - name: nfs-client-root
              mountPath: /persistentvolumes
          env:
            - name: PROVISIONER_NAME
              value: fuseim.pri/ifs
            - name: NFS_SERVER
              value: 192.168.0.114        #nfs服务器
            - name: NFS_PATH
              value: /home/nfstestdir     #共享目录
      volumes:
        - name: nfs-client-root
          nfs:
            server: 192.168.0.114         #nfs服务器
            path: /home/nfstestdir        #共享目录

kubectl apply -f nfs-client-deployment.yaml

9.6.创建存储类

apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: managed-nfs-storage
provisioner: fuseim.pri/ifs #---动态卷分配者名称,必须和上面创建的"provisioner"变量中设置的Name一致
parameters:
  archiveOnDelete: "true" #---设置为"false"时删除PVC不会保留数据,"true"则保留数据

设置默认存储类(可选):

metadata.annotations:

storageclass.kubernetes.io/is-default-class: "true" #---设置为默认的storageclass

9.7.创建PVC

kind: PersistentVolumeClaim
apiVersion: v1
metadata:
  name: test-claim
  annotations:
    volume.beta.kubernetes.io/storage-class: "managed-nfs-storage"  #---需要与上面创建的storageclass的名称一致spec:
  accessModes:
    - ReadWriteMany
  resources:
    requests:
      storage: 1Mi

9.8.测试

此时,我们要创建一个测试用的pod,将nfs存储挂载至容器的mnt目录,并新建一个success的文件,观察动态供给是否正常工作。

kind: Pod
apiVersion: v1
metadata:
  name: test-pod
spec:
  containers:
  - name: test-pod
    image: busybox:1.24
    command:
      - "/bin/sh"
    args:
      - "-c"
      - "touch /mnt/SUCCESS && exit 0 || exit 1"
    volumeMounts:
      - name: nfs-pvc
        mountPath: "/mnt"
  restartPolicy: "Never"
  volumes:
    - name: nfs-pvc
      persistentVolumeClaim:
        claimName: test-claim           #我们定义的pvc

具体创建流程如下所示:

pod->test-claim(pvc)->managed-nfs-storage(SC存储类)->provisioner: fuseim.pri/ifs(PV:nfs-client)

此时,我们查看相关pv,发现已经动态供给了。

[root@k8s-etcd-mater01 nfs]# kubectl get pv,pvc
NAME                                                        CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS   CLAIM                STORAGECLASS          REASON   AGE
persistentvolume/pvc-50b542db-2ee3-11ea-a207-001c425c73bc   1Mi        RWX            Delete           Bound    default/test-claim   managed-nfs-storage            41m
persistentvolume/pvc-9e0191c8-2ee0-11ea-82c1-001c42662fdd   2Gi        RWO            Delete           Bound    default/test-web-0   managed-nfs-storage            42m

NAME                               STATUS   VOLUME                                     CAPACITY   ACCESS MODES   STORAGECLASS          AGE
persistentvolumeclaim/test-claim   Bound    pvc-50b542db-2ee3-11ea-a207-001c425c73bc   1Mi        RWX            managed-nfs-storage   41m
persistentvolumeclaim/test-web-0   Bound    pvc-9e0191c8-2ee0-11ea-82c1-001c42662fdd   2Gi        RWO            managed-nfs-storage   61m

你也可以到nfs服务器端,查看success文件是否生成。

[root@k8s-node01 nfstestdir]# tree
.
├── 11
├── 12
├── 21313
├── 3
├── default-test-claim-pvc-50b542db-2ee3-11ea-a207-001c425c73bc
│   └── SUCCESS          #看我看我
└── default-test-web-0-pvc-9e0191c8-2ee0-11ea-82c1-001c42662fdd

至此,基于nfs的动态Provisioner供给功能已经演示完毕,你要做的就是根据自己需求选取你所需的volume分类。
在本文第二节,我已经罗列了所有的存储类型官方文档,方便你直接查阅~

@版权声明:51CTO独家出品,未经允许不能转载,否则追究法律责任

版权声明:
作者:WaterBear
链接:https://l-t.top/2048.html
来源:雷霆运维
文章版权归作者所有,未经允许请勿转载。

THE END
分享
二维码
< <上一篇
下一篇>>
文章目录
关闭
目 录