• Ceph RBD 的实现原理与常规操作


    目录

    前文列表

    Ceph 分布式存储架构解析与工作原理
    手动部署 Ceph Mimic 三节点

    RBD

    RBD: Ceph’s RADOS Block Devices , Ceph block devices are thin-provisioned, resizable and store data striped over multiple OSDs in a Ceph cluster.

    Ceph RBD 是企业级的块设备存储解决方案,支持扩缩容、支持精简置备,具有 COW 特性,一个块设备(Volume)在 RADOS 中会被分割为若干个 Objects 储存。

    CEPH BLOCK DEVICE

    • Thin-provisioned
    • Images up to 16 exabytes
    • Configurable striping
    • In-memory caching
    • Snapshots
    • Copy-on-write cloning
    • Kernel driver support
    • KVM/libvirt support
    • Back-end for cloud solutions
    • Incremental backup
    • Disaster recovery (multisite asynchronous replication)

    RBD Pool 的创建与删除

    HELP

    osd pool create <poolname> <int[0-]> {<int[0-]>} {replicated|erasure} {<erasure_code_create pool profile>} {<rule>} {<int>}
    

    创建一个 Pool rbd_pool 并初始化为 RBD 类型

    [root@ceph-node1 ~]# ceph osd pool create rbd_pool 8 8
    pool 'rbd_pool' created
    [root@ceph-node1 ~]# ceph osd pool create rbd_pool02 8 8
    pool 'rbd_pool02' created
    
    [root@ceph-node1 ~]# rbd pool init rbd_pool
    [root@ceph-node1 ~]# rbd pool init rbd_pool02
    

    NOTE:创建 Poo 时会指定 pg_num,官方推荐:

    • 少于 5 个 OSD, 设置 pg_num 为 128
    • 5~10 个 OSD,设置 pg_num 为 512
    • 10~50 个 OSD,设置 pg_num 为 4096
    • 超过 50 个OSD,可以应用 Ceph PGs per Pool Calculator 来进行计算

    查看 Pools 的 df 信息

    [root@ceph-node1 ~]# rados df
    POOL_NAME              USED OBJECTS CLONES COPIES MISSING_ON_PRIMARY UNFOUND DEGRADED RD_OPS     RD WR_OPS      WR
    .rgw.root           2.2 KiB       6      0     18                  0       0        0     63 42 KiB      6   6 KiB
    default.rgw.control     0 B       8      0     24                  0       0        0      0    0 B      0     0 B
    default.rgw.log         0 B     207      0    621                  0       0        0  36870 36 MiB  24516     0 B
    default.rgw.meta        0 B       0      0      0                  0       0        0      0    0 B      0     0 B
    rbd_pool            114 MiB      44      0    132                  0       0        0   2434 49 MiB    843 223 MiB
    
    total_objects    265
    total_used       9.4 GiB
    total_avail      81 GiB
    total_space      90 GiB
    

    查看每个 Pool 的 df 信息

    [root@ceph-node1 ~]# ceph df
    GLOBAL:
        SIZE       AVAIL      RAW USED     %RAW USED
        90 GiB     79 GiB       11 GiB         12.39
    POOLS:
        NAME                    ID     USED        %USED     MAX AVAIL     OBJECTS
        .rgw.root               3      2.2 KiB         0        24 GiB           6
        default.rgw.control     4          0 B         0        24 GiB           8
        default.rgw.meta        5          0 B         0        24 GiB           0
        default.rgw.log         6          0 B         0        24 GiB         207
        images                  9       39 MiB      0.16        24 GiB           9
        volumes                 10        36 B         0        24 GiB           5
        vms                     11        19 B         0        24 GiB           3
        backups                 12        19 B         0        24 GiB           2
    

    查看 Pool 的相关信息

    # 查看 Pools 清单
    [root@ceph-node1 ~]# rados lspools
    rbd_pool
    rbd_pool02
    
    # 查看 Pool 的 PG 和 PGP 数量
    [root@ceph-node1 ~]# ceph osd pool get rbd_pool pg_num
    pg_num: 8
    [root@ceph-node1 ~]# ceph osd pool get rbd_pool pgp_num
    pgp_num: 8
    
    # 查看当前 OSD 状态
    root@ceph-node1 ~]# ceph osd dump | grep pool
    pool 1 'rbd_pool' replicated size 3 min_size 1 crush_rule 0 object_hash rjenkins pg_num 8 pgp_num 8 last_change 71 flags hashpspool,selfmanaged_snaps stripe_width 0 application rbd
    pool 3 '.rgw.root' replicated size 3 min_size 1 crush_rule 0 object_hash rjenkins pg_num 8 pgp_num 8 last_change 56 owner 18446744073709551615 flags hashpspool stripe_width 0 application rgw
    pool 4 'default.rgw.control' replicated size 3 min_size 1 crush_rule 0 object_hash rjenkins pg_num 8 pgp_num 8 last_change 59 owner 18446744073709551615 flags hashpspool stripe_width 0 application rgw
    pool 5 'default.rgw.meta' replicated size 3 min_size 1 crush_rule 0 object_hash rjenkins pg_num 8 pgp_num 8 last_change 61 owner 18446744073709551615 flags hashpspool stripe_width 0 application rgw
    pool 6 'default.rgw.log' replicated size 3 min_size 1 crush_rule 0 object_hash rjenkins pg_num 8 pgp_num 8 last_change 63 owner 18446744073709551615 flags hashpspool stripe_width 0 application rgw
    
    # 查看 Pool 下属 Obejcts 的 OSD Map 信息,可以看出 Pool rbd_pool 的 Objects 具有 3 副本(PG 被映射到 3 个 OSD)
    [root@ceph-node1 ~]# ceph osd map rbd_pool rbd_info
    osdmap e53 pool 'rbd_pool' (1) object 'rbd_info' -> pg 1.ac0e573a (1.2) -> up ([4,0,8], p4) acting ([4,0,8], p4)
    
    [root@ceph-node1 ~]# ceph osd map rbd_pool rbd_directory
    osdmap e53 pool 'rbd_pool' (1) object 'rbd_directory' -> pg 1.30a98c1c (1.4) -> up ([7,3,1], p7) acting ([7,3,1], p7)
    
    [root@ceph-node1 ~]# ceph osd map rbd_pool rbd_id.volume01
    osdmap e53 pool 'rbd_pool' (1) object 'rbd_id.volume01' -> pg 1.8f1d799c (1.4) -> up ([7,3,1], p7) acting ([7,3,1], p7)
    

    删除一个 RBD 类型的 Pool

    [root@ceph-node1 ~]# ceph osd pool delete rbd_pool02
    Error EPERM: WARNING: this will *PERMANENTLY DESTROY* all data stored in pool rbd_pool02.  If you are *ABSOLUTELY CERTAIN* that is what you want, pass the pool name *twice*, followed by --yes-i-really-really-mean-it.
    
    [root@ceph-node1 ~]# ceph osd pool delete rbd_pool02 rbd_pool02 --yes-i-really-really-mean-it
    Error EPERM: pool deletion is disabled; you must first set the mon_allow_pool_delete config option to true before you can destroy a pool
    

    上述表示删除失败,Pool 的删除是一个风险级别非常高的操作,所以 Ceph 为该操作设定了一个配置项,我们修改配置运行删除 Pool:

    # 只允许当前客户端执行删除操作,所以直接修改 /etc/ceph/ceph.conf
    [mon]
    mon allow pool delete = true
    
    $ systemctl restart ceph-mon.target
    

    再次删除 Pool:

    [root@ceph-node1 ~]# ceph osd pool delete rbd_pool02 rbd_pool02 --yes-i-really-really-mean-it
    pool 'rbd_pool02' removed
    

    设置 Pool 的配额

    # 设置允许最大 Objects 数量为 100
    ceph osd pool set-quota test-pool max_objects 100
    
    # 设置允许最大容量限制为 10GB
    ceph osd pool set-quota test-pool max_bytes $((10 * 1024 * 1024 * 1024))
    
    # 取消配额限制只需要把对应值设为 0 即可
    

    Pool 的重命名

    ceph osd pool rename test-pool test-pool-new
    

    创建/删除 Pool Snapshot

    # 创建
    ceph osd pool mksnap test-pool test-pool-snapshot
    
    # 删除
    ceph osd pool rmsnap test-pool test-pool-snapshot
    

    NOTE:Ceph 有两种 Snapshot 类型,这两种类型是互斥的,在存在 Self Managed Snapshot 的 Pool 中不能再执行 Pool Snapshot,反之亦然。

    • Pool Snapshot:对 Pool 执行快照
    • Self Managed Snapshot:对 RBD 块设备执行快照

    设置 Pool 的元数据

    eph osd pool set {pool-name} {key} {value}
    
    # 设置 Pool 的 PG 副本数量为 3
    ceph osd pool set test-pool size 3
    

    块设备的创建与删除

    要创建 RBD 块设备,首先需要登录到 Ceph Cluster 的任意 MON 节点,或登录到具有 Ceph Cluster 管理员权限的 Host,或 Ceph 客户端上。下面我们直接在 MON 节点上执行操作。

    指定 RBD Pool 创建块设备

    [root@ceph-node1 ~]# rbd create rbd_pool/volume01 --size 1024
    [root@ceph-node1 ~]# rbd create rbd_pool/volume02 --size 1024
    [root@ceph-node1 ~]# rbd create rbd_pool/volume03 --size 1024
    

    NOTE:如果不指定 RBD 类型的 Pool Name,则默认为 rbd,所以首选需要有一个 Pool rbd。

    查看块设备信息

    [root@ceph-node1 ~]# rbd --image rbd_pool/volume01 info
    rbd image 'volume01':
        size 1 GiB in 256 objects
        order 22 (4 MiB objects)
        id: 11126b8b4567
        block_name_prefix: rbd_data.11126b8b4567
        format: 2
        features: layering, exclusive-lock, object-map, fast-diff, deep-flatten
        op_features:
        flags:
        create_timestamp: Tue Apr 23 07:30:57 2019
    
    # size:块设备大小
    # order:Object 大小,这里 22 表示 2**22 即 4MiB
    # block_name_prefix:块设备的 Ceph Cluster 全局唯一标示
    # format:块设备格式,有 1、2 两种类型
    # features:卷特性,细分为
    # - layering:支持分层
    # - striping:支持条带化 v2
    # - exclusive-lock:支持独占锁
    # - object-map:支持对象映射索引,依赖 exclusive-lock
    # - fast-diff:支持快速计算差异,依赖 object-map
    # - deep-flatten:支持快照扁平化
    # - journaling:支持记录 IO 操作,依赖独占锁
    

    查看 Pool 下属的块设备的相关 Obejcts

    [root@ceph-node1 ~]# rados -p rbd_pool ls
    ...
    rbd_directory
    rbd_id.volume01
    
    # rbd_id.volume01:保存了 volume01 自己的 block_name_prefix
    # rbd_directory:保存了这个 Pool 下属所有块设备的索引
    

    获取 Pool 下的一个 Objects 并查看其内容

    root@ceph-node1 ~]# rados -p rbd_pool get rbd_info rbd_info
    
    [root@ceph-node1 ~]# ls
    rbd_info
    
    [root@ceph-node1 ~]# hexdump -vC rbd_info
    00000000  6f 76 65 72 77 72 69 74  65 20 76 61 6c 69 64 61  |overwrite valida|
    00000010  74 65 64                                          |ted|
    00000013
    

    删除一个块设备

    [root@ceph-node1 ~]# rbd ls rbd_pool
    volume01
    volume02
    volume03
    
    [root@ceph-node1 ~]# rbd rm volume03 -p rbd_pool
    Removing image: 100% complete...done.
    
    [root@ceph-node1 ~]# rbd ls rbd_pool
    volume01
    volume02
    

    块设备的挂载与卸载

    RBD 的驱动程序已经被集成到 Linux 内核(2.6.39 或更高版本),将 Linux 操作系统作为客户端挂载卷的前提是加载 RBD 内核模块,下面我们首先将卷挂载到 ceph-node1,因为 ceph-node1 就是一个原生的客户端,不需要额外操作。

    映射块设备到客户端本地

    [root@ceph-node1 ~]# lsmod | grep rbd
    rbd                    83640  2
    libceph               306625  1 rbd
    
    [root@ceph-node1 ~]# rbd map rbd_pool/volume01
    rbd: sysfs write failed
    RBD image feature set mismatch. You can disable features unsupported by the kernel with "rbd feature disable rbd_pool/volume01 object-map fast-diff deep-flatten".
    In some cases useful info is found in syslog - try "dmesg | tail".
    rbd: map failed: (6) No such device or address
    

    这里执行映射失败了,原因是因为客户端内核版本较低,无法支持卷的全部特性,可以通过以下修改来解决。

    设定 Ceph 的全局默认 RBD 块设备特性清单:

    $ vi /etc/ceph/ceph.conf
    [global]
    ...
    rbd_default_features = 1
    
    $ ceph-deploy --overwrite-conf admin ceph-node1 ceph-node2 ceph-node3
    

    或者在创建块设备的时候单独指定块设备特性:

    rbd create rbd_pool/volume03 --size 1024 --image-format 1 --image-feature layering
    

    或者关闭内核不支持的块设备特性之后再映射:

    [root@ceph-node1 ~]# rbd info rbd_pool/volume01
    rbd image 'volume01':
        size 1 GiB in 256 objects
        order 22 (4 MiB objects)
        id: 11126b8b4567
        block_name_prefix: rbd_data.11126b8b4567
        format: 2
        features: layering, exclusive-lock, object-map, fast-diff, deep-flatten
        op_features:
        flags:
        create_timestamp: Tue Apr 23 07:30:57 2019
        
    [root@ceph-node1 ~]# rbd feature disable rbd_pool/volume01 object-map fast-diff deep-flatten
    [root@ceph-node1 ~]# rbd feature disable rbd_pool/volume02 object-map fast-diff deep-flatten
    
    [root@ceph-node1 ~]# rbd info rbd_pool/volume01
    rbd image 'volume01':
        size 1 GiB in 256 objects
        order 22 (4 MiB objects)
        id: 11126b8b4567
        block_name_prefix: rbd_data.11126b8b4567
        format: 2
        features: layering, exclusive-lock
        op_features:
        flags:
        create_timestamp: Tue Apr 23 07:30:57 2019
    
    [root@ceph-node1 ~]# rbd map rbd_pool/volume01
    /dev/rbd0
    

    查看客户端本地已映射的块设备

    [root@ceph-node1 ~]# rbd showmapped
    id pool     image    snap device
    0  rbd_pool volume01 -    /dev/rbd0
    
    [root@ceph-node1 ~]# lsblk | grep rbd0
    rbd0                                                                                                  252:0    0    1G  0 disk
    

    块设备映射到本地之后就等同于一个裸设备,需要分区格式化以及创建文件系统:

    [root@ceph-node1 ~]# mkfs.xfs /dev/rbd0
    meta-data=/dev/rbd0              isize=512    agcount=8, agsize=32768 blks
             =                       sectsz=512   attr=2, projid32bit=1
             =                       crc=1        finobt=0, sparse=0
    data     =                       bsize=4096   blocks=262144, imaxpct=25
             =                       sunit=1024   swidth=1024 blks
    naming   =version 2              bsize=4096   ascii-ci=0 ftype=1
    log      =internal log           bsize=4096   blocks=2560, version=2
             =                       sectsz=512   sunit=8 blks, lazy-count=1
    realtime =none                   extsz=4096   blocks=0, rtextents=0
    

    数据最终在 OSDs 上以 Object 的形式储存,Obejcts 的前缀为块设备的 block_name_prefix。随着写入的数据越多,Objects 的数量也会越多:

    [root@ceph-node1 deploy]# rados ls -p rbd_pool | grep rbd_data.121896b8b4567
    rbd_data.121896b8b4567.0000000000000080
    rbd_data.121896b8b4567.00000000000000a0
    rbd_data.121896b8b4567.0000000000000082
    rbd_data.121896b8b4567.00000000000000e0
    rbd_data.121896b8b4567.00000000000000ff
    rbd_data.121896b8b4567.0000000000000081
    rbd_data.121896b8b4567.0000000000000040
    rbd_data.121896b8b4567.0000000000000020
    rbd_data.121896b8b4567.0000000000000000
    rbd_data.121896b8b4567.00000000000000c0
    rbd_data.121896b8b4567.0000000000000060
    rbd_data.121896b8b4567.0000000000000001
    

    NOTE:而且这些块设备对应的 Objects 的后缀是是以 16 进制编码的,Object 的命名规则为 block_name_prefix+index。而且 index range [0x00, 0xff] 就是十进制的 256,表示该块设备的 Size 具有 256 个 Objects。

    [root@ceph-node1 ~]# rbd --image rbd_pool/volume01 info
    rbd image 'volume01':
        size 1 GiB in 256 objects
    

    但很显然,现在实际上并不存在 256 个 Objects,这是因为 Ceph RBD 是精简置备的,并非是完成创建卷时就已经把块设备 Size 对应的 256 个 Objects 都准备好了,Objects 的数量是随着实际数据的写入而逐渐增长的。并且上述的 12 个 Objects 仅仅是格式化 XFS 文件系统时生成的。

    mount 块设备并写入数据

    [root@ceph-node1 ~]# mkdir -pv /mnt/volume01
    
    [root@ceph-node1 ~]# mount /dev/rbd0 /mnt/volume01
    
    [root@ceph-node1 ~]# dd if=/dev/zero of=/mnt/volume01/fi1e1 count=10 bs=1M
    10+0 records in
    10+0 records out
    10485760 bytes (10 MB) copied, 0.0129169 s, 812 MB/s
    
    [root@ceph-node1 deploy]# rados ls -p rbd_pool | grep rbd_data.121896b8b4567 | wc -l
    37
    

    可以看见,块设备的 Objects 动态增长了。

    我们不妨看看块设备 volume01 的第一、第二个 Objects 的内容:

    [root@ceph-node1 ~]# rados -p rbd_pool get rbd_data.121896b8b4567.0000000000000000 rbd_data.121896b8b4567.0000000000000000
    [root@ceph-node1 ~]# rados -p rbd_pool get rbd_data.121896b8b4567.0000000000000001 rbd_data.121896b8b4567.0000000000000001
    
    [root@ceph-node1 ~]# ll -lht
    total 172K
    -rw-r--r--  1 root root  32K Apr 24 06:30 rbd_data.121896b8b4567.0000000000000001
    -rw-r--r--  1 root root 128K Apr 24 06:30 rbd_data.121896b8b4567.0000000000000000
    
    [root@ceph-node1 ~]# hexdump -vC rbd_data.121896b8b4567.0000000000000000 | more
    00000000  58 46 53 42 00 00 10 00  00 00 00 00 00 04 00 00  |XFSB............|
    ...
    

    有两点信息值得我们关注,首先,从第一个 Objects 的内容可以看出它的确是 mkfs.xfs 文件系统时创建的,而且这样的数据就是 XFS 文件系统的格式;再一个,可见 Object0、Object1 的 Size 都没有达到 4MiB,但却创建了更多的 Objects。这是因为客户端将原始数据分片之后是轮询储存到 Object Set 的,而不是存满了一个 Object 再继续存到下一个 Object 的(!!! 这里有待验证,因为 volume01 没有开启条带化特性)。

    卸载块设备

    [root@controller ~]# umount /mnt/volume01/
    
    root@ceph-node1 deploy]# rbd showmapped
    id pool     image    snap device
    1  rbd_pool volume01 -    /dev/rbd1
    
    [root@ceph-node1 deploy]# rbd unmap rbd_pool/volume01
    
    [root@ceph-node1 deploy]# rbd showmapped
    

    关于 RBD 块设备与 XFS 的一个有趣描述:

    RBD 其实是一个完完整整的块设备,如果把 1G 的块想成一个 1024 层楼的高楼的话,xfs 可以想象成住在这个大楼里的楼管,它只能在大楼里面,也就只能看到这 1024 层的房子,楼管自然可以安排所有的住户(文件或文件名),住在哪一层哪一间,睡在地板还是天花板(文件偏移量),隔壁的楼管叫做 ext4,虽然住在一模一样的大楼里,但是它们有着自己的安排策略,这就是文件系统如果组织文件的一个比喻。某一天拆迁大队长跑来说,我不管你们(xfs or ext4)是怎么安排的,盖这么高的楼是想做什么,然后大队长把这 1024 层房子,每 4 层(4MiB)砍了一刀,一共砍成了 256 个四层,然后一起打包带走了,运到了一个叫做 Ceph 的小区里面,放眼望去,这个小区里面的房子最高也就四层(填满的),而有些才打了地基(还没写内容)。

    新建客户端

    这里我们将 OpenStack 的 Controller Node 作为客户端,首先加载 rbd 内核模块:

    [root@controller ~]# uname -r
    3.10.0-957.10.1.el7.x86_64
    
    [root@controller ~]# modprobe rbd
    [root@controller ~]# lsmod | grep rbd
    rbd                    83640  0
    libceph               306625  1 rbd
    

    为了授予客户端访问 Ceph Cluster 的权限,需要将管理员密钥环和配置文件拷贝到客户端上。客户端与 Ceph Cluster 之间的身份验证基于这个密钥环,这里我们使用 admin keyring,使客户端拥有完全访问 Ceph Cluster 的权限。合理的做法应该是创建权限集有限的密钥环分发给非管理员客户端。下面我们依旧通过 ceph-deploy 工具来完成客户端的安装与授权。

    • 在 Controller 上配置 Ceph Mimic YUM 源

    • Controller 与 Ceph Deploy 节点免密登录:

    [root@ceph-node1 deploy]# ssh-copy-id -i ~/.ssh/id_rsa.pub root@controller
    
    • 在 Controller 上安装客户端软件:
    ceph-deploy install controller
    
    • 将密钥环和配置文件拷贝到 Controller
    ceph-deploy --overwrite-conf admin controller
    

    LOG:

    [ceph_deploy.admin][DEBUG ] Pushing admin keys and conf to controller
    
    • 在客户端查询 Ceph Cluster 状态
    [root@controller ~]# ceph -s
      cluster:
        id:     d82f0b96-6a69-4f7f-9d79-73d5bac7dd6c
        health: HEALTH_WARN
                too few PGs per OSD (2 < min 30)
    
      services:
        mon: 3 daemons, quorum ceph-node1,ceph-node2,ceph-node3
        mgr: ceph-node1(active), standbys: ceph-node2, ceph-node3
        osd: 9 osds: 9 up, 9 in
    
      data:
        pools:   1 pools, 8 pgs
        objects: 40  objects, 84 MiB
        usage:   9.3 GiB used, 81 GiB / 90 GiB avail
        pgs:     8 active+clean
    
    • 在 Controller 客户端挂载卷
    [root@controller ~]# rbd map rbd_pool/volume02
    /dev/rbd0
    
    [root@controller ~]# rbd showmapped
    id pool     image    snap device
    0  rbd_pool volume02 -    /dev/rbd0
    
    [root@controller ~]# mkfs.xfs /dev/rbd0
    meta-data=/dev/rbd0              isize=512    agcount=8, agsize=32768 blks
             =                       sectsz=512   attr=2, projid32bit=1
             =                       crc=1        finobt=0, sparse=0
    data     =                       bsize=4096   blocks=262144, imaxpct=25
             =                       sunit=1024   swidth=1024 blks
    naming   =version 2              bsize=4096   ascii-ci=0 ftype=1
    log      =internal log           bsize=4096   blocks=2560, version=2
             =                       sectsz=512   sunit=8 blks, lazy-count=1
    realtime =none                   extsz=4096   blocks=0, rtextents=0
    
    [root@controller ~]# mkdir -pv /mnt/volume02
    mkdir: created directory ‘/mnt/volume02’
    
    [root@controller ~]# mount /dev/rbd0 /mnt/volume02
    
    [root@controller ~]# df -Th
    Filesystem              Type      Size  Used Avail Use% Mounted on
    /dev/mapper/centos-root xfs       196G  3.2G  193G   2% /
    devtmpfs                devtmpfs  9.8G     0  9.8G   0% /dev
    tmpfs                   tmpfs     9.8G     0  9.8G   0% /dev/shm
    tmpfs                   tmpfs     9.8G  938M  8.9G  10% /run
    tmpfs                   tmpfs     9.8G     0  9.8G   0% /sys/fs/cgroup
    /dev/sda1               xfs       197M  165M   32M  84% /boot
    tmpfs                   tmpfs     2.0G     0  2.0G   0% /run/user/0
    /dev/rbd0               xfs      1014M   43M  972M   5% /mnt/volume02
    
    [root@controller ~]# dd if=/dev/zero of=/mnt/volume02/fi1e1 count=10 bs=1M
    10+0 records in
    10+0 records out
    10485760 bytes (10 MB) copied, 0.0100852 s, 1.0 GB/s
    

    块设备的扩缩容

    块设备扩容:

    [root@ceph-node1 deploy]# rbd resize rbd_pool/volume01 --size 2048
    Resizing image: 100% complete...done.
    
    [root@ceph-node1 ~]# rbd info rbd_pool/volume01
    rbd image 'volume01':
        size 2 GiB in 512 objects
        order 22 (4 MiB objects)
        id: 11126b8b4567
        block_name_prefix: rbd_data.11126b8b4567
        format: 2
        features: layering, exclusive-lock
        op_features:
        flags:
        create_timestamp: Tue Apr 23 07:30:57 2019
    

    如果已经被挂载了,还要手动检查新的容量是否被内核接收,刷新一下文件系统的大小:

    [root@ceph-node1 ~]# df -Th
    ...
    /dev/rbd0               xfs      1014M  103M  912M  11% /mnt/volume01
    
    [root@ceph-node1 ~]# xfs_growfs -d /mnt/volume01/
    meta-data=/dev/rbd0              isize=512    agcount=8, agsize=32768 blks
             =                       sectsz=512   attr=2, projid32bit=1
             =                       crc=1        finobt=0 spinodes=0
    data     =                       bsize=4096   blocks=262144, imaxpct=25
             =                       sunit=1024   swidth=1024 blks
    naming   =version 2              bsize=4096   ascii-ci=0 ftype=1
    log      =internal               bsize=4096   blocks=2560, version=2
             =                       sectsz=512   sunit=8 blks, lazy-count=1
    realtime =none                   extsz=4096   blocks=0, rtextents=0
    data blocks changed from 262144 to 524288
    
    [root@ceph-node1 ~]# df -Th
    ...
    /dev/rbd0               xfs       2.0G  103M  1.9G   6% /mnt/volume01
    

    RBD 块设备的 Format 1 VS Format 2

    众所周知,RBD 块设备有两种格式,不同的格式包含了不同块设备特性集合:

    • Format 1:Hammer,rbd_default_features = 3
    • Format 2:Jewel,rbd_default_features = 61

    Features 编号:配置项 rbd_default_features 的值就是由下列编号相加得到的:
    NOTE:Only applies to format 2 images

    • +1 for layering,
    • +2 for striping v2,
    • +4 for exclusive lock,
    • +8 for object map
    • +16 for fast-diff,
    • +32 for deep-flatten,
    • +64 for journaling

    块设备的快照、克隆、恢复

    Ceph 块设备的快照是一个基于时间点的、只读的块设备镜像副本,可以通过创建快照来保存块设备在某一时刻的状态,并且支持创建多次快照,所以快照功能也被称之为 Time Machine(时间机器)

    Ceph RBD 应用的快照技术为 COW(写时复制),通过写时复制可以在保持原始镜像数据不被修改的情况下,得到一个新的镜像或称为快照文件,而新的镜像中储存化了新数据的变更。可见,快照的执行是非常快的,因为它仅更新了块设备的元数据,例如:添加了快照 ID。Ceph RBD 的分层特性与 QCOW2 镜像文件具有一样的特征,更多的 COW 工作原理,请浏览《再谈 COW、ROW 快照技术》。

    :基于具体的实现差异,快照未必会以实际的文件形式而存在。所以,这里 “快照” 的语义表示变更的新数据。

    基于 COW 的链式快照
    在这里插入图片描述
    创建快照

    $ rbd snap create rbd_pool/volume01@snap01
    

    查看快照

    [root@ceph-node1 ~]# rbd snap ls rbd_pool/volume01
    SNAPID NAME    SIZE TIMESTAMP
         4 snap01 2 GiB Tue Apr 23 23:50:23 2019
    

    删除指定快照

    $ rbd snap rm rbd_pool/volume01@snap01
    

    删除全部快照

    [root@ceph-node1 ~]# rbd snap purge rbd_pool/volume01
    Removing all snapshots: 100% complete...done.
    

    克隆就是基于快照恢复出一个新的块设备,它的执行速度同样很快,只会修改了块设备的元数据,例如:添加了 parent 信息。为了便于理解,我们首先统一一下术语定义:

    • 块设备,镜像(RBD Image):Ceph RBD 块设备的统称。
    • 原始镜像,模板镜像:被执行快照的块设备。
    • COW 副本镜像:通过某一个快照克隆出来的块设备。

    NOTE:快照和克隆的区别在于,克隆利用了快照的 COW 分层特性,拷贝了指定快照的数据并转换为一个被 Ceph 认可的新的块设备。
    在这里插入图片描述
    得益于 Ceph RBD 的分层特性,使得对接 Ceph 存储的 Openstack 能够在短时间之内快速地启动数百台虚拟机,而虚拟机磁盘的本质就是 COW 副本镜像,它保存了 GuestOS 更改的数据。

    创建 RBD 块设备

    [root@ceph-node1 ~]# rbd create rbd_pool/volume03 --size 1024 --image-format 2
    
    [root@ceph-node1 ~]# rbd ls rbd_pool
    volume01
    volume02
    volume03
    
    [root@ceph-node1 ~]# rbd info rbd_pool/volume03
    rbd image 'volume03':
    	size 1 GiB in 256 objects
    	order 22 (4 MiB objects)
    	id: 12bb6b8b4567
    	block_name_prefix: rbd_data.12bb6b8b4567
    	format: 2
    	features: layering
    	op_features:
    	flags:
    	create_timestamp: Wed Apr 24 03:53:28 2019
    

    执行快照

    [root@ceph-node1 ~]# rbd snap create rbd_pool/volume03@snap01
    
    [root@ceph-node1 ~]# rbd snap ls rbd_pool/volume03
    SNAPID NAME    SIZE TIMESTAMP
         8 snap01 1 GiB Wed Apr 24 03:54:53 2019
    

    将快照设为保护(不可被删除)状态,此时的快照就是原始镜像

    rbd snap protect rbd_pool/volume03@snap01
    

    执行克隆操作,得到 COW 副本镜像,包含了父镜像信息

    [root@ceph-node1 ~]# rbd clone rbd_pool/volume03@snap01 rbd_pool/vol01_from_volume03
    
    [root@ceph-node1 ~]# rbd ls rbd_pool
    vol01_from_volume03
    volume01
    volume02
    volume03
    
    [root@ceph-node1 ~]# rbd info rbd_pool/vol01_from_volume03
    rbd image 'vol01_from_volume03':
    	size 1 GiB in 256 objects
    	order 22 (4 MiB objects)
    	id: faf86b8b4567
    	block_name_prefix: rbd_data.faf86b8b4567
    	format: 2
    	features: layering
    	op_features:
    	flags:
    	create_timestamp: Wed Apr 24 03:56:36 2019
    	parent: rbd_pool/volume03@snap01
    	overlap: 1 GiB
    

    执行 COW 副本镜像的扁平化,使其不再依赖父镜像,自身就具有块设备的完整数据(旧+新)

    [root@ceph-node1 ~]# rbd flatten rbd_pool/vol01_from_volume03
    Image flatten: 100% complete...done.
    
    [root@ceph-node1 ~]# rbd info rbd_pool/vol01_from_volume03
    rbd image 'vol01_from_volume03':
    	size 1 GiB in 256 objects
    	order 22 (4 MiB objects)
    	id: faf86b8b4567
    	block_name_prefix: rbd_data.faf86b8b4567
    	format: 2
    	features: layering
    	op_features:
    	flags:
    	create_timestamp: Wed Apr 24 03:56:36 2019
    

    解除保护并删除快照

    [root@ceph-node1 ~]# rbd snap unprotect rbd_pool/volume03@snap01
    
    [root@ceph-node1 ~]# rbd snap rm rbd_pool/volume03@snap01
    Removing snap: 100% complete...done.
    
    [root@ceph-node1 ~]# rbd snap ls rbd_pool/volume03
    

    恢复一个快照就是进行一个 “时刻穿越”,将块设备还原到某个特定时间点的状态,所以 Ceph 的恢复指令选择了使用 rollback 一词:

    [root@ceph-node1 ~]# rbd snap rollback rbd_pool/volume01@snap01
    Rolling back to snapshot: 100% complete...done.
    

    NOTE:如果块设备已经被挂载,那么需要 re-mount 以刷新文件系统状态

    块设备的 I/O 模型

    在这里插入图片描述

    1. 客户端应用 librbd 库创建一个块设备,并向块设备写入数据。
    2. 客户端应用 librbd 库调用 librados 库,经过 Pool、RBD(RBD 的专属 Pool)、Object、PG、OSDs 进行层层映射之后,得到 Primary OSD 的 IP:Port。
    3. 客户端与 Primary OSD 建立 Socket 通信,将要写入的数据直接传输给 Primary OSD,再由 Primary OSD 同步到 Replica OSDs 中。

    在这里插入图片描述

    RBD QoS

    QoS(Quality of Service,服务质量)起源于网络技术,主要用于解决网络阻塞和延迟问题,能够为指定的网络通信提供更好的服务质量。在存储领域,集群的 IO 能力同样是有限的,比如:带宽,IOPS 等参数。如何避免用户之间争抢资源,保障高优用户的存储服务质量?就需要对有限的 IO 能力进行合理分配,这就是存储 QoS。而 RBD QoS 就是在 Ceph librbd 模块上实现的 QoS。
    在这里插入图片描述
    librbd 架构

    • librbd 接口层:读取配置,设置配置对象的 Watch 功能
    • Internal:所有 librbd 接口读写的汇聚
    • osdc:对用户数据流进行切片
    • objectcache:用户数据缓冲层
    • send op:数据操作发送层

    RBD QoS 参数选项

    • conf_rbd_qos_iops_limit 每秒 IO 限制

    • conf_rbd_qos_read_iops_limit 每秒读 IO 限制

    • conf_rbd_qos_write_iops_limit 每秒写 IO 限制

    • conf_rbd_qos_bps_limit 每秒带宽限制

    • conf_rbd_qos_read_bps_limit 每秒读带宽限制

    • conf_rbd_qos_write_bps_limit 每秒写带宽限制

    Token bucket algorithm(令牌桶算法)

    在当前版本(Mimic)中已经实现了基于令牌桶算法的 RBD QoS 功能,但暂时只支持 conf_rbd_qos_iops_limit 选项。

    [root@ceph-node2 ~]# rbd create rbd_pool/volume01 --size 10240
    
    [root@ceph-node2 ~]# rbd image-meta set rbd_pool/volume01 conf_rbd_qos_iops_limit 1000
    
    [root@ceph-node2 ~]# rbd image-meta list rbd_pool/volume01
    There is 1 metadatum on this image:
    
    Key                     Value
    conf_rbd_qos_iops_limit 1000
    
    [root@ceph-node2 ~]# rbd image-meta set rbd_pool/volume01 conf_rbd_qos_bps_limit 2048000
    failed to set metadata conf_rbd_qos_bps_limit of image : (2) No such file or directory
    rbd: setting metadata failed: (2) No such file or directory
    

    在这里插入图片描述
    在这里插入图片描述

    令牌桶算法的基本思想

    • 假如用户配置的平均发送速率为 R,则按照 1/R(s) 的速率令牌桶投放令牌;
    • 假设令牌桶最多可以储存 N 个令牌,如果新添的令牌到达时令牌桶已经满了,那么这个令牌被丢弃;
    • 根据预设的匹配规则先对报文进行分类,不符合匹配规则的报文不需要经过令牌桶的处理,直接发送;
    • 反正,符合匹配规则的报文,则需要进行令牌桶处理。当一个 M 字节的数据包到达时,就从令牌桶中取走 M 个令牌,数据包持有令牌运行被发送到网络;
    • 如果令牌桶中少于 M 个令牌,则该数据包不被发送。只有等到桶中投入了新的令牌,报文才可能被发送。这就可以限制报文的流量只能小于或等于令牌投入的速度,以此达到限制流量的目的。

    令牌桶算法的 UML 流程
    在这里插入图片描述

    • 用户发起的请求异步 IO 到达 Image 中。
    • 请求到达 ImageRequestWQ 队列中。
    • 在 ImageRequestWQ 出队列的时候加入令牌桶算法 TokenBucket。
    • 通过令牌桶算法进行限速,然后发送给 ImageRequest 进行处理。
      在这里插入图片描述

    dmClock algorithm

    当前基于 dmClock 实现的 QoS 还在不断的提交 PR,很多尚未 Merge 到 Master,这里不多做讨论,有待继续跟进社区。

    dmClock 是一种基于时间标签的 I/O 调度算法,最先被 VMware 提出用于集中式管理的存储系统。dmClock 可以将以下实体作为 QoS 对象:

    • RBD Image
    • Pool
    • CephFS Directory
    • Client 或者一组 Client
    • 数据集

    dmClock 主要通过 Reservation、Weight 和 Limit 来实现 QoS 控制:

    • reservation:预留,表示客户端获得的最低 I/O 资源。
    • weight:权重,表示客户端所占共享 I/O 资源的比重。
    • limit:上限,表示客户端可获得的最高 I/O 资源。

    块设备性能测试

    使用 RADOS bench 进行基准测试

    Ceph 提供了一个内置的基准测试程序 RADOS bench,它用于测试 Ceph 对象存储器的性能。
    语法:

    rados bench -p <pool_name> <seconds> <write|seq|rand>
    
    • -p:指定 Pool
    • Seconds:指定测试运行时长(s)
    • write|seq|rand:指定测试类型,它应该是写、顺序读或者随机读
    • -t:指定井发数,默认为 160
    • –no-cleanup:指定 RODOS bench 写入到 Pool 的临时数据将不被删除,这些数据可用于读操作,默认为删除。

    创建 Test Pool

    [root@ceph-node1 fio_tst]# ceph osd pool create test_pool 8 8
    pool 'test_pool' created
    
    [root@ceph-node1 fio_tst]# rados lspools
    rbd_pool
    .rgw.root
    default.rgw.control
    default.rgw.meta
    default.rgw.log
    test_pool
    

    写入性能测试

    [root@ceph-node1 ~]# rados bench -p test_pool 10 write --no-cleanup
    hints = 1
    Maintaining 16 concurrent writes of 4194304 bytes to objects of size 4194304 for up to 10 seconds or 0 objects
    Object prefix: benchmark_data_ceph-node1_34663
      sec Cur ops   started  finished  avg MB/s  cur MB/s last lat(s)  avg lat(s)
        0       0         0         0         0         0           -           0
        1      16        16         0         0         0           -           0
        2      16        19         3   5.99838         6     1.66988     1.45496
        3      16        25         9    11.997        24     2.99072     2.19588
        4      16        32        16    15.996        28     3.33757     2.62036
        5      16        39        23   18.3956        28     2.37105     2.54244
        6      16        45        29   19.3289        24     2.65705     2.53162
        7      16        52        36   20.5669        28     1.10485     2.51232
        8      16        54        38   18.9957         8     3.27297     2.55235
        9      16        67        51   22.6617        52     2.22446     2.57639
       10      15        69        54   21.5954        12     2.41363     2.55092
       11       2        69        67   24.3585        52     2.54614     2.54768
    Total time run:         11.0136
    Total writes made:      69
    Write size:             4194304
    Object size:            4194304
    Bandwidth (MB/sec):     25.0599
    Stddev Band       17.0752
    Max bandwidth (MB/sec): 52
    Min bandwidth (MB/sec): 0
    Average IOPS:           6
    Stddev IOPS:            4
    Max IOPS:               13
    Min IOPS:               0
    Average Latency(s):     2.52608
    Stddev Latency(s):      0.615785
    Max latency(s):         4.03768
    Min latency(s):         1.00465
    
    • Average IOPS: 6
    • Bandwidth (MB/sec): 25.0599

    查看写入的临时数据:

    [root@ceph-node1 ~]# rados ls -p test_pool
    benchmark_data_ceph-node1_34663_object59
    benchmark_data_ceph-node1_34663_object42
    ...
    

    测试顺序读性能

    [root@ceph-node1 ~]# rados bench -p test_pool 10 seq
    hints = 1
      sec Cur ops   started  finished  avg MB/s  cur MB/s last lat(s)  avg lat(s)
        0       0         0         0         0         0           -           0
        1      16        35        19   75.9741        76    0.323362    0.505157
        2      16        59        43   85.9734        96    0.198388    0.543002
        3      13        69        56    74.645        52     2.17551    0.543934
    Total time run:       3.22507
    Total reads made:     69
    Read size:            4194304
    Object size:          4194304
    Bandwidth (MB/sec):   85.5795
    Average IOPS:         21
    Stddev IOPS:          5
    Max IOPS:             24
    Min IOPS:             13
    Average Latency(s):   0.716294
    Max latency(s):       2.17551
    Min latency(s):       0.136899
    
    • Average IOPS: 21
    • Bandwidth (MB/sec): 85.5795

    测试随机读性能

    [root@ceph-node1 ~]# rados bench -p test_pool 10 rand
    hints = 1
      sec Cur ops   started  finished  avg MB/s  cur MB/s last lat(s)  avg lat(s)
        0       0         0         0         0         0           -           0
        1      16       108        92    367.61       368   0.0316746    0.119223
        2      16       206       190   379.757       392    0.608621    0.145352
        3      16       299       283   377.153       372   0.0378421    0.149943
        4      15       368       353   352.859       280      0.6233    0.167492
        5      16       473       457   365.474       416     0.66508      0.1645
        6      16       563       547   364.547       360  0.00293503    0.166475
        7      16       627       611   349.038       256  0.00289834    0.173168
        8      16       748       732   365.897       484   0.0360462    0.168754
        9      16       825       809   359.457       308  0.00331438    0.171356
       10      16       896       880   351.908       284     0.75437    0.173779
    Total time run:       10.3753
    Total reads made:     897
    Read size:            4194304
    Object size:          4194304
    Bandwidth (MB/sec):   345.821
    Average IOPS:         86
    Stddev IOPS:          17
    Max IOPS:             121
    Min IOPS:             64
    Average Latency(s):   0.182936
    Max latency(s):       1.06424
    Min latency(s):       0.00266894
    
    • Average IOPS: 86
    • Bandwidth (MB/sec): 345.821

    使用 fio 进行 IO 测试

    fio 是一个第三方 IO 测试工具,在 Linux 系统上使用非常方便。fio 参数解析:

    filename=/dev/emcpowerb 支持文件系统或者裸设备,-filename=/dev/sda2 或 -filename=/dev/sdb
    direct=1                                 测试过程绕过机器自带的 Buffer,使测试结果更真实
    rw=randwread                       测试随机读的 I/O
    rw=randwrite                         测试随机写的 I/O
    rw=randrw                             测试随机混合写和读的 I/O
    rw=read                                 测试顺序读的 I/O
    rw=write                                 测试顺序写的 I/O
    rw=rw                                     测试顺序混合写和读的 I/O
    bs=4k                                     单次 IO 的块文件大小为 4k
    bsrange=512-2048                同上,提定数据块的大小范围
    size=5g                                  本次的测试文件大小为 5G,以每次 4k 的 IO 进行测试
    numjobs=30                           本次的测试线程为 30
    runtime=1000                         测试时间为 1000 秒,如果不写则一直将 5G 文件分 4k 每次写完为止
    ioengine=psync                      IO 引擎使用 pync 方式,如果要使用 libaio 引擎,需要 yum install libaio-devel 包
    rwmixwrite=30                        在混合读写的模式下,写占 30%
    group_reporting                      关于显示结果的,汇总每个进程的信息
    lockmem=1g                           只使用 1G 内存进行测试
    zero_buffers                            用 0 初始化系统 Buffer
    nrfiles=8                                  每个进程生成文件的数量
    

    安装 fio 工具和 librbd 相关开发库(e.g. librbd-devel):

    $ yum install -y fio "*librbd*"
    

    创建测试块设备:

    root@ceph-node1 ~]# rbd create rbd_pool/volume01 --size 10240
    
    [root@ceph-node1 ~]# rbd ls rbd_pool
    volume01
    
    [root@ceph-node1 ~]# rbd info rbd_pool/volume01
    rbd image 'volume01':
    	size 10 GiB in 2560 objects
    	order 22 (4 MiB objects)
    	id: 1229a6b8b4567
    	block_name_prefix: rbd_data.1229a6b8b4567
    	format: 2
    	features: layering
    	op_features:
    	flags:
    	create_timestamp: Thu Apr 25 00:11:20 2019
    

    编辑测试参数配置:

    $ mkdir /root/fio_tst && cd /root/fio_tst
    
    $ cat write.fio
    [global]
    description="write test with block size of 4M"
    direct=1
    ioengine=rbd
    clustername=ceph
    clientname=admin
    pool=rbd_pool
    rbdname=volume01
    iodepth=32
    runtime=300
    rw=randrw
    numjobs=1
    bs=8k
    
    [logging]
    write_iops_log=write_iops_log
    write_bw_log=write_bw_log
    write_lat_log=write_lat_log
    

    执行 IO 测试:

    [root@ceph-node1 fio_tst]# fio write.fio
    logging: (g=0): rw=randrw, bs=(R) 8192B-8192B, (W) 8192B-8192B, (T) 8192B-8192B, ioengine=rbd, iodepth=32
    fio-3.1
    Starting 1 process
    Jobs: 1 (f=1): [m(1)][100.0%][r=392KiB/s,w=280KiB/s][r=49,w=35 IOPS][eta 00m:00s]
    logging: (groupid=0, jobs=1): err= 0: pid=34842: Thu Apr 25 02:41:25 2019
      Description  : ["write test with block size of 4M"]
       read: IOPS=120, BW=965KiB/s (988kB/s)(283MiB/300063msec)
        slat (nsec): min=734, max=688371, avg=4864.30, stdev=11806.74
        clat (usec): min=771, max=1638.5k, avg=112142.48, stdev=118607.44
         lat (usec): min=773, max=1638.5k, avg=112147.35, stdev=118607.37
        clat percentiles (msec):
         |  1.00th=[    3],  5.00th=[    5], 10.00th=[    7], 20.00th=[   20],
         | 30.00th=[   31], 40.00th=[   48], 50.00th=[   71], 60.00th=[  107],
         | 70.00th=[  144], 80.00th=[  192], 90.00th=[  268], 95.00th=[  342],
         | 99.00th=[  523], 99.50th=[  617], 99.90th=[  827], 99.95th=[  894],
         | 99.99th=[ 1133]
       bw (  KiB/s): min=    4, max=10622, per=41.55%, avg=400.92, stdev=773.36, samples=36196
       iops        : min=    1, max=    1, avg= 1.00, stdev= 0.00, samples=36196
      write: IOPS=120, BW=966KiB/s (990kB/s)(283MiB/300063msec)
        slat (usec): min=2, max=1411, avg=18.63, stdev=31.60
        clat (msec): min=4, max=2301, avg=152.15, stdev=137.61
         lat (msec): min=4, max=2301, avg=152.17, stdev=137.61
        clat percentiles (msec):
         |  1.00th=[   11],  5.00th=[   18], 10.00th=[   24], 20.00th=[   40],
         | 30.00th=[   61], 40.00th=[   86], 50.00th=[  116], 60.00th=[  150],
         | 70.00th=[  192], 80.00th=[  245], 90.00th=[  326], 95.00th=[  405],
         | 99.00th=[  609], 99.50th=[  735], 99.90th=[  961], 99.95th=[ 1133],
         | 99.99th=[ 2198]
       bw (  KiB/s): min=    3, max= 1974, per=14.09%, avg=136.11, stdev=164.08, samples=36248
       iops        : min=    1, max=    1, avg= 1.00, stdev= 0.00, samples=36248
      lat (usec)   : 1000=0.01%
      lat (msec)   : 2=0.39%, 4=1.87%, 10=4.40%, 20=7.39%, 50=19.19%
      lat (msec)   : 100=18.12%, 250=33.10%, 500=13.85%, 750=1.35%, 1000=0.28%
      lat (msec)   : 2000=0.05%, >=2000=0.01%
      cpu          : usr=0.33%, sys=0.12%, ctx=5983, majf=0, minf=30967
      IO depths    : 1=0.6%, 2=1.7%, 4=5.4%, 8=17.9%, 16=68.3%, 32=6.1%, >=64=0.0%
         submit    : 0=0.0%, 4=100.0%, 8=0.0%, 16=0.0%, 32=0.0%, 64=0.0%, >=64=0.0%
         complete  : 0=0.0%, 4=95.2%, 8=0.7%, 16=1.3%, 32=2.8%, 64=0.0%, >=64=0.0%
         issued rwt: total=36196,36248,0, short=0,0,0, dropped=0,0,0
         latency   : target=0, window=0, percentile=100.00%, depth=32
    
    Run status group 0 (all jobs):
       READ: bw=965KiB/s (988kB/s), 965KiB/s-965KiB/s (988kB/s-988kB/s), io=283MiB (297MB), run=300063-300063msec
      WRITE: bw=966KiB/s (990kB/s), 966KiB/s-966KiB/s (990kB/s-990kB/s), io=283MiB (297MB), run=300063-300063msec
    
    Disk stats (read/write):
        dm-0: ios=0/1336, merge=0/0, ticks=0/42239, in_queue=45656, util=1.33%, aggrios=0/1356, aggrmerge=0/87, aggrticks=0/46003, aggrin_queue=46002, aggrutil=1.39%
      sda: ios=0/1356, merge=0/87, ticks=0/46003, in_queue=46002, util=1.39%
    
    • read: IOPS=120, BW=965KiB/s (988kB/s)(283MiB/300063msec)
    • write: IOPS=120, BW=966KiB/s (990kB/s)(283MiB/300063msec)

    输出结果参数解析:

    io        执行了多少(M)IO
    bw      平均 IO 带宽
    iops    IOPS
    runt     线程运行时间
    slat     提交延迟
    clat     完成延迟
    lat       响应时间
    cpu     利用率
    IO depths     IO 队列
    IO submit     单个 IO 提交要提交的 IO 数
    IO complete  Like the above submit number, but for completions instead.
    IO issued      The number of read/write requests issued, and how many of them were short.
    IO latencies   IO 完延迟的分布
    
    aggrb        Group 总带宽
    minb          最小平均带宽.
    maxb         最大平均带宽.
    mint           Group 中线程的最短运行时间.
    maxt          Group中线程的最长运行时间.
    ios              所有Group总共执行的IO数.
    merge        总共发生的 IO 合并数.
    ticks           Number of ticks we kept the disk busy.
    io_queue   花费在队列上的总共时间.
    util             磁盘利用率
    

    对块设备的 IOPS 执行 QoS:

    [root@ceph-node1 fio_tst]# rbd image-meta set rbd_pool/volume01 conf_rbd_qos_iops_limit 50
    [root@ceph-node1 fio_tst]# rbd image-meta list rbd_pool/volume01
    There is 1 metadatum on this image:
    
    Key                     Value
    conf_rbd_qos_iops_limit 50
    

    再次执行 IO 测试:

    [root@ceph-node1 fio_tst]# fio write.fio
    logging: (g=0): rw=randrw, bs=(R) 8192B-8192B, (W) 8192B-8192B, (T) 8192B-8192B, ioengine=rbd, iodepth=32
    fio-3.1
    Starting 1 process
    Jobs: 1 (f=1): [f(1)][100.0%][r=56KiB/s,w=200KiB/s][r=7,w=25 IOPS][eta 00m:00s]
    logging: (groupid=0, jobs=1): err= 0: pid=35040: Thu Apr 25 02:50:54 2019
      Description  : ["write test with block size of 4M"]
       read: IOPS=24, BW=199KiB/s (204kB/s)(58.5MiB/300832msec)
        slat (nsec): min=807, max=753733, avg=4863.82, stdev=16831.94
        clat (usec): min=1311, max=1984.2k, avg=482448.41, stdev=481601.17
         lat (usec): min=1313, max=1984.2k, avg=482453.27, stdev=481601.01
        clat percentiles (msec):
         |  1.00th=[    4],  5.00th=[    5], 10.00th=[    6], 20.00th=[    8],
         | 30.00th=[   14], 40.00th=[   23], 50.00th=[   71], 60.00th=[  969],
         | 70.00th=[  978], 80.00th=[  986], 90.00th=[  995], 95.00th=[  995],
         | 99.00th=[ 1003], 99.50th=[ 1011], 99.90th=[ 1036], 99.95th=[ 1938],
         | 99.99th=[ 1989]
       bw (  KiB/s): min=    4, max= 6247, per=100.00%, avg=486.86, stdev=666.26, samples=7483
       iops        : min=    1, max=    1, avg= 1.00, stdev= 0.00, samples=7483
      write: IOPS=25, BW=200KiB/s (205kB/s)(58.8MiB/300832msec)
        slat (usec): min=3, max=1427, avg=19.40, stdev=33.29
        clat (msec): min=6, max=1998, avg=799.32, stdev=501.54
         lat (msec): min=6, max=1998, avg=799.34, stdev=501.54
        clat percentiles (msec):
         |  1.00th=[   13],  5.00th=[   16], 10.00th=[   20], 20.00th=[   34],
         | 30.00th=[  961], 40.00th=[  986], 50.00th=[  995], 60.00th=[  995],
         | 70.00th=[  995], 80.00th=[ 1003], 90.00th=[ 1011], 95.00th=[ 1938],
         | 99.00th=[ 1989], 99.50th=[ 1989], 99.90th=[ 1989], 99.95th=[ 1989],
         | 99.99th=[ 2005]
       bw (  KiB/s): min=    4, max= 1335, per=50.98%, avg=101.96, stdev=184.46, samples=7522
       iops        : min=    1, max=    1, avg= 1.00, stdev= 0.00, samples=7522
      lat (msec)   : 2=0.04%, 4=1.27%, 10=11.24%, 20=11.63%, 50=11.50%
      lat (msec)   : 100=2.03%, 250=0.63%, 500=0.27%, 750=0.34%, 1000=48.66%
      lat (msec)   : 2000=12.41%
      cpu          : usr=0.06%, sys=0.03%, ctx=1118, majf=0, minf=10355
      IO depths    : 1=0.9%, 2=2.7%, 4=7.9%, 8=22.2%, 16=61.5%, 32=4.8%, >=64=0.0%
         submit    : 0=0.0%, 4=100.0%, 8=0.0%, 16=0.0%, 32=0.0%, 64=0.0%, >=64=0.0%
         complete  : 0=0.0%, 4=96.0%, 8=0.2%, 16=0.6%, 32=3.1%, 64=0.0%, >=64=0.0%
         issued rwt: total=7483,7522,0, short=0,0,0, dropped=0,0,0
         latency   : target=0, window=0, percentile=100.00%, depth=32
    
    Run status group 0 (all jobs):
       READ: bw=199KiB/s (204kB/s), 199KiB/s-199KiB/s (204kB/s-204kB/s), io=58.5MiB (61.3MB), run=300832-300832msec
      WRITE: bw=200KiB/s (205kB/s), 200KiB/s-200KiB/s (205kB/s-205kB/s), io=58.8MiB (61.6MB), run=300832-300832msec
    
    Disk stats (read/write):
        dm-0: ios=11/1599, merge=0/0, ticks=68/19331, in_queue=19399, util=0.92%, aggrios=11/1555, aggrmerge=0/46, aggrticks=68/19228, aggrin_queue=19295, aggrutil=0.92%
      sda: ios=11/1555, merge=0/46, ticks=68/19228, in_queue=19295, util=0.92%
    
    • read: IOPS=24, BW=199KiB/s (204kB/s)(58.5MiB/300832msec)
    • write: IOPS=25, BW=200KiB/s (205kB/s)(58.8MiB/300832msec)

    从结果来看 RBD QoS 的效果是还可以的。

  • 相关阅读:
    C++类的内存结构
    emplace与insert的区别(C++11)
    C/C++宏的奇技淫巧
    编译器对内存的分配
    利用C++实现模块隐藏(R3层断链)
    PCB标准规范
    RTC 总结
    0.96寸OLED显示屏 IIC接口(SSD1306)
    串行通信简介(SPI, IIC, UART)
    人生感悟
  • 原文地址:https://www.cnblogs.com/jmilkfan-fanguiju/p/11825071.html
Copyright © 2020-2023  润新知