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独家出品,未经允许不能转载,否则追究法律责任