1. Mục tiêu thay đổi
Giảm tải I/O và hạn chế tác động tới client trong quá trình recovery/backfill trên HDD.
Tối ưu kích thước chunk và số lượng tác vụ recovery song song để phù hợp với mClock scheduler và profile high_client_ops
.
2. Hiện trạng trước thay đổi
Kiểm tra osd_op_queue
ceph config get osd osd_op_queue
# Kết quả: mclock_scheduler
Kiểm tra profile mClock
ceph config get osd osd_mclock_profile
# Kết quả: high_client_ops
Kiểm tra trạng thái override recovery settings
ceph config get osd osd_mclock_override_recovery_settings
# Kết quả: true
Kiểm tra chunk size mặc định
ceph config get osd osd_recovery_max_chunk
# Kết quả: 8388608 (8MiB)
Kiểm tra osd_max_backfills
ceph config get osd osd_max_backfills
# Kết quả: 1
Kiểm tra recovery max active global
ceph config get osd osd_recovery_max_active
# Kết quả: 0 (bỏ qua global limit)
Kiểm tra recovery max active cho HDD
ceph config get osd osd_recovery_max_active_hdd
# Kết quả: 3
3. Thực hiện thay đổi
3.1. Bật chế độ override recovery settings (nếu chưa bật)
ceph config set osd osd_mclock_override_recovery_settings true
3.2. Giữ nguyên osd_max_backfills = 1 để mỗi OSD chỉ xử lý 1 backfill song song
Global:
ceph config set osd osd_max_backfills 1
Per OSD:
ceph tell osd.<ID> injectargs --osd-max-backfills=1
All OSDs:
ceph tell 'osd.*' injectargs --osd-max-backfills=1
3.3. Giảm osd_recovery_max_active_hdd từ 3 xuống 1 (mỗi lần chỉ recovery 1 op trên HDD)
Global:
ceph config set osd osd_recovery_max_active_hdd 1
Per OSD:
# osd_recovery_max_active_hdd
ceph tell osd.<ID> injectargs --osd-recovery-max-active-hdd=1
All OSDs:
# osd_recovery_max_active_hdd
ceph tell 'osd.*' injectargs --osd-recovery-max-active-hdd=1
3.4. Đặt osd_recovery_max_active = 0 để bỏ qua giới hạn global, dùng theo device type
ceph config set osd osd_recovery_max_active 0
3.5. Giảm chunk size từ 8MiB xuống 2MiB
Global:
# osd_recovery_max_chunk
# raw bytes (2 * 1024 * 1024)
ceph config set osd osd_recovery_max_chunk 2097152
Per OSD:
# osd_recovery_max_chunk
# raw bytes (2 * 1024 * 1024)
ceph tell osd.<ID> injectargs --osd-recovery-max-chunk=2097152
All OSDs:
# osd_recovery_max_chunk
# raw bytes (2 * 1024 * 1024)
ceph tell 'osd.*' injectargs --osd-recovery-max-chunk=2097152
Lưu ý với tham số osd_recovery_max_chunk
là tham số startup-only, thay đổi cần restart OSD mới áp dụng.
Nếu muốn áp dụng ngay, bạn phải systemctl restart ceph-osd@<id>
hoặc restart container tương ứng.
Xác minh thay đổi.
shell> ceph config show osd.<ID> | egrep "osd_recovery_max_active|osd_recovery_op_priority|osd_max_backfills|osd_recovery_max_chunk"
osd_max_backfills 1 default
osd_recovery_max_active 0 default
osd_recovery_max_active_hdd 1 override default[3]
osd_recovery_max_active_ssd 10 default
osd_recovery_max_chunk 2097152 override
Dùng script này để check nhanh hơn.
cat <<'BASH' >/tmp/ceph_overrides_sorted.sh
#!/usr/bin/env bash
set -euo pipefail
TMPDIR="$(mktemp -d)"
OUT="${1:-ceph-osd-overrides.json}"
osds="$(ceph osd ls | tr ' ' '\n' | sed '/^$/d')"
P=8 # số OSD xử lý song song
work_osd() {
local osd="$1"
local overrides
overrides="$(timeout 10s ceph config show "osd.$osd" | \
awk '$3=="override" && ($1=="osd_recovery_max_active" || $1=="osd_recovery_op_priority" || $1=="osd_max_backfills" || $1=="osd_recovery_max_chunk"){print $1, $2}')"
if [ -n "$overrides" ]; then
{
echo "{"
echo " \"osd\": \"$osd\","
echo " \"configs\": {"
local first=1
while read -r k v; do
if [ $first -eq 0 ]; then echo ","; fi
first=0
printf " \"%s\": \"%s\"" "$k" "$v"
done <<< "$overrides"
echo
echo " }"
echo "}"
} >"$TMPDIR/$osd.json"
fi
}
export -f work_osd
export TMPDIR
printf "%s\n" $osds | xargs -n1 -P "$P" -I{} bash -c 'work_osd "$@"' _ {}
if command -v jq >/dev/null 2>&1 && ls "$TMPDIR"/*.json >/dev/null 2>&1; then
jq -s 'map(select(has("osd") and has("configs")))
| sort_by(.osd|tonumber)
| map(. as $o | .configs |= (to_entries|sort_by(.key)|from_entries))' \
"$TMPDIR"/*.json >"$OUT"
else
echo "[" >"$OUT"
first=1
for f in $(ls "$TMPDIR"/*.json 2>/dev/null || true); do
if [ $first -eq 0 ]; then echo "," >>"$OUT"; fi
first=0
cat "$f" >>"$OUT"
done
echo "]" >>"$OUT"
fi
rm -rf "$TMPDIR"
echo "Wrote $OUT"
BASH
bash /tmp/ceph_overrides_sorted.sh
4. Tham số liên quan đến recovery/backfill
4.1. Thay đổi nóng qua injectargs được (không cần restart):
osd_max_backfills
osd_recovery_max_active
osd_recovery_max_active_hdd
osd_recovery_max_active_ssd
osd_recovery_sleep
osd_scrub_max_interval
osd_scrub_min_interval
osd_scrub_sleep
4.2. Cần restart OSD để áp dụng:
osd_recovery_max_chunk
osd_client_message_size_cap
osd_op_num_shards
osd_op_num_threads_per_shard
5. Xác minh sau thay đổi (VERIFY)
5.1. Giám sát trạng thái cluster realtime
watch -n1 ceph -s
5.2. Kiểm tra giá trị tham số đã set
ceph config get osd osd_max_backfills
ceph config get osd osd_recovery_max_active_hdd
ceph config get osd osd_recovery_max_chunk
6. Rollback (nếu cần)
# osd_recovery_max_active_hdd
ceph config set osd osd_recovery_max_active_hdd 3
# osd_recovery_max_chunk
# raw bytes (8 * 1024 * 1024)
ceph tell osd.9 injectargs --osd-recovery-max-chunk=8388608
Cần restart OSD để chunk size trở lại mặc định.
7. Lời khuyên
- Với mClock profile
high_client_ops
, nên giảm song song recovery/backfill để ưu tiên client, đặc biệt trên HDD. - Nếu cần giảm thêm tác động, có thể chỉnh
osd_recovery_sleep
(0.1s–0.5s). - Trong môi trường test, có thể thử injectargs trước để đánh giá tác động, sau đó mới set config và restart khi bảo trì.
- Nếu không dùng mClock, có thể áp dụng các giới hạn recovery tương tự qua classic op queue scheduler (opensource, không yêu cầu license).
8. Tài liệu tham khảo
- Ceph Docs – Configuring OSD Recovery: https://docs.ceph.com/en/latest/rados/configuration/osd-config-ref/
- Red Hat Ceph Storage mClock Scheduler: https://access.redhat.com/documentation/en-us/red_hat_ceph_storage/
- Ceph Injectargs usage: https://docs.ceph.com/en/latest/rados/troubleshooting/troubleshooting-mon/#changing-osd-options-at-runtime