UMGUM.COM (лучше) 

Автоматизация DRBD ( Контроль за зеркалированием дисковых устройств файловой системы. )

1 августа 2010  (обновлено 15 августа 2016)

OS: Debian Linux.

Итак, мы рассмотрели, каким образом можно создать виртуальное блочное устройство DRBD и синхронизировать его участников. Перейдем к автоматизации процесса инициализации блочных устройств и контроля за их работой.

Современные реализации DRBD не требуют для обеспечения контроля за собой сторонних приложений, все, что нужно, можно получить от утилит самого DRBD. Невозможность получить от DRBD информации о состоянии блочных устройств само по себя является достаточным поводом для паники.

Наша задача на данном этапе состоит в том, чтобы при запуске физического сервера провести проверку на доступность всех членов виртуальных блочных устройств, установить режимы работы блочных устройств и, если на будет необходимость, информировать администратора о нештатном развитии ситуации.

Будем считать, что все блочные устройства уже созданы и синхронизированы. Создадим условия для автоматизации процесса.


Создаем файл списка DRBD устройств:

# mkdir -p /etc/custom/hdd/drbd
# touch /etc/custom/hdd/drbd/list

Наименования устройств вносим с разделителем в виде пробельного символа. К имени устройства, через разделитель в виде "слэша", прикрепляем назначенный ему статус (primary или secondary):

# cat /etc/custom/hdd/drbd/list

drbd0/primary drbd1/primary drbd2/secondary ... drbdX/status

Пакет DRBD позволяет получать список используемых устройств в интерактивном режиме, но нам нужен список устройств, которые мы уже настроили, протестировали, одобрили и включили в рабочую схему. Нужно это для того, чтобы скрипты не обращали внимания на те устройства, что находятся на предварительной настройке, тестировании или профилактике.

Напишем скрипт проверяющий состояние членов устройств DRBD с определённой периодичностью, в течении работы, устанавливающий режим работы устройства и информирующего администратора об обнаруженных проблемах:

# touch /etc/custom/hdd/drbd/check-drbd.sh
# chmod ugo+x /etc/custom/hdd/drbd/check-drbd.sh

#!/bin/bash

PATH=/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/sbin:/usr/local/bin
HOSTNAME=`cat /etc/hostname`
OBJECTS=`cat /etc/custom/hdd/drbd/list`
DATE=`date +"%Y-%m-%d %H:%M:%S"`
EMAIL=`cat /etc/custom/hdd/email`

# Определяем функцию уведомления администратора о нештатном развитии ситуации
function send-report() {
  local LOCAL_OBJECT=$1
  local LOCAL_REPORT=$2
  # Посылаем электронное письмо с уведомлением о проблеме
  echo -e "Content-Type: text/plain; charset="utf-8"\nSubject: Warning DRBD: ${HOSTNAME}: /dev/${LOCAL_OBJECT}\n${DATE}.\nHost: ${HOSTNAME}.\nDevice: /dev/${LOCAL_OBJECT}.\n${LOCAL_REPORT}" | sendmail -F${HOSTNAME} ${EMAIL}
}

# Проверяем, не установлены ли флаги блокировки от текущего уровня схемы
if [ -e /tmp/custom/drbd/lock ]
then
  exit 0
fi

# Устанавливаем флаги блокировки на время работы скрипта
mkdir -p /tmp/custom/drbd
touch /tmp/custom/drbd/lock

# Проверяем факт запуска DRBD по созданным им конструкциям
if [ ! -e /proc/drbd ]
then
  send-report "DRBD" "Warning! DRBD не запущен."
  echo >&2 "Warning! DRBD не запущен."
  exit 1
fi

# Перебираем в цикле все наши DRBD устройства
for OBJECTIVE in ${OBJECTS}
do
  # Получаем в переменные имя устройства и предназначенную ему роль
  OBJECT=`echo ${OBJECTIVE} | awk -F / '{print $1}'`
  ROLE=`echo ${OBJECTIVE} | awk -F / '{print $2}'`

  # Проверяем, работает ли устройство в полноценной связке с удалённым по сети дубликатом
  if [ `drbdadm cstate ${OBJECT} 2>/dev/null | grep "Connected"` ]
  then

    # Проверяем, доступно ли DRBD устройство для полноценного использования локально
    if [ "`drbdadm dstate ${OBJECT} 2>/dev/null | awk -F / '{print $1}'`" = "UpToDate" ]
    then

      # Проверим, доступен ли для полноценной работы удалённый по сети DRBD дубликат
      if [ "`drbdadm dstate ${OBJECT} 2>/dev/null | awk -F / '{print $2}'`" != "UpToDate" ]
      then

        # Если удалённый по сети DRBD дубликат не готов к работе, то для локального устройства принудительно выставляем роль primary (если в это есть необходимость), что бы некоторое время продержаться на одном диске, до замены вышедшего из строя
        if [ "${ROLE}" != "primary" ]
        then
          ROLE="primary"
        fi

      fi

      # Проверяем на предмет уже назначенной роли
      if [ "`drbdadm state ${OBJECT} | awk -F / '{print $1}' | tr A-Z a-z`" != "${ROLE}" ]
      then
        # Если локальный член DRBD устройства корректно работает, то назначаем ему заданную заранее роль (это может быть как primary так и secondary)
        echo "Waiting 10 seconds for correct setup role DRBD resource /dev/${OBJECT}..."
        drbdsetup /dev/${OBJECT} ${ROLE}
        sleep 10
        if [ "`drbdadm state ${OBJECT} | awk -F / '{print $1}' | tr A-Z a-z`" != "${ROLE}" ]
        then
          send-report ${OBJECT} "Panic! За 10 секунд не произошло применение ролей членов DRBD устройства."
          echo >&2 "Panic! За 10 секунд не произошло применение ролей членов DRBD устройства /dev/${OBJECT}."
        fi
      fi

    else
      send-report ${OBJECT} "Panic! DRBD устройство работает не корректно или не применимо в текущей конфигурации."
      echo >&2 "Panic! DRBD устройство /dev/${OBJECT} работает не корректно или не применимо в текущей конфигурации."
    fi

  else
    send-report ${OBJECT} "Warning! DRBD устройство работает некорректно в ожидании подключения к удалённому узлу."
    echo >&2 "Warning! DRBD устройство /dev/${OBJECT} работает некорректно в ожидании подключения к удалённому узлу."
  fi

done

# Удаляем флаг блокировки во время исполнения
rm --force /tmp/custom/drbd/lock

exit 0

Цель скрипта в том, чтобы сделать доступным виртуальное блочное устройство в том случае, если доступен в полной мере один или более из его членов. Для кластерных систем достаточно было бы сделать всех членов блочного устройства доступными для чтения и записи (условно говоря, сделать всем роли Primary), но в нашем случае необходимо следить за отсутствием конфликтов чтения/записи и целостностью данных членов виртуального устройства. Суть в том, что если скрипт обнаружит недоступность того из членов DRBD устройства, что должен иметь роль первичного, об этом должен сразу же узнать администратор, провести соответствующие работы с последующим восстановлением файловой системы.

Одна из операций созданного нами скрипта производит проверку на подключение виртуального устройства с помощью команды "drbdadm cstate". У упомянутой команды довольно многовариантный вывод, но только одно из них говорит о том, что все члены виртуального устройства подключены и доступны, это: "Connected" - оно говорит о том, что все устройства на связи и готовы к любым операциям с ними. Все остальные варианты вывода команды "drbdadm cstate" говорят о том или ином уровне недоступности устройства и все эти состояния возникают в момент неисправности связки членов виртуального устройства, что служит достаточным поводом объявить тревогу. Устройства могут быть недоступны в момент ввода их в рабочую схему, и для обхода этих критических ситуаций мы создали ручной список проверяемых DRBD устройств; просто не будем включать в него устройства, что ещё не синхронизированы и не введены в рабочую схему.

Созданный нами скрипт автоматического применения ролей членов устройств DRBD должен запускаться периодически. Думаю, что период в десять минут вполне приемлем; если роли к устройствам уже применены ранее, то скрипт просто это проверит (доли секунды), а в случае сбоя работы устройств - чем раньше мы это обнаружим, тем лучше.

Размещаем команду запуска скрипта в таблице /etc/crontab:

# cat /etc/crontab

....
*/10  * * * *  root  /etc/custom/hdd/drbd/check-drbd.sh &
....

Что бы не дожидаться периодического запуска вышеописанного скрипта при старте системы, разместим команду запуска в исправленном ранее скрипте управления DRBD (следует иметь в виду то, что DRBD может затратить одну-три минуты на освоение всего дискового массива, общий объём которого может достигать 10TB - потому дадим ему на это время отдельно, при первом запуске):

# vi /etc/init.d/drbd

....
case "$1" in
  start)
....
      # Проверяем успешность загрузки модуля DRBD по наличию созданных им служебных конструкций
      if [ -e /proc/drbd ]
      then
        echo >&2 "DRBD driver started."
        echo "Wait 300 seconds before start configuration..."
        sleep 300
        /etc/custom/hdd/drbd/check-drbd.sh
....
  reload)
....
    drbdadm adjust all
    /etc/custom/hdd/drbd/check-drbd.sh &
  ;;
....


Заметки и комментарии к публикации:


Оставьте свой комментарий ( выразите мнение относительно публикации, поделитесь дополнительными сведениями или укажите на ошибку )