zoukankan      html  css  js  c++  java
  • Kubernetes使用StorageClass动态生成NFS类型的PV

    最近几天在测试StatefulSet的使用时,遇到了接触Kubernetes以来最大的一个困难,即配置StorageClass动态生成PersistentVolume。考虑到NFS存储操作相对简洁,因此在刚接触StorageClass的情况下选择了NFS作为Provisioner,没想到却是一段噩梦的开始。。。前前后后花费了将近一个星期的时间,才初步实现了PV的动态创建,并完成了一个简单的StatefulSet的案例。现在将我踩过的坑记录如下:

    一、自己配置NFS系统

    主要参考了下面的这篇文章:

    http://www.showerlee.com/archives/2280

    注意,文章中配置NFS共享目录的"# echo -e "/srv/pv-demo    kube-master(rw,sync)" > /etc/export"应为"/etc/exports"。

    完成配置后,可以参考官方文档编写yaml文件:

    https://github.com/kubernetes-incubator/external-storage/tree/master/nfs/docs/demo

    最后一直没有成功,花费了好多天调试都只能实现数据的本地挂载,无法跨机器远程挂载,所以不详细写了。

    二、使用已配置好的NFS系统

    因为公司刚好有已经配置好的NFS系统,在自己搭建不成功的情况下就使用了现成的系统。仍然是主要参考官方文档:

    https://github.com/kubernetes-incubator/external-storage/tree/master/nfs-client

    1.创建测试的静态PV和PVC

    首先,需要利用静态的PV和PVC来测试一下NFS系统能否正常工作:

    pv.yaml

    apiVersion: v1
    kind: PersistentVolume
    metadata:
      name: mypv1
    spec:
      capacity:
        storage: 4Gi
      accessModes:
        - ReadWriteOnce
      persistentVolumeReclaimPolicy: Recycle
      nfs:
        path: [已配置的NFS系统的路径]
        server: [已配置的NFS系统的IP地址]

    pvc.yaml

    kind: PersistentVolumeClaim
    apiVersion: v1
    metadata:
      name: mypvc1
    spec:
      accessModes:
        - ReadWriteOnce
      resources:
        requests:
          storage: 100Mi

    创建二者后,如果能够自动绑定,说明NFS系统工作正常,这样才能执行下面的步骤。

    2.运行nfs-client-provisioner

    想要动态生成PV,需要运行一个NFS-Provisioner服务,将已配置好的NFS系统相关参数录入,并向用户提供创建PV的服务。官方推荐使用Deployment运行一个replica来实现,当然也可以使用Daemonset等其他方式,这些都在官方文档中提供了。

    在创建Deployment之前,一定要按照官方文档中的Step 3部分配置相关的内容。

    编写rbac.yaml文件如下:

    kind: ClusterRole
    apiVersion: rbac.authorization.k8s.io/v1
    metadata:
      name: nfs-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-provisioner
    subjects:
      - kind: ServiceAccount
        name: nfs-provisioner
        namespace: default
    roleRef:
      kind: ClusterRole
      name: nfs-provisioner-runner
      apiGroup: rbac.authorization.k8s.io
    ---
    kind: Role
    apiVersion: rbac.authorization.k8s.io/v1
    metadata:
      name: leader-locking-nfs-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-provisioner
    subjects:
      - kind: ServiceAccount
        name: nfs-provisioner
        # replace with namespace where provisioner is deployed
        namespace: default
    roleRef:
      kind: Role
      name: leader-locking-nfs-provisioner
      apiGroup: rbac.authorization.k8s.io
    

    编写serviceaccount.yaml文件如下:

    apiVersion: v1
    kind: ServiceAccount
    metadata:
      name: nfs-provisioner

    注意,针对已配置好的NFS系统和自己搭建NFS系统,Deployment中使用的镜像不同!这里踩了一个大坑,在转为使用现成系统后没有修改原来的yaml文件中的镜像,导致持续报错,调试了好长时间才意识到问题。

    编写deployment.yaml文件如下:

    kind: Deployment
    apiVersion: extensions/v1beta1
    metadata:
      name: nfs-provisioner
    spec:
      replicas: 1
      strategy:
        type: Recreate
      template:
        metadata:
          labels:
            app: nfs-provisioner
        spec:
          serviceAccount: nfs-provisioner
          containers:
            - name: nfs-provisioner
              image: registry.cn-hangzhou.aliyuncs.com/open-ali/nfs-client-provisioner
              volumeMounts:
                - name: nfs-client-root
                  mountPath: /persistentvolumes
              env:
                - name: PROVISIONER_NAME
                  value: example.com/nfs
                - name: NFS_SERVER
                  value: [已配置的NFS系统的IP地址]
                - name: NFS_PATH
                  value: [已配置的NFS系统的挂载路径]
          volumes:
            - name: nfs-client-root
              nfs:
                server: [已配置的NFS系统的IP地址]
                path: [已配置的NFS系统的挂载路径]

    注意,官方文档提供的镜像在国内无法正常下载,在网上找到了一个阿里云的镜像作为替代。参考https://www.centos.bz/2018/04/%E5%AE%9E%E6%88%98kubernetes%E5%8A%A8%E6%80%81%E5%8D%B7%E5%AD%98%E5%82%A8nfs/

    这个镜像中volume的mountPath默认为/persistentvolumes,不能修改,否则运行时会报错。

    创建后观察Pod能否正常运行。后面如果出现错误,可以用kubectl logs查看这个Pod的日志来查看错误,进行调试。

    3.创建StorageClass

    编写并创建storageclass.yaml如下:

    kind: StorageClass
    apiVersion: storage.k8s.io/v1
    metadata:
      name: nfs
    provisioner: example.com/nfs

    4.创建测试claim

    接下来要创建测试的claim,以检测StorageClass能否正常工作:

    编写并创建test-claim.yaml如下,注意storageClassName应确保与上面创建的StorageClass名称一致。

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

    创建后,用kubectl get pvc查看,观察新创建的PVC能够自动绑定PV。

    5.创建测试Pod

    创建一个测试的Pod使用这个PVC,编写test-pod.yaml文件如下:

    kind: Pod
    apiVersion: v1
    metadata:
      name: test-pod
    spec:
      containers:
      - name: test-pod
        image: busybox
        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-claim1

    查看Pod状态是否变为Completed。如果是,则应该能在NFS系统的共享路径中看到一个SUCCESS文件。

    这样,StorageClass动态创建PV的功能就成功实现了。

    6.创建StatefulSet案例

    本来做StorageClass测试的目的就是为了实现StatefulSet,结果越做越跑偏。。。现在回到原本的目标,来实现一个简单的StatefulSet。

    编写statefulset.yaml文件如下:

    apiVersion: apps/v1beta1
    kind: StatefulSet
    metadata:
      name: web
    spec:
      serviceName: "nginx1"
      replicas: 2
      volumeClaimTemplates:
      - metadata:
          name: test
          annotations:
            volume.beta.kubernetes.io/storage-class: "nfs"
        spec:
          accessModes: [ "ReadWriteOnce" ]
          resources:
            requests:
              storage: 1Gi
      template:
        metadata:
          labels:
            app: nginx1
        spec:
          serviceAccount: nfs-provisioner
          containers:
          - name: nginx1
            image: nginx
            imagePullPolicy: IfNotPresent
            volumeMounts:
            - mountPath: "/persistentvolumes"
              name: test

    注意,这里的mountPath必须指定为/persistentvolumes,否则会出现表面上PV创建成功,其实在NFS系统中找不到的问题。。。

    当发现两个Pod都正常运行,且在NFS系统中能够找到PV,说明试验成功。

    进一步的,可以用kubectl exec -it 进入Pod,并创建一个文件,看看在PV中能否发现相同的文件已生成。

  • 相关阅读:
    Session丢失问题解决方案
    SQL 将txt文件导入sql数据库
    Ajax的应用实例解析
    ViewState与Session
    .net动态创建DataTable
    TSQL查询进阶数据集之间的运算
    【朝夕Net社区技术专刊】Core3.1 WebApi集群实战专题WebApi环境搭建运行发布部署篇
    经典SQL语句大全
    “存储过程”的定义及优点
    搜索关键词
  • 原文地址:https://www.cnblogs.com/00986014w/p/9406962.html
Copyright © 2011-2022 走看看