1. Tổng Quan Về Benchmark Trong Ceph.
Ceph là một hệ thống lưu trữ phân tán mạnh mẽ, nhưng để đảm bảo hiệu suất tối ưu, chúng ta cần thực hiện benchmark để đo tốc độ đọc/ghi, độ trễ cũng như hiệu suất của RBD (RADOS Block Device). Trong bài viết này, chúng ta sẽ tìm hiểu cách thực hiện benchmark hiệu suất Ceph chi tiết.

Benchmark là quá trình đo lường hiệu suất của hệ thống Ceph, bao gồm:
- Tốc độ đọc/ghi (Throughput & IOPS)
- Độ trễ (Latency)
- Hiệu suất của RBD (Ceph Block Storage)
Việc benchmark giúp xác định khả năng xử lý dữ liệu, phát hiện node thắt cổ chai (bottleneck), tối ưu cấu hình OSD, MON, MDS và CRUSH.
2. Các Công Cụ Benchmark Ceph.
Có nhiều công cụ giúp đo hiệu suất Ceph, bao gồm:
rados bench
: Benchmark trực tiếp trên pool Cephfio
: Benchmark RBDdd
: Kiểm tra tốc độ ghi đơn giảnioping
: Đo độ trễ I/O
3. Benchmark Tốc Độ Đọc/Ghi Với RADOS
Công cụ rados bench
được sử dụng để kiểm tra tốc độ đọc/ghi của Ceph object storage.
3.1 Benchmark ghi dữ liệu vào Ceph
ceph osd pool create testpool 128 128
ceph osd pool application enable testpool rados
rados bench -p testpool 60 write --no-cleanup
testpool
: Pool benchmark60
: Chạy thử nghiệm trong 60 giâywrite
: Kiểm tra tốc độ ghi--no-cleanup
: Không xóa dữ liệu ngay sau thử nghiệm
Kết quả mẫu:
Total writes made: 10240
Bandwidth (MB/sec): 450.02
Average latency: 0.055 sec
3.2 Benchmark đọc dữ liệu từ Ceph
rados bench -p testpool 60 seq
seq
: Đọc tuần tự- Kết quả sẽ thể hiện tốc độ đọc và độ trễ.
3.3 Benchmark đọc ngẫu nhiên
rados bench -p testpool 60 rand
rand
: Đọc ngẫu nhiên
4. Benchmark RBD (RADOS Block Device)
4.1. Lựa chọn tool benchmark.
RBD là một trong những ứng dụng phổ biến của Ceph, thường được sử dụng trong OpenStack, Proxmox, Kubernetes.
Vì pool POOL_LAB đang được sử dụng cho RBD (RADOS Block Device), bạn không thể sử dụng rados bench
để benchmark trực tiếp. Lý do là rados bench
hoạt động ở mức object storage, trong khi RBD đã định dạng pool thành block storage.
Tuy nhiên, bạn vẫn có thể benchmark pool bằng cách tạo một RBD image và sử dụng fio
để kiểm tra hiệu suất.
4.2. Lựa chọn client để map RBD.
Bạn có thể map RBD image vào một node trong cluster Ceph, nhưng không nên map nó vào Ceph MON vì:
- Ceph MON (Monitor) chỉ quản lý metadata, không có chức năng xử lý dữ liệu RBD.
- Hiệu suất có thể bị ảnh hưởng, vì MON thường không có OSD, tức là không trực tiếp lưu trữ dữ liệu.
- Nguy cơ ảnh hưởng cluster nếu MON bị quá tải do I/O từ benchmark.
👉 Giải pháp hợp lý hơn
Bạn nên map RBD image trên một client bên ngoài Ceph, ví dụ:
- Một Proxmox node.
- Một VM hoặc Bare-metal server có cài Ceph client.
- Một Ceph OSD node (nếu không ảnh hưởng hiệu suất).
📌 Cách map RBD trên một Ceph MON (hoặc client)
Nếu bạn vẫn muốn thử trên MON (hoặc một node bất kỳ trong cluster), bạn cần:
- Cài đặt Ceph client (nếu chưa có).
- Xác thực và cấu hình môi trường.
- Map RBD image.
- Chạy benchmark.
1️⃣ Cài đặt Ceph client
Nếu node của bạn chưa có Ceph client, hãy cài đặt:
apt update && apt install -y ceph ceph-common
(Trên CentOS/RHEL: yum install -y ceph ceph-common
)
2️⃣ Kiểm tra quyền truy cập
Chạy lệnh sau để đảm bảo node có thể kết nối với Ceph:
ceph -s
Nếu thấy trạng thái HEALTH_OK
hoặc HEALTH_WARN
, nghĩa là kết nối được.
3️⃣ Map RBD image
📌 Lấy thông tin keyring (nếu cần): Nếu bạn dùng user khác admin
, hãy tạo keyring:
ceph auth get-key client.admin | sudo tee /etc/ceph/ceph.client.admin.keyring
Nếu pool POOL_LAB
đang dùng cho RBD, bạn có thể benchmark với fio
.
📌 Tạo RBD Image trên pool
rbd create test-image --size 1T --pool POOL_LAB
📌 Map RBD image:
rbd map test-image --pool POOL_LAB
Map RBD image vào hệ thống
✅ Bạn có thể map RBD vào Ceph MON, nhưng không khuyến khích vì nó không được thiết kế để xử lý I/O.
✅ Nên map RBD trên một Ceph client (Proxmox node, VM, Bare-metal server, hoặc Ceph OSD node).
✅ Benchmark bằng fio
trên /dev/rbdX
để đo tốc độ đọc/ghi, độ trễ và IOPS.
Nếu bạn cần test trực tiếp trên MON, cứ làm theo hướng dẫn trên. Nhưng nếu có client bên ngoài thì tốt hơn. 🚀
Map RBD image để hệ điều hành nhận diện nó như một block device:
shell> rbd map test-image --pool POOL_LAB
/dev/rbd0
Kiểm tra thiết bị được gán:
shell> rbd showmapped
id pool namespace image snap device
0 POOL_LAB test-image - /dev/rbd0
Ví dụ đầu ra:
shell> lsblk | grep ^rbd
rbd0 252:0 0 100G 0 disk
Thiết bị /dev/rbd0
sẽ được dùng để benchmark.
4.1. Kiểm tra Pool và tạo Image RBD để benchmark
Trước tiên, đảm bảo pool POOL_LAB đang được sử dụng cho RBD:
ceph osd pool application get POOL_LAB
{
"rbd": {}
}
Tạo Image RBD để benchmark
rbd create test-image --size 100G --pool POOL_LAB
test-image
: Tên của RBD image.--size 10G
: Dung lượng của image (10GB).--pool POOL_LAB
: Sử dụng pool này.
shell> rbd ls POOL_LAB
test-image
4.2. Benchmark với fio
Sau khi map image, bạn có thể chạy benchmark với fio
.
- Dưới đây là kết quả test pool Ceph của mình, thông số pool như sau:
- Network: 20G
- 154 Disk SSD 1.7T với mỗi node OSD có 22 SSD chia thành 154 ODS.
- 7 Node Storage Node.
- 3 Node Mon.
- 3 MGR.
- POOL_LAB có 8291 pgs.
- MTU 1500
- CPU Dual Xeon
Intel(R) Xeon(R) Silver 4310 CPU @ 2.10GHz
- RAM 256G
Thông tin cluster nhé.
shell> ceph -s
cluster:
id: <cluster_id>
health: HEALTH_OK
services:
mon: 3 daemons, quorum CEPH-LAB-MON-11,CEPH-LAB-MON-13,CEPH-LAB-MON-12 (age 18h)
mgr: CEPH-LAB-MON-11.wpjzqw(active, since 19h), standbys: CEPH-LAB-MON-13.inrfez, CEPH-LAB-MON-12.brlmmo
osd: 154 osds: 154 up (since 13h), 154 in (since 13h)
data:
pools: 1 pools, 8192 pgs
objects: 5 objects, 6.3 KiB
usage: 16 GiB used, 269 TiB / 269 TiB avail
pgs: 8192 active+clean
Benchmark tốc độ write throughput.
shell> fio --name=write_throughput --filename=/dev/rbd0 --numjobs=8 \
--size=10G --time_based --runtime=60s --ramp_time=2s --ioengine=libaio \
--direct=1 --verify=0 --bs=1M --iodepth=64 --rw=write \
--group_reporting=1
write_throughput: (g=0): rw=write, bs=(R) 1024KiB-1024KiB, (W) 1024KiB-1024KiB, (T) 1024KiB-1024KiB, ioengine=libaio, iodepth=64
...
fio-3.28
Starting 8 processes
Jobs: 8 (f=8): [W(8)][100.0%][w=5262MiB/s][w=5262 IOPS][eta 00m:00s]
write_throughput: (groupid=0, jobs=8): err= 0: pid=91703: Tue Mar 11 11:30:36 2025
write: IOPS=5416, BW=5425MiB/s (5688MB/s)(319GiB/60236msec); 0 zone resets
slat (usec): min=30, max=1939, avg=105.22, stdev=29.43
clat (usec): min=1788, max=3784.0k, avg=94505.91, stdev=322070.45
lat (usec): min=1875, max=3784.1k, avg=94611.35, stdev=322070.27
clat percentiles (msec):
| 1.00th=[ 3], 5.00th=[ 4], 10.00th=[ 4], 20.00th=[ 5],
| 30.00th=[ 6], 40.00th=[ 7], 50.00th=[ 8], 60.00th=[ 11],
| 70.00th=[ 18], 80.00th=[ 40], 90.00th=[ 165], 95.00th=[ 498],
| 99.00th=[ 1871], 99.50th=[ 2333], 99.90th=[ 3037], 99.95th=[ 3205],
| 99.99th=[ 3507]
bw ( MiB/s): min= 1582, max=10518, per=100.00%, avg=5438.42, stdev=222.19, samples=960
iops : min= 1582, max=10518, avg=5438.16, stdev=222.19, samples=960
lat (msec) : 2=0.02%, 4=11.77%, 10=46.17%, 20=14.46%, 50=9.73%
lat (msec) : 100=5.05%, 250=5.02%, 500=2.96%, 750=1.39%, 1000=0.85%
lat (msec) : 2000=1.88%, >=2000=0.86%
cpu : usr=5.65%, sys=2.08%, ctx=292119, majf=0, minf=5806
IO depths : 1=0.0%, 2=0.0%, 4=0.0%, 8=0.0%, 16=0.0%, 32=0.0%, >=64=100.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.0%, 16=0.0%, 32=0.0%, 64=0.1%, >=64=0.0%
issued rwts: total=0,326264,0,0 short=0,0,0,0 dropped=0,0,0,0
latency : target=0, window=0, percentile=100.00%, depth=64
Run status group 0 (all jobs):
WRITE: bw=5425MiB/s (5688MB/s), 5425MiB/s-5425MiB/s (5688MB/s-5688MB/s), io=319GiB (343GB), run=60236-60236msec
Disk stats (read/write):
rbd0: ios=0/337582, merge=0/0, ticks=0/31226421, in_queue=31226421, util=99.84%
Benchmark tốc độ write iops.
shell> fio --name=write_iops --filename=/dev/rbd0 --size=10G \
--time_based --runtime=60s --ramp_time=2s --ioengine=libaio --direct=1 --numjobs=8 \
--verify=0 --bs=4K --iodepth=64 --rw=randwrite --group_reporting=1
write_iops: (g=0): rw=randwrite, bs=(R) 4096B-4096B, (W) 4096B-4096B, (T) 4096B-4096B, ioengine=libaio, iodepth=64
...
fio-3.28
Starting 8 processes
Jobs: 8 (f=8): [w(8)][100.0%][w=854MiB/s][w=219k IOPS][eta 00m:00s]
write_iops: (groupid=0, jobs=8): err= 0: pid=91853: Tue Mar 11 11:32:28 2025
write: IOPS=214k, BW=836MiB/s (877MB/s)(49.0GiB/60006msec); 0 zone resets
slat (nsec): min=1328, max=2243.1k, avg=22565.81, stdev=7159.66
clat (usec): min=463, max=2081.0k, avg=2368.85, stdev=9911.12
lat (usec): min=465, max=2081.0k, avg=2391.53, stdev=9911.14
clat percentiles (usec):
| 1.00th=[ 971], 5.00th=[ 1156], 10.00th=[ 1254], 20.00th=[ 1401],
| 30.00th=[ 1516], 40.00th=[ 1614], 50.00th=[ 1745], 60.00th=[ 1876],
| 70.00th=[ 2057], 80.00th=[ 2311], 90.00th=[ 2999], 95.00th=[ 5014],
| 99.00th=[15401], 99.50th=[20579], 99.90th=[31589], 99.95th=[36963],
| 99.99th=[53740]
bw ( KiB/s): min=195924, max=904476, per=100.00%, avg=856772.39, stdev=9948.87, samples=960
iops : min=48977, max=226118, avg=214192.16, stdev=2487.24, samples=960
lat (usec) : 500=0.01%, 750=0.16%, 1000=1.18%
lat (msec) : 2=65.95%, 4=26.18%, 10=4.57%, 20=1.41%, 50=0.53%
lat (msec) : 100=0.01%, 250=0.01%, 500=0.01%, 750=0.01%, 1000=0.01%
lat (msec) : 2000=0.01%, >=2000=0.01%
cpu : usr=3.71%, sys=12.13%, ctx=16436812, majf=0, minf=2542
IO depths : 1=0.0%, 2=0.0%, 4=0.0%, 8=0.0%, 16=0.0%, 32=0.0%, >=64=100.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.0%, 16=0.0%, 32=0.0%, 64=0.1%, >=64=0.0%
issued rwts: total=0,12842883,0,0 short=0,0,0,0 dropped=0,0,0,0
latency : target=0, window=0, percentile=100.00%, depth=64
Run status group 0 (all jobs):
WRITE: bw=836MiB/s (877MB/s), 836MiB/s-836MiB/s (877MB/s-877MB/s), io=49.0GiB (52.6GB), run=60006-60006msec
Disk stats (read/write):
rbd0: ios=0/13297677, merge=0/0, ticks=0/31226539, in_queue=31226540, util=99.91%
| 70.00th=[ 18], 80.00th=[ 40], 90.00th=[ 165], 95.00th=[ 498],
Benchmark tốc độ read throughput
shell> fio --name=read_throughput --filename=/dev/rbd0 --numjobs=8 \
--size=10G --time_based --runtime=60s --ramp_time=2s --ioengine=libaio \
--direct=1 --verify=0 --bs=1M --iodepth=64 --rw=read \
--group_reporting=1
read_throughput: (g=0): rw=read, bs=(R) 1024KiB-1024KiB, (W) 1024KiB-1024KiB, (T) 1024KiB-1024KiB, ioengine=libaio, iodepth=64
...
fio-3.28
Starting 8 processes
Jobs: 8 (f=8): [R(8)][100.0%][r=5530MiB/s][r=5529 IOPS][eta 00m:00s]
read_throughput: (groupid=0, jobs=8): err= 0: pid=92217: Tue Mar 11 11:36:54 2025
read: IOPS=5541, BW=5549MiB/s (5819MB/s)(326GiB/60233msec)
slat (usec): min=18, max=21665, avg=62.37, stdev=102.87
clat (usec): min=892, max=3182.7k, avg=92515.69, stdev=239916.70
lat (usec): min=926, max=3182.7k, avg=92578.19, stdev=239914.48
clat percentiles (usec):
| 1.00th=[ 1565], 5.00th=[ 2966], 10.00th=[ 4621],
| 20.00th=[ 8848], 30.00th=[ 14222], 40.00th=[ 21890],
| 50.00th=[ 33162], 60.00th=[ 48497], 70.00th=[ 69731],
| 80.00th=[ 106431], 90.00th=[ 189793], 95.00th=[ 304088],
| 99.00th=[1216349], 99.50th=[2164261], 99.90th=[2801796],
| 99.95th=[2936013], 99.99th=[3103785]
bw ( MiB/s): min= 3257, max= 8084, per=100.00%, avg=5566.46, stdev=110.60, samples=960
iops : min= 3256, max= 8082, avg=5565.24, stdev=110.55, samples=960
lat (usec) : 1000=0.01%
lat (msec) : 2=2.14%, 4=6.07%, 10=14.29%, 20=15.37%, 50=23.19%
lat (msec) : 100=17.71%, 250=14.64%, 500=4.24%, 750=1.01%, 1000=0.36%
lat (msec) : 2000=0.53%, >=2000=0.60%
cpu : usr=0.18%, sys=2.75%, ctx=601699, majf=0, minf=524
IO depths : 1=0.0%, 2=0.0%, 4=0.0%, 8=0.0%, 16=0.0%, 32=0.0%, >=64=100.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.0%, 16=0.0%, 32=0.0%, 64=0.1%, >=64=0.0%
issued rwts: total=333759,0,0,0 short=0,0,0,0 dropped=0,0,0,0
latency : target=0, window=0, percentile=100.00%, depth=64
Run status group 0 (all jobs):
READ: bw=5549MiB/s (5819MB/s), 5549MiB/s-5549MiB/s (5819MB/s-5819MB/s), io=326GiB (351GB), run=60233-60233msec
Disk stats (read/write):
rbd0: ios=344775/0, merge=0/0, ticks=31435659/0, in_queue=31435659, util=99.95%
Benchmark tốc độ read iops.
shell> fio --name=read_iops --filename=/dev/rbd0 --size=10G \
--time_based --runtime=60s --ramp_time=2s --ioengine=libaio --direct=1 \
--verify=0 --bs=4K --iodepth=64 --rw=randread --group_reporting=1
read_iops: (g=0): rw=randread, bs=(R) 4096B-4096B, (W) 4096B-4096B, (T) 4096B-4096B, ioengine=libaio, iodepth=64
fio-3.28
Starting 1 process
Jobs: 1 (f=1): [r(1)][100.0%][r=281MiB/s][r=72.0k IOPS][eta 00m:00s]
read_iops: (groupid=0, jobs=1): err= 0: pid=92342: Tue Mar 11 11:38:34 2025
read: IOPS=68.5k, BW=268MiB/s (281MB/s)(15.7GiB/60001msec)
slat (nsec): min=1229, max=170929, avg=9432.90, stdev=8623.13
clat (usec): min=87, max=2138.4k, avg=924.12, stdev=7604.38
lat (usec): min=103, max=2138.4k, avg=933.67, stdev=7604.48
clat percentiles (usec):
| 1.00th=[ 155], 5.00th=[ 233], 10.00th=[ 318], 20.00th=[ 510],
| 30.00th=[ 701], 40.00th=[ 807], 50.00th=[ 922], 60.00th=[ 1074],
| 70.00th=[ 1156], 80.00th=[ 1205], 90.00th=[ 1270], 95.00th=[ 1385],
| 99.00th=[ 1795], 99.50th=[ 1909], 99.90th=[ 2114], 99.95th=[ 2180],
| 99.99th=[ 4113]
bw ( KiB/s): min=12520, max=361360, per=100.00%, avg=276464.61, stdev=37692.64, samples=119
iops : min= 3130, max=90340, avg=69116.04, stdev=9423.16, samples=119
lat (usec) : 100=0.01%, 250=6.00%, 500=13.50%, 750=14.96%, 1000=21.46%
lat (msec) : 2=43.82%, 4=0.25%, 10=0.01%, 20=0.01%, 50=0.01%
lat (msec) : 100=0.01%, 250=0.01%, 500=0.01%, 750=0.01%, 1000=0.01%
lat (msec) : 2000=0.01%, >=2000=0.01%
cpu : usr=6.89%, sys=20.45%, ctx=2168919, majf=0, minf=268
IO depths : 1=0.0%, 2=0.0%, 4=0.0%, 8=0.0%, 16=0.0%, 32=0.0%, >=64=100.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.0%, 16=0.0%, 32=0.0%, 64=0.1%, >=64=0.0%
issued rwts: total=4110484,0,0,0 short=0,0,0,0 dropped=0,0,0,0
latency : target=0, window=0, percentile=100.00%, depth=64
Run status group 0 (all jobs):
READ: bw=268MiB/s (281MB/s), 268MiB/s-268MiB/s (281MB/s-281MB/s), io=15.7GiB (16.8GB), run=60001-60001msec
Disk stats (read/write):
rbd0: ios=4238820/0, merge=0/0, ticks=1888131/0, in_queue=1888131, util=99.89%
5. Phân tích kết quả
Kết quả benchmark Ceph của mình thì mình nhận định khá tốt, nhưng cần đánh giá kỹ hơn một số điểm:
Thông số benchmark:
- Write throughput: ~5.4 GiB/s (~5688 MB/s)
- Write IOPS (4K random write): ~214K IOPS (~836 MiB/s)
Throughput (~5.4 GiB/s)
- Với 154 OSD SSD, giả sử mỗi SSD có thể đạt ~500-550 MB/s write sequential, tổng lý thuyết là: 154×500MB/s=77GB/s154 \times 500MB/s = 77GB/s154×500MB/s=77GB/s → Thực tế đạt ~5.4 GiB/s (~7% tổng lý thuyết), có thể bị giới hạn bởi mạng hoặc CPU.
- Mạng 20G: Nếu Ceph sử dụng 20Gbit (≈2.5 GB/s) trên cả public + cluster network, có thể mạng bị nghẽn.
- Check network throughput:
ceph daemon osd.<ID> perf dump | jq '.thruput'
IOPS (~214K)
- SSD Enterprise thường có ~80-120K random write IOPS/drive.
- Tổng lý thuyết 154 x 100K ≈ 15M IOPS, nhưng thực tế đạt ~214K IOPS (~1.4% lý thuyết).
- Điều tra bottleneck:
- Mạng: Xem xét sử dụng RDMA hoặc tăng MTU nếu phù hợp.
- OSD Latency: Kiểm tra
iostat -x 1
- Ceph PG Tuning: Có thể cần giảm PG count hoặc tối ưu thread.
Có thể kiểm tra chi tiết bằng lệnh dưới.
ceph osd perf
ceph daemon osd.<ID> dump_historic_ops
Nếu muốn tối ưu hơn, có thể điều chỉnh osd_op_num_threads_per_shard, osd_op_num_shards, hoặc thử bluestore_cache_size.
6. Gỡ bỏ RBD sau benchmark
Sau khi benchmark xong, gỡ bỏ RBD để tránh chiếm tài nguyên:
rbd unmap /dev/rbd0
Xóa image nếu không cần dùng nữa:
rbd rm test-image --pool POOL_LAB
Removing image: 100% complete...done.
7. Cách Cải Thiện Hiệu Suất Ceph Sau Benchmark
Nếu hiệu suất không đạt kỳ vọng, bạn có thể tối ưu bằng cách:
- Tăng số lượng OSD: Giúp tăng IOPS
- Dùng SSD cho OSD và journal: Giảm độ trễ
- Cấu hình CRUSH tối ưu: Đảm bảo phân bổ dữ liệu đều
- Tối ưu PG (Placement Groups): Tránh tình trạng quá tải một OSD
8. Kết Luận
Benchmark là bước quan trọng giúp đánh giá và tối ưu hiệu suất Ceph. Bằng cách sử dụng rados bench
, fio
, dd
và ioping
, bạn có thể đo lường tốc độ đọc/ghi, độ trễ và hiệu suất RBD để tinh chỉnh hệ thống Ceph một cách hiệu quả.