Разворачиваем высокодоступный сайт на стеке LAMP в InfoboxCloud

По исследованию WEBO Software и AdRiver до 50% маркетингового бюджета тратится впустую только из-за проблем, связанных с сетевой, географической, локальной или технической доступностью сайта. Даже незначительные перебои в работе негативно сказываются на ранжировании сайта в поиске.

В этой статье мы рассмотрим способ обеспечения бесперебойной работы сайта на технологиях LAMP (Linux + Apache + MySQL (MariaDB) + PHP) даже при недоступности виртуального сервера в одном из регионов облака. В процессе работы сайта любой из серверов можно выключать или перезагружать. При этом сайт останется доступным для пользователей.



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


Получение доступа к нескольким регионам InfoboxCloud и создание серверов

Закажите 2 подписки на InfoboxCloud в Москве и Амстердаме для создания геораспределенного решения.
Для того, чтобы подписки были привязаны к единому аккаунту пользователя действовать нужно так:
1. Зайдите на http://infoboxcloud.ru и закажите облачную инфраструктуру в любом регионе (например в Амстердаме). Далее войдите в панель управления и закажите облако в другом регионе (например в Москве) с главной страницы панели управления, как показано ниже.


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


Создайте сервер в Москве:



В данной статье будет использоваться Ubuntu 14.04 LTS, но подобным образом можно настроить и другие ОС.


Теперь переключите регион подписки и создайте сервер в Амстердаме:


После создания серверов вы получите данные для доступа к ним на электронную почту.

Настройка DNS

Для основного домена, сайт на котором должен быть высокодоступен, создайте две А-записи DNS, указывающие на сервер в Москве и сервер в Амстердаме. В нашем случае сайт будет community.trukhin.com.

Затем создайте служебные поддомены, A–запись которых должна указывать на свой сервер. Например msk.community.trukhin.com указывает на сервер в Москве, а ams.community.trukhin.com указывает на сервер в Амстердаме. Отдельные поддомены для каждого из серверов нужны, чтобы, в случае если сервер выйдет из строя, с резервного сервера развернуть еще реплику и перенаправить поддомен на нее.

Убедитесь, что записи DNS обновились:



Базовая настройка серверов и обмен ключами

Подключитесь к каждому из серверов по SSH.

Сгенерируйте ключ SSH на каждом из серверов (на вопросы можно просто нажать Enter):
ssh-keygen

С сервера в Москве добавьте ключ на сервер в Амстердаме:
ssh-copy-id root@ams.community.trukhin.com

С сервера в Амстердаме добавьте ключ на сервер в Москве:
ssh-copy-id root@msk.community.trukhin.com

Теперь подключитесь с сервера в Москве (root@msk.community.trukhin.com) к серверу в Амстердаме (root@ams.community.trukhin.com) и наоборот. Пароль запрашиваться не должен. На вопросы при подключении ответьте yes.

Установка обновление системы и установка веб-сервера Apache

Установите Apache на каждом из серверов, запустите его и добавьте в автозагрузку:
apt-key update && apt-get update && apt-get -y upgrade && apt-get -y install apache2

Если при обновлении у вас будет вопрос про конфигурацию Postfix – выберите Internet Site и введите имя основного домена сайта.

Добавьте Apache в автозагрузку:
update-rc.d apache2 defaults

Установка последней стабильной версии MySQL

Установите последнюю версию MySQL с официального репозитория Oracle. Вы можете использовать и MariaDB, но тоже рекомендуется последняя версия.

Для тех, кто ставит MySQL: вы можете скачать deb пакет на локальный компьютер и скопировать его на сервера командой
scp mysql-apt-config_0.3.3-2ubuntu14.04_all.deb root@msk.community.trukhin.com:/root

или скопировать ссылку у скачавшегося пакета и скачать на серверах пакет с wget по ней:
wget http://repo.mysql.com/mysql-apt-config_0.3.3-2ubuntu14.04_all.deb


Установите пакет на каждом из серверов:
dpkg -i mysql-apt-config_0.3.3-2ubuntu14.04_all.deb


При установке у вас попросят указать нужную версию MySQL и инструментов.


Выберите MySQL 5.6 (5.7 еще не вышел) и Utilites 1.5. После этого нажмите Apply.

Установите MySQL сервер на обоих серверах:
apt-get update && apt-get install -y mysql-server 

При установке задайте пароль для root пользователя MySQL:


Добавьте MySQL в автозагрузку на обоих серверах:
update-rc.d mysql defaults


Запустите MySQL Secure Installation. Используйте свой root–пароль, заданный при установке базы. Удалите анонимных пользователей, возможность подключаться root–пользователю удаленно, удалите тестовую базу данных и перезагрузите привилегии таблиц. В процессе работы Secure Installation просто спросит вас об этом и нужно будет ответить y.
/usr/bin/mysql_secure_installation

Установка последней стабильной версии PHP

В состав Ubuntu 14.04 PHP 5.6 еще не включен, поэтому нужно добавить репозиторий для установки.
Для работы команды add-apt-repository установите пакет software-properties-common:
apt-get -y install software-properties-common

Добавьте репозиторий с PHP 5.6:
add-apt-repository -y ppa:ondrej/php5-5.6 && apt-get update

Установите PHP 5.6:
apt-get install -y php5

В процессе установки Apache будет автоматически перезапущен.

Давайте проверим работоспособность PHP. В директории /var/www/html удалите файл index.html (rm /var/www/html/index.html) и создайте файл index.php.
<!DOCTYPE html>
<html>
   <head>
      <meta charset="utf-8">
      <title>
         PHP Info
      </title>
   </head>
   <body>
   <?php
       phpinfo();
   ?>
   </body>
</html>

Если вы никогда ранее не редактировали файлы в Linux, можно установить простой редактор nano:
apt-get install -y nano

Для редактирования файла наберите
nano /var/www/html/index.php

Смените пользователя у файла index.php, чтобы Apache мог получать доступ к нему:
chown www-data:www-data index.php

Теперь проверьте, что страница PHP Info корректно открывается с обоих серверов.

Отлично!

Включаем mod_rewrite для поддержки .htaccess сайта

На обоих серверах выполните команду:
a2enmod rewrite

В файле /etc/apache2/sites-enabled/000-default.conf после строки с DocumentRoot добавьте:
<Directory /var/www/html>
            AllowOverride All
        </Directory>

Перезапустите Apache.
service apache2 restart


Устанавливаем phpMyAdmin

Для работы с базой данных удобно использовать phpMyAdmin.
apt-get install phpmyadmin

При установке будет предложено автоматически сконфигурировать веб-сервер. Выберите Apache, нажмите пробел для пометки сервера и Enter для продолжения установки.

Также в процессе установки согласитесь с предложением конфигурации phpMyAdmin:

Укажите root пароль от базы данных MySQL и продолжите установку.

После установки проверьте, что phpmyadmin корректно открывается на обоих серверах:
http://ams.community.trukhin.com/phpmyadmin



Залогиньтесть с помощью root логина и пароля от MySQL для проверки работоспособности:



Настраиваем двустороннюю асинхронную репликацию файлов веб-серверов с Lsyncd

Lsyncd (Live Syncing Daemon) – приложение для своевременного интерактивного зеркалирования данных серверов для использования в кластерах высокой доступности. Особенно хорошо lsyncd подходит для систем с небольшим трафиком синхронизации. Приложение собирает информацию об изменениях данных через подсистему ядра Linux inotify в течение определенного в конфигурации периода и запускает процессы зеркалирования изменений (через rsync по умолчанию, но есть и другие варианты). По-умолчанию lsyncd запускается как демон в фоне и протоколирует свои действия с помощью syslog. Для целей тестирования можно запустить приложение без демонизации, чтобы видеть происходящие действия в терминале для отладки.

Lsyncd не использует отдельную файловую систему или блочное устройство и не влияет сильно на производительность локальной файловой системы.

Использование опции Rsync + SSH позволяет передавать файлы сразу в целевую директорию вместо передачи места размещения на удаленный сервер.

Давайте установим lsyncd на обоих серверах:
apt-get install -y lsyncd

Создайте директории для хранения логов и временных файлов lsyncd на обоих серверах:
mkdir -p /var/log/lsyncd && mkdir -p /var/www/temp && mkdir -p /etc/lsyncd

Создайте файл конфигурации lsyncd по адресу: /etc/lsyncd/lsyncd.conf.lua
settings {
  logfile    = "/var/log/lsyncd/lsyncd.log",
  statusFile = "/var/log/lsyncd/lsyncd.status",
  nodaemon   = false
}
sync {
  default.rsyncssh,
  source="/var/www/html",
  host="ams.community.trukhin.com",
  targetdir="/var/www/html",
  rsync = {
    archive=true,
    compress=true,
    temp_dir="/var/www/temp",
    update=true,
    links=true,
    times=true,
    protect_args=true
  },
  exclude={
              "templates/cache/",
              "templates/compiled/"
  },
  delay=3,
  delete="startup",
  ssh = {
    port = 22
  }
}

Значение host: ams.community.trukhin.com замените на ваш поддомен, направленный только на сервер в другом регионе. В source указывается папка на текущем сервере. В targetdir указывается папка на удаленном сервере. Параметр delay – период, через который будет выполняться синхронизация изменений на сервере. Данное значение подобрано экспериментальным путем, значение по умолчанию — 10. delete = «startup» указывает на то, что файлы будут удаляться только при перезапуске lsyncd, если числятся еще как удаленные. Это помогает избежать некоторых проблем целостности. Полностью все параметры lsyncd можно найти в официальной документации. Важно: в exclude укажите папки, в которых сайт создает кэш. Их синхронизировать нельзя — будет плохо.

На втором из серверов разместите такой же файл конфигурации, но в качестве host укажите поддомен первого сервера. В нашем случае это msk.community.trukhin.com.

Для отладки установите параметр nodaemon=true и сохраните изменения.
Запустите lsyncd на обоих серверах:
lsyncd /etc/lsyncd/lsyncd.conf.lua

Будет отображаться процесс синхронизации. Подключитесь в другом окне терминала к серверам по SSH еще раз.
Создайте файл на сервере в Москве:
touch /var/www/html/msk
В первом окне терминала вы увидите, что файл был реплицирован на сервер в Амстердаме:



Проверьте его наличие в Амстердаме со второго терминала командой
ls /var/www/html


Теперь создайте файл в Амстердаме:
touch /var/www/html/ams

Вы увидите, что файл реплицировался в Москву.


Теперь на обоих серверах есть файлы ams и msk, проверьте это.



Отлично. Lsyncd работает в обе стороны при записи на любой из серверов.

Остановите lsyncd. Для этого в первом терминале, где отображается лог lsyncd для каждого из серверов надо нажать ctrl+c, чтобы вернуться в командную строку. В файле конфигурации lsyncd (/etc/lsyncd/lsyncd.conf.lua) верните значение nodaemon=false на каждом из серверов.

Добавьте lsyncd в автозагрузку:
update-rc.d lsyncd enable

И наконец запустите сервис на каждом из серверов.
service lsyncd start

Перезагрузите сервера, подключитесь снова и убедитесь, что lsyncd успешно реплицирует данные в папке /var/www/html в обе стороны.

Удалите тестовые файлы в /var/www/html на любом из серверов и убедитесь, что изменения произошли и на другом.

Разворачиваем сайт на первом сервере

Вот мы и дошли до установки нашего сайта. В данной статье мы рассмотрим перенос Сообщества InfoboxCloud. Для вашего сайта этот процесс может сильно отличаться, но общее следующее: копируем файлы сайта в /var/www/html, создаем или импортируем базу данных и прописываем доступ к базе данных на localhost. Далее проверяем доступ. Это необходимо сделать только для первого сервера, например для Москвы. Изменения файлов сами синхронизируются с Амстердамом, а базу будем настраивать отдельно на втором сервере.

Скопируем файлы со старого сервера на сервер в Москве. Упакуем сайт в архив:
tar -zcvf /root/html.tar.gz /var/www/html

Скопируем архив на сервер в Москве:
scp html.tar.gz root@msk.community.trukhin.com:/root/

Распакуем файлы архива в /var/www/html/:
cp -r var/www/html/* /var/www/html/

Устанавливаем правильного владельца файлов, чтобы веб-сервер мог получать к ним доступ.
chown -R www-data:www-data html/

На старом сервере экспортируем базы данных:
mysqldump -uroot -p --all-databases > alldb.sql

Копируем дамп на московский сервер.
scp alldb.sql root@msk.community.trukhin.com:/root/

Импортируем на московский сервер:
mysql -u root -p < alldb.sql

Убедитесь, что нужная база данных присутствует.


В конфигурационных файлах вашего сайта укажите правильный адрес 127.0.0.1 базы данных, логин и пароль для доступа.
Попробуйте открыть сайт на сервере в Москве (http://msk.community.trukhin.com).


Проверьте, идет ли репликация файлов сайта в Амстердам. Если в процессе работы вы удаляли каталог /var/www/html – перезапустите lsyncd и репликация начнется. Узнать статус репликации можно в файле lsyncd.status:
cat /var/log/lsyncd/lsyncd.status

Настраиваем асинxронную Master Master репликацию MySQL

В файле /etc/mysql/my.cnf московского сервера в разделе [mysqld] включите бинарный лог и сделайте дополнительные настройки:
binlog_do_db=livestreet
log_bin = /var/log/mysql/mysql-bin.log
server_id=1
skip-networking=0
bind-address    = 0.0.0.0
, где livestreet – имя реплицируемой базы данных.

Перезапускаем MySQL.
service mysql restart

Необходимо создать пользователя, из-под которого будет проходить репликация.
Для ввода SQL–команд используйте:
mysql -u root -p

Потребуется root пароль от MySQL, который вы задали при установке.
Создайте пользователя replicator, при этом password замените на пароль для него:
create user 'replicator'@'%' identified by 'password';

Дайте права на репликацию пользователю replicator.
grant replication slave on *.* to 'replicator'@'%';

Сохраните изменения:
FLUSH PRIVILEGES;


Проверим статус мастера:
show master status; 


Запишите значение File и Position, они нам понадобятся в дальнейшей настройке.

В файле /etc/mysql/my.cnf амстердамского сервера в разделе [mysqld] включите бинарный лог и сделайте дополнительные настройки:
binlog_do_db=livestreet
log_bin = /var/log/mysql/mysql-bin.log
server_id=2
#relay-log=/var/log/mysql/mysql-relay-bin.log
skip-networking=0
bind-address    = 0.0.0.0

Заметьте, что от конфигурации московского сервера отличается server_id. При репликации server_id должны быть различными!

Перезапускаем MySQL.
service mysql restart

Подключитесь в командный интерфейс mysql:
mysql -u root -p

Создайте пользователя replicator, при этом password замените на пароль для него:
create user 'replicator'@'%' identified by 'password';

Дайте права на репликацию пользователю replicator.
grant replication slave on *.* to 'replicator'@'%';

Сохраните изменения:
FLUSH PRIVILEGES;

Создайте базу данных в Амстердаме, в которую будем реплицировать:
create database livestreet;
, где livestreet замените на имя вашей базы данных.
В Москве экспортируйте базы данных:
cd /root
mysqldump -uroot -p --all-databases > alldb.sql

Скопируйте дамп в Амстердам:
scp /root/alldb.sql root@ams.community.trukhin.com:/root/

Теперь импортируйте базу в MySQL Амстердама:
mysql -u root -p < alldb.sql


Приступаем ко включению репликации на сервере в Амстердаме.
stop slave;

CHANGE MASTER TO MASTER_HOST = 'msk.community.trukhin.com', MASTER_USER = 'replicator', MASTER_PASSWORD = 'password', MASTER_LOG_FILE = 'mysql-bin.000002', MASTER_LOG_POS = 502;
, где вместо password задайте пароль пользователя replicator, укажите корректное значение MASTER_LOG_FILE и MASTER_LOG_POS, которые мы записали, когда делали show master status; на первом сервере.
start slave;


Проверим статус лога мастера в Амстердаме и запомним поля MASTER_LOG_FILE и MASTER_LOG_POS:
show master status;

Включим репликацию в Москве.
stop slave;

CHANGE MASTER TO MASTER_HOST = 'ams.community.trukhin.com', MASTER_USER = 'replicator', MASTER_PASSWORD = 'password', MASTER_LOG_FILE = 'mysql-bin.000001', MASTER_LOG_POS = 502;
, где вместо password задайте пароль пользователя replicator, укажите корректное значение MASTER_LOG_FILE и MASTER_LOG_POS, которые мы записали, когда делали show master status; на первом сервере.
start slave;

Проверить статус репликации можно командой:
SHOW SLAVE STATUS\G


Как мы видим — репликация идет в обе стороны.

Теперь проверьте, что сайт доступен и по амстердамскому адресу:



Примечание: во многих сайтах домен задается в конфигурационных файлах. Для тестирования msk.community.trukhin.com пропишите этот домен, для тестирования ams.community.trukhin.com – этот. После мы изменим окончательно адрес на community.trukhin.com, но пока рано.

Примечание 2: если сайт использует memcached – вы можете увидеть неприятные побочные эффекты. В этом случае рекомендуется использовать CouchBase, который имеет совместимый интерфейс с Memcached и умеет реплицироваться. Тестирование такого подхода ожидается в последующих статьях. Как временное решение предлагается временно отключите кеш.

Давайте проверим, как работает двусторонняя репликация.
Создадим какой-нибудь пост или изменение на сайте из Амстердама:



Теперь посмотрим на него из Москвы:


Видим, что синхронизация проходит корректно.

Настройка реверс-прокси NGINX

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

Для этого перенаправим Apache на обоих серверах на порт 8080.
Для этого в файле /etc/apache2/ports.conf изменим разрешенные порты:
Listen 8080
<IfModule ssl_module>
        Listen 8443
</IfModule>

<IfModule mod_gnutls.c>
        Listen 8443
</IfModule>

И укажем порт в файле /etc/apache2/sites-available/000-default.conf:
<VirtualHost *:8080>

Теперь перезапустим apache:
service apache2 restart

В конфигурационных файлах вашей CMS имя сервера меняем на имя основного сайта (в нашем случае это community.trukhin.com).

Теперь установим NGINX:
apt-get -y install nginx

Добавим в автозагрузку и запустим сервис:
update-rc.d nginx enable
service nginx start

Теперь настроим реверс-прокси. Для этого выберем основной сервер, который будет обслуживать запросы постоянно (Мы выбрали msk.community.trukhin.com).

Содержимое /etc/nginx/sites-enabled/default московского сервера:
upstream ups  {
          server 127.0.0.1:8080;
          server ams.community.trukhin.com:8080 backup;
}

server {
        listen 80 default_server;
        index index.html index.htm;

        # Make site accessible from http://localhost/
        server_name community.trukhin.com;


        location / {
            proxy_cookie_domain Host $host;
            proxy_set_header Host $host;
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

            proxy_pass  http://ups;
        }
}


Содержимое /etc/nginx/sites-enabled/default сервера в Амстердаме:
upstream ups  {
          server msk.community.trukhin.com:8080;
          server 127.0.0.1:8080 backup;
        }

server {
        listen 80 default_server;

        index index.html index.htm;

        # Make site accessible from http://localhost/
        server_name community.trukhin.com;

        location / {
            proxy_cookie_domain Host $host;
            proxy_set_header Host $host;
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

            proxy_pass  http://ups;
        }
}


Теперь перезапустите NGINX на обоих серверах:
service nginx restart


Вот и все. Теперь зайдите на ваш сайт по основному домену (community.trukhin.com). Теперь ваш сайт высокодоступный и вы можете перезагружать любой из серверов без ухода в офлайн всего сайта. Не забывайте делать бекапы, так как репликация — не замена бекапов. До запуска в продакшн протестируйте свой сайт. Возможные проблемы, а также усовершенствования при эксплуатации этого подхода будут рассмотрены в дальнейшем.

Заключение

В данной статье мы рассмотрели общие принципы развертывания отказоустойчивого геораспределенного сайта на LAMP. Это только базовое руководство, показывающee возможное направление действий. В рассмотренном сценарии подход успешно работает. Детали необходимо отлаживать для конкретного сайта или CMS. В дальнейшем мы продолжим рассматривать подходы и детали подходов по обеспечению высокой доступности.

Если вы обнаружили ошибку в статье, автор ее с удовольствием исправит. Пожалуйста напишите в ЛС или на почту о ней.

Успешного использования InfoboxCloud!

0 комментариев

Только зарегистрированные и авторизованные пользователи могут оставлять комментарии.