📜 ⬆️ ⬇️

Highly available, fault-tolerant web application on Apache2 and MySQL

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:
ServerIP address
apache-app1192.168.8.221
apache-app2192.168.8.222
mysql-proxy1192.168.8.224
mysql-proxy2192.168.8.225
mysql-data1192.168.8.226
mysql-data2192.168.8.227

')
Additionally, we will need two more ip-addresses:
IP addressPurpose
192.168.8.220Address for client access to the web-application
192.168.8.223Address 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

Source: https://habr.com/ru/post/104342/


All Articles