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