Как стать автором
Обновить

Высокодоступное отказоустойчивое web-приложение на Apache2 и MySQL

Время на прочтение 7 мин
Количество просмотров 17K

HA-Apache2 Web-Site and HA-MySQL


Цель: обеспечить высокую доступность web-приложения и минимальное время простоя при отказе одного как web-сервера, так и сервера баз данных.
Замечание! Схема предполагает, что web-приложение и база данных находится на разных серверах.
Для примера будем устанавливать wordpress.

Вариант решения:
Поскольку web-приложение должно быть постоянно доступно, то необходимо минимум два сервера с установленным приложением. Серверы будут отслеживать состояние друг друга, при этом в каждый момент времени ведущим будет только один из них. В случае отказа ведущего сервера его роль принимает второй. Когда первый сервер будет вновь доступен, к нему опять вернется роль ведущего.

Т.к. для обеспечения отказоустойчивости базы данных будут использоваться минимум два сервера, то для обращения к ним мы будем использовать один виртуальный ip-адрес, на который и настроим наше web-приложение. В этом случае отказ одного из серверов никак не скажется на работоспособности web-сервера, т.к. оно продолжит работать с базой резервного сервера. Для синхронизации баз на основном и резервном сервере будем использовать механизм двунаправленной репликации («master-master»). Для увеличения уровня безопасности и балансировки запросов от web-приложения добавим два проксирующих сервера в архитектуру. Серверы будут слушать запросы на порт 3306 и распределять их между серверами баз данных. Один из серверов будет ведущим. При отказе ведущего, его роль на себя принимает второй сервер (принцип аналогичен работе web-серверов).
Архитектура системы:


Будем использовать следующие имена серверов и ip-адреса:
Сервер IP-адрес
apache-app1 192.168.8.221
apache-app2 192.168.8.222
mysql-proxy1 192.168.8.224
mysql-proxy2 192.168.8.225
mysql-data1 192.168.8.226
mysql-data2 192.168.8.227


Дополнительно нам потребуются еще два ip-адреса:
IP-адрес Назначение
192.168.8.220 Адрес для клиентских обращений к web-приложению
192.168.8.223 Адрес для обращения к базе MySQL


Замечание! Все используемые в данном руководстве системы работают под управлением Ubuntu Server 8.04 LTS с установленным OpenSSH-сервером.

Для начала приступим к настройке серверов баз данных (mysql-data1 и mysql-data2).
Замечание! Все действия выполняются от суперпользователя.
Ставим необходимые компоненты на обоих серверах. Нам потребуется MySQL-сервер. Во время установки вводим надежный пароль для пользователя root.

apt-get install mysql-server --yes

Переходим к настройке. Для начала настроим наши серверы таким образом, чтобы они слушали запросы к серверу MySQL из сети. Для этого отредактируем файл /etc/mysql/my.cnf. В нем необходимо найти строку bind-address=127.0.0.1 и заменить ее на

bind-address=192.168.8.226

для сервера mysql-data1 и

bind-address=192.168.8.227

для сервера mysql-data2
Рестартуем службы:

/etc/init.d/mysql restart

Переходим к настройке репликации.
При однонаправленной репликации («master-slave») в случае записи в подчиненную базу данных база данных данные могут оказаться противоречивыми, что может привести к ошибке репликации. В случае двунаправленной репликации базы данных будут находиться в согласованном состоянии.
Для репликации будем использовать пользователя MySQL replication с паролем some_password.
На сервере mysql-data1 редактируем файл /etc/mysql/my.cnf. Вставляем следующие строки в раздел, относящийся к репликации:

server-id = 1
log_bin = /var/log/mysql/mysql-bin.log
max_binlog_size = 100M
binlog_ignore_db = test
binlog_ignore_db = mysql
master-host = 192.168.8.227 #ip-адрес сервера mysql-data2
master-user = replication #пользователь для репликации
master-password = some_password #пароль пользователя
master-port = 3306


Заходим в MySQL под пользователем root и даем право пользователю replication подключаться к нашему серверу с сервера mysql-data2:

mysql -u root -p
Enter password: Вводим пароль для пользователя root, заданный во время установки
>grant replication slave on *.* to 'replication'@'192.168.8.227' identified by 'some_password';
>flush privileges;
>quit;
/etc/init.d/mysql restart


Переходим на сервер mysql-data2.
Редактируем файл /etc/mysql/my.cnf. Вставляем следующие строки в раздел, относящийся к репликации:

server-id = 2
log_bin = /var/log/mysql/mysql-bin.log
max_binlog_size = 100M
binlog_ignore_db = test
binlog_ignore_db = mysql
master-host = 192.168.8.226 #ip-адрес сервера mysql-data1
master-user = replication #пользователь для репликации
master-password = some_password #пароль пользователя
master-port = 3306


Заходим в MySQL под пользователем root и даем право пользователю replication подключаться к нашему серверу с сервера mysql-data1:

mysql -u root -p
Enter password: Вводим пароль для пользователя root, заданный во время установки
>grant replication slave on *.* to 'replication'@'192.168.8.226' identified by 'some_password';
>flush privileges;
>quit;
/etc/init.d/mysql restart


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

mysql —u root —p
Enter password: Вводим пароль для пользователя root, заданный во время установки
>show slave status \G


В выведенной информации нас интересуют три параметра:

Slave_IO_State: Waiting for master to send event
Slave_IO_Running: Yes
Slave_SQL_Running: Yes


Если указанные параметры на обоих серверах соответствуют указанным выше, то все замечательно, репликация настроена. Если нет, смотрим логи.
Создадим базу данных для нашего приложения. На сервере mysql-data1 выполним следующее:

mysql —u root —p
Enter password: Вводим пароль для пользователя root, заданный во время установки
>create database wp_database;


Перейдем на сервер mysql-data2 и проверим, что база реплицировалась на этот сервер:

mysql —u root —p
Enter password: Вводим пароль для пользователя root, заданный во время установки
>show databases;


Вывод должен содержать имя созданной нами ранее базы.
Настроим права доступа к этой базе со стороны проксирующих серверов. На обоих серверах выполняем следующее:

mysql —u root —p
Enter password: Вводим пароль для пользователя root, заданный во время установки
>grant all on wp_database.* to 'wp_user'@'192.168.8.224' identified by 'wp_user_password';
>grant all on wp_database.* to 'wp_user'@'192.168.8.225' identified by 'wp_user_password';
>flush privileges;
>quit;


Переходим к настройке балансировки и mysql-proxy.
На серверах mysql-proxy1 и mysql-proxy2 устанавливаем необходимые компоненты (здесь и далее, все команды выполняются от имени суперпользователя).

apt-get install mysql-proxy heartbeat

Запускаем службу mysql-proxy на обоих серверах. В параметрах запуска указываем IP-адреса серверов mysql-data1 и mysql-data2:

mysql-proxy --proxy-backend-addresses=192.168.8.226 \
--proxy-backend-addresses=192.168.8.227 \
--proxy-address=:3306
—daemon


Переходим к настройке высокой доступности на основе heartbeat на обоих серверах.
Создадим необходимые файлы:

touch /etc/ha.d/authkeys
touch /etc/ha.d/ha.cf
touch /etc/ha.d/haresources


Выставим параметры безопасности на файл /etc/ha.d/authkeys

chmod 600 /etc/ha.d/authkeys

И отредактируем его следующим образом:

auth 2
2 sha1 your-strong-password


Отредактируем файл /etc/ha.d/ha.cf в соответствии с нашей конфигурацией. Файл должен быть идентичным на обоих узлах.

logfile /var/log/ha-log #куда писать лог
logfacility local0
keepalive 2 #как часто опрашивать хосты, в секундах
deadtime 10 #через какое время хост признается умершим
initdead 120
bcast eth0
udpport 694
auto_failback on
node mysql-proxy1
node mysql-proxy2


Замечание! Параметр node должен соответствовать выводу команды uname -n на обоих узлах!

Отредактируем файл /etc/ha.d/haresources. Файл должен быть идентичным на обоих узлах.

mysql-proxy1 192.168.8.223 #общий адрес для обращения приложений к MySQL

Все готово. Осталось только рестартовать службы на обоих серверах (сначала на mysql-proxy1, а потом mysql-proxy2).

/etc/init.d/heartbeat restart

Приступаем к настройке web-серверов apache-app1 и apache-app2.
Устанавливаем необходимые компоненты.

apt-get install apache2 php5 php5-gd php5-mysql libapache2-mod heartbeat --yes

Переходим к настройке отказоустойчивости.
Создадим необходимые файлы:

touch /etc/ha.d/authkeys
touch /etc/ha.d/ha.cf
touch /etc/ha.d/haresources


Выставим параметры безопасности на файл /etc/ha.d/authkeys

chmod 600 /etc/ha.d/authkeys

И отредактируем его следующим образом:

auth 2
2 sha1 your-strong-password


Отредактируем файл /etc/ha.d/ha.cf в соответствии с нашей конфигурацией. Файл должен быть идентичным на обоих узлах.

logfile /var/log/ha-log #куда писать лог
logfacility local0
keepalive 2 #как часто опрашивать хосты, в секундах
deadtime 10 #через какое время хост признается умершим
initdead 120
bcast eth0
udpport 694
auto_failback on
node apache-app1
node apache-app2


Отредактируем файл /etc/ha.d/haresources. Файл должен быть идентичным на обоих узлах.

apache-app1 192.168.8.220 apache2 #общий адрес для обращения приложений к нашему web-приложению

Все готово. Осталось только рестартовать службы на обоих серверах (сначала на apache-app1, а потом apache-app2).

/etc/init.d/heartbeat restart

Установка wordpress.
Wordpress устанавливаем на оба web-сервера и настраиваем одинаково. Подробная инструкция по установке есть на официальном сайте. Здесь привожу параметры из файла wp-config.php для подключения к созданной нами ранее базе.

/** Имя базы данных для WordPress */
define(’DB_NAME’, ’wp_database’);
/** Имя пользователя MySQL */
define(’DB_USER’, ’wp_user’);
/** Пароль пользователя MySQL */
define(’DB_PASSWORD’, ’wp_user_password’);
/** Адрес сервера MySQL */
define(’DB_HOST’, ’192.168.8.223′);


Все готово. Для обращения к wordpress используем адрес 192.168.8.220/имя_узла_wordpress

Updated.
Создадим start-up скрипт для запуска служб mysql-proxy с использованием конфигурационного файла. Для начала создадим каталог для хранения конфига.

mkdir /etc/mysql-proxy

В созданном каталоге создадим файл mysql-proxy.conf. Содержимое моего фала:

#########################################
# Service configuration section
# Specify backend MySQL servers (one per line)
#########################################
proxy-backend-addresses = 192.168.8.226
proxy-backend-addresses = 192.168.8.227
#########################################
# Port configuration section
#########################################
proxy-address = :3306


Теперь создадим файл mysql-proxy в /etc/init.d/ со следующим содержимым:

#!/usr/bin/perl -w
$appPath='mysql-proxy ';
#Path for configuration file. Modify if different.
$configFileName='/etc/mysql-proxy/mysql-proxy.conf';
chomp($input=lc($ARGV[0]));
if ($input eq 'start')
{
open(CONFIG, "$configFileName")||die "File open error!: $!\n";
while (){push (@fileStrings, $_);}
close(CONFIG);
chomp(@addresses = grep {/^\s*proxy-backend-addresses\s*=/i} @fileStrings);
foreach (@addresses)
{
($parameter,$value)=split(/=/);
$parameter =~ s/\s+//g;
$value =~ s/\s+//g;
$appPath=$appPath."--".$parameter."=".$value." ";
}
chomp(@addresses = grep {/^\s*proxy-address\s*=/i} @fileStrings);
@addresses= split(/=/,$addresses[0]);
$addresses[1] =~ s/\s+//g;
$appPath=$appPath."--proxy-address=".$addresses[1]." --daemon";
print "Starting mysql-proxy...\n";
system($appPath);
print "Done!\n";
}
else
{
if ($input eq 'stop')
{
print "Trying to kill mysql-proxy...\n";
system ('killall mysql-proxy');
print "Done!\n";
}
else {print "Usage: /etc/init.d/mysql-proxy start|stop\n";}
}


Ссылки по теме:
1. High Availability Apache on Ubuntu 8.04
2. Load-balanced highly available MySQL on Ubuntu 8.04
3. High Availability MySQL on Ubuntu 8.04
4. MySQL Failover
5. How to quickly setup a load balanced, high availability, Apache cluster
6. ApacheMySQLPHP
Теги:
Хабы:
+27
Комментарии 34
Комментарии Комментарии 34

Публикации

Истории

Ближайшие события

Московский туристический хакатон
Дата 23 марта – 7 апреля
Место
Москва Онлайн
Геймтон «DatsEdenSpace» от DatsTeam
Дата 5 – 6 апреля
Время 17:00 – 20:00
Место
Онлайн
PG Bootcamp 2024
Дата 16 апреля
Время 09:30 – 21:00
Место
Минск Онлайн
EvaConf 2024
Дата 16 апреля
Время 11:00 – 16:00
Место
Москва Онлайн