Ceph 和防火墙的故事

转自: http://www.xuxiaopang.com/2016/10/31/exp-turn-on-firewalld-of-one-node/
实验目的
前段时间,有一个存储节点的系统盘进行了重装,按照正常流程:重装系统->配置系统->部署ceph->重建journal->OSD上线,很快就可以恢复了,可是当时这个节点的OSD上线后,导致前台的VM批量不能开机,紧急处理方法是临时先将这个节点的OSD下线,VM就能正常开机了,后来思考了半天意识到可能是防火墙没有关导致的,并且这个问题的现象是可以复现的,于是就有了下面的实验,目的是探讨下一个节点的防火墙没有关闭,对整个ceph集群有什么样的影响。

实验过程
这里完全模拟上述环境进行搭建了一个类似的ceph环境:

CentOS 7.1511 + Hammer 0.94.7。
三个主机ceph-1,ceph-2,ceph-3,每台上面部署一个MON和一个OSD。
建立三个pool:size-1,size-2,size-3,各有1,2,3个副本。
删除ceph-2这个节点上的MON,卸载OSD,开始实验。

[root@ceph-1 cluster]# ceph -s
    cluster f1136238-80d6-4c8e-95be-787fba2c2624
     health HEALTH_WARN

            1/3 in osds are down
            1 mons down, quorum 0,2 ceph-1,ceph-3
     monmap e1: 3 mons at {ceph-1=172.23.0.101:6789/0,ceph-2=172.23.0.102:6789/0,ceph-3=172.23.0.103:6789/0}
            election epoch 20, quorum 0,2 ceph-1,ceph-3
     osdmap e31: 3 osds: 2 up, 3 in; 44 remapped pgs
      pgmap v49: 256 pgs, 4 pools, 0 bytes data, 0 objects
            74420 kB used, 4083 GB / 4083 GB avail
                 128 active+undersized+degraded
                  62 active+clean
                  44 active+remapped
                  22 stale+active+clean

开启ceph-2的防火墙,重装ceph-2这个节点上的MON和OSD,注意重装MON我采用的是mon create-initial,重装OSD我采用的是直接挂载启动:

[root@ceph-2 mon]# systemctl start  firewalld
[root@ceph-1 cluster]# ceph-deploy mon create-initial
[root@ceph-2 mon]# mount /dev/sdb1  /var/lib/ceph/osd/ceph-1/
[root@ceph-2 mon]# service ceph start osd.1
=== osd.1 === 
create-or-move updated item name 'osd.1' weight 1.99 at location {host=ceph-2,root=default} to crush map
Starting Ceph osd.1 on ceph-2...
Running as unit ceph-osd.1.1477890009.210635415.service.
[root@ceph-2 mon]# ceph -s
    cluster f1136238-80d6-4c8e-95be-787fba2c2624
     health HEALTH_OK
     monmap e1: 3 mons at {ceph-1=172.23.0.101:6789/0,ceph-2=172.23.0.102:6789/0,ceph-3=172.23.0.103:6789/0}
            election epoch 32, quorum 0,1,2 ceph-1,ceph-2,ceph-3
     osdmap e82: 3 osds: 3 up, 3 in
      pgmap v132: 256 pgs, 4 pools, 0 bytes data, 0 objects
            118 MB used, 6125 GB / 6125 GB avail
                 256 active+clean

这时候,集群是正常的!这是很可怕的事情,注意,osd.1是ceph-2这个节点上的,该节点的防火墙被打开了。

现在来做几个有意思的实验来说明防火墙的影响,我们先找几个有代表性的PG:

[root@ceph-2 mon]# ceph df
GLOBAL:
    SIZE      AVAIL     RAW USED     %RAW USED 
    6125G     6125G         118M             0 
POOLS:
    NAME       ID     USED     %USED     MAX AVAIL     OBJECTS 
    rbd        0         0         0         2041G           0 
    size-1     1         0         0         6125G           0 
    size-2     2         0         0         3062G           0 
    size-3     3         0         0         2041G           0
Num PG  Pool    OSD
T1  1.1a    size-1  [1]
T2  1.1c    size-1  [2]
2.3 size-2  [2,0]
T3  2.5 size-2  [2,1]
T4  2.25    size-2  [1,0]
3.1 size-3  [1,0,2]

T1: 首先,向PG 1.1a写入数据,分为在ceph-2节点执行写入指令,和在其他节点执行写入指令:

-------在ceph-2写入,很快返回,写入成功。

[root@ceph-2 mon]# ceph osd map size-1 file
osdmap e173 pool 'size-1' (1) object 'file' -> pg 1.2e6fb49a (1.1a) -> up ([1], p1) acting ([1], p1)
[root@ceph-2 mon]# rados -p size-1 put file /etc/ceph/ceph.conf 
[root@ceph-2 mon]# 

-------在ceph-1写入,指令卡死,写入失败。

[root@ceph-1 cluster]# rados -p size-1 put file /etc/ceph/ceph.conf
2016-10-31 01:31:10.903053 7fa436afb700  0 -- 172.23.0.101:0/3070569903 >> 172.23.0.102:6800/6965 pipe(0x2f9a010 sd=5 :0 s=1 pgs=0 cs=0 l=1 c=0x2f92a80).fault
^Z
[1]+  已停止               rados -p size-1 put file /etc/ceph/ceph.conf

可见,在ceph-2节点上,可以正常写入,因为这不需要通过防火墙,而在ceph-1写入时,客户端需要连接到ceph-2的osd.1,此时防火墙打开,请求被挡住了,写入失败。

T2: 现在向PG 1.1c写入数据,同样分为在ceph-2内外两种情况:

-------在ceph-2写入,很快返回,写入成功。

[root@ceph-2 mon]# ceph osd map size-1 file-2
osdmap e201 pool 'size-1' (1) object 'file-2' -> pg 1.fb2f2dc (1.1c) -> up ([2], p2) acting ([2], p2)
[root@ceph-2 mon]# rados -p size-1 put file-2 /etc/ceph/ceph.conf 
[root@ceph-2 mon]#

-------在ceph-1写入,很快返回,写入成功。

[root@ceph-1 cluster]# rados -p size-1 put file-2 /etc/ceph/ceph.conf
[root@ceph-1 cluster]#

因为PG 1.1c位于osd.2即ceph-3这个节点上,所以从ceph-2这个节点写入没有问题,同样从ceph-1节点写入也没有问题。

很容易猜测到,向PG 2.3写入都正常,实验现象也一致。

T3: 继续向PG 2.5写入数据:

--------在ceph-2写入,很快返回,写入成功

[root@ceph-2 mon]# ceph osd map size-2 file-1
osdmap e229 pool 'size-2' (2) object 'file-1' -> pg 2.9c8cdcc5 (2.5) -> up ([2,1], p2) acting ([2,1], p2)
[root@ceph-2 mon]# rados -p size-2 put file-1 /etc/ceph/ceph.conf 
[root@ceph-2 mon]#

-------在ceph-1写入,居然,写入成功了

[root@ceph-1 cluster]# rados -p size-2 put file-1 /etc/ceph/ceph.conf
[root@ceph-1 cluster]#

很容易理解,在ceph-2中写入成功。但是在ceph-1中写入也成功了,这里我的理解是这样的,首先客户端向osd.2写入主副本,然后osd.2向osd.1进行从副本的拷贝,但是这里的拷贝应该是失败的,因为osd.1的防火墙被打开了,但是这里是成功的,是因为osd.1在上线时,建立了和osd.2的peer关系,从osd.1->osd.2建立了socket通讯关系,那么这条通讯线路应该形如osd.1<->osd.2,所以,osd.2就可以向osd.1进行副本拷贝。

T4 : 综合T1的外部写入失败,和T3的外部写入成功,我找了一个PG,其OSD分布为[1,0],也就是说,主OSD在osd.1上,实验结果如下:

[root@ceph-3 ~]# ceph osd map size-2 file-6
osdmap e412 pool 'size-2' (2) object 'file-6' -> pg 2.bc387525 (2.25) -> up ([1,0], p1) acting ([1,0], p1)

------在ceph-2上写入,很快返回,写入成功

[root@ceph-2 ~]# rados -p size-2 put file-6 /etc/ceph/ceph.conf 
[root@ceph-2 ~]#

------在ceph-1上写入,卡死,写入失败。

[root@ceph-1 ~]# rados -p size-2 put file-6 /etc/ceph/ceph.conf
2016-10-31 04:51:19.329528 7f20d686b700  0 -- 172.23.0.101:0/3159973327 >> 172.23.0.102:6800/3532 pipe(0x7f20cc00c3b0 sd=6 :0 s=1 pgs=0 cs=0 l=1 c=0x7f20cc010650).fault
^Z
[1]+  已停止               rados -p size-2 put file-6 /etc/ceph/ceph.conf
这里的情况就很容易理解了,因为客户端从ceph-1节点上写入数据时,是建立与osd.1的通讯关系,这时候被防火墙挡住,所以写入失败。

对于三副本,我们可以按照刚刚四个实验进行猜测,对于形如[1,0,2]的PG,只要从外部写入都会是失败的,因为主OSD:osd.1的防火墙被打开,无法建立通讯,但是对于形如[0,1,2]的PG,写入会成功,因为主OSD可以正常通讯,然后osd.1和其他OSD从osd.1的主机内部向外建立通讯关系,使得他们之间的通讯是没有被防火墙阻碍的。这些猜测已经证实过,没有问题。

在实验过程中,查看ceph -w可以看到如下一段log:


mon.0 [INF] pgmap v846: 256 pgs: 256 active+clean; 1190 bytes data, 133 MB used, 6125 GB / 6125 GB avail
mon.0 [INF] osd.1 172.23.0.102:6800/3532 failed (8 reports from 2 peers after 21.271377 >= grace 20.995909)
mon.0 [INF] osdmap e546: 3 osds: 2 up, 3 in
mon.0 [INF] pgmap v847: 256 pgs: 89 stale+active+clean, 167 active+clean; 1190 bytes data, 133 MB used, 6125 GB / 6125 GB avail
mon.0 [INF] osdmap e547: 3 osds: 2 up, 3 in
mon.0 [INF] pgmap v848: 256 pgs: 89 stale+active+clean, 167 active+clean; 1190 bytes data, 133 MB used, 6125 GB / 6125 GB avail
mon.0 [INF] osd.1 172.23.0.102:6800/3532 boot
mon.0 [INF] osdmap e548: 3 osds: 3 up, 3 in
mon.0 [INF] pgmap v849: 256 pgs: 89 stale+active+clean, 167 active+clean; 1190 bytes data, 133 MB used, 6125 GB / 6125 GB avail
mon.0 [INF] osdmap e549: 3 osds: 3 up, 3 in
mon.0 [INF] pgmap v850: 256 pgs: 89 stale+active+clean, 167 active+clean; 1190 bytes data, 133 MB used, 6125 GB / 6125 GB avail
osd.1 [WRN] map e547 wrongly marked me down
mon.0 [INF] pgmap v851: 256 pgs: 89 stale+active+clean, 167 active+clean; 1190 bytes data, 132 MB used, 6125 GB / 6125 GB avail
mon.0 [INF] pgmap v852: 256 pgs: 256 active+clean; 1190 bytes data, 137 MB used, 6125 GB / 6125 GB avail
有几个关键字:

8 reports from 2 peers after 21.271377 >= grace 20.995909
3 osds: 2 up, 3 in
osd.1 172.23.0.102:6800/3532 boot
map e547 wrongly marked me down
pgmap v852: 256 pgs: 256 active+clean;
也就是说在一些peer关系的OSD报告这个osd.1无法建立peer关系后,也就是osd.0和osd.2从外部向osd.1建立peer关系失败了,集群就会主动上报osd.1为down,但是实际上,osd.1并没有挂掉,因为它无法接受从外部过来的通讯请求,所以它向集群汇报自己被错误的标记为down了,这时候是osd.1自内向外发送请求,所以不会被堵塞,然后集群在接收到自UP信息之后,会再次将该OSD标记为UP,然后就进入了一个死循环,如果grace时间被设置较长,那么很容忽略掉这个OSD的down的过程,而长时间认为这个OSD是UP的,从人为角度来看,UP的OSD写入数据是没有问题的,但是实际上,Openstack+Ceph的写入可以看做都是从外部写入的,所以对于主OSD的防火墙被打开的PG,所有请求会被阻塞。再回过头来看最开始的VM无法开机的情况就可以理解了,同时,关闭那个节点的所有OSD后,主OSD被转移到其他节点的副OSD上了,写入就可以成功了。

实验结论
这个实验正好验证了ceph的写入过程:client-> osd.primary -> osd.secondary,打开防火墙会阻塞client->osd.primary的写操作,但是不会阻塞副本间的拷贝操作,我的理解就是osd.primary<->osd.secondary 通讯关系可以从防火墙内部向外部建立,一旦建立就不会受防火墙阻塞,所以尽管osd.seconday防火墙被打开,也可以正常写入。

你可能感兴趣的:(Ceph 和防火墙的故事)