⬆️ ⬇️

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