[Из песочницы] Бесплатный мониторинг CRC ошибок
Нередко на сети хранения данных возникают такие неприятные вещи, как рост числа ошибок на портах и увеличение уровня затухания сигнала на sfp модулях. Принимая во внимание высокий уровень надежности SAN инфраструктуры, состоящей из двух и более фабрик, вероятность возникновения аварийной ситуации не так велика, но наложение негативных факторов может привести к потере данных или деградации производительности. К примеру, представьте себе ситуацию: на одной из фабрик проводится обновление FOS, все работает через вторую фабрику, а на ней между коммутатором к которому подключен дисковый массив и коммутатором к которому подключены серверы начинают быстро расти CRC ошибки на одном из транковых портов. Или еще хуже, пропадает линк из-за понижения уровня сигнала, вызванного повышением температуры SFP модуля, которая в свою очередь возросла из-за повысившейся утилизации данного канала. В таких случаях обычно говорят: «Ну кто же знал» или »100% надежных систем не бывает» и тд.
Грамотная архитектура + правильный мониторинг = отказоустойчивость
Итак проблема обозначена, необходимо разработать комплекс мер по повышению отказоустойчивости сети хранения данных, его можно разделить на два этапа:
- приведение архитектуры сети хранения данных в соответствие с «SAN best practices»
- развертывание системы мониторинга
Если про SAN best practices есть много литературы и курсов обучения, и можно пригласить крутых специалистов из интегратора для проведения экспертизы, то выбрать верный способ создать хорошую систему мониторинга SAN сети не так легко. Это можно объяснить жесткой привязкой: разработчик ПО — изготовитель коммутаторов. Я конечно не хочу сказать, что Cisco Fabric Manager или Brocade Network Advisor плохи, но они не позволяют делать все то, что необходимо на мой взгляд для повышения отказоустойчивости SAN сети.
Что делать
И так, задача поставлена, необходимо найти путь решения, часто это может осложняться отсутствием денег в бюджете на этот год, или неосведомленностью интегратора о существовании подходящего ПО, но это не проблема т.к. все необходимые компоненты есть в свободном доступе и требуется лишь заставить это все работать.
Разберем реализацию мониторинга CRC ошибок на портах SAN свичей brocade, большинство остальных параметров можно мониторить аналогичным образом.Шаг первый, протокол сбора данных
Информацию о числе CRC ошибок можно получать с коммутаторов разными способами (snmp, https, telnet и ssh) мой выбор пал на последний т.к. telnet не безопасен и его лучше отключать, https сложен для извлечения конкретных значений, а snmp дерево может значительно меняться как на разных свичах, так и при переходе на новый FOS.Шаг второй, метод сбора данных
Для работы с ssh лучше всего адаптирован linux в связке bash+expect, этим методом можно подключаться по ssh с диалоговым вводом команд.Шаг третий, где хранить
Тут большой разницы нет, можно хранить хоть в текстовых файлах, но мы рассмотрим пример с mysql. Весь мониторинг реализован в двух скриптах:
porterrshow.sh — сбор информации и поиск инкремента значений CRC ошибок
expect.tcl — подключение по ssh
и трех txt файлах:
temp.txt — буфер данных
switches.txt — список san свичей в формате имя логин пароль на каждой строке
crc.txt — отчет о найденных CRC ошибках
Select запрос ищет инкремент роста CRC ошибок по сравнению с данными полученными один час назад, соответственно запуск скрипта необходимо производить один раз в час, причем начать и закончить свою работу скрипт должен в одном и том же часу. Данное ограничение можно легко обойти, если ввести поле порядкового номера запуска скрипта, либо потерять в производительности и задать более сложное условие выборки значений времени. На сервере должны быть установлены пакеты expect, mysql и ssh клиент. В базе данных dbname должен присутствовать пользователь user с правами на чтение и запись в таблицу tablename. В таблице tablename получаем данные аналогичные выводу команды porterrshow на свиче + дата и время.
porterrshow.sh
#!/bin/bash
rm /var/scripts/temp.txt #Удаляем ранее созданный temp.txt
while read line #Читаем строку из файла switches.txt
do read sw user pass <<< $line #Разбиваем строку на переменные
n=0 #Обнуляем счетчик
while read line; #Читаем строку из вывода expect.tcl
do array[n]="$line"; n=$[n+1]; #Заполняем массив строками из вывода expect.tcl
done < <(/var/scripts/expect.tcl $sw $user $pass porterrshow) #Отправляем данные в цикл
if echo ${array[4]} | grep -q '='; #Проверяем с какой строки начинается вывод полезной информации
then k=5;
else k=4;
fi;
for i in `seq $k $[n-1]`; #В последней строке данных нет
do read a1 a2 a3 a4 a5 a6 a7 a8 a9 a10 a11 a12 a13 a14 a15 a16 a17 a18 a19 <<< ${array[i]}; #Разбиваем строку на значения
(echo $sw,${a1%:},`date +%F`,`date +%T`,$a2,$a3,$a4,$a5,$a6,$a7,$a8,$a9,$a10,$a11,$a12,$a13,$a14,$a15,$a16,$a17) >> temp.txt #Формируем подгрузочный файл
done;
done < /var/scripts/switches.txt #Читаем файл со списком свичей
mysql -uuser -ppass dbname << EOF;
LOAD DATA LOCAL INFILE "temp.txt" INTO TABLE tablename FIELDS TERMINATED BY ',';
EOF
#Загружаем данные в БД
(mysql -uuser -ppass dbname << EOF
select new.switch, new.port, new.crcerr-old.crcerr from tablename new, tablename old where new.switch=old.switch and new.port=old.port and new.date=old.date and new.crcerr!=old.crcerr and new.crcerr!=0 and new.date=curdate() and hour(new.time)=hour(now()) and hour(old.time)=hour(now())-1;
EOF
) > /var/scripts/crc.txt #Проверяем инкремент CRC по портам и пишем отчет в файл
if grep -q 'switch' /var/scripts/crc.txt
then
cat /var/scripts/crc.txt | mailx -r SAN_Switch_CRC_Tester -s "CRC errors is increased" sanadmin1@mywork.com
fi
#Отправляем информацию администратору
expect.tcl
#!/usr/bin/expect
#Устанавливаем таймаут соединения 10 сек
set timeout 10
#Проверям число параметров передаваемых скрипту
if {$argc != 4} {
puts "Usage $argv0 host user pass command"
exit 1}
#Назначаем параметры переменным
set host [lindex $argv 0]
set user [lindex $argv 1]
set pass [lindex $argv 2]
set command [lindex $argv 3]
#Производим подключение по SSH
spawn ssh -oStrictHostKeyChecking=no -oCheckHostIP=no $user@$host $command
expect *assword:
send "$pass\r"
expect eof