注意
本文档适用于 Ceph 的开发版本。
块设备与 Kubernetes
您可以通过 ceph-csi 在 Kubernetes v1.13 及更高版本中使用 Ceph 块设备镜像,ceph-csi 动态地为 Kubernetes 卷配置 RBD 镜像,并将这些 RBD 镜像映射为块设备(可选地挂载镜像中包含的文件系统)到运行引用 RBD 支持卷的 pod 的工作节点上。Ceph 将块设备镜像条带化为跨集群的对象,这意味着大型 Ceph 块设备镜像比独立的服务器具有更好的性能!
要在 Kubernetes v1.13 及更高版本中使用 Ceph 块设备,您必须在 Kubernetes 环境中安装和配置 ceph-csi。下图描绘了 Kubernetes/Ceph 技术栈。
创建池
默认情况下,Ceph 块设备使用 rbd 池。为 Kubernetes 卷存储创建一个池。确保您的 Ceph 集群正在运行,然后创建池。
$ ceph osd pool create kubernetes
有关为池指定放置组数量的详细信息,请参阅 创建池;有关应为池设置的放置组数量的详细信息,请参阅 放置组。
新创建的池在使用前必须进行初始化。使用 rbd 工具初始化池
$ rbd pool init kubernetes
配置 ceph-csi
设置 Ceph 客户端认证
为 Kubernetes 和 ceph-csi 创建一个新用户。执行以下命令并记录生成的密钥
$ ceph auth get-or-create client.kubernetes mon 'profile rbd' osd 'profile rbd pool=kubernetes' mgr 'profile rbd pool=kubernetes'
[client.kubernetes]
key = AQD9o0Fd6hQRChAAt7fMaSZXduT3NWEqylNpmg==
生成 ceph-csi ConfigMap
ceph-csi 需要一个存储在 Kubernetes 中的 ConfigMap 对象来定义 Ceph 集群的 Ceph monitor 地址。收集 Ceph 集群唯一的 fsid 和 monitor 地址
$ ceph mon dump
<...>
fsid b9127830-b0cc-4e34-aa47-9d1a2e9949a8
<...>
0: [v2:192.168.1.1:3300/0,v1:192.168.1.1:6789/0] mon.a
1: [v2:192.168.1.2:3300/0,v1:192.168.1.2:6789/0] mon.b
2: [v2:192.168.1.3:3300/0,v1:192.168.1.3:6789/0] mon.c
注意
ceph-csi 目前仅支持 传统的 V1 协议。
生成一个类似于下面示例的 csi-config-map.yaml 文件,将 “clusterID” 替换为 fsid,将 “monitors” 替换为 monitor 地址
$ cat <<EOF > csi-config-map.yaml
---
apiVersion: v1
kind: ConfigMap
data:
config.json: |-
[
{
"clusterID": "b9127830-b0cc-4e34-aa47-9d1a2e9949a8",
"monitors": [
"192.168.1.1:6789",
"192.168.1.2:6789",
"192.168.1.3:6789"
]
}
]
metadata:
name: ceph-csi-config
EOF
生成后,将新的 ConfigMap 对象存储在 Kubernetes 中
$ kubectl apply -f csi-config-map.yaml
最近版本的 ceph-csi 还需要另一个 ConfigMap 对象来定义密钥管理服务 (KMS) 提供者详细信息。如果未设置 KMS,请在 csi-kms-config-map.yaml 文件中放置空配置,或者参考 https://github.com/ceph/ceph-csi/tree/master/examples/kms 处的示例
$ cat <<EOF > csi-kms-config-map.yaml
---
apiVersion: v1
kind: ConfigMap
data:
config.json: |-
{}
metadata:
name: ceph-csi-encryption-kms-config
EOF
生成后,将新的 ConfigMap 对象存储在 Kubernetes 中
$ kubectl apply -f csi-kms-config-map.yaml
最近版本的 ceph-csi 还需要另一个 ConfigMap 对象来定义要添加到 CSI 容器内 ceph.conf 文件中的 Ceph 配置
$ cat <<EOF > ceph-config-map.yaml
---
apiVersion: v1
kind: ConfigMap
data:
ceph.conf: |
[global]
auth_cluster_required = cephx
auth_service_required = cephx
auth_client_required = cephx
# keyring is a required key and its value should be empty
keyring: |
metadata:
name: ceph-config
EOF
生成后,将新的 ConfigMap 对象存储在 Kubernetes 中
$ kubectl apply -f ceph-config-map.yaml
生成 ceph-csi cephx Secret
ceph-csi 需要 cephx 凭据才能与 Ceph 集群通信。生成一个类似于下面示例的 csi-rbd-secret.yaml 文件,使用新创建的 Kubernetes 用户 ID 和 cephx 密钥
$ cat <<EOF > csi-rbd-secret.yaml
---
apiVersion: v1
kind: Secret
metadata:
name: csi-rbd-secret
namespace: default
stringData:
userID: kubernetes
userKey: AQD9o0Fd6hQRChAAt7fMaSZXduT3NWEqylNpmg==
EOF
生成后,将新的 Secret 对象存储在 Kubernetes 中
$ kubectl apply -f csi-rbd-secret.yaml
配置 ceph-csi 插件
创建必需的 ServiceAccount 和 RBAC ClusterRole/ClusterRoleBinding Kubernetes 对象。这些对象不一定需要针对您的 Kubernetes 环境进行自定义,因此可以按原样使用 ceph-csi 部署 YAML 文件中的内容
$ kubectl apply -f https://raw.githubusercontent.com/ceph/ceph-csi/master/deploy/rbd/kubernetes/csi-provisioner-rbac.yaml
$ kubectl apply -f https://raw.githubusercontent.com/ceph/ceph-csi/master/deploy/rbd/kubernetes/csi-nodeplugin-rbac.yaml
最后,创建 ceph-csi 供应程序和节点插件。除了 ceph-csi 容器版本之外,这些对象不一定需要针对您的 Kubernetes 环境进行自定义,因此可以按原样使用 ceph-csi 部署 YAML 文件中的内容
$ wget https://raw.githubusercontent.com/ceph/ceph-csi/master/deploy/rbd/kubernetes/csi-rbdplugin-provisioner.yaml
$ kubectl apply -f csi-rbdplugin-provisioner.yaml
$ wget https://raw.githubusercontent.com/ceph/ceph-csi/master/deploy/rbd/kubernetes/csi-rbdplugin.yaml
$ kubectl apply -f csi-rbdplugin.yaml
重要
默认情况下,供应程序和节点插件 YAML 文件将拉取 ceph-csi 容器的开发版本 (quay.io/cephcsi/cephcsi:canary)。对于生产工作负载,应更新 YAML 文件以使用发布版本容器。
使用 Ceph 块设备
创建 StorageClass
Kubernetes StorageClass 定义了一类存储。可以创建多个 StorageClass 对象来映射到不同的服务质量级别(即 NVMe 与基于 HDD 的池)和功能。
例如,要创建映射到上面创建的 kubernetes 池的 ceph-csi StorageClass,可以在确保 “clusterID” 属性与您的 Ceph 集群 fsid 匹配后使用以下 YAML 文件
$ cat <<EOF > csi-rbd-sc.yaml
---
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: csi-rbd-sc
provisioner: rbd.csi.ceph.com
parameters:
clusterID: b9127830-b0cc-4e34-aa47-9d1a2e9949a8
pool: kubernetes
imageFeatures: layering
csi.storage.k8s.io/provisioner-secret-name: csi-rbd-secret
csi.storage.k8s.io/provisioner-secret-namespace: default
csi.storage.k8s.io/controller-expand-secret-name: csi-rbd-secret
csi.storage.k8s.io/controller-expand-secret-namespace: default
csi.storage.k8s.io/node-stage-secret-name: csi-rbd-secret
csi.storage.k8s.io/node-stage-secret-namespace: default
reclaimPolicy: Delete
allowVolumeExpansion: true
mountOptions:
- discard
EOF
$ kubectl apply -f csi-rbd-sc.yaml
请注意,在 Kubernetes v1.14 和 v1.15 中,卷扩展功能处于 alpha 状态,需要启用 ExpandCSIVolumes 功能门控。
创建 PersistentVolumeClaim
A PersistentVolumeClaim 是用户对抽象存储资源的请求。PersistentVolumeClaim 将与 Pod 资源关联,以配置一个由 Ceph 块镜像支持的 PersistentVolume。可以包含一个可选的 volumeMode 来选择挂载的文件系统(默认)或基于原始块设备的卷。
使用 ceph-csi 时,为 volumeMode 指定 Filesystem 可以支持 ReadWriteOnce 和 ReadOnlyMany accessMode 声明,为 volumeMode 指定 Block 可以支持 ReadWriteOnce、ReadWriteMany 和 ReadOnlyMany accessMode 声明。
例如,要创建一个基于块的 PersistentVolumeClaim,该声明使用上面创建的基于 ceph-csi 的 StorageClass,可以使用以下 YAML 文件从 csi-rbd-sc StorageClass 请求原始块存储
$ cat <<EOF > raw-block-pvc.yaml
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: raw-block-pvc
spec:
accessModes:
- ReadWriteOnce
volumeMode: Block
resources:
requests:
storage: 1Gi
storageClassName: csi-rbd-sc
EOF
$ kubectl apply -f raw-block-pvc.yaml
以下示例演示了将上述 PersistentVolumeClaim 作为原始块设备绑定到 Pod 资源
$ cat <<EOF > raw-block-pod.yaml
---
apiVersion: v1
kind: Pod
metadata:
name: pod-with-raw-block-volume
spec:
containers:
- name: fc-container
image: fedora:26
command: ["/bin/sh", "-c"]
args: ["tail -f /dev/null"]
volumeDevices:
- name: data
devicePath: /dev/xvda
volumes:
- name: data
persistentVolumeClaim:
claimName: raw-block-pvc
EOF
$ kubectl apply -f raw-block-pod.yaml
要创建一个基于文件系统的 PersistentVolumeClaim,该声明使用上面创建的基于 ceph-csi 的 StorageClass,可以使用以下 YAML 文件从 csi-rbd-sc StorageClass 请求挂载的文件系统(由 RBD 镜像支持)
$ cat <<EOF > pvc.yaml
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: rbd-pvc
spec:
accessModes:
- ReadWriteOnce
volumeMode: Filesystem
resources:
requests:
storage: 1Gi
storageClassName: csi-rbd-sc
EOF
$ kubectl apply -f pvc.yaml
以下示例演示了将上述 PersistentVolumeClaim 作为挂载的文件系统绑定到 Pod 资源
$ cat <<EOF > pod.yaml
---
apiVersion: v1
kind: Pod
metadata:
name: csi-rbd-demo-pod
spec:
containers:
- name: web-server
image: nginx
volumeMounts:
- name: mypvc
mountPath: /var/lib/www/html
volumes:
- name: mypvc
persistentVolumeClaim:
claimName: rbd-pvc
readOnly: false
EOF
$ kubectl apply -f pod.yaml