在一个四节点的Docker Swarm集群上,尝试使用Ceph做为Docker集群的共享存储,解决有状态服务在分布式环境下的数据存储问题。html
通过尝试,成功使用CephFS实现了多个Docker节点之间的存储共享。但同时注意到,对于小规模Docker集群而且运维成本有限的场景,Ceph这样的分布式对象存储系统仍然显得有点重了,本文的4节点docker swarm集群上,在Ceph集群与Portainer-Agent(docker运维工具)部署以后,容器数量达到了30个。所以最终决定采用其余方案实现小规模docker集群的共享存储,好比NFS。node
但Ceph做为一个高可用高性能的分布式对象/块/文件存储系统,在其余场景仍是有使用价值的。python
本文主要记述Ceph的搭建过程以及如何用cephfs实现docker swarm集群的共享存储。其余诸如原理机制,运维资料等请参考社区文档。linux
Ceph对外提供了三种存储接口,分别是对象存储 RGW(rados gateway)、块存储 RBD(rados block device) 和文件存储 CephFS。RGW是RestAPI,docker的数据卷没法直接使用。从性能角度考虑,应该是RBD最快,但本文使用的Ceph版本与使用RBD作共享存储所须要的中间件RexRay貌似存在版本不兼容问题,最终没能成功。。。git
最终本文使用了CephFS来实现docker swarm集群的共享存储。github
本文搭建Ceph使用了目前社区文档推荐的安装工具cephadm
,安装的版本为octopus
。四个节点的操做系统均为CentOS7
。docker
https://docs.ceph.com/docs/master/
http://docs.ceph.org.cn/
注意,编写本文时,中文社区文档并不是最新版本,好比社区文档中目前建议使用的安装工具
cephadm
在中文社区文档中就没有相关资料。
No | ip | hostname | OSD盘 | Ceph角色 |
---|---|---|---|---|
1 | 172.17.13.1 | manager01.xxx.com | /dev/sdb | mon,osd,ceph-mds,mgr |
2 | 172.17.13.2 | manager02.xxx.com | /dev/sdb | mon,osd,ceph-mds |
3 | 172.17.13.3 | worker01.xxx.com | /dev/sdb | mon,osd,ceph-mds |
4 | 172.17.13.4 | worker02.xxx.com | /dev/sdb | mon,osd,ceph-mds,mgr,cephadm,NTP服务器 |
Ceph用于存储数据的服务OSD须要使用干净的磁盘,要求以下:shell
- 设备没有分区
- 设备不得具备任何LVM状态
- 设备没有挂载
- 设备不包含任何文件系统
- 设备不包含ceph bluestore osd
- 设备必须大于5G
也就是给节点增长一块新磁盘以后,只要linux能识别到便可,不要作分区/格式化/mount等操做。json
提早将Ceph相关防火墙规则设置好。或直接关闭防火墙。bootstrap
firewall-cmd --permanent --zone=public --add-service=http firewall-cmd --permanent --zone=public --add-service=https firewall-cmd --permanent --zone=public --add-service=ceph firewall-cmd --permanent --zone=public --add-service=ceph-mon firewall-cmd --reload firewall-cmd --zone=public --list-services firewall-cmd --zone=public --add-port=3300/tcp --permanent firewall-cmd --zone=public --add-port=3300/udp --permanent firewall-cmd --zone=public --add-port=6789/tcp --permanent firewall-cmd --zone=public --add-port=6800-7300/tcp --permanent firewall-cmd --zone=public --add-port=8443/tcp --permanent firewall-cmd --reload firewall-cmd --zone=public --list-ports
Ceph集群在使用中最好禁用Selinux。在各个节点上以root用户vi /etc/selinux/config
,修改:
#SELINUX=enforcing SELINUX=disabled
而后执行setenforce 0
从阿里云镜像获取/etc/yum.repos.d/epel.repo
,以下:
wget -O /etc/yum.repos.d/epel.repo http://mirrors.aliyun.com/repo/epel-7.repo
填坑的过程当中尝试过不一样的搭建方案,这里有些依赖库可能不是必须的。。。
yum -y install python3 yum-utils yum install yum-plugin-priorities -y yum install gcc python-setuptools python-devel -y easy_install pip
本文的环境已经提早安装了docker ce,docker compose,并建立了docker swarm集群。
每一个节点都须要先安装好Docker,具体方法参考官方文档:https://docs.docker.com/engine/install/centos/
。
注意最好使用国内的dokcer安装yum镜像。
yum-config-manager \ --add-repo \ http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
安装完成以后,添加docker镜像仓库地址,vi /etc/docker/daemon.json
,添加:
"registry-mirrors": [ "https://docker.mirrors.ustc.edu.cn", "https://dockerhub.azk8s.cn", "https://reg-mirror.qiniu.com", "https://hub-mirror.c.163.com", "https://mirror.ccs.tencentyun.com", "https://registry.docker-cn.com" ],
而后重启docker服务:
systemctl daemon-reload systemctl restart docker
而后提早为每一个节点拉取Ceph相关镜像:
docker pull ceph/ceph:v15 docker pull ceph/ceph-grafana docker pull prom/prometheus:v2.18.1 docker pull prom/alertmanager:v0.20.0 docker pull prom/node-exporter:v0.18.1
各节点安装ntp服务
yum install ntp ntpdate ntp-doc -y
在管理节点worker02.xxx.com
上安装ntp服务,vi /etc/ntp.conf
:
... restrict 127.0.0.1 restrict ::1 restrict 172.17.13.0 mask 255.255.255.0 # Hosts on local network are less restricted. #restrict 192.168.1.0 mask 255.255.255.0 nomodify notrap # Use public servers from the pool.ntp.org project. # Please consider joining the pool (http://www.pool.ntp.org/join.html). #server 0.centos.pool.ntp.org iburst #server 1.centos.pool.ntp.org iburst #server 2.centos.pool.ntp.org iburst #server 3.centos.pool.ntp.org iburst server 127.127.1.0 ...
配置了NTP服务的管理节点须要防火墙配置端口:
firewall-cmd --zone=public --add-port=123/udp --permanent firewall-cmd --reload firewall-cmd --zone=public --list-ports
在其余节点设置ntp服务器为刚刚设定的ntp服务器,vi /etc/ntp.conf
:
… # Use public servers from the pool.ntp.org project. # Please consider joining the pool (http://www.pool.ntp.org/join.html). server worker02.xxx.com #server 0.centos.pool.ntp.org iburst #server 1.centos.pool.ntp.org iburst #server 2.centos.pool.ntp.org iburst #server 3.centos.pool.ntp.org iburst …
重启各个节点的ntp服务,并设置开机启动:
systemctl enable ntpd systemctl restart ntpd systemctl status ntpd # Centos7默认安装了chronyd而且默认enable,这里须要关闭,不然重启之后会致使ntpd不能启动 systemctl disable chronyd
管理节点从外网同步时间,其余节点从管理节点同步时间:
# 管理节点 ntpdate -u ntp1.aliyun.com # 其余节点 ntpdate -u worker02.xxx.com
各节点默认已安装,能够更新最新版本,并确认服务状态
yum install openssh-server -y service sshd status
在每一个节点以root身份vi /etc/hosts
,添加:
172.17.13.1 manager01 172.17.13.2 manager02 172.17.13.3 worker01 172.17.13.4 worker02
Ceph默认使用短域名,社区文档在环境检查中要求能以短域名ping通,但本文环境都是用的FQDN,这里即便设置短域名到hosts文件,后续依然有些许小问题。
如下操做均在cephadm节点上执行。(本文规划将worker02.xxx.com
做为cephadm节点)
cd ~ mkdir cephadmin cd cephadmin curl --silent --remote-name --location https://hub.fastgit.org/ceph/ceph/raw/octopus/src/cephadm/cephadm chmod +x cephadm ll -h
官方地址
https://github.com/ceph/ceph/raw/octopus/src/cephadm/cephadm
老是下载失败,所以使用了国内某镜像地址。
如下操做均在cephadm节点上执行。
生成ceph的yum源文件并将其替换为使用阿里云yum源:
./cephadm add-repo --release octopus cat /etc/yum.repos.d/ceph.repo sed -i 's#download.ceph.com#mirrors.aliyun.com/ceph#' /etc/yum.repos.d/ceph.repo cat /etc/yum.repos.d/ceph.repo yum list | grep ceph
注意版本是
octopus
安装cephadm:
./cephadm install which cephadm
引导ceph集群:
mkdir -p /etc/ceph cephadm bootstrap --mon-ip 172.17.13.4 --allow-fqdn-hostname
成功后会出现以下信息:
... INFO:cephadm:Ceph Dashboard is now available at: URL: https://worker02.xxx.com:8443/ User: admin Password: 3y44vf60ms INFO:cephadm:You can access the Ceph CLI with: sudo /usr/sbin/cephadm shell --fsid fbd10774-c8cf-11ea-8bcc-00505683571d -c /etc/ceph/ceph.conf -k /etc/ceph/ceph.client.admin.keyring INFO:cephadm:Please consider enabling telemetry to help improve Ceph: ceph telemetry on For more information see: https://docs.ceph.com/docs/master/mgr/telemetry/ INFO:cephadm:Bootstrap complete.
尝试登陆Ceph CLI:
[root@worker02 ~]# cephadm shell --fsid fbd10774-c8cf-11ea-8bcc-00505683571d -c /etc/ceph/ceph.conf -k /etc/ceph/ceph.client.admin.keyring INFO:cephadm:Using recent ceph image ceph/ceph:v15 [ceph: root@worker02 /]# exit exit
在浏览器中访问https://worker02.xxx.com:8443/
,打开 ceph ui, 第一次登录要求更改默认密码
域名访问前先配置浏览器所在节点的hosts文件
如下操做均在cephadm节点上执行。
安装 ceph 工具包, 其中包括 ceph, rbd, mount.ceph 等命令:
cephadm install ceph-common
验证集群状态:
# 查看 ceph 集群全部组件运行状态 ceph orch ps # 查看指定组件运行状态 ceph orch ps --daemon-type mon # 查看集群当前状态 ceph status ceph -s
将以前cephadm bootstrap初始化集群命令所生成的ceph密钥拷贝到其余节点root用户的"~/.ssh"目录。注意要输入其余节点root用户密码。
ssh-copy-id -f -i /etc/ceph/ceph.pub root@manager01.xxx.com ssh-copy-id -f -i /etc/ceph/ceph.pub root@manager02.xxx.com ssh-copy-id -f -i /etc/ceph/ceph.pub root@worker01.xxx.com
将其余节点加入集群
ceph orch host add manager01.xxx.com ceph orch host add manager02.xxx.com ceph orch host add worker01.xxx.com ceph orch host ls
查看集群当前服务分布(此时应该有4个crash,4个mon,两个mgr)
ceph orch ps
检查每一个节点是否有一块还没有分区的新磁盘,例如这里的sdb
:
[root@worker01 ~]# lsblk NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT fd0 2:0 1 4K 0 disk sda 8:0 0 300G 0 disk ├─sda1 8:1 0 500M 0 part /boot └─sda2 8:2 0 299.5G 0 part ├─centos-root 253:0 0 295.5G 0 lvm / └─centos-swap 253:1 0 4G 0 lvm [SWAP] sdb 8:16 0 300G 0 disk sr0 11:0 1 1024M 0 rom
对于虚拟机,在虚拟机控制台直接给运行中的虚拟机添加新磁盘以后,每一个节点执行如下命令就能够刷出磁盘信息,不用重启:
echo "- - -" > /sys/class/scsi_host/host0/scan echo "- - -" > /sys/class/scsi_host/host1/scan echo "- - -" > /sys/class/scsi_host/host2/scan
将新磁盘设备加入集群
ceph orch daemon add osd manager01.xxx.com:/dev/sdb ceph orch daemon add osd manager02.xxx.com:/dev/sdb ceph orch daemon add osd worker01.xxx.com:/dev/sdb ceph orch daemon add osd worker02.xxx.com:/dev/sdb # 查看设备信息 ceph orch device ls # 查看挂载好的osd信息 ceph osd df
为了在其余节点也可以直接访问Ceph集群,咱们须要在其余节点上也安装ceph-common。
cephadm之外的其余节点执行:
mkdir ~/cephadmin mkdir /etc/ceph
从cephadm节点以拷贝ceph.repo,cephadm,ceph集群配置文件,ceph客户端管理员密钥到其余节点:
scp /etc/yum.repos.d/ceph.repo root@manager01.xxx.com:/etc/yum.repos.d scp /etc/yum.repos.d/ceph.repo root@manager02.xxx.com:/etc/yum.repos.d scp /etc/yum.repos.d/ceph.repo root@worker01.xxx.com:/etc/yum.repos.d scp ~/cephadmin/cephadm root@manager01.xxx.com:~/cephadmin/ scp ~/cephadmin/cephadm root@manager02.xxx.com:~/cephadmin/ scp ~/cephadmin/cephadm root@worker01.xxx.com:~/cephadmin/ scp /etc/ceph/ceph.conf root@manager01.xxx.com:/etc/ceph/ scp /etc/ceph/ceph.conf root@manager02.xxx.com:/etc/ceph/ scp /etc/ceph/ceph.conf root@worker01.xxx.com:/etc/ceph/ scp /etc/ceph/ceph.client.admin.keyring root@manager01.xxx.com:/etc/ceph/ scp /etc/ceph/ceph.client.admin.keyring root@manager02.xxx.com:/etc/ceph/ scp /etc/ceph/ceph.client.admin.keyring root@worker01.xxx.com:/etc/ceph/
其余节点执行:
cd ~/cephadmin ./cephadm install ceph-common ceph -s
在执行ceph -s
或者ceph health
时,可能会发现以下的错误:
Module 'cephadm' has failed: auth get failed: failed to find client.crash.worker02 in keyring retval: -2
推测是Ceph对长域名支持不足的缘由。经过ceph auth ls
命令能够查看ceph集群全部的用户的密钥,能查到对应的长域名client.crash.worker02.xxx.com
用户但没有短域名用户。经过如下命令建立对应的短域名用户:
# 手动添加用户client.crash.xxx,任意节点执行 ceph auth add client.crash.worker02 mgr 'profile crash' mon 'profile crash' ceph auth add client.crash.manager01 mgr 'profile crash' mon 'profile crash' ceph auth add client.crash.manager02 mgr 'profile crash' mon 'profile crash' ceph auth add client.crash.worker01 mgr 'profile crash' mon 'profile crash' # 查看新增用户是否成功 ceph auth ls # 重启ceph集群,各个节点上都须要执行 systemctl restart ceph.target # 也能够用下面的命令中止再重启ceph集群,各个节点上都须要执行 systemctl stop ceph.target systemctl stop ceph\*.service ceph\*.target ps -ef | grep ceph docker ps -a systemctl restart ceph.target # 重启后从新检查状态 ceph -s
任意节点上执行:
# 建立一个用于cephfs数据存储的池,相关参数自行参阅社区文档,一言难尽。。。 ceph osd pool create cephfs_data 64 64 # 建立一个用于cephfs元数据存储的池 ceph osd pool create cephfs_metadata 32 32 # 建立一个新的fs服务,名为cephfs ceph fs new cephfs cephfs_metadata cephfs_data # 查看集群当前的fs服务 ceph fs ls # 设置cephfs最大mds服务数量 ceph fs set cephfs max_mds 4 # 部署4个mds服务 ceph orch apply mds cephfs --placement="4 manager01.xxx.com manager02.xxx.com worker01.xxx.com worker02.xxx.com" # 查看mds服务是否部署成功 ceph orch ps --daemon-type mds
本文在这里遇到一个问题,mds服务一直不能启动,查看ceph health
发现一个1 filesystem is online with fewer MDS than max_mds
的警告,应该是ceph fs set cephfs max_mds 4
没有生效。后来重启了整个集群就行了。
# 在全部节点上执行 systemctl restart ceph.target # 重启以后检查相关服务 ceph orch ps --daemon-type mds ceph osd lspools ceph fs ls
建立用户,用于客户端访问CephFs
ceph auth get-or-create client.cephfs mon 'allow r' mds 'allow r, allow rw path=/' osd 'allow rw pool=cephfs_data' -o ceph.client.cephfs.keyring
查看输出的ceph.client.cephfs.keyring
密钥文件,或使用下面的命令查看密钥:
ceph auth get-key client.cephfs
在各个节点执行:
mkdir /mnt/cephfs/ mount -t ceph manager01.xxx.com:6789,manager02.xxx.com:6789,worker01.xxx.com:6789,worker02.xxx.com:6789:/ /mnt/cephfs/ -o name=cephfs,secret=<cephfs访问用户的密钥>
manager01.xxx.com:6789,manager02.xxx.com:6789,worker01.xxx.com:6789,worker02.xxx.com:6789 是全部mon服务
编辑各个节点的/etc/fstab
文件,实现开机自动挂载,添加如下内容:
manager01.xxx.com:6789,manager02.xxx.com:6789,worker01.xxx.com:6789,worker02.xxx.com:6789:/ /mnt/cephfs ceph name=cephfs,secretfile=<cephfs访问用户的密钥>,noatime,_netdev 0 2
相关参数请自行查阅linux下fstab的配置资料。
将挂载到本地的cephfs做为本地磁盘使用便可。例如本文中,能够在docker run命令中,或者docker compose编排文件中,使用volume本地挂载到/mnt/cephfs
下。
示例,注意volumes:
... portainer: image: portainer/portainer ... volumes: - /mnt/cephfs/docker/portainer:/data ... deploy: mode: replicated replicas: 1 placement: constraints: [node.role == manager] ...
至此,使用cephfs实现docker共享存储的尝试已经OK。
Ceph的RBD对外提供的是块存储,但块存储直接做为磁盘挂载到各节点的话,并不能实现不一样节点之间的数据共享。所以须要配合中间件Rexray
,以及docker插件rexray/rbd
来实现共享存储。
但本文并未成功,缘由后叙。
在任意节点上执行:
ceph osd pool create rbd01 32 rbd pool init rbd01 # 在rbd01上建立一个300G的image rbd create img01 --size 307200 --pool rbd01 rbd ls rbd01 rbd info --image img01 -p rbd01
此时能够在各个节点上挂载RBD的img01,可是并不能实现存储共享。
# 向linux系统内核载入rbd模块 modprobe rbd # 将img01映射到系统内核 rbd map img01 --pool rbd01 --id admin # 失败,须要禁用当前系统内核不支持的feature rbd feature disable img01 --pool rbd01 exclusive-lock, object-map, fast-diff, deep-flatten # 从新映射 rbd map img01 --pool rbd01 --id admin # 映射成功后,会返回映射目录"/dev/rbd0",对该目录进行格式化: [root@worker01 ~]# mkfs.xfs /dev/rbd0 meta-data=/dev/rbd0 isize=512 agcount=17, agsize=4914176 blks = sectsz=512 attr=2, projid32bit=1 = crc=1 finobt=0, sparse=0 data = bsize=4096 blocks=78643200, imaxpct=25 = sunit=1024 swidth=1024 blks naming =version 2 bsize=4096 ascii-ci=0 ftype=1 log =internal log bsize=4096 blocks=38400, version=2 = sectsz=512 sunit=8 blks, lazy-count=1 realtime =none extsz=4096 blocks=0, rtextents=0 # mount到本地 mkdir /mnt/data01 mount /dev/rbd0 /mnt/data01 # 查看本地磁盘信息 df -hT # 卸除挂载并删除image umount /mnt/data01 rbd unmap img01 --pool rbd01 --id admin rbd rm --image img01 -p rbd01
任意某个节点下载rexray:
curl -sSL https://rexray.io/install | sh
编辑配置文件vi /etc/rexray/config.yml
,内容以下:
rexray: logLevel: debug libstorage: logging: level: debug httpRequests: true httpResponses: true libstorage: service: rbd rbd: defaultPool: rbd01
尝试启动Rexray服务,这里一直失败:
[root@manager01 rexray]# rexray start ... error: service startup failed: agent: mod init failed: error initializing instance ID cache
日志中除了最后的错误,并没有其余有用的信息。在github对应项目的issue中有相似问题,解决方法是ceph配置文件/etc/ceph/ceph.conf
中添加mon_host
配置。但本文使用的ceph版本octopus
的配置文件中已经明确配置了mon_host
,且格式与issue所述不一样。最终也没有找到缘由,怀疑是Ceph版本太新,与rexray不兼容所致。因此这里的尝试到此为止,后续安装docker插件与建立rbd数据卷并未进行。
若是Rexray服务能成功启动,那么后续还须要在每一个节点安装docker插件rexray/rbd
:
docker plugin install rexray/rbd RBD_DEFAULTPOOL=rbd01 LINUX_VOLUME_FILEMODE=0777
最后在docker swarm上建立rbd驱动的数据卷:
docker volume create -d <rexrayHost>:5011/rexray/rbd <数据卷名称>
若是成功,docker run或编排文件中的volume使用事先建立好的数据卷便可实现存储共享。