二维码

初探Kubernetes(K8S)动态卷存储(NFS)

1529 人阅读 | 时间:2019年09月30日 14:04

初探Kubernetes动态卷存储(NFS)

 

前言:K8S是一个成熟的容器业务集群管理方案,但是目前来讲,在存储方面显得过于复杂和繁琐,更不要说中间穿插着资源访问权限和认证的管理,尽管google在开源它之前有很多年的实战经验,但是从目前官方的发布文档来看,依然显得学习成本略高,我们来看看这个学习流程:

1,最初,学习k8s发现它罗列了一系列存储方案,无非就是对一系列本地和云存储的广泛支持:

初探Kubernetes(K8S)动态卷存储(NFS)

看到这么多的存储卷类型的确很唬人,但是没有办法,在目前存储界没有达到统一(也不可能统一)之前,为了保持自己的强大的生态兼容性,K8S作出了无奈之举。

2,好在我们不需要学习每一种存储类型,只要要针对需要的存储卷类型进行了解和学习,接着,为了让Pod和存储资源管理解耦,K8S又引入了PVPVC的概念,于是集群管理员和研发人员各司其职,但是带来了额外的PVPVC的创建,删除以及存储卷的绑定和回收以及读写控制等资源管理工作。

3,当集群规模增长后,发现PVPVC的管理开销惊人的时候,K8S又引入StorageClass的动态卷以及基于storageClass CSI的概念,这是目前K8S存储灵活分配的终极方案。

4,就在我们还没有完全理解StorageClassCSI的时候,我们在官网又看到相关的CloneSnapshot已经出来了。

 说明一个问题,业务需求场景不断升级,业务需求量不断变大,解决方案也不断更新和变更,仅仅一个存储就前后涉及诸多概念,实在让人有点无所适从,弱水三千,取一瓢饮,今天这个实验是针对NFS的共享存储展开的。

 为什么围绕NFS展开实验呢?因为从企业来讲,NFS共享在企业私有云内部非常容易取得,并且成本较低,一台普通的四盘位的企业级NAS服务器出厂即携带稳定可靠的NFS服务,无需自己部署,和企业的文件共享服务器集成,无需另外的硬件和部署成本。

首先,我们验证NAS服务器的NFS服务是否就位:

1,启动NFS客户端:

挂载前,请确保系统中已经安装了nfs-utilsnfs-common,安装方法如下:
CentOS

yum install nfs-utils -y

Ubuntu  Debian

apt-get install nfs-common

创建挂载路径:

mkdir  /nfs

确认远端NAS服务器上面存在的NFS服务和共享路径:

初探Kubernetes(K8S)动态卷存储(NFS)

挂载NFS共享路径:

mount -t nfs  NAS服务器的IP:/NAS-NFS

我们可以进入挂载路径尝试创建文件夹,看是否挂载成功并且读写正常;

容易出问题的是,挂载成功但是无法创建文件夹,提示文件系统只读,但是ls命令显示777,这是因为NAS服务器的NFS服务权限没有开放匿名访问的读写权限:

初探Kubernetes(K8S)动态卷存储(NFS)

以上全部成功后进一步测试NFS共享存储在PVPVC中是否工作正常:

2,创建测试的静态PVPVC

pv.yml

apiVersion: v1

kind: PersistentVolume

metadata:

  name: mypv1

spec:

  capacity:

    storage: 4Gi

  accessModes:

    - ReadWriteOnce

  persistentVolumeReclaimPolicy: Recycle

  nfs:

    path: /NAS-NFS

    server: [NAS服务器IP或域名]

pvc.yml

kind: PersistentVolumeClaim

apiVersion: v1

metadata:

 name: mypvc1

spec:

 accessModes:

 - ReadWriteOnce

 resources:

 requests:

 storage: 100Mi

开始创建资源对象(为了简化实验,所有资源对象都是默认的命名空间default展开):

初探Kubernetes(K8S)动态卷存储(NFS)

并且dashboard里面显示,绑定成功:

初探Kubernetes(K8S)动态卷存储(NFS)

以上实验充分证明nfs系统工作正常,删除以上测试的内容,进行下一步。

注意:

如果不删除PVC来解除资源的占用,是无法直接删除PV并释放资源,

具体操作表现在三个方面:

1,kubectl delete命令一直停留在执行状态不显示结果;

2,Dashboard资源对象一直正常显示存在,无视删除操作;
 

3,命令行强制退出删除命令,但是并不代表撤销删除操作,而是挂起,一直等待PVC手工清除,随即立即删除PV.

 

想要动态生成PV,需要运行一个NFS-Provisioner服务,将已配置好的NFS系统相关参数录入,向用户提供创建PV的服务。

官方推荐使用Deployment运行一个副本集来实现,当然也可以使用Daemonset等其他方式,这些都在官方文档中提供了。

创建持久卷的服务访问角色,角色绑定,权限分配供Provisioner角色后台调用:

编写serviceaccount.yaml文件如下:

apiVersion: v1

kind: ServiceAccount

metadata:

 name: nfs-provisioner

编写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

创建NFS服务的provisioner角色,部署结果是得到一个Pod来响应各种cliet提交的存储资源请求:

编写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

 #官方镜像:quay.io/external_storage/nfs-client-provisioner:latest 无法下载,使用上面阿里云镜像代替

 volumeMounts:

 - name: nfs-client-root

 mountPath: /persistentvolumes

 env:

 - name: PROVISIONER_NAME

 value: example.com/nfs

 - name: NFS_SERVER

 value: [NAS服务器的IP地址]

 - name: NFS_PATH

 value: /NAS-NFS #NFS系统的挂载路径

 volumes:

 - name: nfs-client-root

 nfs:

 server: [NAS服务器的IP地址]

 path: /NAS-NFS #NFS系统的挂载路径

将以上文件通过kubectl命令创建完毕后,我们查看K8S部署结果:

初探Kubernetes(K8S)动态卷存储(NFS)

我们得到一个副本集和这个副本集启动一个Pod,来充当nfs-client-provisioner角色,这个角色用来响应各种存储资源请求,但是并不能直接使用,需要用StorageClass去触发。

创建存储类StorageClass

编写并创建storageclass.yaml如下:

kind: StorageClass

apiVersion: storage.k8s.io/v1

metadata:

 name: nfs

provisioner: example.com/nfs

初探Kubernetes(K8S)动态卷存储(NFS)

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

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

kind: PersistentVolumeClaim

apiVersion: v1

metadata:

 name: test-claim1

spec:

 accessModes:

 - ReadWriteMany

 resources:

 requests:

 storage: 1Mi

 storageClassName: nfs #这里和创建的SC名称保持一致

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

创建一个测试的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的功能就成功实现了。

普通的pod是在编排文件里面通过声明预先手工创建PVC去请求storageclass来自动获取动态卷,实际上这种自动由于PVC的存在也属于半自动,还是不够灵活,所以,官方推荐使用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" # nfs和前面定义的storageclass的名称保持一致

 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: "/my_dir" #此挂载路径可以任意指定

 name: test

查看执行结果:

初探Kubernetes(K8S)动态卷存储(NFS)

查看存储资源创建结果:

初探Kubernetes(K8S)动态卷存储(NFS)

打开nfs的文件系统目录,发现和PV对应的资源文件夹自动生成:

初探Kubernetes(K8S)动态卷存储(NFS)

文件夹的自动命名规则为pod的各种资源名称的集合。

进一步的,可以用kubectl exec -it 进入其中一个Pod中验证:

初探Kubernetes(K8S)动态卷存储(NFS)

至此,实验基本完成,注意,使用statefulset的方式去创建pod,删除statefulset会自动销毁pod,但是并不销毁pod中的提交创建的pvpvc,因为违反数据持久化原则,所以需要手工删除。

初探Kubernetes(K8S)动态卷存储(NFS)

 


©著作权归作者所有:来自ZhiKuGroup博客作者没文化的原创作品,如需转载,请注明出处,否则将追究法律责任 来源:ZhiKuGroup博客,欢迎分享。

评论专区
  • 昵 称必填
  • 邮 箱选填
  • 网 址选填
◎已有 0 人评论
搜索
作者介绍
30天热门
×
×
本站会员尊享VIP特权,现在就加入我们吧!登录注册×
»
会员登录
新用户注册
×
会员注册
已有账号登录
×