目录

使用Docker部署Ceph

这篇文章是根据Sébastien Han的演示视频进行整理的,对过程中有问题的部分进行了修复。

Docker作为持久化集成的最佳工具,特别是在部署中有着得天独厚的优势。Ceph作为开源的分布式存储得到越来越多的使用,但是作为分布式系统,Ceph在部署和运维上仍然有不小的难度,本文重点介绍利用Docker快速的进行Ceph集群的创建,以及各个组件的安装。

部署环境

  • 至少需要三台虚拟机或者物理机,每台虚拟机或者物理机至少有两块硬盘,这里我是在一台物理机上用vagrant模拟出三台CentOS 6.6虚拟机进行的实验
  • 三台虚拟机需要安装docker,本文附带Docker加速方案
  • 获取ceph/daemon镜像

部署流程

/images/blogs/bootstrap-ceph-docker-flow.png

部署架构

主机名和集群的对应关系如下:

  • node1 -> 192.168.33.11
  • node2 -> 192.168.33.12
  • node3 -> 192.168.33.13

/images/blogs/bootstrap-ceph-docker-architecture.png

环境准备

安装Docker,下载镜像

国内安装Dcoker还是速度很慢的,这里推荐使用daocloud的加速方案。不但docker安装速度提高了,pull镜像的速度也大幅度提高。

1
curl -sSL https://get.daocloud.io/docker | sh

我是在CentOS系统上进行的测试,将docker加入自动启动,并启动docker,接下来pull ceph daemon镜像,该镜像包含了所有的ceph服务和entrypoint。

1
2
3
chkconfig docker
service docker start
docker pull ceph/daemon

启动第一个Monitor

在node1上启动第一个Monitor,注意,如果你的环境中IP和我不同,请修改MON_IP。

1
2
3
4
5
6
7
sudo docker run -d \
     --net=host \
     -v /etc/ceph:/etc/ceph \
     -v /var/lib/ceph/:/var/lib/ceph/ \
     -e MON_IP=192.168.33.11 \
     -e CEPH_PUBLIC_NETWORK=192.168.33.0/24 \
     ceph/daemon mon

验证一下效果:

1
docker ps
1
2
CONTAINER ID        IMAGE               COMMAND                CREATED             STATUS              PORTS               NAMES
7babea544ef1        ceph/daemon         "/entrypoint.sh mon"   3 seconds ago       Up 2 seconds                            backstabbing_brattain

查看一下集群状态:

1
docker exec 7babea544ef1 ceph -s

当前集群状态,能看到当前已经有一个mon启动起来了。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
    cluster 0de1fc5a-084d-4396-bb0b-59db72a9a439
     health HEALTH_ERR
            64 pgs stuck inactive
            64 pgs stuck unclean
            no osds
     monmap e1: 1 mons at {node1.docker.com=192.168.33.11:6789/0}
            election epoch 2, quorum 0 node1.docker.com
     osdmap e1: 0 osds: 0 up, 0 in
            flags sortbitwise
      pgmap v2: 64 pgs, 1 pools, 0 bytes data, 0 objects
            0 kB used, 0 kB / 0 kB avail
                  64 creating

复制配置文件

接下来需要将node1的配置文件复制到node2和node3上,复制的路径包含/etc/ceph和/var/lib/ceph/bootstrap-*下的所有内容。这些配置文件非常重要,如果没有这些配置文件的存在,我们在其他节点启动新的docker ceph daemon的时候会被认为是一个新的集群。 我们在node1执行以下命令:

1
2
3
4
5
6
7
ssh root@node2 mkdir -p /var/lib/ceph
scp -r /etc/ceph root@node2:/etc
scp -r /var/lib/ceph/bootstrap* root@node2:/var/lib/ceph

ssh root@node3 mkdir -p /var/lib/ceph
scp -r /etc/ceph root@node3:/etc
scp -r /var/lib/ceph/bootstrap* root@node3:/var/lib/ceph

启动第二个和第三个Monitor

在node2上执行:

1
2
3
4
5
6
7
sudo docker run -d \
     --net=host \
     -v /etc/ceph:/etc/ceph \
     -v /var/lib/ceph/:/var/lib/ceph/ \
     -e MON_IP=192.168.33.12 \
     -e CEPH_PUBLIC_NETWORK=192.168.33.0/24 \
     ceph/daemon mon

在node3上执行:

1
2
3
4
5
6
7
sudo docker run -d \
     --net=host \
     -v /etc/ceph:/etc/ceph \
     -v /var/lib/ceph/:/var/lib/ceph/ \
     -e MON_IP=192.168.33.13 \
     -e CEPH_PUBLIC_NETWORK=192.168.33.0/24 \
     ceph/daemon mon

在node1上查看集群状态:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
    cluster 0de1fc5a-084d-4396-bb0b-59db72a9a439
     health HEALTH_ERR
            64 pgs stuck inactive
            64 pgs stuck unclean
            no osds
     monmap e3: 3 mons at {node1.docker.com=192.168.33.11:6789/0,node2.docker.com=192.168.33.12:6789/0,node3.docker.com=192.168.33.13:6789/0}
            election epoch 6, quorum 0,1,2 node1.docker.com,node2.docker.com,node3.docker.com
     osdmap e1: 0 osds: 0 up, 0 in
            flags sortbitwise
      pgmap v2: 64 pgs, 1 pools, 0 bytes data, 0 objects
            0 kB used, 0 kB / 0 kB avail
                  64 creating

启动OSD的遇到的问题

按照原视频的介绍的方法,启动OSD可以直接指定某个分区,然后用osd_ceph_disk作为启动ceph/daemon的参数,之后docker镜像会自动的进行分区等动作。但是经过实际验证却发现在mkjournal创建错误,OSD无法启动。

经过和社区确认,发现这个Bug在之前版本中得到过修复,但是之后的版本又出现了。根据社区的建议使用jewel版本的ceph daemon进行了再次验证,发现问题依旧,所以这里介绍的方法只能退而求其次,采用手动方式分区、格式化,之后用osd_directory启动ceph/daemon。

这是github上的相关讨论:https://github.com/ceph/ceph-docker/issues/171

这是用osd_ceph_disk方式启动后的错误日志:

1
2
3
4
5
6
7
command_check_call: Running command: /usr/bin/ceph-osd --cluster ceph --mkfs --mkkey -i 4 --monmap /var/lib/ceph/tmp/mnt.BT8FXG/activate.monmap --osd-data /var/lib/ceph/tmp/mnt.BT8FXG --osd-journal /var/lib/ceph/tmp/mnt.BT8FXG/journal --osd-uuid 89e240e1-17e9-4d6c-8d4f-f1a3e0278b91 --keyring /var/lib/ceph/tmp/mnt.BT8FXG/keyring --setuser ceph --setgroup disk
2016-06-12 23:37:26.180610 7f8889654800 -1 filestore(/var/lib/ceph/tmp/mnt.BT8FXG) mkjournal error creating journal on /var/lib/ceph/tmp/mnt.BT8FXG/journal: (2) No such file or directory
2016-06-12 23:37:26.180752 7f8889654800 -1 OSD::mkfs: ObjectStore::mkfs failed with error -2
2016-06-12 23:37:26.180918 7f8889654800 -1 ** ERROR: error creating empty object store in /var/lib/ceph/tmp/mnt.BT8FXG: (2) No such file or directory
mount_activate: Failed to activate
unmount: Unmounting /var/lib/ceph/tmp/mnt.BT8FXG
command_check_call: Running command: /bin/umount -- /var/lib/ceph/tmp/mnt.BT8FXG

启动OSD

第一步先进行分区和格式化,这里只给出node1的操作方式,其他两个节点的方式类似。

先来安装必要的工具:

1
yum install -y parted xfsprogs
 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
[root@node1 vagrant]# parted /dev/sdb
GNU Parted 2.1
Using /dev/sdb
(parted) mklabel
New disk label type? gpt
(parted) p
Model: ATA VBOX HARDDISK (scsi)
Disk /dev/sdb: 107GB
Sector size (logical/physical): 512B/512B
Partition Table: gpt

Number  Start  End  Size  File system  Name  Flags

(parted) mkpart
Partition name?  []? "Linux filesystem"
File system type?  [ext2]? xfs
Start? 0G
End? 107GB
(parted) p
Model: ATA VBOX HARDDISK (scsi)
Disk /dev/sdb: 107GB
Sector size (logical/physical): 512B/512B
Partition Table: gpt

Number  Start   End    Size   File system  Name              Flags
 1      1049kB  107GB  107GB               Linux filesystem

(parted) quit

格式化:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
[root@node1 vagrant]# mkfs.xfs /dev/sdb1
meta-data=/dev/sdb1              isize=256    agcount=4, agsize=6553472 blks
         =                       sectsz=512   attr=2, projid32bit=1
         =                       crc=0        finobt=0
data     =                       bsize=4096   blocks=26213888, imaxpct=25
         =                       sunit=0      swidth=0 blks
naming   =version 2              bsize=4096   ascii-ci=0 ftype=0
log      =internal log           bsize=4096   blocks=12799, version=2
         =                       sectsz=512   sunit=0 blks, lazy-count=1
realtime =none                   extsz=4096   blocks=0, rtextents=0

我们把目录在node1上进行挂载。

1
2
mkdir -p /ceph/sdb
mount /dev/sdb1 /ceph/sdb

最后启动OSD,这里最重要的就是把我们刚刚挂载好的OSD的实际路径透传给Docker内部的/var/lib/ceph/osd,如果每个节点有多个OSD的情况下,只需要在Host上映射到不同的目录,启动Docker的时候变更和/var/lib/ceph/osd的映射关系即可。

1
2
3
4
5
6
7
8
sudo docker run -d \
    --net=host \
    -v /etc/ceph:/etc/ceph \
    -v /var/lib/ceph/:/var/lib/ceph/ \
    -v /dev/:/dev/ \
    -v /ceph/sdb:/var/lib/ceph/osd \
    --privileged=true \
    ceph/daemon osd_directory

按照同样的方法,将node2和node3的OSD也加入到集群,最终的效果如下:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
    cluster 0de1fc5a-084d-4396-bb0b-59db72a9a439
     health HEALTH_WARN
            clock skew detected on mon.node2.docker.com
            64 pgs degraded
            64 pgs stuck unclean
            64 pgs undersized
            Monitor clock skew detected
     monmap e3: 3 mons at {node1.docker.com=192.168.33.11:6789/0,node2.docker.com=192.168.33.12:6789/0,node3.docker.com=192.168.33.13:6789/0}
            election epoch 6, quorum 0,1,2 node1.docker.com,node2.docker.com,node3.docker.com
     osdmap e13: 3 osds: 3 up, 3 in
            flags sortbitwise
      pgmap v18: 64 pgs, 1 pools, 0 bytes data, 0 objects
            4551 MB used, 11306 MB / 16720 MB avail
                  64 active+undersized+degraded

创建MDS

创建好基本的环境,其他的就容易了很多,下面来启动MDS。

1
2
3
4
5
6
sudo docker run -d \
    --net=host \
    -v /etc/ceph:/etc/ceph \
    -v /var/lib/ceph/:/var/lib/ceph/ \
    -e CEPHFS_CREATE=1 \
    ceph/daemon mds

启动RGW,并且映射80端口

1
2
3
4
5
sudo docker run -d \
    -p 80:80 \
    -v /etc/ceph:/etc/ceph \
    -v /var/lib/ceph/:/var/lib/ceph/ \
    ceph/daemon rgw

最终的集群状态

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
    cluster 0de1fc5a-084d-4396-bb0b-59db72a9a439
     health HEALTH_WARN
            clock skew detected on mon.node2.docker.com
            48 pgs stuck inactive
            48 pgs stuck unclean
            Monitor clock skew detected
     monmap e3: 3 mons at {node1.docker.com=192.168.33.11:6789/0,node2.docker.com=192.168.33.12:6789/0,node3.docker.com=192.168.33.13:6789/0}
            election epoch 6, quorum 0,1,2 node1.docker.com,node2.docker.com,node3.docker.com
     mdsmap e5: 1/1/1 up {0=mds-node1.docker.com=up:active}
     osdmap e25: 3 osds: 3 up, 3 in
            flags sortbitwise
      pgmap v38: 128 pgs, 9 pools, 588 bytes data, 11 objects
            6791 MB used, 16996 MB / 25081 MB avail
                  80 active+clean
                  45 creating
                   3 creating+activating

总结

在Docker中部署Ceph并没有想象中的那么顺利,社区的版本中仍然有Bug需要解决。

Docker作为一种快捷的部署方式,的确可以大幅度提高Ceph的部署效率,提高扩展的速度。但是从另一个角度我们应该注意到,随着Docker的引入也改变了Ceph的运维方式,比如在OSD增减的时候,需要到容器中对Ceph集群进行维护。再比如配置文件变更后的重启问题等。

但是无论如何,我相信这些问题都会得到完美的解决,用Docker部署Ceph作为一种新的尝试,值得推广。 之后还会为大家带来,如何使用Ansible结合Docker更快速的部署Ceph集群,敬请期待。