Kubernetes/Ceph 技术堆栈
要使用 Ceph 块设备,您必须在 Kubernetes 环境中安装和配置Ceph-CSI。 下图描绘了Kubernetes/Ceph 技术堆栈。
创建 pool
默认情况下,Ceph块设备使用RBD池。 为Kubernetes卷存储创建一个池。 确保您的Ceph集群正在运行,然后创建池。
ceph osd pool create kubernetes
有关指定池的放置组数以及放置组的详细信息,请参阅创建池,了解您应该为池所设置的放置组数量的详细信息。
必须在使用前初始化新创建的池。 使用RBD工具初始化池:
rbd pool init kubernetes
配置 CEPH-CLI
创建用户
为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==
创建集群ID和集群地址
Ceph-CSI要求存储在Kubernetes中的ConfigMap对象来定义Ceph集群的Ceph监视器地址。 收集Ceph集群唯一的FSID和监视器地址:
$ 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
生成类似于下面示例的CSI-Config-Map.yaml文件,替换FSID,以及集群地址
$ 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
执行
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
运行
$ kubectl apply -f csi-kms-config-map.yaml
创建凭证
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
执行
$ kubectl apply -f csi-rbd-secret.yaml
配置 CEPH-CSI 插件
创建所需的 ServiceAccount、RBAC ClusterRole、ClusterRoleBinding Kubernetes对象。
$ 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 Provisioner和Node插件。
$ 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
使用块设备
创建 STORAGECLASS
Kubernetes StorageClass 定义了一类存储。 可以创建多个StorageClass对象来映射到不同的服务质量级别(即NVME基于HDD的池)和功能。
例如,要创建一个Ceph-CSI StorageClass,可映射到上面创建的Kubernetes池,可以在确保“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
创建
Filesystem for volumeMode
- ReadWriteOnce
- ReadOnlyMany
Block for volumeMode
- ReadWriteOnce
- ReadWriteMany
- ReadOnlyMany
基于 block
创建 PVC
$ 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
创建测试 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
基于 filesystem
创建 PVC
$ 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
创建测试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
kubernetes 挂载 Ceph NFS
部署所需环境
部署 CephFS
要使用 NFS,需要先部署 CephFS
# 创建一个 pool 用于存储 cephfs 数据
ceph osd pool create cephfs_data
# 创建一个 pool 用于存储 cephfs 元数据
ceph osd pool create cephfs_metadata
# 创建 cephfs, 指定 cephfs_metadata 存储元数据, 指定 cephfs_data 存储实际数据
ceph fs new cephfs cephfs_metadata cephfs_data
# 查看 cephfs
ceph fs ls
部署 MDS
# 在 ceph01, ceph02, ceph03 部署 mds
ceph orch apply mds cephfs --placement="3 ceph01 ceph02 ceph03"
创建 NFS
ceph osd pool create ganesha_data
ceph osd pool application enable ganesha_data nfs
ceph orch apply nfs nfs ganesha_data --placement=3
# eph orch apply nfs nfs ganesha_data --placement="1 ceph1"
在 CephFS 中创建 nfs 文件夹作为 nfs 存储的根目录
# 挂载CephFS(需要安装ceph-commons):
mkdir -p /mnt/cephfs
mount -t ceph ceph1:/ /mnt/cephfs -o name=admin,secret=AQBYSjZfQF+UJBAAC6QJjNACndkw2LcCR2XLFA==
Ceph的NFS是基于CephFS提供的,我们首先在CephFS中创建一个/nfs目录,用于作为NFS服务的根目录。
# 前一步骤中已经挂载了CephFS到/mnt/cephfs
mkdir /mnt/cephfs/nfs
# 其中mount的时候的secret是/etc/ceph/ceph.client.admin.keyring的值,也可以替换成secretfile=/etc/ceph/ceph.client.admin.keyring。
在 dashboard 中创建 nfs 存储
最后,在dashboard中创建一个NFS即可
挂载 nfs
挂载NFS:
mount -t nfs 192.168.7.14:/nfs /mnt/nfs
storageclass
制作镜像
https://github.com/kubernetes-sigs/nfs-subdir-external-provisioner/releases
下载 Source code
更改 Dockerfile
FROM alpine # 修改镜像,避免无法下载
LABEL maintainers="Kubernetes Authors"
LABEL description="NFS subdir external provisioner"
ARG binary=./bin/nfs-subdir-external-provisioner
COPY ${binary} /nfs-subdir-external-provisioner
ENTRYPOINT ["/nfs-subdir-external-provisioner"]
制作镜像,成成 nfs-subdir-external-provisioner:latest 镜像
make build
make container
更改镜像标签
docker tag nfs-subdir-external-provisioner:latest k8s.gcr.io/sig-storage/nfs-subdir-external-provisioner:v4.0.2
部署
$ helm repo add nfs-subdir-external-provisioner https://kubernetes-sigs.github.io/nfs-subdir-external-provisioner/
$ helm install nfs-subdir-external-provisioner nfs-subdir-external-provisioner/nfs-subdir-external-provisioner \
--set nfs.server=x.x.x.x \
--set nfs.path=/exported/path
测试
kind: PersistentVolumeClaim
apiVersion: v1
metadata:
name: test-claim
spec:
storageClassName: nfs-client
accessModes:
- ReadWriteMany
resources:
requests:
storage: 1Mi
---
kind: Pod
apiVersion: v1
metadata:
name: test-pod
spec:
containers:
- name: test-pod
image: busybox:stable
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-claim
kubectl appply -f