Mục đích.
Giám sát và điều chỉnh weight của các thiết bị lưu trữ đối tượng (OSD) cụ thể trong cụm Ceph.
Mục tiêu là đạt được sự phân phối dữ liệu cân bằng trên tất cả các OSD.
Script reweight.sh
này được viết để tự động điều chỉnh trọng số của các OSD (Object Storage Daemon) trong một cụm Ceph, dựa trên các điều kiện nhất định.
Chức năng chính.
- Giám sát trọng lượng OSD: Script kiểm tra định kỳ weight hiện tại của mỗi OSD được liệt kê.
- Điều chỉnh trọng lượng OSD: Nếu weight của OSD thấp hơn giá trị mục tiêu (được xác định bởi
TARGET_WEIGHT
), script sẽ tăng weight của nó lên một mức tăng nhỏ (INCREMENT_WEIGHT
). - Nhận thức về việc lấp đầy dữ liệu: Script chỉ cố gắng điều chỉnh weight của OSD nếu hoạt động lấp đầy dữ liệu của cụm thấp (cho thấy việc di chuyển dữ liệu tối thiểu). Điều này giúp tránh làm gián đoạn các hoạt động di chuyển dữ liệu đang diễn ra.
- Xác thực: Script bao gồm xác thực cơ bản để đảm bảo các tham số do người dùng xác định là các số hợp lệ trong phạm vi quy định.
Tính năng bổ sung.
Thông báo Telegram: Script có thông báo đến trò chuyện Telegram khi weightcủa OSD được điều chỉnh.
#!/bin/bash
OSDs="1 2 3 4 5 6 7 8 9"
INCREMENT_WEIGHT=0.01 # IMPORTANT
TARGET_WEIGHT=1.45
INTERVAL_CHECK=1 # second
WORK_DIR=/opt/weight
### telegram var
#read -p "Enter TOKEN_BOT: " TELEGRAM_BOT_TOKEN
#TELEGRAM_BOT_TOKEN=$(echo "$TELEGRAM_BOT_TOKEN" | tr -d '"')
#read -p "Enter CHAT_ID: " TELEGRAM_CHAT_ID
TELEGRAM_BOT_TOKEN=''
TELEGRAM_CHAT_ID=''
# basic validation on weird number
validate_weight () {
local w=$1
re='^[+-]?[0-9]+\.?[0-9]*$'
if ! [[ $w =~ $re && $INCREMENT_WEIGHT =~ $re && $TARGET_WEIGHT =~ $re && $INTERVAL_CHECK =~ $re ]] ; then
echo "xx Not a number" >&2
exit 1
elif (( $(echo "$w > $TARGET_WEIGHT" | bc -l) )); then
echo "xx Weight cannot higher than target"
exit 1
elif (( $(echo "$TARGET_WEIGHT > 1.5" | bc -l) )) || (( $(echo "$TARGET_WEIGHT < 0" | bc -l) )); then
echo "xx TARGET_WEIGHT cannot be out of range [0;1.5]"
exit 1
elif (( $(echo "$INCREMENT_WEIGHT > 0.05" | bc -l) )) || (( $(echo "$INCREMENT_WEIGHT < 0" | bc -l) )); then
echo "xx INCREMENT_WEIGHT cannot be higher than 0.05"
exit 1
elif (( $(echo "$INCREMENT_WEIGHT > $TARGET_WEIGHT" | bc -l) )); then
echo "xx INCREMENT_WEIGHT cannot be higher than TARGET_WEIGHT"
exit 1
fi
return 0
}
## init the weight for listed OSD
## store to /opt/weight.X
for OSD in $OSDs; do
init_weight=$(printf '%.2f\n' $(ceph osd df | grep "^$OSD" | awk '{ print $3}'))
echo $init_weight > $WORK_DIR/weight.$OSD
echo "=Init $OSD with weight $init_weight"
validate_weight $init_weight
done
## idea: while loop for keep running
## for loop to loop through OSDs
## while loop to wait and reweight
## if backfill < 10 and weight < target then reweight
while true; do
sleep 1 &&
#if (( $(cat test.ceph-s | grep -E "active\+remapped\+backfilling|active\+remapped\+backfill_wait" | awk '{sum+=$1} END {print sum}') < 15)) 2>/dev/null; then
if (( $(ceph -s | grep -E "active\+remapped\+backfilling|active\+remapped\+backfill_wait" | awk '{sum+=$1} END {print sum}') < 15)) 2>/dev/null; then
#TELERAM_MESSAGE=""
for OSD in $OSDs; do # 141 142
echo "Waiting for osd.$OSD"
while true; do
#if (( $(cat test.ceph-s | grep -E "active\+remapped\+backfilling|active\+remapped\+backfill_wait" | awk '{sum+=$1} END {print sum}') < 15 )) 2>/dev/null; then
if (( $(ceph -s | grep -E "active\+remapped\+backfilling|active\+remapped\+backfill_wait" | awk '{sum+=$1} END {print sum}') < 15 )) 2>/dev/null; then
echo "+++++ Start: $(date)"
ceph -s | grep backfill
## get current weight
#w=$(cat $WORK_DIR/weight.$OSD)
w=$(printf '%.2f\n' $(ceph osd df | grep "^$OSD" | awk '{ print $3}'))
## only reweight if current < TARGET_WEIGHT
if (( $(echo "$w < $TARGET_WEIGHT" | bc -l) )); then
echo "++ osd.$OSD current weight: $w will increase by $INCREMENT_WEIGHT"
## increase the current weight
w=$(echo $w + $INCREMENT_WEIGHT | bc)
if (( $(echo "$w < 1" | bc -l) )); then w=0$w; fi # .21 -> 0.21
echo "++ reweight: $(date)"
## reweight
#if echo osd.$OSD $w; then
if ceph osd crush reweight osd.$OSD $w; then
#echo $w > $WORK_DIR/weight.$OSD;
#notify
TELERAM_MESSAGE="== New osd.$OSD weight $w\n$TELERAM_MESSAGE"
break # out while loop
fi
else # if current >= TARGET_WEIGHT
break # out while loop
fi # target-weight check
fi # backill check
sleep $INTERVAL_CHECK
done # inner while-loop
done # for-loop
echo "++ Notify Telegram!"
#curl -X POST --silent --proxy http://192.168.100.100:3128 \
# -H "Content-Type: application/json" \
# -d "{\"chat_id\":\"$TELEGRAM_CHAT_ID\", \"text\": \"$TELERAM_MESSAGE\", 'disable_notification': true}" \
# https://api.telegram.org/bot$TELEGRAM_BOT_TOKEN/sendMessage > /dev/null
else
### one endless loop case is when pgbackfill cleaned so fast and at least one OSD is not get TARGET
is_break=1
ceph osd df > /tmp/osd-df # reduce load ceph api
for OSD in $OSDs; do
w=$(printf '%.2f\n' $(grep "^$OSD" /tmp/osd-df | awk '{ print $3}'))
# if all OSD >= TARGET -> BREAK OUTER WHILE
# if one OSD < TARGET -> BREAK FOR -> CONTINUE TO INCREASE
if (( $(echo "$w < $TARGET_WEIGHT" | bc -l) )); then
is_break=0
break
else
OSDs=$(echo $OSDs | sed s/$OSD//)
echo "++ osd is removed: $OSD. Current list: $OSDs"
fi
done
## value didn't changed thru for, no OSD < TARGET, then exit while
if (( $is_break == 1 )); then break 2; fi
fi
done
Luồng thực thi script.
- Khởi tạo:
- Đọc danh sách ID OSD từ biến
OSDs
. - Xác định mức tăng
INCREMENT_WEIGHT
,TARGET_WEIGHT
) và khoảng thời gian kiểm traINTERVAL_CHECK
. - Xác thực các tham số do người dùng xác định.
- Lấy weight ban đầu cho mỗi OSD và lưu trữ nó trong một tệp.
- Đọc danh sách ID OSD từ biến
- Vòng lặp chính:
- Liên tục lặp lại cho đến khi bị hủy.
- Kiểm tra tổng hoạt động lấp đầy dữ liệu bằng cách sử dụng
ceph -s
. - Lặp qua từng OSD được liệt kê:
- Chờ trong vòng lặp cho đến khi hoạt động lấp đầy dữ liệu thấp.
- Lấy weight hiện tại cho OSD.
- Nếu weight hiện tại thấp hơn trọng lượng mục tiêu:
- Tăng weight lên mức tăng đã xác định.
- Điều chỉnh weight của OSD bằng cách sử dụng
ceph osd crush reweight
. - (Đã được bình luận) Gửi thông báo qua Telegram (nếu được bật).
- Xử lý tình huống ngoại lệ:
- Nếu hoạt động lấp đầy dữ liệu vẫn cao đối với tất cả các OSD, script sẽ kiểm tra lại tất cả weight OSD (giảm tải bằng cách lưu đầu ra vào tệp tạm thời).
- Nếu tất cả các OSD đạt đến weight mục tiêu, script sẽ thoát.
- Nếu bất kỳ OSD nào vẫn thấp hơn weight mục tiêu, OSD khớp sẽ bị xóa khỏi danh sách và script sẽ tiếp tục lặp qua các OSD còn lại.
Bạn có thể sử dụng kết hợp lại, nohup ./reweight.sh &
sẽ chạy script reweight.sh
trong nền.
nohup ./reweight.sh &
nohup
: Viết tắt của “no hang up”. Đây là một lệnh được sử dụng để chạy một lệnh khác “trong nền” và giữ cho lệnh đó tiếp tục chạy ngay cả khi người dùng đăng xuất khỏi hệ thống. nohup
ngăn chặn lệnh được chạy từ việc bị tín hiệu SIGHUP (hang up) gửi đến, điều này thường xảy ra khi terminal đóng lại. Điều này đảm bảo rằng quá trình không bị gián đoạn bởi việc đóng terminal hoặc đăng xuất.
./reweight.sh
: Chỉ định rằng script reweight.sh
nằm trong thư mục hiện tại sẽ được thực thi. Dấu ./
trước tên file chỉ rõ rằng file đó nằm trong thư mục hiện tại.
&
: Khi được đặt ở cuối một lệnh, dấu &
cho biết lệnh đó sẽ được thực thi “trong nền” (background). Điều này có nghĩa là bạn không cần phải chờ đợi lệnh hoàn thành và có thể tiếp tục sử dụng terminal cho các lệnh khác ngay lập tức.
Kết hợp lại, nohup ./reweight.sh &
sẽ chạy script reweight.sh
trong nền, đảm bảo rằng nó tiếp tục chạy ngay cả khi người dùng đăng xuất hoặc terminal được đóng lại, và không chiếm giữ terminal hiện tại, cho phép người dùng thực hiện các lệnh khác ngay sau đó. Đầu ra mặc định của lệnh được chạy bởi nohup
sẽ được chuyển hướng vào file nohup.out
trong thư mục hiện tại, trừ khi được chỉ định khác.
Kết luận.
Nhìn chung, script này tự động hóa quy trình điều chỉnh weight OSD trong cụm Ceph để đạt được sự phân phối dữ liệu cân bằng hơn đồng thời giảm thiểu sự gián đoạn trong các hoạt động cân bằng lại dữ liệu.
Lưu ý: Script này sử dụng các lệnh Ceph và các khái niệm cụ thể về Ceph, vì vậy người dùng cần có kiến thức cơ bản về Ceph để sử dụng nó hiệu quả.