Kubernetes 使用 Openstack Cinder 作为存储后端
一直以来,我都在寻找一个私有云下 Kubernetes 存储方案的“最佳实践“,常见如 GlusterFS 的部署方案并不太适合现有的环境,裸机方案需要三台服务器进行集群部署,然而手头并没有多余的机器了,在当前部署 Openstack 的机器上进行部署就更不用想了,这只会增加之后维护的复杂性,特别是服务器的磁盘我并没有进行特别的分区操作,Openstack 的卷存储是直接挂载在 /dev/loop
下,使用的是整个磁盘的空间,引入其他的分布式文件系统可能会与 Cinder 产生冲突。
GlusterFS 的另一种部署方案是在 k8s 集群上进行部署,直接使用 Node 上的存储资源,这要求我必须为虚拟机实例直接分配更多的存储,存储利用率很难保证;而根据使用情况将 Openstack 中的卷挂载到各个实例上,管理起来太过麻烦。
总结下来,存储方案需要满足的最关键的两点:
- 存储与 kubernetes 环境脱离,保证每个 kubernetes 的 Node 所需 Volume 都很小,PersistentVolume 以动态的形式引入,即实现一个云存储,有利于迁移和提升资源利用率;
- 直接利用 Openstack 的 Cinder 来提供存储功能,不引入额外复杂度。
那么基于以上两点,我恰好发现官网上有提到可以使用 Openstack Cinder 作为 Provisioner 。
前置条件
- kubernetes 1.19
- Openstack train 版本
配置文件
要使用 Openstack Cinder 作为持久化存储,首先需要使 Kubernetes 具有访问 Openstack API 的能力。这里需要配置一份 cloud-config
文件:
1 | [Global] |
这些值为构建 Openstack 时使用的,如果你是使用 Kolla 部署的 Openstack,可以直接在 Openstack 控制节点的 /etc/kolla/admin-openrc.sh
中找到对应字段的值。
如果是通过其他方式部署,可以尝试直接 echo
对应的值。
将这份配置文件保存在 Kubernetes 控制节点的 /etc/kubernetes
路径下 (注意区分机器) 。
引入存储
在 1.17 以前的版本中,kubernetes 直接内置了 Cinder 、Manila 、FlexVolume 这些存储器的驱动,但在 1.18 以后,这些内置驱动就全部被移除了,取而代之的是 CSI Plugin。
如果你对 1.17 以前的 Cinder 引入方法感兴趣,可以查看 StackOverflow 上的这篇答案,一个很明显的特点是,这种方案需要对 kube-controller-manager 的参数进行修改,侵入型比较强。
Kubernetes 通过 PV、PVC、StorageClass 提供了非常强大的基于插件的存储管理机制,但是所有存储插件都以 in-tree
的方式提供,耦合程度过高。
CSI 的引入是为了将存储逻辑与 Kubernetes 进行解耦,提供一个标准的容器存储接口,存储插件的开发由提供方自行维护,部署也与 Kubernetes 核心组件分离。
https://github.com/kubernetes/cloud-provider-openstack 仓库中维护了许多 Kubernetes 与 Openstack 相关的插件,其中就包括我们需要的 Cinder CSI Plugin 。
将该仓库中 manifests/cinder-csi-plugin
下的文件下载下来,按照以下步骤部署。
创建 secret
1 | $ base64 -w 0 < /etc/kubernetes/cloud-config |
将这行命令的结果放入 manifests/cinder-csi-plugin/csi-secret-cinderplugin.yaml
中,并创建 secret :
1 | $ kubectl create -f manifests/cinder-csi-plugin/csi-secret-cinderplugin.yaml |
部署 CSI 插件
手工部署:
1 | $ kubectl -f manifests/cinder-csi-plugin/ apply |
这一步会创建 cluster roles、cluster role bindings 及与 Openstack 交互的 statefulsets ,可以使用命令进行查看:
1 | $ kubectl get pods -n kube-system |
另外,也可以使用 helm 的方式进行部署 (需要在 /etc/kubernetes
路径下存放 cloud-config
,在 /etc/cacert
路径下存放 Openstack 的证书):
1 | $ helm install --namespace kube-system --name cinder-csi ./charts/cinder-csi-plugin |
使用
功能包括:
- Dynamic Provisioning
- Topology
- Raw Block Volume
- Volume Expansion
- Volume Cloning
- Volume Snapshots
- Inline Volumes
- Multiattach Volumes
参照如下样例:
1 | apiVersion: storage.k8s.io/v1 |
更多使用样例参考仓库中的 example.
补充
由于 cinder 驱动默认并不支持 RWX
的读写方式,在对同一个 PVC 进行多点挂载的时候,会碰到无法正确挂载:挂载超时的错误。
可以参考文档,首先在 Openstack 中创建一个支持 multiattach 的卷:
1 | $ cinder type-create multiattach |
在 StorageClass 中需要注明类型参数:
1 | apiVersion: storage.k8s.io/v1 |
但在实际使用中,还是有 bug 存在 (issues#1248) ,目前处理的方法还是使用多个 PVC 分别进行存储。
参考
- https://stackoverflow.com/questions/46067591/how-to-use-openstack-cinder-to-create-storage-class-and-dynamically-provision-pe
- https://programmersought.com/article/43204509549/
- https://kubernetes.io/docs/concepts/storage/storage-classes/#openstack-cinder
- https://docs.openshift.com/container-platform/3.4/install_config/persistent_storage/persistent_storage_cinder.html
- https://docs.gluster.org/en/latest/Quick-Start-Guide/Quickstart/
- https://github.com/kubernetes/cloud-provider-openstack/blob/master/docs/cinder-csi-plugin/using-cinder-csi-plugin.md
- https://docs.openstack.org/cinder/latest/admin/blockstorage-volume-multiattach.html