过去,当Kubernetes版本还很低(v1.0.0左右)时,就有了卷插件。他们须要将持久数据存储卷链接到Kubernetes。当时数量还不多。 GCE PD,Ceph,AWS EBS和其余一些存储服务提供商都是最先的存储提供商。json
一般,它们与Kubernetes绑定在一块儿。所以,它们被称为“in-tree plugins”。可是,许多开发人员认为可用插件是有局限性的。所以,他们建立了本身的解决方案,经过补丁将它们集成到Kubernetes核心中,编译了本身的Kubernetes版本并将其安装在服务器上。可是随着时间的流逝,Kubernetes开发人员已经意识到,您不能经过给“一我的一条鱼”来解决问题-您必须教他“钓鱼”。所以,他们决定在1.2.0版本中为须要的人添加“钓鱼竿”…bash
Kubernetes开发人员建立了FlexVolume插件,该插件是用于使用第三方FlexVolume驱动程序的变量和方法的逻辑封装。 服务器
让咱们仔细看看什么是FlexVolume驱动程序。它是一个可执行文件(二进制文件,Python脚本,Bash脚本等),将命令行参数做为输入并以JSON格式返回包含预约义字段的消息。按照约定,第一个参数是方法,全部其余参数是其参数。dom
FlexVolume驱动程序必须实现如下基本方法集:学习
flexvolume_driver mount # mounts volume to a directory in the pod # expected output: { "status": "Success"/"Failure"/"Not supported", "message": "<Reason for success/failure>", } flexvolume_driver unmount # unmounts volume from a directory in the pod # expected output: { "status": "Success"/"Failure"/"Not supported", "message": "<Reason for success/failure>", } flexvolume_driver init # initializes the plugin # expected output: { "status": "Success"/"Failure"/"Not supported", "message": "<Reason for success/failure>", // defines if attach/detach methods are supported "capabilities":{"attach": True/False} }
attach
和detach
方法肯定调用驱动程序时kubelet
的行为。一样,有两种特定的方法,expandvolume
和expandfs
,它们容许动态调整卷大小。 您能够在Rook Ceph运算符中使用咱们的pull请求,做为expandvolume
方法提供的更改的示例,以及动态调整卷大小的功能。flex
这是用于NFS的FlexVolume驱动程序的示例:google
usage() { err "Invalid usage. Usage: " err "\t$0 init" err "\t$0 mount <mount dir> <json params>" err "\t$0 unmount <mount dir>" exit 1 } err() { echo -ne $* 1>&2 } log() { echo -ne $* >&1 } ismounted() { MOUNT=`findmnt -n ${MNTPATH} 2>/dev/null | cut -d' ' -f1` if [ "${MOUNT}" == "${MNTPATH}"]; then echo "1" else echo "0" fi } domount() { MNTPATH=$1 NFS_SERVER=$(echo $2 | jq -r '.server') SHARE=$(echo $2 | jq -r '.share') if[ $(ismounted) -eq 1] ; then log '{"status": "Success"}' exit 0 fi mkdir -p ${MNTPATH} &> /dev/nullmount -t nfs ${NFS_SERVER}:${SHARE} ${MNTPATH} &> /dev/null if [ $? -ne 0]; then err "{ \"status\": \"Failure\", \"message\": \"Failed to mount ${NFS_SERVER}:${SHARE} at ${MNTPATH}\"}" exit 1 fi log '{"status": "Success"}' exit 0 } unmount() { MNTPATH=$1 if [ $(ismounted) -eq 0 ] ; then log '{"status": "Success"}' exit 0 fi umount ${MNTPATH} &> /dev/null if [ $? -ne 0 ]; then err "{ \"status\": \"Failed\", \"message\": \"Failed to unmount volume at ${MNTPATH}\"}" exit 1 fi log '{"status": "Success"}' exit 0 } op=$1 if [ "$op" = "init" ]; then log '{"status": "Success", "capabilities": {"attach": false}}' exit 0 fi if [ $# -lt 2 ]; then usage fi shift case "$op" in mount) domount $* ;; unmount) unmount $* ;; *) log '{"status": "Not supported"}' exit 0 esac exit 1
建立可执行文件后,必须将驱动程序部署到Kubernetes集群。该驱动程序必须存在于每一个群集节点上的预约义路径中。默认路径是
/usr/libexec/kubernetes/kubelet-plugins/volume/exec/vendor_name〜driver_name/spa
…可是,路径可能在各类Kubernetes发行版(OpenShift,Rancher等)中有所不一样。插件
将FlexVolume驱动程序部署到群集节点是一项艰巨的任务。您能够手动执行此操做,可是,因为添加新节点,自动水平缩放,或者因为节点故障而替换节点时,群集中出现新节点的可能性很高。在这种状况下,除非在此处手动复制FlexVolume驱动程序,不然根本不可能在这些节点上使用永久性存储。命令行
可是,Kubernetes的资源之一DaemonSet能够解决此问题。在集群中建立新节点时,它将自动获取DaemonSet中定义的新容器。而后,将本地卷安装到与FlexVolume驱动程序的路径匹配的本地目录中。成功建立后,Pod将驱动程序所需的文件复制到磁盘。
这是用于部署FlexVolume插件的DaemonSet的示例:
以及用于复制FlexVolume驱动程序的Bash脚本示例:
请注意,复制操做不是原子操做。在kubelet的准备过程完成以前,确实存在kubelet开始使用该驱动程序的风险,从而致使错误。正确的方法是使用不一样的名称复制驱动程序文件,而后重命名它们(由于重命名操做是原子的)。
使用FlexVolume驱动程序时的下一个问题是,您必须为大多数类型的卷安装一些先决条件(例如,用于Ceph的ceph-common软件包)。最初,FlexVolume插件并非为如此复杂的系统设计的。
针对Rook运算符的FlexVolume驱动程序实现了针对此问题的创新解决方案。驱动程序自己是RPC客户端。用于通讯的IPC套接字位于驱动程序的目录中。如上所述,DaemonSet是交付驱动程序文件的理想选择,由于它会自动将Rook驱动程序做为卷挂载目录。复制完成后,此Pod经过已安装的卷做为功能齐全的RPC服务器链接到IPC套接字。 ceph-common软件包已经安装在pod的容器中。 IPC套接字确保kubelet将与同一节点中的相应pod通讯。很棒的主意,不是吗?
在某个时候,Kubernetes开发人员发现有20个用于存储卷的in-tree插件。它们中的每一个(甚至很小)更改都必须通过整个Kubernetes发行周期。
事实证实,您必须更新整个集群才能使用新的插件版本!此外,您可能会遇到不愉快的惊喜:新的Kubernetes版本可能与当前的Linux内核不兼容!所以,您擦干眼泪,恳求老板和客户得到更新Linux内核和Kubernetes集群的许可(可能会致使停机)…
这不是很奇怪又有趣吗?随着时间的流逝,对于整个社区来讲,现有的方法已经行不通了。所以,Kubernetes开发人员已决定中止在核心中包含新的卷插件。
CSI是核心中包含的最后一个插件,旨在完全解决持久性存储的问题。 Kubernetes 1.9中宣布了其alpha版本,简称为Out-of-Tree CSI卷插件。
首先,咱们要强调的是,CSI不是一个卷插件,它是用于建立自定义组件以与数据存储一块儿使用的成熟标准。容器编排系统(例如Kubernetes和Mesos)应该“学习”如何使用根据此标准实现组件。好吧,Kubernetes已经成功作到了。
Kubernetes CSI插件如何工做? CSI插件使用由第三方开发人员建立的自定义驱动程序(CSI驱动程序)。 Kubernetes的CSI驱动程序必须至少包含如下两个组件(pod):
StatefulSet
部署形式实现为gRPC服务器。DaemonSet
部署形式实现为gRPC服务器。您能够在本文中得到有关其工做原理的更多详细信息:了解CSI。
您以为这个清单熟悉吗?正确,CSI的优点弥补了FlexVolume插件的不足。
做为建立用于数据存储的自定义插件的标准,CSI受到了社区的热烈欢迎。此外,因为其优点和多功能性,甚至对于Ceph或AWS EBS也已经实现了CSI驱动程序,而Ceph或AWS EBS以前已经拥有本身的插件(从一开始就集成到Kubernetes中)。
在2019年初,in-tree插件被宣布弃用。 Kubernetes开发人员将维护FlexVolume插件,可是新功能只会添加到CSI,而不会添加到FlexVolume。