HA-Apache2 Web-Site and HA-MySQL
Objective: To ensure high availability of the web application and minimal downtime if one of the web server and the database server fails.
Comment! The scheme assumes that the web application and the database are on different servers.
For example, we will install wordpress.
Solution option:
Since the web application must be constantly available, you need at least two servers with the installed application. Servers will monitor each other’s status, while at the same time only one of them will lead. In case of failure of the leading server, its role takes the second. When the first server is available again, the role of the leader will be returned to it again.
Because To ensure database resiliency, at least two servers will be used, then we will use one virtual IP address to access them, which we will use to configure our web application. In this case, the failure of one of the servers does not affect the performance of the web server, since it will continue to work with the backup server base. To synchronize the databases on the primary and backup servers, we will use the bidirectional replication mechanism (“master-master”). To increase the level of security and balance requests from a web application, add two proxy servers to the architecture. Servers will listen to requests for port 3306 and distribute them between database servers. One of the servers will be leading. If the lead fails, the second server assumes its role (the principle is similar to the work of web servers).
System architecture:
We will use the following server names and ip-addresses:
Server | IP address |
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 |
')
Additionally, we will need two more ip-addresses:
IP address | Purpose |
192.168.8.220 | Address for client access to the web-application |
192.168.8.223 | Address for accessing the MySQL database |
Comment! All systems used in this manual are running Ubuntu Server 8.04 LTS with an OpenSSH server installed.
First of all, let's start setting up database servers (mysql-data1 and mysql-data2).
Comment! All actions are performed from the superuser.
We put the necessary components on both servers. We need a mysql server. During installation, enter a strong password for the root user.
apt-get install mysql-server --yes
Go to the setting. To begin, we will configure our servers so that they listen to requests to the MySQL server from the network. To do this, edit the file /etc/mysql/my.cnf. It is necessary to find the string bind-address = 127.0.0.1 and replace it with
bind-address=192.168.8.226
for the mysql-data1 server and
bind-address=192.168.8.227
for mysql-data2 server
Restarting the service:
/etc/init.d/mysql restart
Go to setting up replication.
With unidirectional replication (“master-slave”), if data is written to a subordinate database, the data may be inconsistent, which can lead to a replication error. In the case of bidirectional replication, the databases will be in a consistent state.
For replication, we will use a MySQL replication user with the password some_password.
On the mysql-data1 server, edit the /etc/mysql/my.cnf file. Insert the following lines into the section related to replication:
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
We go into MySQL as root and give the replication user the right to connect to our server from the mysql-data2 server:
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
Go to the server mysql-data2.
Edit the file /etc/mysql/my.cnf. Insert the following lines into the section related to replication:
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
We go into MySQL as root and give the replication user the right to connect to our server from the mysql-data1 server:
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
On both servers, we verify that the replication process is running. To do this, perform the following:
mysql —u root —p
Enter password: root,
>show slave status \G
In the output, we are interested in three parameters:
Slave_IO_State: Waiting for master to send event
Slave_IO_Running: Yes
Slave_SQL_Running: Yes
If the specified parameters on both servers correspond to the above, then everything is fine, replication is configured. If not, look at the logs.
Let's create a database for our application. On the mysql-data1 server, do the following:
mysql —u root —p
Enter password: root,
>create database wp_database;
Go to the server mysql-data2 and check that the database has replicated to this server:
mysql —u root —p
Enter password: root,
>show databases;
The output should contain the name of the database we created earlier.
Configure access rights to this database by proxying servers. On both servers, do the following:
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;
Go to setting up balancing and mysql-proxy.
On the servers mysql-proxy1 and mysql-proxy2, we install the necessary components (hereinafter, all commands are executed on behalf of the superuser).
apt-get install mysql-proxy heartbeat
We start the mysql-proxy service on both servers. In the startup parameters we specify the IP addresses of the servers mysql-data1 and mysql-data2:
mysql-proxy --proxy-backend-addresses=192.168.8.226 \
--proxy-backend-addresses=192.168.8.227 \
--proxy-address=:3306
—daemon
Moving on to setting up high availability based on heartbeat on both servers.
Create the necessary files:
touch /etc/ha.d/authkeys
touch /etc/ha.d/ha.cf
touch /etc/ha.d/haresources
Set security parameters to the /etc/ha.d/authkeys file
chmod 600 /etc/ha.d/authkeys
And edit it as follows:
auth 2
2 sha1 your-strong-password
Edit the /etc/ha.d/ha.cf file according to our configuration. The file must be identical on both nodes.
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
Comment! The node parameter must match the output of the uname -n command on both nodes!
Edit the /etc/ha.d/haresources file. The file must be identical on both nodes.
mysql-proxy1 192.168.8.223 # MySQL
All is ready. It remains only to restart the service on both servers (first on mysql-proxy1, and then mysql-proxy2).
/etc/init.d/heartbeat restart
We are starting to configure apache-app1 and apache-app2 web servers.
Install the necessary components.
apt-get install apache2 php5 php5-gd php5-mysql libapache2-mod heartbeat --yes
Go to the failover setting.
Create the necessary files:
touch /etc/ha.d/authkeys
touch /etc/ha.d/ha.cf
touch /etc/ha.d/haresources
Set security parameters to the /etc/ha.d/authkeys file
chmod 600 /etc/ha.d/authkeys
And edit it as follows:
auth 2
2 sha1 your-strong-password
Edit the /etc/ha.d/ha.cf file according to our configuration. The file must be identical on both nodes.
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
Edit the /etc/ha.d/haresources file. The file must be identical on both nodes.
apache-app1 192.168.8.220 apache2 # web-
All is ready. It remains only to restart the services on both servers (first on apache-app1, and then apache-app2).
/etc/init.d/heartbeat restart
Install wordpress.
We install Wordpress on both web-servers and configure them in the same way. Detailed installation instructions are on the official site. Here I provide the parameters from the wp-config.php file for connecting to the database we created earlier.
/** 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′);
All is ready. For the appeal to wordpress we use the address
192.168.8.220/name_word_wordpress
Updated.
Create a start-up script to start the mysql-proxy services using the configuration file. To begin, create a directory for storing the config.
mkdir / etc / mysql-proxy
In the created directory, create the file mysql-proxy.conf. Content of my file:
#########################################
# 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
Now create a mysql-proxy file in /etc/init.d/ with the following contents:
#!/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";}
}
Related Links:
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.
Apache cluster
6.
ApacheMySQLPHP