Высокая доступность?!! Дома?!! Да, заголовок звучит странно, но если Вы поддерживаете дома какой-то сервис, то возможно подобные мысли уже посещали и Вас. Давайте на минутку представим себе этакого крутого гика, который горит желанием хостить сайт у себя дома и взглянем на мир его глазами…
Размышления, доступность — зачем?
Конечно, если у нас есть дома публичный сайт, доступный через сеть Интернет, то нам просто необходимо иметь хорошую доступность и максимальный аптайм для него. Так что, нам ни в коем случае нельзя обижать поисковых ботов и допускать бесследную пропажу нашего сайта из Сети. Но давайте сразу договоримся, что денег на покупку всяких вкусных «плюшек» у нас нет и надо все реализовать своими силами. Наш бюджет, в лучшем случае, несколько сотен рублей в месяц. Кроме того, мы же живем не одни и кто-то еще периодически прибирает наш творческий порядок, попутно разбирая завалы из жестких дисков, контроллеров, старой денди и обязательно задевая пару из тысяч разбросанных по полу проводов. Такой подход тоже оказывает негативное влияние на работоспособность сайта. А ведь и мы иногда отключаем свои компьютеры, чтоб покопаться в них и быть может пропылесосить.
Планируем нашу высокую доступность
Итак, в простейшем варианте, наша цель заключается в обеспечении максимально высокого аптайма сайта в домашних условиях. Для начала мы отбросим все решения с резервированием сайта в пределах нашего дома, все-таки у нас не датацентр Tier 3 :). А значит нам надо поддерживать копию нашего сайта где то в «Интернетах». Тут нам на помощь может прийти, к примеру, дешевый хостинг или VPS. Также, предполагается что Интернет у нас дома раздается роутером, прошитым OpenWRT или же другой подобной прошивкой.
И реализуем доступность
Первым делом, нам необходимо разместить копию сайта на хостинге. Конечно еще будет необходимо настроить синхронизацию между Вашим домашним сайтом и его копией, но так как этот процесс сильно зависит от архитектуры сайта, то я пожалуй пропущу размышления о том, как это можно сделать и, в простейшем случае, порекомендую просто делать не копию, а сайт-заглушку, т.е. просто одну страничку со словами о нахождении сайта на техобслуживании и HTTP кодом 503.
Во вторых, реализуем механизм переключения на копию сайта в случае недоступности оригинала. Идея будет такая — через заданные промежутки времени мы проверяем доступность нашего сайта и в случае падения переводим все запросы к нему на сайт-копию. Для этого мы зайдем на роутер по ssh (или telnet) и создадим следующий скрипт:
#!/bin/sh ## Сперва зададим ряд настроек # Определим заголовок HTTP Host для нашего сайта HTTP_HOST="www.mysite.ru" # Наш сайт открывается по этому адресу HTTP_URL="http://myserver/" # Доступность будем проверять, пытаясь найти следующую строчку в содержимом сайта SITE_CONTENT='This is my cool site' # Если недоступен то перенаправим все запросы на этот адрес FAILOVER_IP="1.1.1.1" # И на этот порт FAILOVER_PORT="80" # Имя WAN интерфейса роутера WAN_IF=`uci get network.wan.ifname` ## Проверим, есть ли в iptables правила перенаправляющие запросы на сайт-копию FAILOVER_RULE_DNAT=`iptables -L -n -t nat | grep "^DNAT.*0\.0\.0\.0/0.*$FAILOVER_IP.*80"` FAILOVER_RULE_ACCEPT=`iptables -L -n | grep "^ACCEPT.*0\.0\.0\.0/0.*$FAILOVER_IP.*80"` ## В зависимости от этих правил мы определяем переключены ли мы на запасной IP или нет if [[ "$FAILOVER_RULE_DNAT" ]] && [[ "$FAILOVER_RULE_ACCEPT" ]] then FAILOVER="yes" else FAILOVER="no" fi ## Проверим работает ли сайт-оригинал if [[ "`wget -O - --header 'host: $HTTP_HOST' $HTTP_URL 2>&1 | grep \"$SITE_CONTENT\"`" ]] then MAINTENANCE="no" else MAINTENANCE="yes" fi ## Если оригинал не работает и мы не переключились на копию, то выполняем переключение ## Если же сайт работает, но мы переключены, то убираем переключение if [[ $MAINTENANCE = "yes" ]] && [[ $FAILOVER = "no" ]] then iptables -t nat -A prerouting_rule -i $WAN_IF -p tcp --dport www -j DNAT --to-destination $FAILOVER_IP:$FAILOVER_PORT iptables -A forwarding_rule -i $WAN_IF -p tcp --dport www -d $FAILOVER_IP -j ACCEPT logger -t FAILOVER "Looks like website down! Failing over to failover page!" elif [[ $MAINTENANCE = "no" ]] && [[ $FAILOVER = "yes" ]] then iptables -t nat -D prerouting_rule -i $WAN_IF -p tcp --dport www -j DNAT --to-destination $FAILOVER_IP:$FAILOVER_PORT iptables -D forwarding_rule -i $WAN_IF -p tcp --dport www -d $FAILOVER_IP -j ACCEPT logger -t FAILOVER "Website up! Failing back to primary site!" fi
Теперь, все что осталось, это добавить запуск этого скрипта в cron, выполняем команду crontab -e и добавляем следующую строку:
*/1 * * * * /root/bin/http_failover.sh
Вот и все! Спасибо за внимание! Успехов в достижении высокой доступности!