ceph on kubernetes

本文简介

本文主要叙述在 ubuntu 16.04 环境上搭建 ceph 集群,并介绍 k8s 集群以 storageclass 方式使用 ceph 的两种方式。本文测试环境共 4 台机器:

1
2
3
4
ceph-mon
ceph-01
ceph-02
ceph-03

其中 ceph-mom 当做集群的监控节点,剩下三台当做数据节点,其中 ceph-01ceph-02ceph-03 机器有挂了 2 块磁盘,其中一块为系统盘,另外一块为数据盘 /dev/sdb

前置条件

在真正的安装 ceph 集群之前,需要完成以下前置条件:

  • 建立机器间的 SSH 信任关系
  • 安装 Python2 环境
  • 格式化数据盘,并制作文件系统,本文选择的是 XFS 文件系统

建立机器间的 SSH 信任关系

ceph-mon 为登录机器和部署机器,通过

1
ssh-keygen -t rsa

来生成 RSA 钥匙,建立 ceph-mon 与剩下三台机器的 SSH 信任关系。

安装 Python2 环境

分别在这4台机器上安装 Python2 环境,并建立 python2 链接到 python2.7 的软链。

格式化数据盘

首先检查磁盘分区

1
sudo fdisk -l /dev/sdb

格式化数据盘

1
sudo parted -s /dev/sdb mklabel gpt mkpart primary xfs 0% 100%

制作 XFS 文件系统

1
sudo mkfs.xfs -f /dev/sdb

然后再检查一下磁盘分区

1
2
sudo fdisk -s /dev/sdb
sudo blkid -o value -s TYPE /dev/sdb

开始安装

现在正式开始安装 ceph 集群,本文的安装方法是通过 ceph-deploy 脚本来辅助安装的。

安装 ceph-mon 节点

首先登录 ceph-mon 节点,执行

1
2
3
wget -q -O- 'https://download.ceph.com/keys/release.asc' | sudo apt-key add -
echo deb http://download.ceph.com/debian-${ceph-stable-release}/ $(lsb_release -sc) main | sudo tee /etc/apt/sources.list.d/ceph.list
sudo apt-get update && sudo apt-get install ceph-deploy

其中 ${ceph-stable-release} 那一行可以替换为

1
echo "deb http://mirrors.163.com/ceph/debian-jewel xenial main" | sudo tee /etc/apt/sources.list.d/ceph.list

通过这些步骤就可以在 ceph-mon 上安装了 ceph-deploy 部署工具。然后开始创建集群

1
2
mkdir -p /home/ceph/mon && cd /home/ceph/mon
ceph-deploy new ceph-mon

其中 ceph-mon 是 mon 节点,执行该命令会生成 ceph 配置文件、monitor 密钥文件以及日志文件。因为我们是使用 XFS 文件系统,所以在本路径下的 ceph.conf 中添加一下配置

1
2
3
osd max object name len = 256
osd max object namespace len = 64
osd pool default size = 2

安装 ceph-node 节点

接下来开始安装 ceph-node 节点,执行以下命令:

1
ceph-deploy install ceph-01 ceph-02 ceph-03

在这三台机器上安装好 ceph 组件之后,就可以继续初始化 mon 节点和收集集群信息了。

初始化集群

1
ceph-deploy mon create-initial

执行完毕,目录应该有以下文件:

1
2
3
4
${cluster-name}.client.admin.keyring
${cluster-name}.bootstrap-osd.keyring
${cluster-name}.bootstrap-mds.keyring
${cluster-name}.bootstrap-rgw.keyring

初始化数据节点

首先检查一下每个数据节点的磁盘情况:

1
ceph-deploy disk list ceph-01 ceph-02 ceph-03

接下来初始化数据节点的磁盘,本次使用的是 /dev/sdb

1
ceph-deploy disk zap ceph-01:/dev/sdb ceph-02:/dev/sdb ceph-03:/dev/sdb

然后开始准备 OSD 节点,确保没有错误发生

1
ceph-deploy osd prepare ceph-01:/dev/sdb ceph-02:/dev/sdb ceph-03:/dev/sdb

接下来激活 OSD

1
ceph-deploy osd activate ceph-01:/dev/sdb ceph-02:/dev/sdb ceph-03:/dev/sdb

可以再次检查一下如下节点:

1
ceph-deploy disk list ceph-01:/dev/sdb ceph-02:/dev/sdb ceph-03:/dev/sdb

配置 admin 节点

将管理钥匙分发给每个节点

1
ceph-deploy admin ceph-01 ceph-02 ceph-03

确保每个节点上文件钥匙仅具有可读权限

1
sudo chmod +r /etc/ceph/ceph.client.admin.keyring

集群测试

首先检查集群是否健康

1
ceph health

检查集群的状态

1
ceph -s

观察集群 osd 情况

1
ceph osd tree

ceph on k8s

接来下着重介绍一下 k8s 如何使用 ceph 集群,目的是把 ceph 作为 k8s 的分布式存储,这里是通过 k8s 的 storageclass 实现的。

创建 pool

所有用户使用共享的 pool

1
ceph osd pool create kube 1024 1024 # 生产环境下,“1024 1024”参数需要根据实际情况调整

创建 kube 用户

kube 是可以读写 kube pool 并可以 lock image 等的用户,用于挂载 PV。

1
2
ceph auth add client.kube mon 'allow r' osd 'allow rwx pool=kube'
added key for client.kube

为 k8s 使用 secret 创建 secret

创建 secret yaml 文件,如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
apiVersion: v1
kind: Secret
metadata:
name: ceph-admin-secret
namespace: kube-system
type: "kubernetes.io/rbd"
data:
# 使用 ceph auth get-key client.admin | base64 命令获取
key: QVFDQk9ReFpMMzRiS0JBQXp4Y3hPYjgyU1lPdVBXajc2VjhyV0E9PQ==
---
apiVersion: v1
kind: Secret
metadata:
name: ceph-secret
type: "kubernetes.io/rbd"
data:
# 使用 ceph auth get-key client.kube | base64 命令获取
key: QVFDS3NnbFpJWTZTTGhBQTRjOXVmbWhFUEdKVTQyd2tlQzFsMXc9PQ==

注意:

  • ceph-admin-secret 是用于 RBD Provisioner 创建 image 用,使用 ceph 的 client.admin 用户即可
  • ceph-secret 是用于 RBD Volume Plugin 在 node 上挂载 image 用,使用前面新建的 client.kube 用户

创建 RDB storageclass(方式一)

有两种方式可以创建 RDB storageclass,方式一通过 kube-controller-manager 内置的 RBD Provisioner

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#
# Using rbd provisioner to create image dynamically, need
# kube-controller-mananger to access `rbd` command.
#
kind: StorageClass
apiVersion: storage.k8s.io/v1
metadata:
name: ceph
provisioner: kubernetes.io/rbd
parameters:
monitors: 100.64.0.20:6789 # ceph monitors 地址
pool: kube # ceph pool,从这个 pool 创建 image
adminId: admin # ceph 管理员账户,StorageClass 使用改帐号创建 image
adminSecretNamespace: kube-system # ceph 管理员账户的 secret 所在 ns,可以配置任意 ns,推荐非用户的 kube-system
adminSecretName: ceph-admin-secret # ceph 管理员账户的 secret 名字
userId: kube # ceph 用户账户,用于 map image 的,只需要 rwx `kube` 这个 pool 的权限即可
userSecretName: ceph-secret # ceph 用户帐号的 secret,挂载 pv 时从 pvc 所在的 ns 中找对应的 secret,所以每个用户 ns 下都需要用该 secret,里面内容保持一样
fsType: xfs # default ext4

注意:

  • StorageClass 是全局资源,不属于某一个 namespace,由集群管理员配置(用户不可见)
  • adminSecret 放在 kube-system namespace 下,由集群管理员配置(用户不可见)
  • userSecret 需要给每一个需要使用 pvc 的用户 namespace 下配置一个(用户可见)

备注如果是使用 coreos 搭建的 k8s 集群,work 节点在绑定 pvc 的时候出现 rbd command not find 错误,这个是由于 kubelet 在绑定 pvc 的时候没有找到 rbd 命令,

解决办法参考:https://github.com/ceph/ceph-container/tree/master/examples/kubernetes-coreos
主要思想是通过容器安装 rbd 的方式,将 rbd 二进制挂载出来给 kubelet 用,因为 coreos 系统本身不支持安装。

创建 RDB storageclass(方式二 推荐做法)

Kuberentes 社区在将 Volume Provisioner 实现独立出来,见:https://github.com/kubernetes-incubator/external-storage 。以下是 RBD Provisioner 部署方法:

首先是部署 RBD Provisioner 程序,请到 https://quay.io/repository/external_storage/rbd-provisioner?tag=latest&tab=tags 查看,建议每次部署使用最新版。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: rbd-provisioner
namespace: kube-system
spec:
replicas: 1
template:
metadata:
labels:
app: rbd-provisioner
spec:
containers:
- name: rbd-provisioner
image: "quay.io/external_storage/rbd-provisioner:<latest-tag>"

接下来配置 RBD StorageClass

1
2
3
4
5
6
7
8
9
10
11
12
13
kind: StorageClass
apiVersion: storage.k8s.io/v1
metadata:
name: rbd
provisioner: ceph.com/rbd
parameters:
monitors: ceph monitor addresses
pool: kube
adminId: admin
adminSecretNamespace: kube-system
adminSecretName: ceph-admin-secret
userId: kube
userSecretName: ceph-secret

最后,使用前面的 name 为 “rbd” 的 storage class 申请 PV

1
2
3
4
5
6
7
8
9
10
11
12

kind: PersistentVolumeClaim
apiVersion: v1
metadata:
name: claim1
spec:
accessModes:
- ReadWriteOnce
storageClassName: rbd
resources:
requests:
storage: 1Gi

参考资料

最后感谢付总(https://github.com/cofyc)的 ceph rbd on k8s 文献。