新鈦雲服已累計為您分享821篇技術乾貨
簡介
背景:因為當時CPU的速度增長很快,而磁碟驅動器的資料傳輸速率無法大幅提高,所以需要有一種方案解決二者之間的矛盾。
所以raid的方案就誕生,raid是由很多廉價的磁碟,組合成一個容量巨大的磁碟組,在RAID中,可以讓很多磁碟驅動器同時傳輸資料,而這些磁碟驅動器在邏輯上又是一個磁碟驅動器,所以使用RAID可以達到單個的磁碟驅動器幾倍、幾十倍甚至上百倍的速率,RAID最後成功解決了磁碟驅動器的資料傳輸速率的問題。
分類
一是外接式磁碟陣列櫃、二是內接式磁碟陣列卡,三是利用軟體實現
外接式磁碟陣列櫃是一種獨立的儲存裝置,可以透過外部介面(如 USB、eSATA、Thunderbolt 等)連線到計算機或其他伺服器,適合個人使用者、小型辦公室或作為備份解決方案,在此不展開討論。
內接式磁碟陣列卡是安裝在計算機內部的硬體裝置,直接連線到主機板的 PCIe 插槽,並管理連線到它的硬碟。raid卡可以提供更多的 RAID 配置選項和高階功能,如快取、電池後備寫入快取(BBU)等
軟體 RAID 是透過作業系統或獨立的軟體來管理硬碟的 RAID 配置,如mdadm,LVM2,成本較低,配置靈活。
級別
常見的有:RAID 0,RAID 1,RAID 5,RAID 6,RAID 10

RAID 0(至少需要兩塊盤)
RAID 0是以條帶化的方式,分別向兩塊盤,並行地寫入資料,讀取時也是並行的。一方面,並行操作可以充分利用I/O匯流排的**頻寬**,提高磁碟整體存取效能;另一方面,它有RAID級別中最高的空間利用率,但是沒有資料冗餘,存在單點故障。

RAID 1(至少需要2塊硬碟,一般為雙數)
RAID 0是以映象的方式,分別向兩塊盤,並行寫入相同的資料。有資料冗餘,可靠性強,一半寫資料,一半用來做備份,但是硬碟容量會減少一半。讀取時,從兩塊硬碟上並行讀取,寫入慢,讀取快。

RAID 5(需要3塊以上硬碟)
RAID 5採用奇偶校驗,可靠性強,磁碟校驗和被雜湊到不同的磁盤裡面,增加了讀寫速率。只有當兩塊磁碟同時丟失時,資料才無法恢復,至少三塊硬碟並且硬碟大小應該相等才能組成Raid 5陣列

軟raid
mdadm是multiple devices admin的簡稱,它是Linux下的一款標準的軟體 RAID 管理工具
安裝:
#直接用yum\apt安裝即可
yum install mdadm
常用引數:

mdadm工具指令基本格式:
mdadm-C -v 目錄 -l 級別 -n 磁碟數量 裝置路徑
舉例:
mdadm-C -v /dev/md0 -l 0 -n 2 /dev/sda1 /dev/sdb1
//在/dev/md0目錄下將sda1與sdb1兩塊磁碟建立為RAID級別為0,磁碟數為2的RAID0陣列
建立流程
1.使用 lsblk 命令檢視可用的磁碟:
lsblk
2、使用 mdadm 命令建立 RAID 0 陣列:
mdadm -C -v /dev/md0 -l 0 -n 2 /dev/sda /dev/sdb
需要將 /dev/sda 和 /dev/sdb 替換為您的磁碟名稱。
#檢查/dev/md0裝置是否已經正確建立並且處於“活動”狀態
mdadm --detail /dev/md0
3.格式化 RAID 0 陣列:
mkfs.ext4 /dev/md0
4.掛載 RAID 0 陣列:
mkdir/mnt/raid0
mount/dev/md0 /mnt/raid0(臨時掛載)
硬raid
Raid卡市場主要是LSI、Adaptec、Highpoint、Promise等廠商提供。Adaptac被PMC收購後,提供的Raid卡即為PMC,簡稱為P卡。LSI公司提供的Raid卡,即為L卡。
檢視raid卡的型別可以使用 lspci | grep -i raid命令。
PMC配置操作工具為:arcconf,LSI配置操作工具為:MegaCli、storcli。本文僅討論MegaCli工具的使用
安裝
MegaCli 安裝指令碼
#下載安裝包
wget --user=hetzner --password=download <http://download.hetzner.de/tools/LSI/tools/MegaCLI/8.07.14_MegaCLI.zip>
# 獲取作業系統 ID
os_id=$(grep -oP '^ID=\\K.*' /etc/os-release)
# 判斷作業系統並執行相應的命令
if [ "$os_id" = "debian" ]; then
apt install unzip alien libncurses5 -y
unzip -d ./megacli 8.07.14_MegaCLI.zip
cd ./megacli/Linux/
alien MegaCli-8.07.14-1.noarch.rpm
dpkg -i megacli_8.07.14-2_all.deb
echo"MegaCLI安裝成功"
elif [ "$os_id" = '"centos"' ] || [ "$os_id" = '"rocky"' ]; then
yum install unzip -y
unzip -d ./megacli 8.07.14_MegaCLI.zip
cd ./megacli/Linux/
rpm -ivh MegaCli-8.07.14-1.noarch.rpm
echo"MegaCLI安裝成功"
else
echo"作業系統不符,已退出"
exit 1
fi
MegaCli常用命令
# 檢視raid卡資訊
/opt/MegaRAID/MegaCli/MegaCli64 -AdpAllInfo -aALL
# 檢視所有 raid 級別
/opt/MegaRAID/MegaCli/MegaCli64 -LDInfo -Lall -aALL
# 檢視所有硬碟狀態
/opt/MegaRAID/MegaCli/MegaCli64 -PDList -aALL
/opt/MegaRAID/MegaCli/MegaCli64 -PDList -aALL | grep'Firmware state'
#刪除raid (注意這裡L1的數字為Target Id的數字)
/opt/MegaRAID/MegaCli/MegaCli64 -CfgLdDel -L1 -a0
建立流程
1.檢視所有硬碟的資訊
/opt/MegaRAID/MegaCli/MegaCli64 -PDList -aALL

常見引數含義
Medai Error Count 不為0,表示磁碟可能錯誤,可能是磁碟有壞道,數值越大,危險係數越高
Other Error Count 不為0,表示磁碟可能存在鬆動,可能需要重新再插入
Firmware state: 磁碟的狀態,Online是最好的狀態,除此之外還有 Unconfigured、Offline、Failed
2.根據磁碟數量建立raid
/opt/MegaRAID/MegaCli/MegaCli64 -CfgLdAdd -rX [Enclosure:Slot,...] [WT|WB] [NORA|RA] [Direct|Cached]
-r:指定raid級別
WB:寫快取策略
WT:直接寫入磁碟,不適用RAID卡快取
Direct:讀操作不快取到RAID卡快取
Cached:讀操作快取到RAID卡快取
舉例:建立一個包括4塊盤的raid0,寫快取策略,自適應預讀,不快取到RAID卡快取
/opt/MegaRAID/MegaCli/MegaCli64 -CfgLdAdd -r0 [0:0,0:1,0:2,0:3] WB Direct -a0
3.檢視raid和磁碟的狀態
#檢視raid的狀態
/opt/MegaRAID/MegaCli/MegaCli64 -LDInfo -Lall -aALL
#檢視磁碟的狀態
/opt/MegaRAID/MegaCli/MegaCli64 -PDList -aALL | grep'Firmware state'
透過指令碼監控硬raid狀態
#配置告警資訊
TIME=$(date +'%Y-%m-%d %H:%M:%S')
HOST=$(hostname)
IP="`hostname -I | awk 'BEGIN{FS=""}{print $1}'`"
logfile=/logs/check_megacli.log
# Telegram資訊
t_token='xxxxx'
t_chat_ID="xxxxx"
t_url='https://api.telegram.org/bot'xxxx'/sendMessage'
# Telegram通知函式
functionsend_telegram() {
local msg="$1"
local formatted_msg=$(echo -e "$msg")
curl -s -X POST "$t_url" -d chat_id="$t_chat_ID" -d text="$formatted_msg" -d parse_mode="$t_mode"
}
# 定義 MegaCli64 的路徑
MEGACLI_PATH="/opt/MegaRAID/MegaCli/MegaCli64"
# 獲取 RAID 狀態
raid_status=$($MEGACLI_PATH -LDInfo -Lall -aALL | grep -i "State" | awk '{print $NF}')
echo"$raid_status" > /tmp/raidstate.log
# 獲取硬碟狀態
disk_status=$($MEGACLI_PATH -pdlist -aALL | grep "Firmware state" | awk -F : '{print $2}' | awk -F , '{print $1}')
echo"$disk_status" > /tmp/fireware.log
# 檢查 RAID 狀態
for i in `cat < /tmp/raidstate.log`
do
if [[ "$i" != "Optimal" ]]; then
echo"$current_time - RAID 狀態異常: $raid_status" >> $logfile
# 傳送Telegram告警
send_telegram "時間: $(date +'%Y-%m-%d %H:%M:%S')\n伺服器: $(hostname)\nIP: $(hostname -I | awk '{print $1}')\n告警資訊: RAID狀態:$i,請立即檢查!\n報錯詳細資訊: /logs/check_megacli.log"
fi
done
# 檢查硬碟狀態
for i in `cat < /tmp/fireware.log`
do
if [[ "$i" != "Online" ]]; then
echo"$current_time - 硬碟狀態異常: $i" >> $logfile
# 傳送Telegram告警
send_telegram "時間: $(date +'%Y-%m-%d %H:%M:%S')\n伺服器: $(hostname)\nIP: $(hostname -I | awk '{print $1}')\n告警資訊: RAID狀態:$i,請立即檢查!\n報錯詳細資訊: /logs/check_megacli.log"
fi
done
透過指令碼監控軟raid狀態
TIME=$(date +'%Y-%m-%d %H:%M:%S')
HOST=$(hostname)
IP="`hostname -I | awk 'BEGIN{FS=""}{print $1}'`"
logfile=/logs/check_mdadm.log
# 釘釘
token="xxxx"
dingtalk_url="https://oapi.dingtalk.com/robot/send?access_token=$token"
# Telegram
t_chat_ID="xxxx"
t_mode='HTML'
t_url='https://api.telegram.org/bot"xxxx"/sendMessage'
# 釘釘通知函式
functionsend_dingtalk() {
local msg="$1"
local json_payload=$(cat <<EOF
{
"msgtype": "text",
"text": {
"content": "時間: $TIME\n伺服器: $HOST\nIP: $IP\n告警資訊: $msg\n報錯日誌路徑: /logs/check_mdadm.log"
},
"at": {
"isAtAll": false
}
}
EOF
)
curl -X POST "$dingtalk_url" \
-H 'Content-Type: application/json' \
-d "$json_payload"
}
# Telegram通知函式
functionsend_telegram() {
local msg="$1"
local formatted_msg=$(echo -e "$msg")
curl -s -X POST "$t_url" -d chat_id="$t_chat_ID" -d text="$formatted_msg" -d parse_mode="$t_mode"
}
hostname=`hostname`
cd /dev
list=`ls md?`
if [ ! -n "$list" ] ; then
exit
fi
#主迴圈
for name in$list ; do
subject=`/sbin/mdadm -D /dev/$name |grep "State :"`
num1=`echo$subject |grep degraded |wc -l`
num2=`echo$subject |grep FAILED |wc -l`
num3=`echo$subject |grep clean |wc -l`
status="`sudo mdadm --detail /dev/md? | grep -e "State : " | awk 'BEGIN{FS=":"}{print $2}' | uniq`"
remark=$(GetRemark /tmp/$name-lastsend)
if [ $num1 -ne 0 ] || [ $num2 -ne 0 ] ; then
echo -e " \e[31m Hello World \e[0m"
echo -e "$hostname$name \e[31m Error \e[0m $subject"
if [ "$remark" = "" ] ; then
/sbin/mdadm -D $name > /tmp/disk_result.txt
disklist=`ls /dev/sd?`
for disk in$disklist ; do
echo$disk >> /tmp/disk_result.txt
smartctl -a $disk |grep Serial >> /tmp/disk_result.txt
done
# 傳送釘釘告警
send_dingtalk "主機RAID狀態:$status,請立即檢查!"
# 傳送Telegram告警
#send_telegram "時間: $(date +'%Y-%m-%d %H:%M:%S')\n伺服器: $(hostname)\nIP: $(hostname -I | awk '{print $1}')\n告警資訊: 主機RAID狀態:$status,請立即檢查!\n報錯詳細資訊: /logs/check_mdadm.log"
fi
elif [ $num3 -eq 1 ] ; then
echo -e "$(date +'%Y-%m-%d %H:%M:%S')$hostname$name \e[34m OK \e[0m $subject" >>$logfile
fi
done