在Docker容器里运行Ceph集群

原理

Docker中运行Ceph是存在一些争议的,很多人可能认为完全没必要这样做。虽然将Monitors, Metadata Server和Rados Gateway容器化没什么问题,但当涉及到OSD时,事情就变得棘手。Ceph的OSD与它运行的主机紧密相关,与底层硬件如此紧密的联系在一起,对所有软件来说都是少见的。基于此,如果OSD依赖的硬盘损坏,OSD也就无法工作,这也是容器化场景中的问题所在。

坦白的说,我经常这样想:

我也不知道我为什么做这个。我只知道人们需要(是的,可能他们也不知道为什么)。不管怎样,我感觉这样做很重要,所以就让我们试试看吧。

我知道这听起来一点都不乐观,但在某种程度上就是事实。我的观点后来也有所变化,所以让我来解释一下为什么值得这样做。希望这也能改变你的看法。是的我的解释不仅仅是:Docker很酷,所以让我们Dockerize一切。

人们已经投入了很多努力以在自己的平台上运行容器化的软件。因此,他们在使用各种工具来构建和编排他们的环境。而且看到Kubernetes成为这类的编排工具,我一点都不吃惊。有些人还喜欢在生产环境尝试最新的技术,不然会觉得自己的工作很无聊(Seán,对吗?)。所以,在容器化一切的道路上,他们看到自己喜欢的开源存储解决方案也容器化了会非常高兴:)。

凡是与yum或者apt-get相关的,都不容易回滚,这与容器不同。容器使得升级和回滚都变得非常容易,因为你可以很容易地用docker stop和docker run来运行程序的新版本。你也可以在一台机器上运行多个相互隔离的集群。这也是开发模式的理想状态。

项目

如前所述,一切都源于Seán C. McCord的工作,我们只是围绕他的工作做迭代。当前你可以用ceph-docker在Ubuntu或者CentOS上运行单个的Ceph守护进程。
Docker Hub上我们有很多可用的镜像。我们有一个Ceph命名空间,所以我们镜像的前缀是ceph/。我们使用了自动构建,因此每次合并一个新补丁就会触发构建,并生成一个新版本的容器镜像。由于我们目前正处于重构过程中,你会看到大量可用的镜像。历史的原因,每个守护进程都有一个镜像(在合并这个补丁前,我们会一直这样做 )。因此monitor,OSD,MDS和radosgw各有一个容器镜像。这真不完美而且实际中也没必要。这也是我们为什么开始daemon镜像工作的原因。这个镜像包含了Ceph所有的守护程序,并且执行docker run命令时,你可以通过指定参数启动你想要的实例。也就是说,如果你准备开始,我建议直接使用ceph/daemon镜像。在下一节我举例说明如何运行它。

容器化CEPH

MONITORS

由于monitors不能通过NAT网络进行通信,我们需要使用–net=host暴露Docker主机网络:

$ sudo docker run -d --net=host \
 -v /etc/ceph:/etc/ceph \
 -v /var/lib/ceph/:/var/lib/ceph \
 -e MON_IP=192.168.0.20 \
 -e CEPH_PUBLIC_NETWORK=192.168.0.0/24 \
 ceph/daemon mon

可用选项列表:

MON_IP是你运行Docker的主机IP地址
MON_NAME是你的monitor名称(默认:$(hostname))
CEPH_PUBLIC_NETWORK是你运行Docker的主机CIDR,应该与MON_IP是相同的网络
CEPH_CLUSTER_NETWORK是你运行Docker的主机的第二块网卡的CIDR,用于OSD复制流量

OBJECT STORAGE DAEMON

当前的实现允许你在每个容器运行一个OSD进程,按照微服务的理念,我们也不应该在容器中运行多个服务。在我们的例子中,一个容器中运行多个OSD进程打破了这种理念,这可能会引入(我们)不期望的行为。也增加了方案安装和维护的复杂性。

在这个配置中,–privileged=true是必须的,因为我们需要完全访问/dev/和其他内核功能。不过在简单的暴露OSD目录基础上支持另外一种配置,在这种方式下运维人员需要对设备做适当的准备工作。之后只要简单的暴露OSD目录并由entrypoint来完成OSD(ceph-osd mkfs)的安装。我现在展示的配置更容易开始了,因为你只需要指定一个块设备,然后entrypoint会完成剩下的工作。

对于那些不希望使用–privileged=true的,请向后看第二个例子。

$ sudo docker run -d --net=host \
 --privileged=true \
 -v /etc/ceph:/etc/ceph \
 -v /var/lib/ceph/:/var/lib/ceph \
 -v /dev/:/dev/ \
 -e OSD_DEVICE=/dev/vdd \
 ceph-daemon osd_ceph_disk

如果你不希望使用–privileged=true,你也可以使用你选择的配置管理工具手动配置OSD。

没有特权模式的例子,在这个例子中假设你已经分区和配置了文件系统并挂载了OSD分区。要创建OSD,只需运行下面的命令:

$ sudo docker exec  ceph osd create.

然后运行您的容器,如下所示:

docker run -v /osds/1:/var/lib/ceph/osd/ceph-1 -v /osds/2:/var/lib/ceph/osd/ceph-2

$ sudo docker run -d --net=host \
 -v /etc/ceph:/etc/ceph \
 -v /var/lib/ceph/:/var/lib/ceph \
 -v /osds/1:/var/lib/ceph/osd/ceph-1 \
 ceph-daemon osd_disk_directory

可用选项列表:

OSD_DEVICE是OSD设备,如:/dev/sdb
OSD_JOURNAL是用于存储OSD日志的设备,如:/dev/sdz
HOSTNAME是运行OSD容器主机的主机名(默认:$(hostname))
OSD_FORCE_ZAP将强制指定设备内容zapping(默认值:0,1是开启)
OSD_JOURNAL_SIZE是OSD日志大小(默认值:100)

METADATA SERVER

这个是非常直观和容易实现的。目前唯一要注意的是Docker中需要Ceph管理员密钥。这个密钥将被用来创建CephFS池和文件系统。如果你运行旧版本的Ceph(0.87之前的版本)你不用这个。但是最好运行最新版本,所以你还是需要!

$ sudo docker run -d --net=host \
 -v /var/lib/ceph/:/var/lib/ceph \
 -v /etc/ceph:/etc/ceph \
 -e CEPHFS_CREATE=1 \
 ceph-daemon mds

可用选项列表:

MDS_NAME是元数据服务的名称(默认:mds-$(hostname))
CEPHFS_CREATE会为元数据服务创建一个文件系统(默认值:0,1是启用)
CEPHFS_NAME是元数据文件系统的名称(默认:cephfs)
CEPHFS_DATA_POOL是元数据服务的数据池名称(默认:cephfs_data)
CEPHFS_DATA_POOL_PG是数据池placement group的数量(默认值:8)
CEPHFS_DATA_POOL是元数据服务的元数据池名称(默认:cephfs_metadata)
CEPHFS_METADATA_POOL_PG是元数据池placement group的数量(默认值:8)
RADOS GATEWAY

对于Rados Gateway,我们部署时会默认开启civetweb。也可以通过简单地指定远程地址和端口以使用不同的CGI前端。

$ sudo docker run -d --net=host \
 -v /var/lib/ceph/:/var/lib/ceph \
 -v /etc/ceph:/etc/ceph \
 ceph-daemon rgw

可用选项列表:

RGW_REMOTE_CGI指定是否使用Rados Gateway嵌入的Web服务(默认值:0,1是不使用)
RGW_REMOTE_CGI_HOST指定运行CGI进程的远程主机
RGW_REMOTE_CGI_PORT运行CGI进程的远程主机端口
RGW_CIVETWEB_PORT是civetweb的监听端口(默认:80)
RGW_NAME是Rados Gateway实例名称(默认:$(hostname))

后续工作

配置存储后端

缺省情况下,在monitor首次启动时,会生成ceph.conf和所有的CEPH密钥。此过程假设你将集群扩展到多个节点时,你会分发这些配置到所有节点。这一点都不灵活,我们希望改善这一点。我马上提出的一个方案是使用Ansible生成配置/密钥并分发他们到所有机器。

另外,我们也希望能够在不同的后端KV存储上存储所有配置文件,例如etcd和consul。

编排部署

最简单的方法是使用ceph-ansible,其中主要的逻辑已经完成了。我只需要再提交一些修改,而且大部分的工作已经完成。

Kubernetes也发布了可用的运行monitors的预览版。

Rocket等其他容器技术延伸

你可以简单地将你的Docker镜像放到Rocket容器环境中并启动他们(这里一语双关,你懂了没?)。

 

分享到:更多 ()