最近收到一个需求,客户希望将运行了多年的ceph集群服务器全部更换掉,因为这些老服务器性能和容量都已经无法满足当前业务的需求,并希望在迁移到新服务器的过程中,业务不中断。在参考一些网上的方案后,选择了一个方案进行了测试,效果还不错,决定将测试过程记录下来,并且自己写了些自动化的脚本,希望以后迁移能够变得更轻松。
本文测试环境为centos7,+ceph 14.2.0,主要使用RBD(块存储),暂不包含RGW,MDS。
具体节点配置如下:
主机名 | IP地址 | Ceph 组件 |
---|---|---|
node1 | 192.168.10.17 | mon,osd*1 |
node2 | 192.168.10.18 | mon,osd*1 |
node3 | 192.168.10.19 | mon,osd*1 |
集群迁移完成后,各组件分布如下:(将node1,node2,node3上的集群迁移到node4,node5,node6这3台新机器上)
主机名 | IP地址 | Ceph 组件 |
---|---|---|
node1 | 192.168.10.17 | |
node2 | 192.168.10.18 | |
node3 | 192.168.10.19 | |
node4 | 192.168.10.123 | mon,osd*2 |
node5 | 192.168.10.124 | mon,osd*2 |
node6 | 192.168.10.125 | mon,osd*2 |
注意:原集群一共3个osd,我在每个新节点上多增加了一块硬盘,所以迁移后集群共有6个osd
(注意:osd_crush_update_on_start = false 这一项必须设置为false,否则加入osd后会自动分配到默认的crush下,造成了数据迁移。)
编辑config.ini配置文件,添加集群信息。示例配置如下:
#重要:请保证配置信息正确,不要配错,否则会影响到数据迁移后续操作
#此项name属性为需要迁移的存储池名称,size为此存储池的副本数
[pool]
name=rbd
size=3
#此项name属性所有新节点的主机名,用“,”号隔开(请用英文输入法的逗号隔开,不要有空格)
[host]
name=node4,node5,node6
#以下配置为新节点所对应的osd信息,其中osd属性为osd的id,size属性为osd的大小,单位为GB,用“,”号隔开(请用英文输入法的逗号隔开,不要有空格)
#此项配置意思为在节点node4上有两个osd,分别为osd.3 大小为20GB,osd.4,大小为20GB.
[node4]
osd=3,4
size=20,20
#此项配置意思为在节点node5上有两个osd,分别为osd.5 大小为20GB,osd.6,大小为20GB.
[node5]
osd=5,6
size=20,20
#此项配置意思为在节点node6上有两个osd,分别为osd.7 大小为20GB,osd.8,大小为20GB.
[node6]
osd=7,8
size=20,20
确认config.ini信息配置无误后,开始迁移数据。
1.执行sh crush.sh(此脚本会创建一些迁移规则,如下图所示,等待控制台不再刷新集群动态的消息时,按ctrl+c退出集群监控,继续执行下面的步骤,若想再次打开集群监控,可执行ceph -w命令)
rule.sh:(crush.sh会调用)
#!/bin/bash
poolName=$1
migrateCrush=$2
size=$3
maxId=$4
echo "rule src_${size} {
id $[${maxId}+1]
type replicated
min_size 1
max_size 10
step take ${poolName}
step chooseleaf firstn ${size} type host
step emit
}
rule src_temp_${size} {
id $[${maxId}+2]
type replicated
min_size 1
max_size 10
step take ${poolName}
step chooseleaf firstn ${size} type host
step emit
step take ${migrateCrush}
step chooseleaf firstn ${size} type host
step emit
}
rule target_${size} {
id $[${maxId}+3]
type replicated
min_size 1
max_size 10
step take ${migrateCrush}
step chooseleaf firstn ${size} type host
step emit
}"
crush.sh:
#!/bin/bash
config="config.ini"
poolName=`awk -F '=' '/\[pool\]/{a=1}a==1&&$1~/name/{print $2;exit}' $config`
poolSize=`awk -F '=' '/\[pool\]/{a=1}a==1&&$1~/size/{print $2;exit}' $config`
migrateCrush=$poolName"_migrate_temp"
ceph osd crush add-bucket $migrateCrush root
hostnames=`awk -F '=' '/\[host\]/{a=1}a==1&&$1~/name/{print $2;exit}' $config`
for hostname in `echo "$hostnames" | sed 's/,/\n/g'`
do
ceph osd crush add-bucket $hostname"_"$poolName host
ceph osd crush move $hostname"_"$poolName root=$migrateCrush
osds=`awk -F '=' '/\['$hostname'\]/{a=1}a==1&&$1~/osd/{print $2;exit}' $config`
sizes=`awk -F '=' '/\['$hostname'\]/{a=1}a==1&&$1~/size/{print $2;exit}' $config`
sizeArr=(${sizes//,/ })
index=0
for osd in `echo "$osds" | sed 's/,/\n/g'`
do
weight=`awk 'BEGIN{printf "%0.5f",'${sizeArr[$index]}'/1000}'`
ceph osd crush create-or-move osd.$osd $weight host=$hostname"_"$poolName
done
done
ceph osd getcrushmap -o crushmap
crushtool -d crushmap -o crushmap.txt
id=`grep 'id' -A 0 crushmap.txt |tail -n 1`
idArr=(${id// / })
maxId=${idArr[1]}
sh rule.sh $poolName $migrateCrush $poolSize $maxId>> crushmap.txt
crushtool -c crushmap.txt -o crushmap.bin
ceph osd setcrushmap -i crushmap.bin
ceph osd pool set $poolName crush_rule "src_"$poolSize
ceph osd pool set $poolName size $[$poolSize*2]
ceph -w
2.执行sh migrate.sh(此脚本开始复制集群数据,数据量越大耗时越长,等待集群ok了就代表复制完毕,执行ceph -w可监控集群实时状态)
#!/bin/bash
config="config.ini"
poolName=`awk -F '=' '/\[pool\]/{a=1}a==1&&$1~/name/{print $2;exit}' $config`
poolSize=`awk -F '=' '/\[pool\]/{a=1}a==1&&$1~/size/{print $2;exit}' $config`
ceph osd pool set $poolName crush_rule "src_temp_"$poolSize
ceph -w
3,.执行sh target.sh(此脚本将删除旧osd上的数据,看到cluster is now healthy表示完成)
#!/bin/bash
config="config.ini"
poolName=`awk -F '=' '/\[pool\]/{a=1}a==1&&$1~/name/{print $2;exit}' $config`
poolSize=`awk -F '=' '/\[pool\]/{a=1}a==1&&$1~/size/{print $2;exit}' $config`
ceph osd pool set $poolName crush_rule "target_"$poolSize
ceph osd pool set $poolName size $poolSize
ceph -w
此时集群数据已经完成迁移,可以将旧的osd删除掉
先增加一个MON,成功后再删除一个MON。
1.将node4设置为mon和管理节点。
2.将node1的mon和管理节点去掉。
3.将node5设置为mon和管理节点。
4.将node2的mon和管理节点去掉。
5.将node6设置为mon和管理节点。
6.将node3的mon和管理节点去掉。
mon和osd等服务都迁移完成后就可以删除旧的主机了。