k8s无脑系列(七)- NFS存储(动态存储)
1. 为什么需要动态存储
大概其的说一说,不一定对。总之一开始就觉得是个好东西。用到了,自然能体会到好处。
为每一个需要存储的资源编写pv,pvc很繁琐。
相同类型的请求有很多,急需快速可控的方案来实现动态申请。pvc申请,自动绑定pv
需要可以精细控制的存储回收重利用。既要保证容量,又要保证数据安全
2. 了解StorageClass
2.1 基础术语
- pv - Persistent Volume(持久化存储卷)
- pvc - Persistent Volume Claim(持久化存储卷请求)
- pvp - Persistent Volume Provisioner(持久化存储卷供应者)
- cluster role 集群操作角色,直接翻译role为角色,引申含义是角色具备哪些权限
2.1 原理
管理员创建Provisioner(供应者),负责为外部请求提供pv(持久化存储卷)实例
StorageClass代替pvc(持久存储卷请求)向绑定的Provistioner发出pv(持久化存储卷)实例的请求
Pod绑定的pvc通过pvc获取pv实例进行存储
3. 前期准备
物料 | 内容 | 备注 |
---|---|---|
nfs服务 | 192.168.56.4 | 一台 |
存储目录 | /data/nfs/db-svc-dynamic-volume | 用于存放数据 |
k8s集群 | 无脑系列有介绍 | 版本1.16.4 |
3.1 Yaml涉及的概念
名称 | 解释 | 备注 |
---|---|---|
StorageClass | k8s API Doc | |
ServiceAccount | 服务账户 | |
Role/ClusterRole | 角色/集群角色 | |
RoleBinding/ClusterRoleBinding | 角色与账户绑定 |
3.2 先定义服务账户与权限
定义一个服务账户,该账户负责向集群申请资源。
定义“集群角色”,“角色”并与服务账户绑定。所以,yaml中才会分五部分。分别是
- service account
- cluster role
- cluster role 与 service account绑定
- role
- role 与 service account 绑定
nfs-storage-rbac.yaml
apiVersion: v1 # 定义服务账户 kind: ServiceAccount metadata: # 名字要知命达意,这个账户专门为数据库服务 # {用途}-svc-{卷类型}-account name: db-svc-nfs-account namespace: default --- # 定义集群角色声明该角色的权限列表,可以看出全是存储相关 kind: ClusterRole apiVersion: rbac.authorization.k8s.io/v1 metadata: # 与 db-svc-nfs-account 相呼应 name: db-svc-nfs-cluster-role 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"] --- # 定义完角色后,就要将ServiceAccount与ClusterRole来绑定 kind: ClusterRoleBinding apiVersion: rbac.authorization.k8s.io/v1 metadata: name: db-svc-nfs-account-cluster-role-bind subjects: # 这里用的数组结构,那么可以认为这一个“角色”可以被多个账户绑定 - kind: ServiceAccount # 账户名字,见ServiceAccount的name name: db-svc-nfs-account namespace: default roleRef: kind: ClusterRole # 角色的名字,见ClusterRole的name name: db-svc-nfs-cluster-role apiGroup: rbac.authorization.k8s.io --- # 专门用来操作pvc与pv绑定时,ServiceAccount可以使用的权限 kind: Role # 角色 apiVersion: rbac.authorization.k8s.io/v1 metadata: name: db-svc-nfs-role namespace: default rules: - apiGroups: [""] resources: ["endpoints"] verbs: ["get", "list", "watch", "create", "update", "patch"] --- # 与角色绑定的ServiceAccount kind: RoleBinding apiVersion: rbac.authorization.k8s.io/v1 metadata: name: db-svc-nfs-account-role-bind subjects: - kind: ServiceAccount # 账户名字,见ServiceAccount的name name: db-svc-nfs-account namespace: default roleRef: kind: Role # 角色名字,见role name: db-svc-nfs-role apiGroup: rbac.authorization.k8s.io
$kubectl create -f nfs-storage-rbac.yaml serviceaccount/db-svc-nfs-account created clusterrole.rbac.authorization.k8s.io/db-svc-nfs-cluster-role created clusterrolebinding.rbac.authorization.k8s.io/db-svc-nfs-account-cluster-role-bind created role.rbac.authorization.k8s.io/db-svc-nfs-role created rolebinding.rbac.authorization.k8s.io/db-svc-nfs-account-role-bind created
3.3 创建StorageClass
nfs-storage-class.yaml
apiVersion: storage.k8s.io/v1 kind: StorageClass metadata: name: db-svc-nfs-storage-class # 这个名字要记住 provisioner: db-svc-nfs-provistioner parameters: archiveOnDelete: "false" reclaimPolicy: Retain
3.4 创建NFS Provisioner
nfs-provisioner.yaml
apiVersion: apps/v1 kind: Deployment metadata: name: db-svc-nfs-provisioner labels: app: db-svc-nfs-provisioner namespace: default spec: replicas: 1 strategy: type: Recreate selector: matchLabels: app: db-svc-nfs-provisioner template: metadata: labels: app: db-svc-nfs-provisioner spec: # 这里说明,用上面创建的service account来创建pv serviceAccountName: db-svc-nfs-account containers: - name: nfs-client-provisioner image: quay.io/external_storage/nfs-client-provisioner:latest volumeMounts: - name: nfs-client-root mountPath: /persistentvolumes env: #------ 这里是有学问的,见3.7 - name: PROVISIONER_NAME value: db-svc-nfs-provistioner - name: NFS_SERVER value: 192.168.56.4 - name: NFS_PATH value: /data/nfs/db-svc-dynamic-volume volumes: - name: db-svc-dynamic-volume nfs: #----- 这里是有学问的,见3.7 server: 192.168.56.4 path: /data/nfs/db-svc-dynamic-volume
$kubectl create -f nfs-provisioner.yaml
3.5 创建Persistent Volume Claim
nfs-dynamic-pvc.yaml
apiVersion: v1 kind: PersistentVolumeClaim metadata: name: mysql-pvc namespace: default spec: accessModes: - ReadWriteOnce resources: requests: storage: 1Gi storageClassName: db-svc-nfs-storage-class
$kubectl create -f nfs-dynamic-pvc.yaml
*注意:如果系统报告下面的错误,说明您看过了无脑系列其它部分内容
Error from server (AlreadyExists): error when creating "nfs-dynamic-pvc.yaml": persistentvolumeclaims "mysql-pvc" already exists
请调用如下命令删除
$kubectl delete pvc mysql-pvc
3.6 校验系统是否正常运行
$kubectl get pv,pvc NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE persistentvolume/pvc-e95e6bfb-aeba-4a96-b8eb-90c0db607ad9 1Gi RWO Retain Bound default/mysql-pvc db-svc-nfs-storage-class 17m NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE persistentvolumeclaim/mysql-pvc Bound pvc-e95e6bfb-aeba-4a96-b8eb-90c0db607ad9 1Gi RWO db-svc-nfs-storage-class 17m
出现了ersistentvolume/pvc-e95e6bfb-aeba-4a96-b8eb-90c0db607ad9 这样的PV
- mysql-pvc状态显示‘Bound’
系统正常运行!
3.7 多问一个为什么
为什么Provisioner中出现了重复设定NFS的内容呢?
说一下nfs-client-provisioner这个镜像
这个镜像的代码在Github中,查看代码得出结论
与集群ApiServer联通,并完成PV的创建过程。
在创建PV过程中,需要用到NFS_SERVER与NFS_PATH这两个变量,并传递给新建的PV
$kubectl describe pv pvc-e95e6bfb-aeba-4a96-b8eb-90c0db607ad9 Name: pvc-e95e6bfb-aeba-4a96-b8eb-90c0db607ad9 Labels: <none> Annotations: pv.kubernetes.io/provisioned-by: db-svc-nfs-provistioner Finalizers: [kubernetes.io/pv-protection] StorageClass: db-svc-nfs-storage-class Status: Bound Claim: default/mysql-pvc Reclaim Policy: Retain Access Modes: RWO VolumeMode: Filesystem Capacity: 1Gi Node Affinity: <none> Message: Source: Type: NFS (an NFS mount that lasts the lifetime of a pod) Server: 192.168.56.4 <--------这里 Path: /data/nfs/db-svc-dynamic-volume/default-mysql-pvc-pvc-e95e6bfb-aeba-4a96-b8eb-90c0db607ad9 ReadOnly: false Events: <none>
之所以还需要给镜像挂载一个volume,是因为需要代码来完成集群给PV下达的reclaimPolicy指令,并完成具体操作
来源:https://www.cnblogs.com/smokelee/p/12445155.html