k8s无脑系列(七)- NFS存储(动态存储)

爱⌒轻易说出口 提交于 2020-03-08 22:18:44

k8s无脑系列(七)- NFS存储(动态存储)

1. 为什么需要动态存储

大概其的说一说,不一定对。总之一开始就觉得是个好东西。用到了,自然能体会到好处。

  1. 为每一个需要存储的资源编写pv,pvc很繁琐。

  2. 相同类型的请求有很多,急需快速可控的方案来实现动态申请。pvc申请,自动绑定pv

  3. 需要可以精细控制的存储回收重利用。既要保证容量,又要保证数据安全

2. 了解StorageClass

2.1 基础术语

  • pv - Persistent Volume(持久化存储卷)
  • pvc - Persistent Volume Claim(持久化存储卷请求)
  • pvp - Persistent Volume Provisioner(持久化存储卷供应者)
  • cluster role 集群操作角色,直接翻译role为角色,引申含义是角色具备哪些权限

2.1 原理

原理图

  1. 管理员创建Provisioner(供应者),负责为外部请求提供pv(持久化存储卷)实例

  2. StorageClass代替pvc(持久存储卷请求)向绑定的Provistioner发出pv(持久化存储卷)实例的请求

  3. 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中才会分五部分。分别是

  1. service account
  2. cluster role
  3. cluster role 与 service account绑定
  4. role
  5. 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
  1. 出现了ersistentvolume/pvc-e95e6bfb-aeba-4a96-b8eb-90c0db607ad9 这样的PV

  2. mysql-pvc状态显示‘Bound’
  3. 系统正常运行!

3.7 多问一个为什么

为什么Provisioner中出现了重复设定NFS的内容呢?

说一下nfs-client-provisioner这个镜像

这个镜像的代码在Github中,查看代码得出结论

  1. 与集群ApiServer联通,并完成PV的创建过程。

  2. 在创建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>
  3. 之所以还需要给镜像挂载一个volume,是因为需要代码来完成集群给PV下达的reclaimPolicy指令,并完成具体操作

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!