|
为什么需要BlueStore Ceph作为软件定义存储(SDS)解决方案,其首要目标是保障存储数据的安全。为了达到数据安全的目的,Ceph使用了WAL的方式(Write-Ahead-Log),这就是我们日常最熟悉的journal. 但是写前记录日志这种技术有一个主要缺陷就是它把你的硬盘性能降低到原来的二分之一(仅当日志和OSD数据共享同一个硬盘时),因为filestore在写数据前需要先写journal,所以有一倍的写放大。 filestore设计初衷就是就是为了充分发挥普通机械盘的性能,没有对SSD进行优化考虑。但随着SSD全面普及(主要性价比越来越实惠,也是新技术不断推陈出新的结果),Ceph应用在SSD之上案例越来越多,对于性能的需求是更加迫切。基于以上现实,社区推出了Bluestore的存储引擎,剔除journal方案,缩减写放大,优化SSD写入,同时数据直写裸盘。 BlueStore架构整体架构 内部组件- RocksDB: 存储预写式日志、数据对象元数据、Ceph的omap数据信息、以及分配器的元数据(分配器负责决定真正的数据应在什么地方存储)
- BlueRocksEnv: 与RocksDB交互的接口
- BlueFS: 迷你的文件系统(相对于xfs,ext2/3/4系列而言),解决元数据、文件空间及磁盘空间的分配和管理。因为rocksdb一般是直接存储在POSIX兼容的文件系统(如ext3/xfs等)之上,但BlueStore引擎是直接面向裸盘管理,没有直接兼容POSIX的文件接口。但幸运的是,rocksdb的开发者充分考虑了适配性,只要实现了rocksdb::Env 接口,就能持久化rocksdb的数据存储(包含RocksDB日志和sst文件)。BlueStore就是为此而设计开发的,它只包含了最小的功能,用来承接rocksdb。在osd启动的时候,它会被"mount"起来,并完全载入内存
- Allocator: 用来从空闲空间分配block(block是可分配的最小单位)
/ v2 B3 N) I6 P* {9 Y8 y
说明:
# Q% t' y# I/ f r- ~5 k: x1.对象数据存储部分即osd指定的data设备(可以是裸盘分区,或者lvm卷,下同)1 A/ f% d$ \1 q/ ?3 }
2.RocksDB日志即osd指定的wal设备% r- v0 G) D$ j# H6 @
3.RocksDB数据部分即osd指定的db设备
) I5 e% U! C& E" K. l' P: n4.以上设备可以共用同一物理盘设备,也可以分开在不同的物理设备,这充分体现了ceph的灵活性
以上只是本人粗糙的理解(未必完全正确或者跟实际有出入),希望有大师出来指点一二。 部署实战基础环境1
9 u$ d0 I8 s- k4 Y( ?/ @& i2# j. S$ r9 J' h* u
3
: O9 t) S ?. t7 Z6 @7 H% n/ `0 l |
. _9 j" ^9 {. ^2 T" [ F5 j[root@compute ~]# ceph -v
& \7 Z% I- N6 M" C- s' ^ceph version 13.2.0 (79a10589f1f80dfe21e8f9794365ed98143071c4) mimic (stable)
9 C) F( x; S5 q# |) B1 m: i! F* B L
|
在创建osd之前,集群已经初始化完毕(即已经有Mon节点)。先熟悉下ceph-volume,可以看到当前支持lvm和simple两类子命令集。lvm用来创建osd,simple则是管理已经创建的osd。 1
2 S% L) ]' l. Q$ F& U- x* c2/ ?2 r( K8 P) j9 {
31 W2 h7 A8 u9 Q9 Y$ D/ L
4$ D! X5 U* h$ ~; ~% x- h _
5
( @9 K2 p: `3 G4 X6
) s s1 Q# m9 h A& q75 _$ Q3 i9 a+ E! E. e& _
| ceph-volume -h9 |+ A& ^0 P* `$ m, w
+ e4 H8 Q9 y$ T8 g: b' ]... <中间省略>' z9 S0 V# S; A! R! C, q5 [
Available subcommands:+ o5 b) V2 q+ m& o8 u1 t
8 ?$ T* {1 W! r7 G5 ]+ ~8 @$ a! z
lvm Use LVM and LVM-based technologies like dmcache to deploy OSDs4 S4 f! E; ?& C- q k
simple Manage already deployed OSDs with ceph-volume Y3 c# U9 m) t$ S* u
|
预先创建好需要的lvm卷,如果没有独立的盘来单独存放wal和db,不推荐再在设备上面创建lvm卷分配给db和wal。默认只需要指定数据路径(–data)即可。Bluestore会自动管理所有的空间(包括data、db、wal)。 注意, C/ j4 O& ?5 A7 E
如果有独立的盘来存放db,官方推荐db的空间不应小于数据空间的4%,以1T的数据空间为例,db的大小不应该小于40G.官方连接 创建lvm卷以下创建的lvm卷只做演示用,data、db、wal分别创建独立的卷 10 n+ |$ [9 J _
29 N) E" ?+ ?1 ?( p' H- N
3
+ W% S& W& g& I0 i; S& W4- x$ `: L- `6 i7 N- H
5
: X$ h. j9 J8 I, c4 G0 o6
6 S9 T' U% `" ?. U" G76 Q0 @8 X5 j8 e ~
84 n+ S5 y4 }5 b
9
8 A, s/ Q+ b; I; E9 Y10
+ l: K `% K2 L- C11" y' h, C! ~$ ?
| [root@compute osd]# vgcreate osd.3 /dev/sde
2 Y) P" y# K( ` Volume group "osd.3" successfully created
4 @* h) q0 v0 b* d3 z2 Z9 T8 k" C3 u3 A) m, M2 v, e ?/ g# \) K
[root@compute osd]# lvcreate -L 1G -n osd.3.db osd.3
/ x: B7 r- U, ?# i2 O Logical volume "osd.3.db" created.
. W( O% p# _4 l+ i, T# `' R, x6 p9 `
. C+ y; Y& Z0 e: W2 N7 x3 A1 H' Z[root@compute osd]# lvcreate -L 1G -n osd.3.wal osd.3
8 _( Y8 g4 d% P" T! F' K) z/ } Logical volume "osd.3.wal" created.
- g. ?. v: l& n9 |7 Z7 t* @8 E' A1 E- s2 x% K4 v3 j
[root@compute osd]# lvcreate -l 100%FREE -n osd.3.data osd.31 i B2 \' v% E- _$ u8 \4 i% n( y
Logical volume "osd.3.data" created.
3 B/ ?, m e: c: j) I4 q7 n | 创建osdimage_1cn618mlp1eskvqdeov12o1vgj19.png-232.8kB 从上面的截图其实可以把整个create流程分解为prepare和activate阶段,下面就开始庖丁解牛。 prepare 阶段- 收集keyring
13 X& k' Q+ [7 X
| Running command: /bin/ceph-authtool --gen-print-key
6 o' h9 w4 g' m' n8 h5 l2 B+ L3 ~ |
- 创建新的osd id
1, J$ h# p* P! I( C5 Y
| Running command: /bin/ceph --cluster ceph --name client.bootstrap-osd --keyring /var/lib/ceph/bootstrap-osd/ceph.keyring -i - osd new 9501a491-625f-4c2c-bf8e-a1a27cc0e6e5
; D0 e# a- m' K+ a |
- 挂载tmpfs目录,这不同于旧版本使用本地文件系统。BlueStore把这些依赖的文件信息都写入到了裸盘里(在osd启动之前,会重新生成)
10 ?5 L1 {& T8 @
| Running command: /bin/mount -t tmpfs tmpfs
0 o g; s: z; _. ^ |
- data对应设备创建软链
1
2 R% `1 w7 k9 F! ]+ ~/ a7 p | Running command: /bin/ln -s /dev/osd.3/osd.3.data /var/lib/ceph/osd/ceph-3/block
0 N1 E- G0 u+ O. F |
- 获取当前集群的monmap
17 B4 U, @1 d) H1 k6 U
| Running command: /bin/ceph --cluster ceph --name client.bootstrap-osd --keyring /var/lib/ceph/bootstrap-osd/ceph.keyring mon getmap -o /var/lib/ceph/osd/ceph-3/activate.monmap
; A9 i' p& ]" @% ]' B |
- 写入keyring文件并在集群注册
1 u, J% A7 B( Y) R, w7 O) e! L
| Running command: /bin/ceph-authtool /var/lib/ceph/osd/ceph-3/keyring --create-keyring --name osd.3 --add-key AQCy/Zdb4rTZIRAApGGe5QENqb/UPUHVRzI5Dw==& X3 m Y0 R/ X. q% G3 Q
|
- keyring文件和工作目录以及设备的权限设置
1
7 v- b* ~& {6 Z0 u27 h( [. B2 J; s) r; d
3/ s# _) ]# i& M: s- g
4
' J! F: j& @9 C! ?. b | Running command: /bin/chown -R ceph:ceph /var/lib/ceph/osd/ceph-3/keyring
[* D2 d# Z# ?8 c6 X3 mRunning command: /bin/chown -R ceph:ceph /var/lib/ceph/osd/ceph-3/( i! |) D" e6 D8 b' \
Running command: /bin/chown -R ceph:ceph /dev/dm-16
. O n! [& ]0 z! k! IRunning command: /bin/chown -R ceph:ceph /dev/dm-15
" P L+ @: h( T |
- mkfs初始化bluestore
1
^% E* T* G# e. c7 i, Y | Running command: /bin/ceph-osd --cluster ceph --osd-objectstore bluestore --mkfs -i 3 --monmap /var/lib/ceph/osd/ceph-3/activate.monmap --keyfile - --bluestore-block-wal-path /dev/osd.3/osd.3.wal --bluestore-block-db-path /dev/osd.3/osd.3.db --osd-data /var/lib/ceph/osd/ceph-3/ --osd-uuid 9501a491-625f-4c2c-bf8e-a1a27cc0e6e5 --setuser ceph --setgroup ceph) ?' z' e( [7 U/ a) ?. r- ]2 q; j2 o
| 以上就是prepare的过程中涉及到的相关操作。
* Z0 @/ n3 L' T. @, b acitivate 阶段小结:
8 C8 k5 ?/ ]1 x: B4 B9 T E以上分解的osd创建步骤,为后续使用ansible来自动化部署Ceph集群至关重要。后续打算写个简单部署ceph的playbook,在此先mark下。 启动分析BlueStore的OSD启动不同于老版本基于udev规则触发ceph-disk相关命令来启动,它依赖于ceph-volume相关服务与命令。 ceph-volume 系统服务上面可以看到,在创建osd的过程中有注册一个系统服务ceph-volume@lvm-3-9501a491-625f-4c2c-bf8e-a1a27cc0e6e5, 1
/ N" J, X j! G) x4 {9 _1 ^2
0 F. X$ ?3 h2 g5 W4 l1 F& Y, E) y3
! i' w) G, |, H4
) w2 v) `2 f u; O51 Y8 ~2 b4 h4 X" u6 E; r# {* i
6
9 q" F$ \3 ?4 I& s, h77 |+ \' _! n3 F( m0 g7 |
8
# i% I/ N# u. H; N" ]5 ~2 p6 _9 F9 X9
( m- N$ s4 G) x5 ?+ F. |107 T8 w: E, p- h. t# z8 O% l- O3 C
11% d; {# p! W; Y' K/ U
12& A+ t% X& x# P# H
13
5 q, I3 V0 ^+ ~6 p% [6 Z14
`. l# b% W7 j15
/ e( f/ i/ E# a, a; n* `6 n | #cat /usr/lib/systemd/system/ceph-volume@.service
6 ~ I$ P2 W7 e, F: W[Unit]
+ |9 L) M9 V3 q1 v( HDescription=Ceph Volume activation: %i
% ?1 s6 u; x. lAfter=local-fs.target1 b8 V1 ~8 g# j+ M
Wants=local-fs.target
G+ ^/ S- W9 d/ J% o6 H) G3 Z) s, l9 P
[Service]$ C/ [# T, y- a0 r& m# c( v; Q
Type=oneshot
q6 `0 b0 Q5 YKillMode=none; U9 B8 R2 G6 W; x. d L
Environment=CEPH_VOLUME_TIMEOUT=10000; o3 Z1 N3 U* c" L, N' j+ S
ExecStart=/bin/sh -c 'timeout $CEPH_VOLUME_TIMEOUT /usr/sbin/ceph-volume-systemd %i'$ m* L1 k' }# V5 R8 M
TimeoutSec=04 I9 Q/ _ {( s8 e6 p* m; o+ m6 ~* |
1 q. i5 b0 q! x4 l1 s5 l
[Install], u0 U. z. r$ u- o1 i+ p8 h
WantedBy=multi-user.target
- C o1 P& c U$ l* F. w! _- b3 j |
这个系统服务是在local-fs之后就执行了,优先级别是比较高的。这个服务传入的参数是lvm-3-9501a491-625f-4c2c-bf8e-a1a27cc0e6e5。其时可以分解为lvm、3、9501a491-625f-4c2c-bf8e-a1a27cc0e6e5.见明知意,分别是是lvm标签,osd的id,osd的uuid。
2 @# ? i9 U& w# E: o" R9 l系统服务只有一个简单的脚本。 12 l r' p9 _ X2 E2 K
2
" y7 e, G0 V' M3 y; Y1 r E; W' A3
1 x* \$ M8 s4 p T0 I4$ a# p- s: `6 Z& [) e! A8 t( O T
5% k8 G% n8 \0 w; ^1 o% M8 p% ?
6
$ R' O' x. [: }2 u5 N) ^7
. `) x1 V: J8 j+ E) L) ~) k. b& i | # cat /usr/sbin/ceph-volume-systemd
4 _2 w+ M/ x P0 [; O* {#!/usr/bin/python2.76 ]! }% e2 s& Y* V9 |
$ a& y6 Z! O d7 U: O- N1 f( \1 s7 N
from ceph_volume.systemd import main
$ u! C: H" Y* |9 m& O% V% J' |6 |1 e; [: \0 b' u1 _' F3 l/ T
if __name__ == '__main__':
$ y8 J9 ?! F/ M# W0 C main.main()
. j. _) S9 O; C5 ]' k3 p+ p" o: { |
从上面看,已经开始进入ceph-volume项目了。
6 a1 l& S4 v/ n- C s1 J. J e项目路径是ceph/src/ceph-volume 1
0 ?9 v2 Q; ? t' ?' D8 j20 Q' z! V; J+ M7 n
3
3 \# Q7 g6 @0 x4; x5 B2 C0 J% g& Q* i2 x
5& i# F" W' p. l- `/ a; d
60 W" V: T1 Z, Y: |. E
7
" \8 Z& y- }0 K: k5 r5 [7 X. y! W8
5 A4 Y- f/ L0 m9 ]& J9
. Y6 y$ @- `7 t6 S10
, A) s6 i% |' H4 F9 |. ]3 p11
1 u7 v" a8 g( k s12( b+ B1 a5 i$ ?' j& o6 {0 p% W/ ?/ L3 w; S
13
5 B' H6 t8 f/ y" `1 U14
2 X& z& o9 p2 T159 f" Q/ N. y8 Y! I" c# y
16* k! k. @# W: N$ q- ]
17" c Z5 Z* M. k! U
18
9 w8 B- e+ m* q, R3 c9 k0 I7 f19/ X0 U& N- v$ A- h/ z
204 H& @! c6 ?9 w; Q+ W! L9 p
21
: G+ ]8 H8 o& J+ I% x; l7 J | ## ceph/src/ceph-volume/systemd/main
! B$ ^8 U. K+ ~* B8 J# Zdef main(args=None):0 X! R. n V; @, M0 {: g5 B; `
"""9 m$ f" K5 J$ K1 s( \+ ?
... < 中间省略> 0 M6 A: q( m7 Q8 I! C! s1 K
## 转换为ceph-volume lvm 命令 继续执行 ## 8 B7 X$ s+ M7 ?8 q4 U! Y
ceph-volume lvm trigger 0-8715BEB4-15C5-49DE-BA6F-401086EC7B41
$ y* G, x/ A6 [+ u1 ]4 |6 B, y' {" {6 I9 s
"""6 V# y+ h; `7 S1 Z4 @ {+ \' B" ?
log.setup(name='ceph-volume-systemd.log', log_path='/var/log/ceph/ceph-volume-systemd.log')
9 o% F& l0 Q0 Q logger = logging.getLogger('systemd')0 @- J% l; [: p% ~! Z6 o
... < 中间省略>
2 ]4 O! n% R0 s$ i. O( X6 n ## 参数解析, K; {5 \5 _) o9 j5 b g$ e+ I
sub_command = parse_subcommand(suffix)
( t' c5 t7 X: S$ V9 G extra_data = parse_extra_data(suffix)
8 y. b5 K+ M( o1 Y ... < 中间省略>
" W% `' E) @2 s ## 构造成为['ceph-volume','lvm','trigger','id-uuid']的格式2 j( `8 i( k6 {+ n# H+ V* G
command = ['ceph-volume', sub_command, 'trigger', extra_data]& ^" D u3 k; m; a* F' K
tries = os.environ.get('CEPH_VOLUME_SYSTEMD_TRIES', 30)7 h0 G Z: ?! @& D; ?7 _
interval = os.environ.get('CEPH_VOLUME_SYSTEMD_INTERVAL', 5)' T. h" n* [! O+ Q$ X
... < 中间省略>
& ^, q6 C6 H$ M3 I# |3 L* Z4 K6 g" M: W process.run(command, terminal_logging=False) ##下一步执行入口##, F! I" ?2 m* x! v8 q3 N/ J& f c# U
|
这里只是对传入的参数进行处理,最后调用ceph-volume lvm trigger ceph-volume lvm trigger 处理1
. X$ s' C' A5 ?& {) B J2 u4 U: T2- z" z( |" t1 a2 W
36 e, \9 d3 f5 o5 t8 A+ F
4* `; P4 f: X; Y: ^4 G
5- W$ }9 a. T: @8 n! k+ T n
6
- `. ~) z; P8 \/ q7
Q. M6 s3 y7 x8 v, d6 q | #cat /usr/sbin/ceph-volume5 z; @+ b0 F. B- p7 L
#!/usr/bin/python2.7
+ c" ~0 a. X! u2 o- |9 ` Y% l2 M/ _7 w( X+ P" v
from ceph_volume import main
4 a9 f5 V9 P2 ]
" k' D4 T* D; C5 e" z, ~; nif __name__ == '__main__':
, M' v) q% o! d9 H$ c main.Volume()" O1 [6 t/ q8 C7 T& ^
|
下面进入ceph/src/ceph-volume/main,找到入口函数main() 17 A3 p' h/ y$ H0 h/ L8 }+ F
28 `' X5 S1 R6 n
3, ^ k* s# `: E. G/ v
4% A+ U7 J R& [$ x. K
55 H. E2 c5 U/ b) i6 `! F
6# D& N$ W# X" N3 t
7
4 K3 x9 G& S% C. p8
7 c- E' R% Z9 b: r3 L9( S( a3 t6 {9 ~( c9 v m+ ~
10 m0 F' u2 W1 n( O
| def main(self, argv):
) r- ^* H. s4 T0 T M) i2 y- m( `/ f # these need to be available for the help, which gets parsed super( r" C0 N" _6 O/ B' |
# early
. T% n9 X/ E. E3 {: \! y+ Z& H ## 一些预备处理,比如日志,ceph配置路径等
( i: l8 j9 l; p$ [9 O self.load_ceph_conf_path()
/ q ]* t5 l! t" b! ^ self.load_log_path(): l' `6 r- M8 Z0 g; D
self.enable_plugins()
) l7 N4 Z: j, a4 k' P0 t main_args, subcommand_args = self._get_split_args()
- s& b9 I6 P) P& Z ...<中间省略>
0 c3 U) I- a) P: Q! I; n4 d terminal.dispatch(self.mapper, subcommand_args)
, k, |9 h- w2 x( [0 | |
最终进入的是terminal.dispatch,核心是传入的参数。, h' |4 ~5 J$ W* B+ Q; S
以下是pdb的结果,其实这是一个工厂模式的设计实现,根据subcommand_args里类型,创建对应的实例,通过实例方法实现功能处理。! s& ]/ D& ~( X1 b* a6 h0 P: P) ^( Z
image_1cn6k8a3e1f754eu15armjhcgj9.png-25.6kB 1" f; W, V8 S8 A+ v$ B+ y
2+ Q N: R: \; R
3
1 ~! G* K5 \4 T" j49 k$ i' m! s+ }, m% {3 t6 F: i& Z
5- q; ~# N$ L5 [# Y8 y: n7 ~# B% [
6. ]3 h/ R; x% k
7
" O8 q, T7 h+ o4 H$ H/ K8
# {1 d3 R* [; V% D0 l+ o+ i" |/ ~9
$ R$ P) t$ g4 \6 x I0 W10
: t- U* N A; _# z118 d8 ?/ Y2 P+ P% T4 k5 m. Z3 O
| ## ceph/src/ceph-volume/ceph_volume/terminal.py
) X4 ^( E0 V, @$ _5 s) L9 wdef dispatch(mapper, argv=None):
& n2 q D1 L# y7 q. |+ M# M2 H7 e; b argv = argv or sys.argv
' o% K% Q, h. g* j for count, arg in enumerate(argv, 1):, [. `' D$ \ f1 V
if arg in mapper.keys():! }, m: f" h3 s4 e- s! v8 Q# c
## 创建实例
' F# n8 l7 L' l& X ^# | b instance = mapper.get(arg)(argv[count:])
% j1 c6 M/ F' }, ^ if hasattr(instance, 'main'):, N4 @1 ? t- g. L1 c, v
## 实例main方法
, P9 k, x2 L* [1 H4 d, W8 Z instance.main()
$ A# p5 R% Q& _, s$ d) h7 E raise SystemExit(0)
% }& H f8 I1 R |
显然根据传入的参数创建了LVM的实例,然后进入实例的main方法 1. T2 y% V) N$ O/ d1 p8 \
2
2 ^" S y1 g- V9 o v3
* j+ W8 m7 v* o% G5 |7 Y, |4 S( F" G43 g& O/ ^0 f2 |/ h- F3 y
5
. L2 V) V C' [4 `4 f68 l! `0 h3 ? z2 X k
7
9 s& w4 }% L `* C81 Q9 t' }) z+ u
9
2 t- k8 @; K# V |$ X p- {; T10
; V4 u9 f$ P. k: z1 g& `# _$ r* R11
( B: T1 [/ p2 l( k% Q8 j12
# U! z$ y8 Z/ x: L/ m" @13
3 n; k) F: O6 L. V# U14
. l+ K k7 f2 C% q | ## ceph/src/ceph-volume/ceph_volume/devices/lvm/main.py
3 x7 T% t, i4 L7 Zclass LVM(object): ; } i: s: |# T0 Q' E" G
mapper = {7 |1 F/ l0 H. u: g6 v% V# G0 {* f
'activate': activate.Activate,
5 P* e8 l* V% ] V4 e. E* B8 W3 i: @ 'batch': batch.Batch,
. v7 X0 u7 X) Z/ z$ }/ y2 [ N. ~/ w+ g 'prepare': prepare.Prepare,
# D; w K2 i, q0 T 'create': create.Create,- _/ Y- \+ \! _
'trigger': trigger.Trigger, ### 关注这里###
4 Y) a. G, R9 V/ N/ u 'list': listing.List,
" k: N% Z- ^' T; w# I6 _ 'zap': zap.Zap,: E- q# m2 t( a/ Q7 B
}
7 D! B) x% V; W! P7 R def main(self):
* S2 T( k& ]) \( O4 v# g terminal.dispatch(self.mapper, self.argv)$ v/ z! l8 P, }( ~3 C
...<中间省略>8 U1 F3 q; `0 U$ y
|
跟前面如出一辙,根据传入的参数对应进入trigger.Trigger实例的main方法 15 |4 i" E0 u: h- U t
2
% X6 A1 X2 y2 d- t30 W# Z( ^* Y0 v/ q. @- m
4) s+ U q3 G( }' }9 L
5: j) A6 z+ v4 ]8 n T( T
6+ R# |# H* e% t6 R9 E; {* M5 b
7
3 e5 I; h8 X" `: T8 n" X89 z. g( V3 }$ C. f9 |+ e
92 N- c, y3 y6 \- O' _
10. T+ A* _8 ^# f5 x0 k
11
/ v/ D n5 o: f12
5 U1 \/ Y3 \: ?7 z3 L# y13
/ }( _7 @: h( j, N: u: I14
" e. ]/ X% x/ c5 ]5 p159 {& k& h1 }) w7 Z1 Y0 k
16( G: |0 C4 V' K- d$ s& O/ f* M
170 G ?* x5 Z6 B4 w1 g* E( M. M
18
5 J# m, w( d( _5 y, D1 @19
/ J! e5 o F4 [' ]8 f! I( N | ## ceph/src/ceph-volume/ceph_volume/devices/lvm/trigger.py
" B. c% L) x- }) @8 w2 q, ?; Wclass Trigger(object):
& X; n: B$ g' m6 P" S- q, o5 }( ^6 \9 }, ?" {1 P! E
help = 'systemd helper to activate an OSD'
& c& X- z2 Z( J/ n& b
- @9 _; D& ^( o: j0 d5 h' H+ N% S def __init__(self, argv):
0 y1 k: f% X) J self.argv = argv/ E7 B O5 c+ e0 [8 x
0 _" G7 _6 x% p" T% e9 _ @decorators.needs_root! p+ D! y& `% [" _, ]/ j
def main(self):# [& P# T. U- q3 t- w' F: \
... <中间省略>( G# n5 D) { \
## 解析参数
1 k% v- {8 Z& ]' }: w7 r+ J args = parser.parse_args(self.argv); p$ v& O4 f# L/ b6 o. m* j- e! x
## 检验osd id. v: c. ?. X0 E _
osd_id = parse_osd_id(args.systemd_data)
5 o8 r. ^& ^$ ~- H2 X2 \( W2 J ## 检验uuid5 @0 r3 e' d$ N {* j( C4 z! b, h
osd_uuid = parse_osd_uuid(args.systemd_data)+ `7 D8 K0 H5 f: A8 i, e+ O( A
## 再次跳转到Activate实例main方法: _2 W$ S2 v& H% t" x/ f9 F! v
Activate(['--auto-detect-objectstore', osd_id, osd_uuid]).main()
6 m/ y+ `& b( l7 n8 W |
以下是Activate类的main方法 1
$ ?) ]7 }2 ?) i2
6 D' \- j1 O* u! G% @# Q0 {+ O2 P4 i3 L3
- J2 w/ k" ^2 g4& y. k, T% t& W% d; A! U4 t4 h
53 F* D$ J9 X0 Q8 ]5 i4 F4 Q; n$ W- ]
6& c" n8 z1 u- e4 t
7
/ V1 N9 P) K, ]/ @$ W8 x8* b# M3 W& U1 K$ J* z# ~
9
! P3 l6 V0 s8 u6 V10! J- i! E1 W/ x2 R9 P
11
$ }) i5 `6 Z) U2 H. m12) n' K3 X0 M- ?; U
13
; j; N/ Z* ?* ]- G) N14
& |# d2 }+ Y& ^/ ?' H1 U- Z7 i | ##ceph/src/ceph-volume/ceph_volume/devices/lvm/activate.py
; x0 |1 O4 S, z% Y8 u f( ]def main(self):& K! L9 l) ~& u+ `- \, v) _) P4 P& b
sub_command_help = dedent("""
0 ^ B; E% n B. n ...<中间省略># j/ ^4 V4 U1 b7 d9 |: T
)
0 m) z! M8 |' S1 ] ## 参数解析
# p# O$ s; T J* M args = parser.parse_args(self.argv)7 H7 s2 Q! j2 _( W# G) [
## 如果不指定是bluestore或者filestore,默认按bluestore来处理% k! q/ A* B# {; Y% p( i
if not args.bluestore and not args.filestore:
" ?3 |0 B$ c5 X1 I# K args.bluestore = True$ e5 B' C8 K* ^5 a& |
if args.activate_all:
& R! P/ Q; w% W. h% u8 C0 Q self.activate_all(args)( s* u/ ~2 [; M. l, }2 `3 M7 c
else:
Q9 `0 E& |: `+ y7 o self.activate(args)9 X ^) I9 J; {$ w/ }% A+ G7 p
|
最后通过实例的activate方法来激活 16 |$ g+ V6 }8 H: O& m5 q
2$ _1 ?# G6 N0 M' g) n, R
3! S0 J( v8 R6 ]$ P! ^: d; w w
4
. I( G' S1 D/ X1 P50 D) A9 Z1 R& H% l) F1 L8 K- Z3 P
68 H: V1 }( l3 K8 e
7
/ W) j; Y7 }* v) t8% `+ f8 y" g" {1 ]$ K2 Y" k
9/ @3 O7 {$ B: e
10
! r: ~+ k. M6 o9 R- W4 r1 h11
; C3 {* t/ g" Y% U7 t12. X6 v9 s2 u& K* i0 y' c7 x
13
! m8 M1 Q, n* R/ ?% e0 |. s% F14
4 W$ ?( `1 d! P: z | ##ceph/src/ceph-volume/ceph_volume/devices/lvm/activate.py6 s* O P& Q) \$ \" o
def activate(self, args, osd_id=None, osd_fsid=None):
1 D7 e! j& t- d. ?' `' k ...<中间省略>
9 i4 }' U/ h8 y" h8 X* J ## 获取本地所有的lvm卷信息
* l. \5 t" _+ T3 Y2 R2 {. | lvs = api.Volumes()
& y' D" ?# i/ ]2 O( ^* z ...<中间省略>2 C; g6 G# m" o! x; r8 ~
for lv in lvs:
* \. a' m6 M9 u ....
" s" R# Z7 Q' n ## 通过lvm的tags来判断传入的osd id跟uuid是否已经存在,这些tags是在创建osd的时候写入(请继续往下看^_^) ) f- }; ^0 K) \: f" p. }: t
return activate_bluestore(lvs)
2 l" V# ^6 n0 s/ i% k) F, | if args.bluestore:; |% H* Y& x0 S" |
activate_bluestore(lvs, no_systemd=args.no_systemd)
! U, J( H f% Q$ x/ U# Z6 G elif args.filestore:
4 {$ x* |/ n5 N' z activate_filestore(lvs, no_systemd=args.no_systemd)$ h4 B/ }' B, \% l
|
BlueStore的osd则继续跳转到activate_bluestore 1* V; o+ i9 O: V
2
4 x) s9 Z' R! X' Z39 u) z1 v( ~; \2 f+ P
4
- Y1 D8 A8 N& ]6 K" c5) G6 f7 x. a5 j2 O5 B6 O- q5 n
6
* ~9 k( a. p5 c- \79 q6 P, {' j9 F5 b
8+ ~/ F( c, q' i! L) N3 e) c) Z
9
* D! [$ ?, ?1 m1 v10
" h" f H7 K0 e11/ V2 Q8 b) ^( P/ Y& O- w
128 q5 d& G( X6 C6 ~6 _
13
5 }/ X' g/ B& g; p. L' Z0 I14. f0 `9 U8 e1 d3 U
15
7 r0 D7 \7 ~2 p* W" `% H16# a$ w/ [1 G. f6 ?, t. c
174 ~- r# c6 a6 ~# L
18
, Y8 L( u, j0 H. ]1 {19
" j/ b. T" {7 _0 Z5 ^20% U s5 S: B% l/ P$ @1 t
213 ?9 V" t/ |7 m% H- }: g
22
/ e( a. V. L2 ~9 L23! p' M2 }. p, P& R0 z. m9 q
244 T0 C* E) v& g$ K, }2 [6 H
25( C/ y6 y2 b3 h" q+ u0 x
266 }& Z" u8 o$ ?8 G
27 I4 V& ?$ E' D, `
28
% s# ?: t, i: o- o0 x( s4 J/ v7 I29
9 ^' S) H4 a5 h) w" Z$ d' {- H30
3 i, E/ ?* L5 U& j* u31- @. ?9 i, E% }1 c3 {
32' w& a% ~. _9 r3 @8 ]7 B1 Y& d
33: J" U* u+ I: ?4 n
346 u H0 U" o/ h: E i
35
$ R( G- \" Z7 O36
{! ~# ~. b, R' `! `; Z37
/ I& v" c; y" x3 g38. S( I8 D- Q; \ M
39$ L: [- p* m5 s3 ^. w
40
}7 Y% b" S3 \" W) y, t41
( I. N2 l5 W1 P1 L42+ @2 V: P0 Q2 T( X1 j) ^
43
8 o) V0 c3 c3 k9 P1 R. I* j44$ z+ @0 c1 t6 w3 l# o; u. m. x5 O0 S
45
' l- _% p$ L) y( w1 L46
: m( } O4 U! j& ^47( c2 Y! q1 i' K' k8 S( K1 G
48
4 c; I3 p, U# h49# e9 J/ \* C7 t& v
50
1 H4 m3 m$ Y$ q7 _+ {/ x51# {4 ~( n6 V+ \$ g
52, S# G' W6 a' _7 g% T: W! _- ?6 u2 N
| ##ceph/src/ceph-volume/ceph_volume/devices/lvm/activate.py. F8 @# Q" W* p) L$ z/ ?- Q
def activate_bluestore(lvs, no_systemd=False):# u; w# G) P: w, G& o& F
# 从tags里找osd相关id、fsid、cluster_name等信息, m3 D5 H- r1 A F. m' T
osd_lv = lvs.get(lv_tags={'ceph.type': 'block'})
7 K. T4 B6 f+ _! E, }2 B/ y- J if not osd_lv:: p& S3 U% i) f+ ^% o3 b9 d
raise RuntimeError('could not find a bluestore OSD to activate')
$ \. x4 a: T- Q. D is_encrypted = osd_lv.tags.get('ceph.encrypted', '0') == '1'2 n3 _1 v) H3 H; F2 N, t
dmcrypt_secret = None. m# l3 T6 N) X& g# i8 t% o
osd_id = osd_lv.tags['ceph.osd_id']
5 V8 k5 I( a, Y0 e: A0 u7 ]3 { conf.cluster = osd_lv.tags['ceph.cluster_name']
# D, ?' z# v6 ?% Q+ V osd_fsid = osd_lv.tags['ceph.osd_fsid']6 [5 A7 [, E6 X4 T2 J
: C5 Z$ ?# z$ ~/ j1 [' Z) g osd_path = '/var/lib/ceph/osd/%s-%s' % (conf.cluster, osd_id)
4 \& X+ `% f7 _# Z `% i7 u ### 有没有很熟悉,其时就是前面分析的activate阶段的相关命令###
% J. v) t/ L7 _' U if not system.path_is_mounted(osd_path):
& n" @ D# A. W# Z* e # ## 创建工作目录并挂载tmpfs " O9 k, G+ c) R" o; O+ ?
prepare_utils.create_osd_path(osd_id, tmpfs=True)
4 A1 g( X% |# x3 i, W/ C ## 构建data、db、wal的软链路径
}' K, g# s o( V+ i) M for link_name in ['block', 'block.db', 'block.wal']:5 H7 J0 _0 Y; n+ [3 O
link_path = os.path.join(osd_path, link_name)' q) _7 Q" b6 n! j; |5 ]
if os.path.exists(link_path):
# m5 S+ m2 r& y5 X6 M& K: ^ os.unlink(os.path.join(osd_path, link_name))
+ s/ X8 ~: i- E4 g! c F7 S ## 获取设备路径 ##
$ k0 J: `# F. ^7 }2 M. W1 ?- \7 h7 I db_device_path = get_osd_device_path(osd_lv, lvs, 'db', dmcrypt_secret=dmcrypt_secret)9 A) z% K1 y# m
wal_device_path = get_osd_device_path(osd_lv, lvs, 'wal', dmcrypt_secret=dmcrypt_secret); ?2 R5 Q1 s7 C! |, E5 l) C
; [" {$ g! y0 k1 F$ I7 G6 g
### 看这里!看这里!看这里!重要的事情说三遍,就是调用ceph-bluestore-tool工具读出元数据并写入工作目录,一模一样,下面都一样了。很熟悉了吧 ^__^
' Q/ V/ F8 s4 v0 ? process.run([. l4 u! `5 m u E/ }. h
'ceph-bluestore-tool', '--cluster=%s' % conf.cluster,
9 g5 J* b$ w) x1 x 'prime-osd-dir', '--dev', osd_lv_path,
! a/ j- y3 F# z- F1 t '--path', osd_path])
1 ~0 R* @3 G' }( k/ E2 g" i* l/ m& `+ t5 Z$ C+ S
process.run(['ln', '-snf', osd_lv_path, os.path.join(osd_path, 'block')])' u, ~5 m! Q# H! ?2 v7 e) R
## 所有者修改以及创建软连
& S I+ m% s( Q system.chown(os.path.join(osd_path, 'block')); T, t; R! z$ l) C
system.chown(osd_path)
1 M- {% [! \* x if db_device_path:
" c4 h: C S! M destination = os.path.join(osd_path, 'block.db')9 q( T# V0 ?; r" b2 O- f
process.run(['ln', '-snf', db_device_path, destination])2 j$ Q3 s' u! G# J
system.chown(db_device_path)5 R0 ^* n. M# Y7 U4 q
if wal_device_path:. t ^8 m; C. s( M) P
destination = os.path.join(osd_path, 'block.wal')1 C. o5 ^3 \" @5 k4 `
process.run(['ln', '-snf', wal_device_path, destination])0 U5 A! l+ X9 l4 K: K1 H. B
system.chown(wal_device_path)
# S% g ~8 j& g; @) Z* h7 y9 C& i0 c: W" i; I- ?# i$ S3 _
if no_systemd is False:
6 z+ _5 k _! Q. ~' Z9 l # enable the ceph-volume unit for this OSD7 s5 D9 n, p) [! G
systemctl.enable_volume(osd_id, osd_fsid, 'lvm')
' Q+ [- s3 P k5 y
3 _5 n' T& ?! t6 F # 启动osd进程0 V0 a% y7 V+ O! x; v
systemctl.start_osd(osd_id); H% I# {) Z/ g1 H$ b
terminal.success("ceph-volume lvm activate successful for osd ID: %s" % osd_id)# U! U; [- q. I7 g2 k' Z/ Z
|
到此,相信大部分读者已经豁然开朗了。ceph-volume系统服务会触发ceph-volume lvm trigger, 再进入activate阶段,最后一系列的系统命令调用,完成osd启动。 整个启动流程大致如下图所示:
- h6 U q, ? c, H0 Uimage_1cn8kcnnbh521niu16djegnqhb4d.png-40.8kB 创建分析osd的创建跟启动代码入口是一样的,都是从ceph/src/ceph-volume/main的main()开始 image_1cn8melrej3a5glk0c1cpqeqv4q.png-21.5kB# C9 V8 E; g9 L* D$ _: C
根据传入的mapper和argv,再次回看下terminal.py里的dispatch 1
- k$ Q$ R) a6 R5 x; M2" ?2 e( g6 m' d) k
30 {; K" S0 m6 X: @/ o
4
9 h6 {1 L& z3 |2 O8 `" a5
0 i' o- ?/ D: F; Y- |7 c- t) h6
9 o( y" N# o, |' r71 R* G" @* l; v5 Z" k1 c8 u, I
8
% q8 P# `5 V, e0 e/ b- c7 q" A93 j0 P( r9 _3 n+ S: \! h) ]/ X
100 d! v3 U3 R: n- J. s2 V: B/ f
11
) g, {+ ?) ~1 W! v | ## ceph/src/ceph-volume/ceph_volume/terminal.py( B- N$ B: n$ A. D h# Y0 E) C
def dispatch(mapper, argv=None):: H# }5 i9 `+ r/ g1 y
argv = argv or sys.argv
V$ P6 K1 Z0 t! x; ~ for count, arg in enumerate(argv, 1):5 L+ A1 z0 ]. V d
if arg in mapper.keys():0 Z) p. ~- A# m, N& i- L3 j
## 创建实例1 Z: \ Y( G0 b- i. k+ @7 s
instance = mapper.get(arg)(argv[count:])& d) f) o( v; Z& ]
if hasattr(instance, 'main'):- e# I9 c) T9 \! R/ i
## 实例main方法
9 B E1 c9 b3 e6 B. P# s instance.main()
7 F- W6 N; l* e/ _ raise SystemExit(0)
( m; u7 K, Z9 ?$ T6 s |
如下图所示的LVM的类变量mapper,结合上面内容,实例instacne实际上就是create.Create(),然后执行实例的main()方法
6 y- ]9 T+ B$ h" v- t- G4 Mimage_1cn8i7f3l12b61ap1i0a1u1h124440.png-65.5kB 1' g2 ?7 {) _/ y' U
22 q: e+ r- a8 {- |9 m$ L( D
3 M0 w8 H" N5 @2 a* {; v
4
# O& i6 p" M3 _: a' O' a5
* Y7 p. s& J: J4 ~- C5 i6 _/ p6. E$ ~5 a) [; A: K& }/ b* L
7
/ U$ S. J1 r2 o0 j: z% H88 J, G6 I& p$ k9 r) L* c( i
9, H: F9 k7 u# S" C- _* S+ x I
10
M- C6 N9 g. ~# H8 {11
6 f" d& x9 w$ }7 y) H; I12
4 _) `: L5 e( L, j13, j; D0 L* T, t, g
14
" ^. Q- e! m$ K1 L6 m5 | | ## ceph/src/ceph-volume/ceph_volume/devices/lvm/create.py
4 W% X3 \5 G4 O6 \; h def main(self):
0 C* [; c3 P! I- U ... <中间省略>
6 f/ q' `) Q1 r ## 解析参数
+ v: @! k8 |1 E3 S3 ?, |+ D if len(self.argv) == 0:" \8 w. c. m. v- A
print(sub_command_help)
' D7 D! T3 ?7 ^# y/ P3 W" p return
8 F. `1 T- ^; b2 A U exclude_group_options(parser, groups=['filestore', 'bluestore'], argv=self.argv)5 z* ^+ [5 C* t: w" {& F0 w+ e
args = parser.parse_args(self.argv)
6 H, z& B! a7 ?/ J1 j ## 判断是bluestore还是filestore,默认为bluestore
& y& S E5 |5 r if not args.bluestore and not args.filestore:$ ^; O4 A `: v
args.bluestore = True
, f" _0 e+ h# B5 Z; m ## 调用create()方法
- _& `9 F% }4 A self.create(args)
* @# {( M+ S, L9 } |
进入create()方法,重点关注它里包含了创建Prepare实例,然后进入Activate().activate(),这在前面启动阶段已经分析了。下面重点分析下Prepare里具体做了哪些处理。 1
5 {+ n" ?8 V5 m2
/ g/ M' x( X% c3( M) D+ r- q% h7 W/ ~7 I
40 L" i4 Z* T& d6 p% I4 u+ I2 i
5) y8 ~0 \. a. \
6
9 h2 X3 ^- E4 B6 q+ K7
6 b& T4 |, a3 h/ A0 k& J7 q88 M+ h" }. t/ s
9
- }+ A7 K9 B0 r3 @: i# c10, W; f. K9 I, k" n
11
' k# n# I$ Z' I9 k+ h6 f5 g3 y6 d12% j4 h8 I9 \4 @ ^
13# e6 ]" |" M0 M+ y' Z0 F
14
) \! A, t4 N. i# d" H( U155 Z* C: Y2 b+ C7 G2 q2 U5 H/ A9 o: a
16
8 s4 R/ b' W1 N5 l0 p2 o) A6 C" v17
0 @/ X8 Y o3 J' w+ k18
& I3 V; f" ^' s) T# [5 H | ## ceph/src/ceph-volume/ceph_volume/devices/lvm/create.py7 r3 b! G1 m ~* I1 Q' x
@decorators.needs_root
- k" l$ I1 B( }6 X3 Wdef create(self, args):
" Z+ O$ f4 {9 U+ X: a. z5 x# T if not args.osd_fsid:: O9 G) _9 L: W9 z# A7 w
args.osd_fsid = system.generate_uuid()& y$ t( A, \7 ~+ X# Z6 b
### 注意看这里!! 包含了prepare ###
9 e2 n8 `/ S `+ X a/ I4 X prepare_step = Prepare([])
# r' c; v; x+ O$ x+ F prepare_step.safe_prepare(args)
$ e" o8 f* q( h9 |# C osd_id = prepare_step.osd_id8 l/ U. \: S& P' q3 |1 m' m6 {* b
try:) p$ m, ^' V9 j- d$ d5 ]4 P
Activate([]).activate(args)! u Y/ I: ~, b0 I0 g
except Exception:
/ Z: z* C: y+ G' r7 ^ logger.error('lvm activate was unable to complete, while creating the OSD')
9 G8 S2 Z; A" a3 O3 ~/ A7 r logger.info('will rollback OSD ID creation')
2 N; U8 w0 L" H# | ## 创建失败,就回滚,删除osd,其实就是调用ceph osd purge 相关命令 ##
* f) K7 @; [# a/ I rollback_osd(args, osd_id)
2 u# F5 X- ~4 `6 `, h9 e* y raise
% F, ^/ s$ a* G: x. Z terminal.success("ceph-volume lvm create successful for: %s" % args.data)
i/ Q* ^# B, |* J2 Q; h |
1& j& r" E- n( p# r1 m k$ o" ~
2
+ t! Y0 P7 [6 T- E3( T+ Q* U6 E# k+ |
4! @9 r2 _$ h; {' W
5* C [/ @2 x. d4 h4 c6 d% U# L
6
4 ?1 ^! `' X# Q, w$ O72 y9 v! p! \3 c! G
81 [5 `- I/ I1 X) M) L6 W
9
4 m" F6 Z0 }: G; `7 t0 A10
& t& b5 ?9 f5 q5 J) `11
# {% X* |, g0 k4 f) F0 Q12
: Y/ j$ f1 O% n" q5 | G/ U9 @13
. M+ p0 M: @% u5 u1 \$ s146 E+ S, Q' h' {/ S( o0 ~
15
. o8 c, O* C+ l) i7 S/ e16$ F2 d# z$ t. q2 B: g" Z
17! v3 B1 z/ b. i3 I) F x4 Z
18
; ^9 b! F. ]6 R) ]19
3 P8 {. k, b& c* A& E, q20
6 v7 j# ^7 ~* Y# Z21: L% ?! V! ?, Y5 Q2 L# g7 r
22
& ~" A0 }6 J) N; E: S$ C! ~2 R5 t23; v4 e: Q. P" W, K
24
. o, i, m& X5 }- d& D25 @& m' x. c, g9 u+ N g" i0 ?
26
3 B- U0 c6 [8 K, o% G& }+ a27
' Z; L: B0 C8 H" W283 C5 z' p9 ~% B: Q$ f
29: Z4 G+ S9 S% D9 ^, h
30& D N9 Q. f* p1 M' P3 Y
31
# ?5 c" Z6 P+ N2 B32
* N/ f0 g+ D' N0 Y" i33! Y2 S5 R/ ~3 w7 X2 T& {; i4 X
34
, y" B9 g$ Y' v( y8 t7 C35
/ L# j' v3 b9 W, l) s" C. V l36
) L& m3 z9 Q# M6 \8 Z( i37
& u/ L) l' O' Q- x9 N$ i38' F8 z0 L: @$ L% E
39
% o3 Z' w ~' J! J3 [+ H" [6 K7 r40
, @8 U3 N9 ]) I/ a' w- u* i | ##ceph/src/ceph-volume/ceph_volume/devices/lvm/prepare.py, _5 S0 `( S) D, B6 J l" ^
@decorators.needs_root
5 G% e/ G' o8 ^1 x! U. {- Ndef prepare(self, args):
: o/ B% G7 R& d& o( \
* ~& }4 b' T' N& V ...<中间省略>
% N) B) d0 H" J0 y$ `: {% d/ P) @
### 创建osd的一些准备工作,比如keyring,osd id,osd uuid等
5 v) w7 ?, a" ? cluster_fsid = conf.ceph.get('global', 'fsid')
6 s4 ~1 O, ^1 Z9 Q3 L9 }4 c: R osd_fsid = args.osd_fsid or system.generate_uuid()
' p/ c0 b, v. G1 H8 T% Q: [ crush_device_class = args.crush_device_class
! d4 j/ x& g3 \% U& \6 y! B if crush_device_class:3 M1 i* s& X& w) V s
secrets['crush_device_class'] = crush_device_class
v" l, x$ X7 j' s6 o1 h4 q self.osd_id = prepare_utils.create_id(osd_fsid, json.dumps(secrets), osd_id=args.osd_id)
& P9 U/ y' p( v2 u7 t) O ## 这些元数据打包到tags里2 J) Z" M4 k$ i% q: E
tags = {
0 G& _7 k% w1 | 'ceph.osd_fsid': osd_fsid,. D( ~ n% y5 o) C4 ?
'ceph.osd_id': self.osd_id,
) f3 l3 x! _1 |+ W+ Z& v+ T 'ceph.cluster_fsid': cluster_fsid,
$ [5 }; g. ]- Y+ `" u% c 'ceph.cluster_name': conf.cluster,' \* B1 F9 t4 p- ]9 g
'ceph.crush_device_class': crush_device_class,
6 g1 K/ \9 S9 E7 F# `5 i) Z+ R: r- d }
& {2 V2 ]6 \' a1 \& B5 ]. h ...<中间省略>
$ X8 s( a% i$ V* V# N& P #### 看重点!!!根据传入的数据先去扫描本地所有lvm卷信息,是否已经存在,如果没有,就把这些tags写入lvm的tags里
. t7 u$ a* N+ J3 ^9 i data_lv = self.get_lv(args.data)
8 C6 K4 w% @& @( O1 ?- q/ ? if not data_lv:
; v$ R6 \) K5 A/ H8 l" m { ### prepare_device方法里会把tags写入到lvm卷的tags( P- F e) p5 P# m6 n8 e
data_lv = self.prepare_device(args.data, 'data', cluster_fsid, osd_fsid)3 Y: x7 _0 q6 l8 y
- f; H" k: H3 u; C
...<中间省略>
" S7 V0 Y* L/ B$ d3 F- z
1 K) K8 b) D' E3 N- U #### bluestore 初始化准备,跳转进入preabluestore继续处理
: p. q$ b& g6 x) F! h% E( w" k' A prepare_bluestore(
7 y$ u; h' P$ c4 v( J block_lv.lv_path,
; e. y& ]! U6 b2 [3 q4 I8 `0 Q! G wal_device,
6 r& `0 \. O# h7 P db_device," t$ N& x' N H3 ]9 Q$ R# t
secrets,% l/ L7 c* {4 z3 B7 U
tags,; T+ x) `: I* }% Q9 D
self.osd_id,$ J! K: c+ B* f
osd_fsid,, H1 t' k F% m; q; C7 C, T4 ~3 D/ ]$ N
)
4 w6 d3 s" J) C9 p |
1. F: x2 Z7 s% y t" t* T, {
2! A0 b3 ~8 Y# b& {% D0 A: U* K5 y" i
3
& ], e$ c- \! _4
. ~/ P2 c7 ^3 m f& g S5+ ^- K/ z. I9 r- `9 L
6; |2 w0 _) J5 `; p- g
7
: n& r8 Q) I# o) R8 \8
9 a3 Q: P0 w5 v1 J( L# E9
% d' E' f$ M* G8 q) @4 y3 C7 e& H8 l10
d0 Q" i# q" }- O, k% v | ### ceph/src/ceph-volume/ceph_volume/devices/lvm/prepare.py
' t% O! u8 U+ M% T% u3 M; p/ tdef prepare_bluestore(block, wal, db, secrets, tags, osd_id, fsid):
/ o- ~0 Z- a2 K8 G l8 s( B ...<中间省略>$ p: a- n" X3 e$ e
### 其中都是一些准备工作,核心就是这个初始化了,也就是前面出面过的初始化
% k& S9 e& g2 t9 ?) A prepare_utils.osd_mkfs_bluestore(. U& g3 Z" b. o1 ^" u O
osd_id, fsid,
4 _4 L, ^/ x* P5 J: f keyring=cephx_secret,
/ \1 o! t! W& X- |* Q wal=wal,
- k' }7 {* J. d db=db5 V7 J o4 c$ M0 |
)
6 G$ V( e: D, j" ~+ @, x' c! [ |
至此,bluestore已经初始化完毕了,然后接着走启动流程就可以了。4 ^# ~, W( b* F0 v9 A. p
image_1cn8n9740i5nilf19jgjl1l1264.png-45.7kB 小结通过阅读学习ceph-volume的代码,可以清楚地理解整个osd的创建与启动流程 |