背景
Ceph 集羣在運行一段時間後常會碰到OSD 數據不均衡的時候,有的OSD 使用率超過的80%,有的甚至不足60%。一般有兩種方法去均衡各個OSDs 間的數據
OSD Reweight
其實就是給各個OSDs 設置均衡權重(區別OSD weight 是根據容量設置的固定權重)
調整數據量超過閥值的OSD的權重,閥值默認值爲120%。
ceph osd reweight-by-utilization [threshold]
若要預覽效果,則可以使用以下命令:
ceph osd test-reweight-by-utilization [threshold]
當然,也可以根據每個OSD上的PG數量來調整,閥值默認值也是120%。
ceph osd reweight-by-pg [threshold]
若要預覽效果,則可以使用以下命令:
ceph osd test-reweight-by-pg [threshold]
Ceph Balancer
從Luminous 開始,Ceph 新增的了balancer ,可以將PG 在各個OSD上自動遷移,已達到均衡的效果。推薦使用。
1)查看balancer 模塊狀態
ceph mgr module ls # 查看各個模塊的狀態
ceph balancer status
2)啓用balancer 模塊(默認enable)
ceph mgr module enable balancer
3)啓用均衡(默認active 是false)
ceph balancer on
4)設置模式(修改PG mapping)
ceph balancer mode upmap
或設置模式(修改weight)
ceph balancer mode crush-compat
其中upmap 模式設置兼容版本
ceph osd set-require-min-compat-client luminous
Luminous 需要手動設置均衡計劃?
ceph balancer eval #對集羣所有pool進行權重調整計算,針對特定pool 採用
ceph balancer eval <POOL_NAME>
ceph balancer optimize plan2 #生成一個調優配置,或指定存儲池ceph balancer optimize plan2 default.rgw.buckets.data
ceph balancer eval plan2 #執行調優計算
ceph balancer show plan2 #查看調優計算最終的結果
ceph balancer execute plan2 #根據上面模擬計算的結果,執行最終的權重調整
5)查看調整結果
ceph osd df
6)關閉自動調整
ceph balancer off
ceph balancer status
OSD PG 數統計腳本:包含osd pool的排序,包含osd的排序,輸出平均pg數目,輸出最大的osd編號,輸出最大超過平均值的百分比,輸出最少pg的osd編號,輸出最小低於平均值的百分比,
用於輔助查看集羣各個OSD 的PG 分佈情況,參考武漢-磨渣的博客《查詢osd上的pg數》
ceph pg dump | awk '
/^PG_STAT/ { col=1; while($col!="UP") {col++}; col++ }
/^[0-9a-f]+\.[0-9a-f]+/ { match($0,/^[0-9a-f]+/); pool=substr($0, RSTART, RLENGTH); poollist[pool]=0;
up=$col; i=0; RSTART=0; RLENGTH=0; delete osds; while(match(up,/[0-9]+/)>0) { osds[++i]=substr(up,RSTART,RLENGTH); up = substr(up, RSTART+RLENGTH) }
for(i in osds) {array[osds[i],pool]++; osdlist[osds[i]];}
}
END {
printf("\n");
slen=asorti(poollist,newpoollist);
printf("pool :\t");for (i=1;i<=slen;i++) {printf("%s\t", newpoollist[i])}; printf("| SUM \n");
for (i in poollist) printf("--------"); printf("----------------\n");
slen1=asorti(osdlist,newosdlist)
delete poollist;
for (j=1;j<=slen;j++) {maxpoolosd[j]=0};
for (j=1;j<=slen;j++) {for (i=1;i<=slen1;i++){if (array[newosdlist[i],newpoollist[j]] >0 ){minpoolosd[j]=array[newosdlist[i],newpoollist[j]] ;break } }};
for (i=1;i<=slen1;i++) { printf("osd.%i\t", newosdlist[i]); sum=0;
for (j=1;j<=slen;j++) { printf("%i\t", array[newosdlist[i],newpoollist[j]]); sum+=array[newosdlist[i],newpoollist[j]]; poollist[j]+=array[newosdlist[i],newpoollist[j]];if(array[newosdlist[i],newpoollist[j]] != 0){poolhasid[j]+=1 };if(array[newosdlist[i],newpoollist[j]]>maxpoolosd[j]){maxpoolosd[j]=array[newosdlist[i],newpoollist[j]];maxosdid[j]=newosdlist[i]};if(array[newosdlist[i],newpoollist[j]] != 0){if(array[newosdlist[i],newpoollist[j]]<=minpoolosd[j]){minpoolosd[j]=array[newosdlist[i],newpoollist[j]];minosdid[j]=newosdlist[i]}}}; printf("| %i\n",sum)} for (i in poollist) printf("--------"); printf("----------------\n");
slen2=asorti(poollist,newpoollist);
printf("SUM :\t"); for (i=1;i<=slen;i++) printf("%s\t",poollist[i]); printf("|\n");
printf("Osd :\t"); for (i=1;i<=slen;i++) printf("%s\t",poolhasid[i]); printf("|\n");
printf("AVE :\t"); for (i=1;i<=slen;i++) printf("%.2f\t",poollist[i]/poolhasid[i]); printf("|\n");
printf("Max :\t"); for (i=1;i<=slen;i++) printf("%s\t",maxpoolosd[i]); printf("|\n");
printf("Osdid :\t"); for (i=1;i<=slen;i++) printf("osd.%s\t",maxosdid[i]); printf("|\n");
printf("per:\t"); for (i=1;i<=slen;i++) printf("%.1f%\t",100*(maxpoolosd[i]-poollist[i]/poolhasid[i])/(poollist[i]/poolhasid[i])); printf("|\n");
for (i=1;i<=slen2;i++) printf("--------");printf("----------------\n");
printf("min :\t"); for (i=1;i<=slen;i++) printf("%s\t",minpoolosd[i]); printf("|\n");
printf("osdid :\t"); for (i=1;i<=slen;i++) printf("osd.%s\t",minosdid[i]); printf("|\n");
printf("per:\t"); for (i=1;i<=slen;i++) printf("%.1f%\t",100*(minpoolosd[i]-poollist[i]/poolhasid[i])/(poollist[i]/poolhasid[i])); printf("|\n");
}'