Operations 16 min read

Design and Implementation of a Two‑Node High Availability Architecture Using Keepalived, Nginx, MySQL, and Atlas

This article describes a complete two‑machine high‑availability solution that uses keepalived to manage virtual IPs, Nginx for load‑balancing, MySQL GTID replication with Atlas as a proxy, and detailed configuration and fail‑over testing steps to ensure seamless service continuity.

Art of Distributed System Architecture Design
Art of Distributed System Architecture Design
Art of Distributed System Architecture Design
Design and Implementation of a Two‑Node High Availability Architecture Using Keepalived, Nginx, MySQL, and Atlas

The author was asked to create a high‑availability architecture for only two servers, where if one machine fails the other automatically takes over, while both servers can serve traffic during normal operation.

Architecture Overview : keepalived provides dual‑machine HA by managing an external VIP and an internal VIP. Nginx on the active server handles static content locally and forwards dynamic PHP requests to both servers. SQL requests are routed through the Atlas MySQL‑proxy, which directs write operations to the internal VIP and read operations to the second server, achieving read/write separation.

Requirements :

Servers must support internal IP configuration and inter‑communication.

External IPs must be assignable without MAC binding.

MySQL version 5.6.5+ with GTID support.

Environment :

Server1: eth0 10.96.153.110 (external), eth1 192.168.3.100 (internal)

Server2: eth0 10.96.153.114 (external), eth1 192.168.3.101 (internal)

Both run CentOS‑6. VIPs: external 10.96.153.239, internal 192.168.3.150. Hosts file maps the internal IPs to server names.

Nginx, PHP, MySQL Installation – recommended via EZHTTP (details omitted).

Nginx Configuration (Server1):

http {
    ...
    upstream php-server {
        server 192.168.3.101:9000;
        server 127.0.0.1:9000;
        keepalive 100;
    }
    ...
    server {
        ...
        location ~ \.php$ {
            fastcgi_pass   php-server;
            fastcgi_index  index.php;
            fastcgi_param  SCRIPT_FILENAME  $document_root$fastcgi_script_name;
            include        fastcgi_params;
        }
        ...
    }
    ...
}

Server2 uses the same block but swaps the internal IP in the upstream.

MySQL Configuration – install mysql‑utilities, enable GTID, set unique server‑id, enable binary logging, and grant remote root access:

grant all on *.* to 'root'@'192.168.3.%' identified by 'Xp29at5F37' with grant option;
grant all on *.* to 'root'@'server1' identified by 'Xp29at5F37' with grant option;
grant all on *.* to 'root'@'server2' identified by 'Xp29at5F37' with grant option;
flush privileges;

Set up master‑slave replication with mysqlreplicate and verify topology with mysqlrplshow and mysqlrplcheck .

Keepalived Installation & Configuration (both servers):

yum -y install keepalived chkconfig keepalived on

Server1 keepalived.conf (higher priority, nopreempt ):

vrrp_sync_group VG_1 {
    group { inside_network outside_network }
}

vrrp_instance inside_network {
    state BACKUP
    interface eth1
    virtual_router_id 51
    priority 101
    advert_int 1
    authentication { auth_type PASS; auth_pass 3489; }
    virtual_ipaddress { 192.168.3.150/24 }
    nopreempt
}

vrrp_instance outside_network {
    state BACKUP
    interface eth0
    virtual_router_id 50
    priority 101
    advert_int 1
    authentication { auth_type PASS; auth_pass 3489; }
    virtual_ipaddress { 10.96.153.239/24 }
    nopreempt
}

Server2 keepalived.conf (lower priority, notify_master runs fail‑over script):

vrrp_sync_group VG_1 { group { inside_network outside_network } }

vrrp_instance inside_network {
    state BACKUP
    interface eth1
    virtual_router_id 51
    priority 100
    advert_int 1
    authentication { auth_type PASS; auth_pass 3489; }
    virtual_ipaddress { 192.168.3.150 }
    notify_master /data/sh/mysqlfailover.sh
}

vrrp_instance outside_network {
    state BACKUP
    interface eth0
    virtual_router_id 50
    priority 100
    advert_int 1
    authentication { auth_type PASS; auth_pass 3489; }
    virtual_ipaddress { 10.96.153.239/24 }
}

Atlas (MySQL‑Proxy) Setup – download, install, and configure:

proxy-backend-addresses = 192.168.3.150:3306
proxy-read-only-backend-addresses = 192.168.3.101:3306
pwds = root:qtyU1btXOo074Itvx0UR9Q==
event-threads = 8

Start Atlas with:

/usr/local/mysql-proxy/bin/mysql-proxy --defaults-file=/usr/local/mysql-proxy/conf/my.cnf

Fail‑over Testing – shut down Server1, verify VIPs moved to Server2, check that MySQL replication role switched to master, and confirm that Server1 does not pre‑empt the VIP after reboot.

Recovery Procedure – when Server1 returns, demote Server2, promote Server1 using mysqlrpladmin , verify replication health, restart keepalived to move VIP back, and bring Atlas backends online with SET ONLINE 1; .

The article concludes with a disclaimer that the content is sourced from public channels and is provided for reference only.

High Availabilityload balancingLinuxNginxMySQL replicationKeepalivedAtlas
Art of Distributed System Architecture Design
Written by

Art of Distributed System Architecture Design

Introductions to large-scale distributed system architectures; insights and knowledge sharing on large-scale internet system architecture; front-end web architecture overviews; practical tips and experiences with PHP, JavaScript, Erlang, C/C++ and other languages in large-scale internet system development.

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.