找回密码
 注册
查看: 587|回复: 1

ceph整体集群迁移方案

[复制链接]

1

主题

0

回帖

12

积分

管理员

积分
12
QQ
发表于 2022-7-22 10:52:13 | 显示全部楼层 |阅读模式
本文的环境均为:Openstack+Ceph 运行虚拟机的场景,即主要使用RBD,不包含RGW,MDS。虚机的系统盘(Nova),云硬盘(Cinder),镜像盘(Glance)的块均保存在共享存储Ceph中。
环境准备. G, y$ u- N. r7 F! z9 N( P
# S! h+ b& O. l# f$ d, c/ Y% U1 v
本文环境为 Openstack (Kilo) + Ceph(Jewel)
本文所用的环境包含一套完整的 Openstack 环境,一套 Ceph 环境,其中 Nova/Cinder/Glance 均已经对接到了 Ceph 集群上,具体节点配置如下:
[td]
主机名IP地址Openstack 组件Ceph 组件
con192.168.10.10nova,cinder,glance,neutronmon,osd*1
com192.168.10.11nova,neutronmon,osd*1
ceph192.168.10.12 mon,osd*1
7 Q2 W1 Q) G& o8 S# B
在集群整体迁移完后,各个组件分布如下,也就是说,将运行于 con,com,ceph三个节点的 Ceph 集群迁移到 new_mon_1,new_mon_2,new_mon_3 这三台新机器上。
[td]
主机名IP地址Openstack 组件Ceph 组件
con192.168.10.10nova,cinder,glance,neutron
com192.168.10.11nova,neutron
ceph192.168.10.12
new_mon_1192.168.10.13 mon,osd*1
new_mon_2192.168.10.14 mon,osd*1
new_mon_3192.168.10.15 mon,osd*1

; U7 @0 Q* w' ^" V
在迁移之前,我们创建一个虚机,一个云盘,上传一个镜像,虚机此时正常运行,并将这这块云盘挂载到虚机上:
[root@con ~(keystone_admin)]# nova list & W5 x5 X) u: A6 ]' d
+--------------------------------------+---------+--------+------------+-------------+-------------------------+
/ l  b, l, G8 G/ x- a) m0 c3 n| ID                                   | Name    | Status | Task State | Power State | Networks                |" r4 Z7 k3 D" q& B7 \7 U3 m5 x
+--------------------------------------+---------+--------+------------+-------------+-------------------------+4 n$ C! {% t& L
| f52191f-9645-448f-977b-80ca515387f7 | vm1-test | ACTIVE | -          | Running     | provider=192.168.8.111 |
" e  H- G0 u# L4 M: w+--------------------------------------+---------+--------+------------+-------------+-------------------------+
6 k+ O4 w8 \6 Z' B  f6 A: Q[root@con ~(keystone_admin)]# cinder list
; Q" r1 N$ g2 @. l5 N9 U/ N( _+--------------------------------------+--------+--------------+------+-------------+----------+--------------------------------------+! e8 {! n+ Z1 [6 M, D! M  k$ l
|                  ID                  | Status | Display Name | Size | Volume Type | Bootable |             Attached to              |
1 K! r3 o2 Y! O" K% P+--------------------------------------+--------+--------------+------+-------------+----------+--------------------------------------+3 W# U/ d: b7 {* i
| 39c76d96-0f95-490c-b7db-b3da6d17331 | in-use |  cinder-rbd  |  1   |     None    |  false   | f52191f-9645-448f-977b-80ca515387f7 |" b3 S$ ^! R, M, R( g' ^, {
+--------------------------------------+--------+--------------+------+-------------+----------+--------------------------------------+, O: ?; k7 V0 F% g7 F9 U9 @6 x- H
[root@con ~(keystone_admin)]# ip netns exec `ip netns` ssh cirros@192.168.8.1115 B. F! u3 O. X2 w' R4 A
cirros@192.168.8.111's password:
! D8 @. G" L# v$ lsblk$ y  `9 t7 u9 q; O2 I# J% c
NAME   MAJ:MIN RM    SIZE RO TYPE MOUNTPOINT& |* i( N6 k0 l+ f1 E0 C- u
vda    253:0    0      1G  0 disk , x6 T# G3 Z& c* ]' C9 L+ @. V# K/ V: e
`-vda1 253:1    0 1011.9M  0 part /: \  N' u6 K$ }3 [
vdb    253:16   0      1G  0 disk
& L$ A: Q! I% a& y& B$
Ceph 集群状态:
[root@ceph cluster]# ceph -s
3 U) G: {. r& Q# R" z    cluster 166889ab-fa7b-4a07-83da-6dfc92913a3d
; \. u& v1 x  G6 M4 y8 U     health HEALTH_OK
. f  ~) _4 X1 X$ J     monmap e47: 3 mons at {ceph=192.168.10.12:6789/0,com=192.168.10.11:6789/0,con=192.168.10.10:6789/0}
  F) t: z+ \; T8 }9 H            election epoch 174, quorum 0,1,2 con,com,ceph$ }0 S1 k$ H  s7 _
     osdmap e57: 3 osds: 3 up, 3 in& X9 r: D( ~! `; X
            flags sortbitwise,require_jewel_osds7 H5 e$ N  V, a: l5 V1 r3 ~6 Y
      pgmap v6577: 768 pgs, 3 pools, 45659 kB data, 23 objects: a! }6 @/ Z" @' F/ x  S% N
            178 MB used, 766 GB / 766 GB avail
3 Z7 n8 M- g( T0 B# J, _                 768 active+clean
1 c& ]6 U* e5 r$ V- c% ~/ ~2 t! w
8 C2 n7 _- H$ g! L% Q9 [[root@ceph cluster]# ceph osd tree# e! r; `5 G2 X" g6 K! {
ID WEIGHT  TYPE NAME     UP/DOWN REWEIGHT PRIMARY-AFFINITY
8 O/ v' L( ~$ Q: g, _9 X3 x" w-1 0.74876 root default                                    + i& l; x1 O; h5 L) k
-2 0.24959     host ceph                                   0 E  U6 V: u! v/ ?
0 0.24959         osd.0      up  1.00000          1.00000 5 T& K) D$ N1 u5 a7 P7 t, V' I
-3 0.24959     host con                                    
( n2 F9 |; m9 u. J' r1 e 1 0.24959         osd.1      up  1.00000          1.00000 / a0 t" o5 u6 w
-4 0.24959     host com                                    / T. l. ?8 V' `, {8 ?( |
2 0.24959         osd.2      up  1.00000          1.00000
9 h8 B) N& h4 V+ o% S  s0 L& t; [# k; e& v) I! T
[root@ceph cluster]# ceph osd pool ls detail   W% c; b4 `: G& `: _9 F; a6 \
pool 1 'volumes' replicated size 2 min_size 1 crush_ruleset 0 object_hash rjenkins pg_num 256 pgp_num 256 last_change 58 flags hashpspool stripe_width 0$ h4 t' W; Q4 D) q
    removed_snaps [1~3]
1 `4 g9 Q. N6 [4 d( `pool 2 'vms' replicated size 2 min_size 1 crush_ruleset 0 object_hash rjenkins pg_num 256 pgp_num 256 last_change 59 flags hashpspool stripe_width 0% R; ?  g; \/ ]7 k& m, ]
    removed_snaps [1~3]0 R; e$ h# r) w( _, t6 v
pool 3 'images' replicated size 2 min_size 1 crush_ruleset 0 object_hash rjenkins pg_num 256 pgp_num 256 last_change 60 flags hashpspool stripe_width 08 S5 j- _# a+ D& j3 p8 K/ S# c
    removed_snaps [1~9]
6 L: S: Q% h! C  o9 L9 ^" p

! B% K; D* K9 lOSD的数据迁移7 _. \' q2 j3 S- R3 d3 _

8 x6 Z5 g7 Q$ D3 D4 V  y) ~

% }  h9 F: X( a, E, J
本次迁移主要分为两个组件的迁移,即 MON 和 OSD,这里我们先介绍 OSD 的数据迁移。相比迁移MON来说,OSD的数据迁移步骤更为单纯一些,因为所有操作均在 Ceph 侧执行,对 Openstack 来说是透明的。
原理简介
由于CRUSH算法的伪随机性,对于一个PG来说,如果 OSD tree 结构不变的话,它所分布在的 OSD 集合总是固定的(同一棵tree下的OSD结构不变/不增减),即对于两副本来说: PG 1.0 => [osd.66, osd.33]
  • 当副本数减少时,PG 1.0 => [osd.66] ,也就是说会删除在osd.33上的第二副本,而在 osd.66上的主副本是维持不变的,所以在降低副本数时,底层OSD实际上只删除了一份副本,而并没有发生数据的迁移。
  • 当副本数增加时,PG 1.0 => [osd.66, osd.33, osd.188, osd.111],也就是说四副本的前两个副本依旧是之前的两个副本,而后面增加的两副本会从主副本osd.66将数据backfill到各自的OSD上。
    5 l/ V- e$ W. H% f: t
迁移思路
      ^# [1 v0 v3 S. Q5 g5 R* f
    ( g- V- C7 S  @3 _; m7 V$ R
    • 我们首先会将新的节点的所有OSD初始化完毕,然后将这些OSD 加入到另一棵osd tree下 (这里简称原先的集群的osd tree叫做old_tree,新建的包含新OSD的 osd tree 叫做 new_tree),这样部署完毕后,不会对原有集群有任何影响,也不会涉及到数据迁移的问题,此时新的OSD下还没有保存数据。
    • 导出 CRUSHMAP,编辑,添加三条 CRUSH rule:

      % V! s# J: e0 o9 X  }2 O% B0 C: p
•  crush rule 0 (原先默认生成的): 从 old_tree 下选出size副本(这里size=2)。
•  crush rule 1 (新生成的第一条): 从 old_tree 下选出两副本。对于副本数为2的集群来说,crush_rule_0 和 crush_rule_1 选出的两副本是一样的。
•  crush rule 2 (新生成的第二条): 从 old_tree 下选出两副本,再从 new_tree 下选出两副本。由**原理简介第二段**可知, 由于 old_tree 下面的 OSD结构不变也没有增加,所以 crush_rule_0 和 crush_rule_1 选出的前两副本是**一样的**。
•  crush rule 3 (新生成的第三条): 从 new_tree 下选出两副本。 由于crush_rule_1 的第二次选择为选出 new_tree下的前两副本,这和 crush_rule_2 选出两副本(也是前两副本)其实是**一样的**。
  • 注入新的CRUSHMAP后,我们做如下操作:
    •  将所有pool(当然建议一个pool一个pool来,后面类似) 的 CRUSH RULE 从  crush_rule_0 设置为 crush_rule_1 ,此时所有PG均保持active+clean,状态没有任何变化。
      •  将所有pool的副本数设置为4, 由于此时各个 pool 的CRUSH RULE 均为 crush_rule_1 ,而这个 RULE 只能选出两副本,剩下两副本不会被选出,所以此时所有PG状态在重新 peer 之后,变为 active + undersized + degraded,由于不会生成新的三四副本,所以集群没有任何数据迁移(backfill) 动作,此步骤耗时短暂。
    •  将所有pool的 CRUSH RULE 从 crush_rule_1 设置为 crush_rule_2,此时上一条动作中没有选出的三四副本会从 new_tree 下选出,并且原先的两副本不会发生任何迁移,整个过程宏观来看就是在 old_tree -> new_tree 单向数据复制克隆生成了新的两副本,而旧的两副本没有移动。此时生成新的两副本耗时较长,取决于磁盘性能带宽数据量等,可能需要几天到一周的时间,所有数据恢复完毕后,集群所有PG变为 active+clean 状态。
      •  将所有pool的 CRUSH RULE 从 crush_rule_2 设置为 crush_rule_3,此时所有PG状态会变为 active+remapped,发生的另一个动作是,原先四副本的PG的主副本是在 old_tree 上的某一个OSD上的,现在这个PG的主副本变为 new_tree下的选出的第一个副本,也就是发生了主副本的切换。比如原先 PG 1.0 => [osd.a, osd.b, osd.c, osd.d] 在这步骤之后会变成 PG 1.0 => [osd.c, osd.d]。原先的第三副本也就是new_tree下的第一副本升级为主副本。
    •  将所有pool的副本数设置为2,此时PG状态会很快变为 active+clean,然后在OSD层开始删除 old_tree 下的所有数据。此时数据已经全部迁移到新的OSD上。

    ) x; n8 x- g6 k8 Q
迁移指令1.初始化新的OSD
一定要记住:在部署目录下的ceph.conf内添加 osd_crush_update_on_start =false,再开始部署新的OSD,并且一定要检查新节点配置,包括但不限于: yum 源,免秘钥配置,ceph的版本,主机名,防火墙,selinux,ntp,ntp,ntp,重要的时间对齐说三遍!
部署新的OSD:
### 前往部署目录
- \5 {# E5 h% r) F* bcd /root/cluster
! y* S4 \3 e4 hecho "osd_crush_update_on_start = false " >> ceph.conf 1 `# n% {1 A2 |  w5 z: m3 W5 o
ceph-deploy --overwrite-conf osd prepare new_mon_1:sdb  new_mon_2:sdb  new_mon_3:sdb --zap-disk
- L  F6 W- E* N# N) g! i' |ceph-deploy --overwrite-conf osd activate  new_mon_1:sdb1  new_mon_2:sdb1  new_mon_3:sdb1
添加完这三个OSD后,集群总共有六个OSD,此时不会有数据迁移。结构如下:
- ~' m8 n8 a& y
[root@ceph ~]# ceph osd tree( [/ g9 _( _! Q$ s$ p8 c( ^
ID WEIGHT  TYPE NAME     UP/DOWN REWEIGHT PRIMARY-AFFINITY , s& k& [( E; }# A
-1 0.75000 root default                                    
( `* X9 g: `7 v- b: G; g) n* h) ~7 n-2 0.25000     host ceph                                   9 h4 t1 q% A4 ]6 X+ z
0 0.25000         osd.0      up  1.00000          1.00000 1 K# v0 x' o/ u# y3 K  _- |
-3 0.25000     host con                                    - Y' e( U* G; W4 J4 x9 Y
1 0.25000         osd.1      up  1.00000          1.00000 ; I. ~, ]8 M- Y8 A# O1 }  N
-4 0.25000     host com                                    
0 a3 ]8 G3 S; z 2 0.25000         osd.2      up  1.00000          1.00000
4 w) T( y7 D1 z7 H* c 3       0 osd.3              up  1.00000          1.00000 7 ~6 \0 S8 G9 r" D. \& ]: J3 j5 G
4       0 osd.4              up  1.00000          1.00000
  X# d4 I1 j( _! k# K& x8 U! U 5       0 osd.5              up  1.00000          1.00000
构建新的new_root根节点,并将这三个新的OSD加入到新的根节点下(注意OSD和主机的物理对应关系):

* S0 j8 V- I# F3 R6 ^* V; ]2 F
ceph osd crush add-bucket new_root  root5 J. Y, I- k/ `" e
ceph osd crush add-bucket new_mon_1 host
. D$ ?% A0 U. e: Bceph osd crush add-bucket new_mon_2 host
: m4 \2 Y4 q: H; v$ l7 a" |$ k: i1 Gceph osd crush add-bucket new_mon_3 host
9 ^* q$ d( K8 U. `/ }# q  v0 k& xceph osd crush move new_mon_1 root=new_root. k+ v$ y+ ]. a0 K. o
ceph osd crush move new_mon_2 root=new_root3 x0 i1 b0 f8 ^; Q' H" A' E
ceph osd crush move new_mon_3 root=new_root
- c- x' \- C  C: J9 fceph osd crush add osd.3 0.25 host=new_mon_1
+ Z! J3 a2 G& n, }5 \$ Hceph osd crush add osd.4 0.25 host=new_mon_2: f0 L* C. O) z( s. s
ceph osd crush add osd.5 0.25 host=new_mon_3
此时,新的 TREE 结构如下:
[root@ceph ~]# ceph osd tree  B9 H0 ^1 w, b& j
ID WEIGHT  TYPE NAME          UP/DOWN REWEIGHT PRIMARY-AFFINITY
8 v+ ]* }. P( B" p( \: c-5 0.75000 root new_root                                       
4 y% l! F3 w1 b-6 0.25000     host new_mon_1                                   $ j' h1 [4 p* u
3 0.25000         osd.3           up  1.00000          1.00000 ! O, S7 z' d! ]4 k
-7 0.25000     host new_mon_2                                   
! r- [6 [! Z+ N  ]7 i 4 0.25000         osd.4           up  1.00000          1.00000 2 b5 a+ N) U; `- h1 D; a
-8 0.25000     host new_mon_3                                   2 A( W& B2 B% K" L1 M" ~
5 0.25000         osd.5           up  1.00000          1.00000 * L6 |& _. T) e* V! `) j9 D$ @$ h
-1 0.75000 root default                                         
% m" ?% J2 u6 p7 p" U$ b0 ^-2 0.25000     host ceph                                       
' D& b5 L  z+ D5 r( a 0 0.25000         osd.0           up  1.00000          1.00000
. k' |1 Z  C4 p9 K0 f-3 0.25000     host con                                         
+ i  U5 v7 V* x# g( g 1 0.25000         osd.1           up  1.00000          1.00000
9 ^9 T, Q  B$ F- ^# \. u) h7 b4 A-4 0.25000     host com                                         / X$ N- Y  l/ ^2 G% m" y6 v7 L+ ~
2 0.25000         osd.2           up  1.00000          1.00000
% ~) _5 M2 Y( e
4 ^* }7 e0 [) E

; b0 \2 W- Y( M/ `0 T( R5 } 2.编辑 CRUSH MAP: S* z& A+ E8 r3 W4 r1 e& f
导出CRUSH MAP,并编辑添加三条新的 CRUSH RULE:
### 导出CRUSH MAP/ ^1 F5 A: h4 ^5 h
ceph osd getcrushmap -o map 2 S7 @' A& ~9 H% s) ]  n, m! K# u
crushtool -d map -o map.txt
- G( g& ?. m. h% m### 在map.txt 最后添加以下内容
6 N) D& _# ?5 f# w. _, @9 M9 [! ^/ ]% `vim map.txt ) }* a+ C7 @5 b- U2 }+ Y

7 D1 f0 ?; R5 n# ?% D3 S! E# rules
4 b$ \. K5 T5 I+ ]6 p8 Krule replicated_ruleset {1 ]( M& K1 Y6 a6 o8 a& U' w
        ruleset 0
  r0 x+ L1 ]8 ~& j7 K( O        type replicated
0 V% c1 o# j/ ?5 Q, u        min_size 1
2 U" B' E- D1 g        max_size 10
) d* B0 o) ]$ z, Q        step take default
* c9 Z- U$ X& y* V: x4 i        step chooseleaf firstn 0 type host3 P' E  t) Y) ^4 a, t
        step emit
9 c5 {+ f. ^! R) h}/ q  k1 E2 _# A7 ]" F5 R
>>>>>>>>>>>>>> 添加开始  >>>>>>>>>>: M% v8 i4 v4 V: u/ {" J! R! a. r
rule replicated_ruleset1 {4 g, p3 p; o1 D; C& v$ T& F) H# C
        ruleset 1
% G1 I; j, u5 A: F; l/ \        type replicated2 V' v9 ~! A; t$ j' P5 M4 }
        min_size 1- m1 s/ a1 P1 ~0 P
        max_size 10
" S4 c8 f# ^0 q3 S        step take default5 y) G0 l' v2 R: Q- r
        step chooseleaf firstn 2 type host4 j7 t& g4 r! a& l$ B7 |2 {
        step emit5 z+ n. E! S! c9 }' s3 Z
}
* \% [* N, ?8 }0 L' k/ Krule replicated_ruleset2 {
1 C; a3 W1 w5 h  ?- [, g        ruleset 2
' l( {) q: j$ Y        type replicated
0 @' k- w+ n5 x( n) R1 E        min_size 1$ E3 @; A' H7 |6 _
        max_size 10
" Y8 u- }8 R) G# t$ E        step take default. v$ L( V5 O( V% d
        step chooseleaf firstn 2 type host0 a1 R, u; d& S. \% a  {
        step emit
+ l- H4 ^# k" j3 m        step take new_root% o$ V4 P9 }$ \1 H% C
        step chooseleaf firstn 2 type host
' b2 D( y5 y7 R+ T7 n$ l& V3 ?        step emit& O) _3 M7 r+ z: q# N3 w9 D& g
}! z, j9 ^4 u% s/ F6 U* B! A; T
rule replicated_ruleset3 {
. `5 _6 p' \( Z1 V6 F# n% \& L7 T0 N        ruleset 3
/ p$ ^0 a! n# V        type replicated
/ ]' m& A/ B5 [0 |* D" x, _$ S        min_size 17 X5 `- J5 w( ]3 Y8 E0 \
        max_size 10
" [3 k5 }  U5 b1 d        step take new_root
6 q$ M  R2 h$ K  e. Q        step chooseleaf firstn 2 type host
7 P7 ~+ O5 F4 c        step emit5 E1 F3 O0 K  \. Z
}
1 o- S" S7 n: s: Q! X/ J<<<<<<<<<<<< 添加结束  <<<<<<<<<<<<( l: c5 {& c, W: l
# end crush map* o$ S8 {/ X  N6 z" U! @& s7 I

( S5 b/ ]% j  b### 编译 CRUSH MAP,并注入到集群中$ T' \9 ?& i' Y: N( O
! ?2 [# `& H( i7 s9 Q) \9 _
crushtool -c map.txt -o map.bin6 a- e* G8 c0 `1 m* ~
ceph osd setcrushmap -i map.bin
  [2 Q0 m% H7 a3 i/ d3 H1 M
* {# ]2 k, t0 T
3. 开始迁移数据
& ~+ u# f' y* f1 {5 ^% L- G
到目前为止的所有操作均不会发生数据迁移,对线上业务也就没有影响,下面我们要开始通过修改 POOL 的 CRUSH RULESET 和 副本数来实现数据的整体迁移(这里我们取 volumes 池来介绍):
###确认当前 volumes 池使用的是 crush_ruleset 0' c& I' s2 U' u' a% p9 _
[root@ceph cluster]# ceph osd pool get volumes crush_ruleset 0 u1 K8 E# h9 D- G
crush_ruleset: 0
0 F2 w* p0 l! j# l. i. a
5 s4 C4 r  T8 ]### 将 volumes 池的 crush_ruleset 设置为 1,设置完后,集群一切正常,PG均为active+clean
6 m* ]* C" B( A; `; }# H[root@ceph cluster]# ceph osd pool set volumes crush_ruleset 12 }  t% r5 ^' z) R+ C1 X% `+ J
set pool 1 crush_ruleset to 13 v8 X) s+ u& u" p+ [9 ~8 x

/ w6 O9 i) H: o### 将 volumes 池的 副本数设置为4, 设置完后,PG经过短暂 Peer,变为 active+undersized+degraded
7 H1 t5 j" L" ]* f% K[root@ceph cluster]# ceph osd pool set volumes size 4
& Y( i$ p: r; j! w- P  V9 Bset pool 1 size to 4
9 M, E1 j/ H$ r$ O7 A, M/ Z4 _# {2 ~
( k3 ]6 Q" p1 Z9 k( c4 x$ R7 {[root@ceph cluster]# ceph -s
; J+ F5 n, J# y2 c0 u9 N    cluster 166889ab-fa7b-4a07-83da-6dfc92913a3d
+ _3 O* _* O4 k/ X     health HEALTH_WARN/ Y" W! ^9 Q- y: X0 g1 h0 \* @
            256 pgs degraded& a- Q4 E: H/ k/ A
            256 pgs undersized
- O5 ]1 p* `7 e* ?+ d  M8 \            recovery 183984/368006 objects degraded (49.995%)& k( U( i; Y9 P1 Y  u- h$ [
     monmap e47: 3 mons at {ceph=192.168.100.112:6789/0,com=192.168.100.111:6789/0,con=192.168.100.110:6789/0}
9 K2 ]3 O/ L6 s+ I6 `0 |            election epoch 182, quorum 0,1,2 con,com,ceph& ]2 O' Y8 S! {
     osdmap e106: 6 osds: 6 up, 6 in
- {: U+ H$ r" u) J5 Y& p- M/ T            flags sortbitwise,require_jewel_osds' U; x2 G& O3 Q, {: a8 y% _2 J
      pgmap v23391: 768 pgs, 3 pools, 403 MB data, 92011 objects* [( v1 Y4 X- y  e& [# i. H, U
            1523 MB used, 1532 GB / 1533 GB avail
+ L* ]* @8 ?1 }5 ^% M+ Q            183984/368006 objects degraded (49.995%)
% L6 F- ]0 p1 \/ }: f# U# X                 512 active+clean/ D  z  X- j  y" `$ R& J
                 256 active+undersized+degraded+ c3 ]& `# {( ^" w9 B

* N, M6 ~* ^6 ^( Z3 G' ~7 R/ m2 H  f7 ]. P8 f
[root@ceph cluster]# ceph osd pool set volumes crush_ruleset 28 Z, g8 n; x% y, }7 ~8 p
set pool 1 crush_ruleset to 28 \1 F2 j% E% U% W+ E" r* t' H

" T" v6 M# r5 ^* W### 等到 volumes 池的所有PG均变为 active+clean 后,将 volumes 池的 crush_ruleset 设置为3, 此步骤后,volumes 池的 PG状态变为 active+remapped。但是不影响集群IO。7 |' l" Y+ L1 ^5 U) P: g" H# h: @+ b
3 f2 g2 U' A2 T+ d& _' u
[root@ceph cluster]# ceph osd pool set volumes crush_ruleset 2" L" Y2 X2 h- n" d& T8 v
set pool 1 crush_ruleset to 2( H1 n' `1 ?9 s* N. k' k- J

: ^8 E  N8 G" w9 I0 q2 ?# Wset pool 1 crush_ruleset to 3+ i/ ^8 T. W2 ]* l/ V0 F7 |

$ ^8 S- |5 g! h( {( e2 f### 此时,将 volumes 池的 副本数 设置为2 ,此时 PG 状态经过 peer 之后,很快变为 active+clean ,volumes 池的两副本均落在新的节点下,并且后台在自行删除之前旧节点上的数据。
/ C) l9 E; n2 D/ D5 x5 |2 O8 q  l% _& u6 g1 }( b7 A; d3 |* F
[root@ceph cluster]# ceph osd pool set volumes size  2
$ F8 q% L) f7 ]6 C  s* J0 m9 Y
0 f% W* ~/ S, `( `, Q) L8 f1 w
注意事项
  H4 t8 O& @% }: X, X7 k  G5 S# ~5 B6 G$ l" w  t% ^. W1 Y1 ]* \
: i" j8 {( p! V& C! e4 _3 W  e
由于本次数据迁移是在生产环境上执行的,所以没有直接执行将数据从旧节点直接 mv到新节点,而是选择了执行步骤较为复杂的上面的方案,先 scp 到新节点,再 rm掉旧节点的数据。并且每一个步骤都是可以快速回退到上一步的状态的,对于生产环境的操作,是比较友好的。在本次方案测试过程中,遇到了如下的一些问题,需要引起充分的注意:
  • Ceph 版本不一致: 由于旧的节点的 Ceph 版本为 0.94.5 ,而新节点安装了较新版本的 10.2.7, 在副本 2=>4 的过程中Peer是正常的,而将池的crush_ruleset 设置为3 ,也就是将新节点的 PG 升级为主副本后,PG由新节点向旧节点发生Peer,此时会一直卡住,PG始终卡在了 remapped + peering,导致该 pool 无法IO。在将新旧节点 Ceph 版本一致后(旧节点升级,新节点降级),此现象得以消除。 为了确保此现象不会在实际操作中发生,应该在变更之前,新建一个测试pool,对其写入部分数据,再执行所有数据迁移指令,查看此过程是否顺畅,确认无误后,再对生产pool进行操作!
  • 新节点 OSD 的重启问题: 如果没有添加了osd_crush_update_on_start 这个配置参数,那么当新节点的OSD重启后,会自动添加到默认的 root=default 下,然后立刻产生数据迁移,因此需要添加这个参数,保证OSD始终位于我们人为指定的节点下,并不受重启影响。这是个基本的Ceph运维常识,但是一旦遗忘了,可能造成较为严重的影响。更不用说防火墙时钟这些配置了。
  • 集群性能降低:总体来说,在副本从2克隆为4这段时间(约2-3天,取决于集群数据量)内,集群的实际IO表现降低到变更前的 25%->80% 左右,时间越往后表现越接近变更前,这虽然不会导致客户端的IO阻塞,但从客户反馈来看,可以感知到较为明显的卡顿。因此克隆时间应该选择业务量较低的节假日等。
  • 新节点IP不cluster_network范围内:这个比较好解决,只需要增大部署目录ceph.conf内的cluster_network 或者 public_network的掩码范围即可,不需要修改旧节点的,当然网络还是要通的。
  • 变更的回退:对于生产环境来说,尽管执行步骤几乎是严谨不会出错的,但是难免会遇到意外情况,就比如上面的版本不一致导致的 peer 卡住现象。因此我们需要制定完善的回退步骤,在意外发生的时候,能够快速将环境回退到上一步集群正常的状况,而不是在意外发生时惊出一身冷汗,双手颤抖得敲指令。。。所以,下面的表格给出了这个变更操作的每一步的回退步骤:

    - _; q- ?+ A' v+ `' z! o4 ]
[td]
变更步骤实际影响回退指令回退影响
ceph osd pool set volumes crush_ruleset 1ceph osd pool set volumes crush_ruleset 0
ceph osd pool set volumes size 4PG由active+clean,变为 active+undersized+degradedceph osd pool set volumes size 2PG很快恢复active+clean
ceph osd pool set volumes crush_ruleset 2PG 开始 backfill,需要较长时间ceph osd pool set volumes crush_ruleset 1PG很快恢复到active+undersized+degraded,并删除在新节点生成的数据。
ceph osd pool set volumes crush_ruleset 3PG 很快变为 active+remapped。ceph osd pool set volumes crush_ruleset2PG很快恢复到 active+clean
ceph osd pool set volumes size 2PG 很快变为 active+clean,并且后台删除旧节点数据。ceph osd pool set volumes size 3PG 变为active+remapped。
: x+ l) r# w5 C# w# _% k5 m- V0 y' ^; v
为何不直接迁移数据到新节点?总体来看数据迁移过程,最耗时的地方是数据从两副本变为四副本的过程,其余过程是短暂且可以快速回退的,而如果直接将池的 crush_ruleset 设置为 3 ,数据开始从旧节点直接backfill到新节点上,其实这么做也是可以的,但是这里我们就会遇到一个问题,一旦数据复制了一天或者一段时间后,集群出现了问题,比如性能骤降,要求必须回退到操作之前的状态,此时已经有部分PG完成了迁移,也就是说旧节点上的两副本已经删除了,那么回退到上一步后,还会发生数据从新节点向旧节点的复制,那么之前复制了多久的数据,可能就需要多久来恢复旧节点上删除的数据,这很不友好。而用了我们的方法来复制数据的话,不会存在这个问题,因为这里的方法在最后一步将池的副本设置为2之前,旧节点上的数据始终都是在的,并且不会发生任何迁移,我们可以在任意意外情况下,通过几条指令将集群恢复到变更之前的状态。
: k6 a( N' K' o
MON的迁移原理介绍
相比于 OSD 的数据迁移,MON 的迁移比较省时省力一些,步骤相对简单,但是里面涉及的原理比较复杂,操作也需要细心又细心。
首先,我们的环境为典型的 Openstack+Ceph的环境,其中 Openstack 的三个组件: Nova/Cinder/Glance 均已经对接到了Ceph集群中,也就是说虚机系统盘,云硬盘,镜像都保存在Ceph中。而这三个客户端调用Ceph的方式不太一样:
  • Glance :上传下载镜像等时,需要新建一个调用 librbd 的 Client 来连接 Ceph集群。
  • Cinder :
    ; u1 s5 n+ i, a2 z
    • 创建删除云盘时,新建一个调用 librbd 的 Client 来连接 Ceph 集群。
    • 挂载卸载云盘时,由Nova调用librbd来实现该操作。
      ; s$ u' |2 N# B9 y4 U2 h7 y  H* v
  • Nova : 虚机(qemu-kvm进程)相当于一个始终在调用librbd的Client,并且进程始终都在。
    8 o. p# }/ i" y# z/ V/ Z
我们需要知道的是,当一个 Client需要连接 Ceph 集群时,它首先通过自己的用户名和秘钥(client.cinder/client.nova...) 来连接到 /etc/ceph/ceph.conf配置文件指定IP的MON,认证成功后,可以获取集群的很多MAP( monmap,osdmap,crushmap...),通过这些 MAP,即可向 Ceph 集群读取数据。
对于一个虚机进程(qemu-kvm)来说,虚机启动之初,它即获取到了集群的 monmap, 而当所连接 MON 的 IP 变化时,比如这个 MON 挂掉时,它便会尝试连接 monmap 里面的其他 IP 的 MON,如果每个MON都挂了,那么这个 Client 就不能连接上集群获取最新的 monmap,osdmap等。下面我们以一个 pid为3171的 qemu-kvm 进程来演示这一过程:
[root@con ~(keystone_admin)]# ps -ef|grep kvm ! T' }8 G1 I1 ?1 H" M! \# `
qemu        3171       1 17 14:32 ?        00:31:08 /usr/libexec/qemu-kvm -name guest=instance-0000000b.........
$ h/ t8 _3 s+ G- M6 H% ^5 @+ {5 {
[root@con ~(keystone_admin)]# netstat -tnp |grep 3171|grep 6789& V  w& \2 p1 O* N  E* g) W" g
tcp        0      0 192.168.100.110:59926   192.168.10.12:6789    ESTABLISHED 3171/qemu-kvm
可以看到,这个进程连接着IP为 192.168.10.12 的 MON,而我们手动将这个IP的 MON 停掉,则会发现这个进程又连接到了剩余两个IP的MON之一上:
[root@con ~(keystone_admin)]# ssh 192.168.10.12 systemctl stop ceph-mon.target
; i- t3 e- t/ B: i2 {1 s0 s' a0 \2 K2 h( K  W0 _$ H
[root@con ~(keystone_admin)]# netstat -tnp |grep 3171|grep 67895 @8 `3 r1 G4 J: U2 a2 t: k
tcp        0      0 192.168.10.10:48792   192.168.10.11:6789    ESTABLISHED 3171/qemu-kvm  
因此,如果我们每次都增加一个MON,再删除一个MON,那么在删除一个MON之后,之前连接到这个MON上的 Client 会自动连接到一个其他MON,并且再获取最新的monmap。那么我们增删过程就是:
  • 原先有三个MON: con, com, ceph
  • 增加 new_mon_1,变为四个: con, com, ceph, new_mon_1
  • 删除con,变为三个:com, ceph, new_mon_1
  • 增加 new_mon_2,变为四个: com, ceph, new_mon_1, new_mon_2
  • 删除com,变为三个:ceph, new_mon_1, new_mon_2
  • 增加 new_mon_3,变为四个: ceph, new_mon_1, new_mon_2, new_mon_3
  • 删除con,变为三个:new_mon_1, new_mon_2, new_mon_3

    5 x! p9 g" O! X1 K
Nova 侧的一个问题
在实际操作中,发现了一个问题,会导致虚机无法重启等问题。
当虚机挂载一个云硬盘时,Nova 会将挂载这个云盘时所连接的MON IP 写入到数据库中,而在修改完MON的IP后,新的MON IP不会被更新到数据库中,而虚机启动时会加载 XML 文件,这个文件由数据库对应字段生成,由于没有更新 MON IP,所以 qemu-kvm 进程在启动时,会尝试向旧的MON IP发起连接请求,当然,旧MON已经删除,导致连接不上而卡住,最终致使虚机进程启动了,但是虚机状态始终不能更新为 RUNNING。
可以通过打开客户端的ceph.conf 内的 debug_rbd=20/20,查看qemu-kvm进程调用librbd时生成的log发现进程在启动时始终尝试连接旧的MON IP。
这里,我们只能手动修改数据库中记录的IP地址来确保虚机重启后能够连接上新的MON,需要注意的是,仅仅修改虚机XML文件是无法生效的,因为会被数据库内的字段覆盖而连上旧MON:
### 具体字段为:
7 t' [# E0 N8 K2 Kmysql =>
: U* |. U. [9 K  M2 a4 y( Pnova  => block_device_mapping => connection_info4 R7 y( S) P! _5 r
9 O) a, N( Q5 B  y6 R# L
*************************** 23. row ***************************9 E$ l. [" W6 L6 b6 _2 B
           created_at: 2018-03-19 08:50:59
. [) J7 L1 h- ]) D           updated_at: 2018-03-26 06:32:06
1 N5 Y, G, o. G) I" W* ]- k           deleted_at: 2018-03-26 09:20:02# p/ S5 l3 O" v5 |, b/ G
                   id: 29; ?; Z. N; N; Y
          device_name: /dev/vdb
4 r3 O7 \5 l/ m% Edelete_on_termination: 0
: \* c4 p6 h/ F+ D8 V) q5 y, G          snapshot_id: NULL
9 m8 Y$ E" ^: j  n- I& n            volume_id: 39c76d96-0f95-490c-b7db-b3da6d17331b) c# z: l% H* y2 Z
          volume_size: NULL( Q0 L) k/ }1 O( c- b$ N5 d
            no_device: NULL) F8 w+ L5 b3 [. V" U
      connection_info: {"driver_volume_type": "rbd", "serial": "39c76d96-0f95-490c-b7db-b3da6d17331b", "data": {"secret_type": "ceph", "name": "volumes/volume-39c76d96-0f95-490c-b7db-b3da6d17331b", "secret_uuid": "0668cc5e-7145-4b27-8c83-6c28e1353e83", "qos_specs": null, "hosts": ["192.168.10.10", "192.168.10.11", "192.168.10.12"], "auth_enabled": true, "access_mode": "rw", "auth_username": "cinder", "ports": ["6789", "6789", "6789"]}}0 |2 @5 ~. D/ X, M. h
        instance_uuid: 4f52191f-9645-448f-977b-80ca515387f76 [( `- Z% z! ~9 E% ~6 {
              deleted: 29/ H/ k) l1 ?8 x# y
          source_type: volume
  |2 H; Q5 h- Z2 }1 @1 c     destination_type: volume# H2 B! T+ T  M0 a1 a8 Q% S! N8 J
         guest_format: NULL
' l, }* }, b* i8 E! x          device_type: disk
; n1 r0 t' S( [+ k# _             disk_bus: virtio0 t3 n9 d4 T' n. E+ ^
           boot_index: NULL
1 N7 z5 q1 Y! v* N7 w: a( V# i             image_id: NULL
迁移指令
这里,我们使用 ceph-deploy 来增删 MON 节点,主要是为了操作的简洁和安全性着想。
首先,我们需要将新的三个MON的IP地址加入到所有节点的/etc/ceph/ceph.conf的mon_host 字段中。保证此时mon_host内是六个MON的IP地址。
### 添加 new_mon_1 - F+ K, F9 z. W8 ^3 R
[root@ceph cluster]# ceph-deploy mon add new_mon_1
& y) K& n4 R/ `6 O8 U* f! O! ]1 L[root@ceph cluster]# ceph -s, |. P  s' R* X( S7 R/ G: [
    cluster 166889ab-fa7b-4a07-83da-6dfc92913a3d/ [. U1 S3 Y5 _% K* A9 f3 \
     health HEALTH_OK3 w5 s  E4 K& i& N) b
     monmap e48: 4 mons at {ceph=192.168.10.12:6789/0,com=192.168.10.11:6789/0,con=192.168.10.10:6789/0,new_mon_1=192.168.10.13:6789/0}
( q+ ?$ Z, O$ E* u     * u3 ^$ `6 S  V
### 删除 con  删除完后,建议等待1-3min再添加新的MON,使得qemu-kvm进程可以建立新的socket链接。
3 c+ U' i, |$ _5 b/ |( d) [" U[root@ceph cluster]# ceph-deploy mon destroy con4 o/ E" x. m& [) k. N1 T
[root@ceph cluster]# ceph -s
* f! T! f7 K3 W    cluster 166889ab-fa7b-4a07-83da-6dfc92913a3d7 Q$ R- l/ |* ~% D2 x; c
     health HEALTH_OK
2 ^, v2 v: n  B     monmap e49: 3 mons at {ceph=192.168.10.12:6789/0,com=192.168.10.11:6789/0,new_mon_1=192.168.10.13:6789/0}
/ U+ D0 G' A9 e  z; g     # \9 t5 L" I, t5 G! A
### 依次添加 new_mon_2 ,删除 com,添加 new_mon_3 , 删除 ceph:/ w1 C! F( k2 K( @* E1 d/ D
[root@ceph cluster]# ceph-deploy mon add new_mon_2
' S4 h& W; d1 X5 k1 k+ [[root@ceph cluster]# ceph-deploy mon destroy com
$ [$ R% i( q2 C8 w2 s### 等待1-3min,
. n" c* n6 \8 |* c[root@ceph cluster]# ceph-deploy mon add new_mon_3
! o9 e+ O$ s1 Y$ C- R3 D+ F[root@ceph cluster]# ceph-deploy mon destroy ceph. X* P5 R* t- S4 G6 y
" v3 c9 b& k" r1 [8 W7 F3 J- t* Z0 z
[root@con ~(keystone_admin)]# ceph -s  A7 [2 o5 g) r3 E- ]
cluster 166889ab-fa7b-4a07-83da-6dfc92913a3d
. S7 Z% I9 x8 J4 |" I6 Q* c     health HEALTH_OK
" t9 x- {, ?: _3 d; |     monmap e53: 3 mons at {new_mon_1=192.168.10.13:6789/0,new_mon_2=192.168.10.14:6789/0,new_mon_3=192.168.10.15:6789/0}
此时,将所有节点/etc/ceph/ceph.conf内的mon_host字段中原先的MON删除,只保留三个新的MON IP地址。

( J! J( i. v0 V/ m. W& d" ^
Glance & Cinder & Nova 服务重启
无需重启 Glance 服务。
需要重启 所有计算节点的 nova-compute 和 控制节点的 Cinder 服务,否则会导致虚机无法创建等问题。
## 在计算节点  H: B) k  ^/ C
openstack-service restart nova-compute0 E" m* l0 E$ D1 c8 \2 X
## 在控制节点
2 `# G- z) }# Z4 E' g% C) F1 Sopenstack-service restart cinder
Nova
由于 nova 不会更新之前的已经挂载的磁盘所连接的MON IP 信息,这会导致虚机在重启等动作时,尝试连接到旧的已经被摧毁的MON的地址,导致动作卡住,因此这里要单独改一下数据库内的MON IP 信息:
这里我们将 192.168.10.10/11/12 改为 192.168.10.13/14/15
mysql >>
6 }1 S4 V0 a; @4 b; M+ l* j$ ]! r( [9 b# N& ]
use nova;. O; N) S9 @2 V
update  block_device_mapping set connection_info=(replace(connection_info,'192.168.10.10','192.168.10.13'));
% o1 c. L8 `( i0 B( _  T; p- Y6 iupdate  block_device_mapping set connection_info=(replace(connection_info,'192.168.10.11','192.168.10.14'));: v- }2 x3 D) R' I- K4 b) V  m
update  block_device_mapping set connection_info=(replace(connection_info,'192.168.10.12','192.168.10.15'));
2 j/ k# z. g: Q2 F
1 |* ]- y& v5 J1 j$ J: yexit;
更新完数据库后,这次数据迁移算是大功告成了。为何不需要重启虚机服务呢,这里再做一些简单的介绍:
qemu-kvm 虚机进程是一个长连接的 Ceph Client,自虚机启动后,进程就和 Ceph 集群保持着连接,在我们更改 MON 后,这些 Client 会自动尝试重连 monmap 里面的其他MON,从而更新 monmap, 来获取最新的 MON 。修改 /etc/ceph/ceph.conf不会对虚机进程产生影响,除非虚机重启等,但是,虚机可以通过更新 monmap 的方式来感知集群MON的改变。

1

主题

0

回帖

12

积分

管理员

积分
12
QQ
 楼主| 发表于 2022-7-22 11:09:56 | 显示全部楼层
[root@ceph-2 ~]# ceph df detail
7 M* f5 B# p, W; F4 UGLOBAL:: U3 I* j. }# V& U4 ~$ s
    SIZE       AVAIL      RAW USED     %RAW USED     OBJECTS / ?/ x9 w) [' M4 v  S# f
    500GiB     490GiB      9.13GiB          1.83           0
+ U2 Y- j0 _* j; o' E( C5 nPOOLS:  U0 i8 Z# e3 Q4 e$ i
    NAME       ID     QUOTA OBJECTS     QUOTA BYTES     USED     %USED     MAX AVAIL     OBJECTS     DIRTY     READ     WRITE     RAW USED 3 s* [2 V. }3 T: w' e" e1 j
    images     1      N/A               N/A               0B         0            0B           0         0       0B        0B           0B
& X: w- R  k# G% n9 ^, P& `, y5 Z[root@ceph-2 ~]#
您需要登录后才可以回帖 登录 | 注册

本版积分规则

返回首页|Archiver|手机版|小黑屋|易陆发现技术论坛 ( 蜀ICP备2026014127号-1 )

GMT+8, 2026-6-12 00:12 , Processed in 0.024139 second(s), 23 queries .

Powered by Discuz! X5.0

© 2001-2026 Discuz! Team.

快速回复 返回顶部 返回列表