Kubernetes 使用 Openstack Cinder 作为存储后端

一直以来,我都在寻找一个私有云下 Kubernetes 存储方案的“最佳实践“,常见如 GlusterFS 的部署方案并不太适合现有的环境,裸机方案需要三台服务器进行集群部署,然而手头并没有多余的机器了,在当前部署 Openstack 的机器上进行部署就更不用想了,这只会增加之后维护的复杂性,特别是服务器的磁盘我并没有进行特别的分区操作,Openstack 的卷存储是直接挂载在 /dev/loop 下,使用的是整个磁盘的空间,引入其他的分布式文件系统可能会与 Cinder 产生冲突。

GlusterFS 的另一种部署方案是在 k8s 集群上进行部署,直接使用 Node 上的存储资源,这要求我必须为虚拟机实例直接分配更多的存储,存储利用率很难保证;而根据使用情况将 Openstack 中的卷挂载到各个实例上,管理起来太过麻烦。

总结下来,存储方案需要满足的最关键的两点:

  1. 存储与 kubernetes 环境脱离,保证每个 kubernetes 的 Node 所需 Volume 都很小,PersistentVolume 以动态的形式引入,即实现一个云存储,有利于迁移和提升资源利用率;
  2. 直接利用 Openstack 的 Cinder 来提供存储功能,不引入额外复杂度。

那么基于以上两点,我恰好发现官网上有提到可以使用 Openstack Cinder 作为 Provisioner 。


前置条件

  • kubernetes 1.19
  • Openstack train 版本

配置文件

要使用 Openstack Cinder 作为持久化存储,首先需要使 Kubernetes 具有访问 Openstack API 的能力。这里需要配置一份 cloud-config 文件:

1
2
3
4
5
6
7
[Global]
auth-url = <OS_AUTH_URL>
username = <OS_USERNAME>
password = <password>
domain-id = <OS_USER_DOMAIN_ID>
tenant-id = <OS_TENANT_ID>
region = <OS_REGION_NAME>

这些值为构建 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

使用

功能包括:

参照如下样例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: csi-sc-cinderplugin
provisioner: cinder.csi.openstack.org

---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: csi-pvc-cinderplugin
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 1Gi
storageClassName: csi-sc-cinderplugin

---
apiVersion: v1
kind: Pod
metadata:
name: nginx
spec:
containers:
- image: nginx
imagePullPolicy: IfNotPresent
name: nginx
ports:
- containerPort: 80
protocol: TCP
volumeMounts:
- mountPath: /var/lib/www/html
name: csi-data-cinderplugin
volumes:
- name: csi-data-cinderplugin
persistentVolumeClaim:
claimName: csi-pvc-cinderplugin
readOnly: false

更多使用样例参考仓库中的 example.


补充

由于 cinder 驱动默认并不支持 RWX 的读写方式,在对同一个 PVC 进行多点挂载的时候,会碰到无法正确挂载:挂载超时的错误。

可以参考文档,首先在 Openstack 中创建一个支持 multiattach 的卷:

1
2
$ cinder type-create multiattach
$ cinder type-key multiattach set multiattach="<is> True"

在 StorageClass 中需要注明类型参数:

1
2
3
4
5
6
7
8
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: csi-sc-cinderplugin-multiattach
provisioner: cinder.csi.openstack.org
parameters:
availability: "nova"
type: "multiattach"

但在实际使用中,还是有 bug 存在 (issues#1248) ,目前处理的方法还是使用多个 PVC 分别进行存储。


参考

  1. https://stackoverflow.com/questions/46067591/how-to-use-openstack-cinder-to-create-storage-class-and-dynamically-provision-pe
  2. https://programmersought.com/article/43204509549/
  3. https://kubernetes.io/docs/concepts/storage/storage-classes/#openstack-cinder
  4. https://docs.openshift.com/container-platform/3.4/install_config/persistent_storage/persistent_storage_cinder.html
  5. https://docs.gluster.org/en/latest/Quick-Start-Guide/Quickstart/
  6. https://github.com/kubernetes/cloud-provider-openstack/blob/master/docs/cinder-csi-plugin/using-cinder-csi-plugin.md
  7. https://docs.openstack.org/cinder/latest/admin/blockstorage-volume-multiattach.html