首页 > 其他分享 >PVE-Ceph-RBD测试

PVE-Ceph-RBD测试

时间:2024-04-26 20:34:57浏览次数:21  
标签:self args Ceph job PVE th RBD fio 0.0%

集群型号与规模
CPU型号:3X24 x Intel(R) Xeon(R) CPU E5-2620 v2 @ 2.10GHz (2 插槽)
内   存:110G
磁   盘:3 X 12 X 三星850 evo 500G (osd以raid0模式加入ceph)+3X1nvme 500G
可用osd个数:33个
ceph集群副本:3副本
ceph版本:ceph version 17.2.6 (810db68029296377607028a6c6da1ec06f5a2b27) quincy (stable)
内核版本 Linux 6.2.16-3-pve #1 SMP PREEMPT_DYNAMIC PVE 6.2.16-3 (2023-06-17T05:58Z)
PVE管理器版本 pve-manager/8.0.3/bbf3993334bfa916

 虚机测试

#!/usr/bin/env python
# Author: Lu Xu <oliver_lew at outlook dot com>
# License: MIT
# Repo: https://github.com/OliverLew/fio-cdm

import argparse
import configparser
import json
import logging
import os
import shutil
import sys
import tempfile
from subprocess import Popen, PIPE


class Job:
    def __init__(self, args):
        args.target = os.path.realpath(args.target)
        # Standradize the size
        args.size = self.readable2byte(args.size)

        self._jobs = []
        self._jobfile_id, self._jobfile_name = tempfile.mkstemp(suffix='.jobfile')
        self._jobfile = os.fdopen(self._jobfile_id, 'w')
        self._testfile_name = '.fio_testmark'
        self._blocksize = {'seq': '1m', 'rnd': '4k'}
        self._config = configparser.ConfigParser(allow_no_value=True)
        self._config.read_dict({
            'global': {
                'ioengine': 'windowsaio' if os.name == 'nt' else 'libaio',
                'filename': self._testfile_name,
                # escape colons, see man page 'filename'
                'directory': args.target.replace(':', r'\:'),
                'size': args.size,
                'direct': '1',
                # borrowed configuration from shell version
                'runtime': '5',
                'refill_buffers': None,
                'norandommap': None,
                'randrepeat': '0',
                'allrandrepeat': '0',
                'group_reporting': None
            }
        })
        if args.zero_buffers:
            self._config.read_dict({'global': {'zero_buffers': None}})
        # Windows does not support pthread mutexes, suppress the warning
        if os.name == 'nt':
            self._config.read_dict({'global': {'thread': None}})

        # TODO: fit output of different lengths
        self._header = "|Name        |  Read(MB/s)| Write(MB/s)|"
        self._sep = "|------------|------------|------------|"
        self._template_row = "|{jobname}|{read:12.2f}|{write:12.2f}|"
        if args.mix:
            self._header += "   Mix(MB/s)|"
            self._sep += "------------|"
            self._template_row += "{mix:12.2f}|"

    def readable2byte(self, raw):
        try:
            num = raw.lower().rstrip("b").rstrip("i")
            units = {'k': 1, 'm': 2, 'g': 3, 't': 4, 'p': 5}
            return float(num[:-1]) * 1024 ** units[num[-1]] if num[-1] in units else float(num)
        except ValueError:
            logging.error("Unrecognised size: %s. Need: [0-9]*[KMGTP][i][B]", raw)
            exit(1)

    def byte2readable(self, num):
        for unit in ['B', 'KiB', 'MiB', 'GiB', 'TiB']:
            if abs(num) < 1024.0:
                return "{:3.1f}{}".format(num, unit)
            num /= 1024.0
        return "{:.1f}{}".format(num, 'PiB')

    def _jobname_templ(self, job, rw):
        return "{}-{rw}-{}-q{}-t{}".format(job["rnd"], job["bs"], job["q"], job["t"], rw=rw)

    def _displayname(self, job):
        return "{}{} Q{:<2}T{:<2}".format(job["rnd"], job["bs"], job["q"], job["t"]).upper()

    def create_job(self, rnd_type, queue_size, thread_num):
        try:
            blocksize = self._blocksize[rnd_type]
        except KeyError as e:
            logging.error("Job type only accepts 'seq' and 'rnd'")
            raise e

        job = {"rnd": rnd_type, "bs": blocksize, "q": queue_size, "t": thread_num}
        self._jobs.append(job)

        for rw in ["read", "write", "rw"] if args.mix else ["read", "write"]:
            self._config.read_dict({
                self._jobname_templ(job, rw): {
                    'rw': rw if rnd_type == 'seq' else 'rand' + rw,
                    'bs': blocksize,
                    'rwmixread': args.mix,
                    'iodepth': queue_size,
                    'numjobs': thread_num,
                    'loops': args.number,
                    'stonewall': None
                }
            })

    def run(self):
        # Will exit if not enough space available
        space_info = self._check_disk_space()

        if args.dump_jobfile:
            if args.dump_jobfile == '-':
                self._config.write(sys.stdout, space_around_delimiters=False)
            else:
                with open(args.dump_jobfile, 'w') as fp:
                    self._config.write(fp, space_around_delimiters=False)
            exit()
        else:
            self._config.write(self._jobfile, space_around_delimiters=False)
            self._jobfile.close()

        print("tests: {}, size: {}, target: {} {}".format(
            args.number,
            self.byte2readable(args.size),
            args.target,
            space_info
        ))
        if args.mix:
            print("Mixed rw: read {:2.0f}%, write {:2.0f}%".format(args.mix, 100 - args.mix))

        FIO_COMMAND = ['fio', '--output-format', 'json', self._jobfile_name]
        try:
            res = Popen(FIO_COMMAND, stdout=PIPE)
            output, _ = res.communicate()
        except KeyboardInterrupt:
            logging.info('interrupted, cleaning up before exit...')
            exit()
        finally:
            if os.path.exists(self._jobfile_name):
                os.remove(self._jobfile_name)
            if os.path.exists(os.path.join(args.target, self._testfile_name)):
                os.remove(os.path.join(args.target, self._testfile_name))

        if res.returncode == 0:
            fio_output = json.loads(output)
        else:
            exit()
        # rearrange to make jobname as keys
        info = {job.pop("jobname"): job for job in fio_output["jobs"]}
        logging.debug(info)

        self._print(info)

    def _printline(self, info, job, name, f):
        read = f(info.get(self._jobname_templ(job, "read"))['read'])
        write = f(info.get(self._jobname_templ(job, "write"))['write'])
        if args.mix:
            mixr = f(info.get(self._jobname_templ(job, "rw"))['read'])
            mixw = f(info.get(self._jobname_templ(job, "rw"))['write'])
            mix = (mixw * (100 - args.mix) + mixr * args.mix) / 100.0
        else:
            mix = None
        print(self._template_row.format(jobname=name, read=read, write=write, mix=mix))

    def _info_get_bw_megabytes(self, info):
        # Unit of I/O speed, use MB/s(10^6) instead of MiB/s(2^30).
        return info.get('bw_bytes', info['bw'] * 1e3) / 1e6

    def _print(self, info):
        print(self._header)
        print(self._sep)
        for job in self._jobs:
            self._printline(info, job, self._displayname(job), self._info_get_bw_megabytes)
            if job['rnd'] == 'rnd' and args.extra_info:
                self._printline(info, job, ". IOPS      ", lambda d: d['iops'])
                self._printline(info, job, ". latency us", lambda d: d['lat_ns']['mean'] / 1000)

    def _check_disk_space(self):
        if hasattr(shutil, "disk_usage"):   # Python3
            du = shutil.disk_usage(args.target)
            free = du.free
            used = du.used
            total = du.total
        elif hasattr(os, "statvfs"):        # Python2 + Unix-like
            stat = os.statvfs(args.target)
            free = stat.f_bsize * stat.f_bavail
            total = stat.f_bsize * stat.f_blocks
            used = total - stat.f_bsize * stat.f_bfree
        else:                               # Python2 + Windows? No way!
            logging.warning("It's hard to get disk usage for current system and"
                            " python version,\nskipping available space checking.")
            return "(disk usage not avallable)"

        if free >= args.size:
            return "{}/{}".format(self.byte2readable(used), self.byte2readable(total))

        logging.error("Not enough space available in %s:", args.target)
        logging.error("Needed: %s. Available: %s",
                      self.byte2readable(args.size),
                      self.byte2readable(free))
        exit(1)


def get_parser():
    parser = argparse.ArgumentParser(
        description='A python script to show disk test results with fio')
    parser.add_argument('target', nargs='?', default='.',
                        help='The path of the directory to test. '
                             'Default to current directory')
    parser.add_argument('-0', dest='zero_buffers', action='store_true',
                        help='Initialize buffers with zeros. '
                             'Default to use random buffers.')
    parser.add_argument('-a', metavar='job', dest='jobs', action="append",
                        help='Manually add multiple jobs. Format is '
                             '"seq|rnd,<queue depth>,<thread number>". '
                             'This overrides the preset jobs. '
                             'This option can be used more than once.')
    parser.add_argument('-E', dest='extra_info', action='store_false',
                        help='Disable extra information (iops, latency) for '
                             'random IO tests. Default is enabled.')
    parser.add_argument('-f', metavar='jobfile', dest='dump_jobfile',
                        help='Save jobfile and quit without running fio. '
                             'Use "-" to print to stdout.')
    parser.add_argument('-n', metavar='number', dest='number', type=int, default=5,
                        help='Number of tests, default is 5.')
    parser.add_argument('-s', metavar='size', dest='size', default='1G',
                        help='The size of file I/O. '
                             'It is directly passed to fio. '
                             'Default is 1G.')
    parser.add_argument('-x', metavar='mix', dest='mix',
                        type=float, nargs="?", const=70, default=0,
                        help='Add mixed rw test. Default is disabled. '
                             '<mix> is read percentage. Default is 70.')
    # hidden option, enable to show debug information
    parser.add_argument('-g', dest='debug', action='store_true', help=argparse.SUPPRESS)
    return parser


if __name__ == '__main__':
    # TODO: Real-time visual feedback, with fio --debug=io? Seams hard.
    # TODO: Linux: vendor and model with lsblk -o +VENDOR,MODEL or /sys/block/*/device/{vendor,model}
    # TODO: Specify device instead of directory
    parser = get_parser()
    args = parser.parse_args()
    logging.basicConfig(level=logging.DEBUG if args.debug else logging.INFO,
                        format="%(message)s")

    fio_job = Job(args)
    if args.jobs:
        for job in args.jobs:
            rnd_type, qd, tn = job.split(',')
            fio_job.create_job(rnd_type, int(qd), int(tn))
    else:
        fio_job.create_job('seq',  8,  1)
        fio_job.create_job('seq',  1,  1)
        fio_job.create_job('rnd', 32, 16)
        fio_job.create_job('rnd',  1,  1)
    fio_job.run()
fio-cdm

顺序读写 8队列深度 1 并发数

[root@localhost ~]# fio -filename=./test_write-10G  -direct=1 -iodepth 8 -thread -rw=write -ioengine=libaio -bs=4k -size=10G -numjobs=1 -runtime=1200 -group_reporting -name=mytest
mytest: (g=0): rw=write, bs=(R) 4096B-4096B, (W) 4096B-4096B, (T) 4096B-4096B, ioengine=libaio, iodepth=8
fio-3.7
Starting 1 thread
mytest: Laying out IO file (1 file / 10240MiB)
Jobs: 1 (f=1): [W(1)][100.0%][r=0KiB/s,w=159MiB/s][r=0,w=40.8k IOPS][eta 00m:00s]
mytest: (groupid=0, jobs=1): err= 0: pid=14326: Mon Aug  7 23:00:43 2023
  write: IOPS=40.7k, BW=159MiB/s (167MB/s)(10.0GiB/64411msec)
    slat (usec): min=5, max=306, avg= 8.69, stdev= 2.87
    clat (usec): min=84, max=7113, avg=185.39, stdev=37.63
     lat (usec): min=117, max=7122, avg=194.70, stdev=37.93
    clat percentiles (usec):
     |  1.00th=[  149],  5.00th=[  161], 10.00th=[  165], 20.00th=[  169],
     | 30.00th=[  174], 40.00th=[  176], 50.00th=[  180], 60.00th=[  186],
     | 70.00th=[  192], 80.00th=[  198], 90.00th=[  210], 95.00th=[  225],
     | 99.00th=[  269], 99.50th=[  293], 99.90th=[  379], 99.95th=[  474],
     | 99.99th=[ 1565]
   bw (  KiB/s): min=123776, max=170408, per=100.00%, avg=162806.35, stdev=6346.37, samples=128
   iops        : min=30944, max=42602, avg=40701.57, stdev=1586.60, samples=128
  lat (usec)   : 100=0.01%, 250=98.16%, 500=1.80%, 750=0.01%, 1000=0.01%
  lat (msec)   : 2=0.02%, 4=0.01%, 10=0.01%
  cpu          : usr=9.87%, sys=52.72%, ctx=1038421, majf=0, minf=6
  IO depths    : 1=0.1%, 2=0.1%, 4=0.1%, 8=100.0%, 16=0.0%, 32=0.0%, >=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=100.0%, 8=0.1%, 16=0.0%, 32=0.0%, 64=0.0%, >=64=0.0%
     issued rwts: total=0,2621440,0,0 short=0,0,0,0 dropped=0,0,0,0
     latency   : target=0, window=0, percentile=100.00%, depth=8

Run status group 0 (all jobs):
  WRITE: bw=159MiB/s (167MB/s), 159MiB/s-159MiB/s (167MB/s-167MB/s), io=10.0GiB (10.7GB), run=64411-64411msec

Disk stats (read/write):
  vda: ios=0/2620260, merge=0/205, ticks=0/430185, in_queue=429635, util=99.86%
[root@localhost ~]#


[root@localhost ~]# fio -filename=./test_write-10G  -direct=1 -iodepth 8 -thread -rw=read -ioengine=libaio -bs=4k -size=10G -numjobs=1 -runtime=1200 -group_reporting -name=mytest
mytest: (g=0): rw=read, bs=(R) 4096B-4096B, (W) 4096B-4096B, (T) 4096B-4096B, ioengine=libaio, iodepth=8
fio-3.7
Starting 1 thread
Jobs: 1 (f=1): [R(1)][100.0%][r=32.6MiB/s,w=0KiB/s][r=8336,w=0 IOPS][eta 00m:00s]
mytest: (groupid=0, jobs=1): err= 0: pid=14354: Mon Aug  7 23:07:47 2023
   read: IOPS=8083, BW=31.6MiB/s (33.1MB/s)(10.0GiB/324283msec)
    slat (usec): min=3, max=478, avg= 8.00, stdev= 3.84
    clat (usec): min=397, max=24999, avg=978.82, stdev=355.61
     lat (usec): min=408, max=25006, avg=987.44, stdev=355.69
    clat percentiles (usec):
     |  1.00th=[  758],  5.00th=[  816], 10.00th=[  848], 20.00th=[  881],
     | 30.00th=[  898], 40.00th=[  914], 50.00th=[  930], 60.00th=[  955],
     | 70.00th=[  979], 80.00th=[ 1012], 90.00th=[ 1057], 95.00th=[ 1156],
     | 99.00th=[ 2040], 99.50th=[ 2769], 99.90th=[ 3720], 99.95th=[ 5735],
     | 99.99th=[18482]
   bw (  KiB/s): min=28864, max=34104, per=100.00%, avg=32333.54, stdev=731.21, samples=648
   iops        : min= 7216, max= 8526, avg=8083.37, stdev=182.81, samples=648
  lat (usec)   : 500=0.01%, 750=0.82%, 1000=76.52%
  lat (msec)   : 2=21.60%, 4=0.98%, 10=0.04%, 20=0.02%, 50=0.01%
  cpu          : usr=2.61%, sys=12.45%, ctx=2456643, majf=0, minf=17
  IO depths    : 1=0.1%, 2=0.1%, 4=0.1%, 8=100.0%, 16=0.0%, 32=0.0%, >=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=100.0%, 8=0.1%, 16=0.0%, 32=0.0%, 64=0.0%, >=64=0.0%
     issued rwts: total=2621440,0,0,0 short=0,0,0,0 dropped=0,0,0,0
     latency   : target=0, window=0, percentile=100.00%, depth=8

Run status group 0 (all jobs):
   READ: bw=31.6MiB/s (33.1MB/s), 31.6MiB/s-31.6MiB/s (33.1MB/s-33.1MB/s), io=10.0GiB (10.7GB), run=324283-324283msec

Disk stats (read/write):
  vda: ios=2620420/3, merge=0/1, ticks=2556885/14, in_queue=2554998, util=99.99%
[root@localhost ~]# 

 

标签:self,args,Ceph,job,PVE,th,RBD,fio,0.0%
From: https://www.cnblogs.com/cyh00001/p/17613583.html

相关文章

  • Ceph的crush算法与一致性hash对比介绍
    本文分享自天翼云开发者社区《Ceph的crush算法与一致性hash对比介绍》,作者:l****n首先,我们先回顾下一致性hash以及其在经典存储系统中的应用。一致性hash的基本原理一致性hash的基本思想是,有一个hash函数,这个hash函数的值域形成了一个环(收尾相接:thelargesthashvaluewraps......
  • pve开启硬件直通命令
    1、打开PVE节点的shell,输入命令: nano/etc/default/grubGRUB_CMDLINE_LINUX_DEFAULT="quiet"#intercpu改为:GRUB_CMDLINE_LINUX_DEFAULT="quietintel_iommu=oniommu=pt"#如果是amdcpu请改为:GRUB_CMDLINE_LINUX_DEFAULT="quietamd_iommu=oniommu=pt"编辑完......
  • PVE下面安装Windows2012R2虚拟机的VirtIO驱动程序
    从官网链接下载不同版本的进行测试安装https://fedorapeople.org/groups/virt/virtio-win/direct-downloads/archive-virtio/测试结果如下virtio-win-0.1.215-2/2022-01-1305:42正常安装virtio-win-0.1.217-2/2022-05-3104:41安装失败virtio-win-0.1.221-1/2022......
  • (PVE)添加硬盘做存储
    wget-q-O/root/pve_source.tar.gz'https://bbs.x86pi.cn/file/topic/2023-11-28/file/01ac88d7d2b840cb88c15cb5e19d4305b2.gz'&&tarzxvf/root/pve_source.tar.gz&&/root/./pve_source用fdisk-l去确认fdisk/dev/sda先分区,输入n(分区)-输入p(主分......
  • VMware虚拟机迁移到PVE
    VMware虚拟机迁移到PVEpve7.4https://blog.csdn.net/o12345612345666885/article/details/129679746从vmware导出虚拟机,导出为ovf上传ovf文件和vmdk磁盘到PVE后台(不要修改vmdk磁盘名称)根据ovf文件和vmdk磁盘创建虚拟机qmimportovf102centos7.ovfsatasdb--formatqco......
  • Proxmox VE 8.1 Kernel 6.5.13-5-pve ,无法支持核显 SR-IOV 的问题
    我的之前的博客《利用显卡的SR-IOV虚拟GPU技术,实现一台电脑当七台用》介绍了ProxmoxVE7.x上启用核显虚拟化的方法。并给出了两个脚本,快速启用核显的SR-IOV。该脚本在PromoxVE7.x和8.x都做了测试。近期重新在ProxmoxVE8.1上部署,发现无法正常工作。 经过检查发现......
  • centos7 部署ceph nautilus 版本
    1、Ceph环境规划主机名Public网络Cluster网络角色ceph0110.12.7.21310.12.252.213osd、mon、mgr、rgw、adminceph0210.12.7.21410.12.252.214osd、mon、mgr、rgwceph0310.12.7.21510.12.252.215osd、mon、mgr、rgwceph0410.12.7.21610.1......
  • PVE 工具1
    PVE工具1(PVE_Source)pve_source是pve脚本可以更方便的初始化PVE,打开Shell粘贴如下命令wget-q-O/root/pve_source.tar.gz'https://bbs.x86pi.cn/file/topic/2023-11-28/file/01ac88d7d2b840cb88c15cb5e19d4305b2.gz'&&tarzxvf/root/pve_source.tar.gz&&/roo......
  • DRBD + keepalived实现文件实时同步和双机热备
    DRBD+keepalived实现文件实时同步和双机热备安装DRBD系统初始化设置注意:需要有数据盘或者多的分区yumupdate-y关闭防火墙systemctlstopfirewalldsystemctldisablefirewalld修改host文件vim/etc/hosts192.168.1.240Primarykylin-01192.168.1.241Seconda......
  • PVE安装PBS注意事项
    注意事项:1.HA需要三节点,添加PBS需要3节点在线2.PBS先创建目录,取消创建数据存储;再单独添加数据存储;3.debian使用vimDebian安装PBS:安装系统时选择debian源参考链接:https://pbs.proxmox.com/docs/installation.html#id31.安装工具;su-apt-getinstallnet-toolsvim-......