Fault-tolerant architecture separates systems into identical, independent stacks. Load balancers like NGINX are employed to distribute load, ensuring that what’s provisioned is utilized. The core concepts of high availability are load balancing over multiple active nodes or an active-passive failover. Highly available applications have no single points of failure; every component must use one of these concepts, including the load balancers themselves. For us, that means NGINX. NGINX is designed to work in either configuration: multiple active or active-passive failover. This chapter details techniques on how to run multiple NGINX servers to ensure high availability in your load-balancing tier.
The nginx-ha-keepalived
package is based on keepalived and manages a virtual IP address exposed to the client. Another process is run on the NGINX server that ensures that NGINX Plus and the keepalived process are running. Keepalived is a process that utilizes the Virtual Router Redundancy Protocol (VRRP), sending small messages, often referred to as heartbeats, to the backup server. If the backup server does not receive the heartbeat for three consecutive periods, the backup server initiates the failover, moving the virtual IP address to itself and becoming the primary. The failover capabilities of nginx-ha-keepalived
can be configured to identify custom failure situations.
Use DNS to round robin across NGINX servers by adding multiple IP addresses to a DNS A record.
When running multiple load balancers, you can distribute load via DNS. The A record allows for multiple IP addresses to be listed under a single FQDN. DNS will automatically round robin across all the IPs listed. DNS also offers weighted round robin with weighted records, which works in the same way as weighted round robin in NGINX as described in Chapter 2. These techniques work great. However, a pitfall can be removing the record when an NGINX server encounters a failure. There are DNS providers—Amazon Route 53 for one, and Dyn DNS for another—that offer health checks and failover with their DNS offering, which alleviates these issues. If you are using DNS to load balance over NGINX, when an NGINX server is marked for removal, it’s best to follow the same protocols that NGINX does when removing an upstream server. First, stop sending new connections to it by removing its IP from the DNS record, then allow connections to drain before stopping or shutting down the service.
Put NGINX behind an AWS NLB by configuring an Auto Scaling group of NGINX servers and linking the Auto Scaling group to a target group and then attach the target group to the NLB. Alternatively, you can place NGINX servers into the target group, manually by using the AWS console, command-line interface, or API.
The HA solution from NGINX Plus based on keepalived will not work on AWS because it does not support the floating virtual IP address, since EC2 IP addresses work in a different way. This does not mean that NGINX can’t be HA in the AWS cloud; in fact, the opposite is true. The AWS NLB is a product offering from Amazon that will natively load balance over multiple, physically separated data centers called availability zones, provide active health checks, and a DNS CNAME endpoint. A common solution for HA NGINX on AWS is to put an NGINX layer behind the NLB. NGINX servers can be automatically added to and removed from the target group as needed. The NLB is not a replacement for NGINX; there are many things NGINX offers that the NLB does not, such as multiple load-balancing methods, rate limiting, caching, and Layer 7 routing. The AWS ALB does perform Layer 7 load balancing based on the URI path and host header, but it does not by itself offer features that NGINX does, such as WAF caching, bandwidth limiting, HTTP/2 server push, and more. In the event that the NLB does not fit your need, there are many other options. One option is the DNS solution: Route 53 from AWS offers health checks and DNS failover.
Use the NGINX Plus exclusive configuration synchronization feature. To configure this feature, follow these steps:
Install the nginx-sync
package from the NGINX Plus package repository.
$
sudo yum install nginx-sync
$
sudo apt-get install nginx-sync
Grant the primary machine SSH access as root to the peer machines.
Generate an SSH authentication key pair for root, and retrieve the public key:
$
sudo ssh-keygen -t rsa -b 2048$
sudo cat /root/.ssh/id_rsa.pub ssh-rsa AAAAB3Nz4rFgt...vgaD root@node1
Get the IP address of the primary node:
$ ip addr 1: lo: mtu 65536 qdisc noqueue state UNKNOWN group default link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00 inet 127.0.0.1/8 scope host lo valid_lft forever preferred_lft forever inet6 ::1/128 scope host valid_lft forever preferred_lft forever 2: eth0: mtu 1500 qdisc pfifo_fast state UP group default qlen 1000 link/ether 52:54:00:34:6c:35 brd ff:ff:ff:ff:ff:ff inet 192.168.1.2/24 brd 192.168.1.255 scope global eth0 valid_lft forever preferred_lft forever inet6 fe80::5054:ff:fe34:6c35/64 scope link valid_lft forever preferred_lft forever
The ip addr
command will dump information about interfaces on the machine. Disregard the loopback interface, which is normally the first. Look for the IP address following inet
for the primary interface. In this example, the IP address is 192.168.1.2
.
Distribute the public key to the root user’s authorized_keys
file on each peer node, and specify to authorize only from the primary IP address:
$ sudo echo ‘from=”192.168.1.2" ssh-rsa AAAAB3Nz4rFgt...vgaD root@node1' >> /root/.ssh/authorized_keys
Add the following line to /etc/ssh/sshd_config and reload sshd
on all nodes:
$ sudo echo 'PermitRootLogin without-password' >> /etc/ssh/sshd_config $ sudo service sshd reload
Verify that the root user on the primary node can ssh
to each of the peer nodes without a password:
$ sudo ssh [email protected]
Create the configuration file /etc/nginx-sync.conf on the primary machine with the following configuration:
NODES="node2.example.com node3.example.com node4.example.com" CONFPATHS="/etc/nginx/nginx.conf /etc/nginx/conf.d" EXCLUDE="default.conf"
This example configuration demonstrates the three common configuration parameters for this feature: NODES
, CONFIGPATHS
, and EXCLUDE
. The NODES
parameter is set to a string of hostnames or IP addresses separated by spaces; these are the peer nodes to which the primary will push its configuration changes. The CONFIGPATHS
parameter denotes which files or directories should be synchronized. Lastly, you can use the EXCLUDE
parameter to exclude configuration files from synchronization. In our example, the primary pushes configuration changes of the main NGINX configuration file and includes the directory /etc/nginx/nginx.conf and /etc/nginx/conf.d to peer nodes named node2.example.com
node3.example.com
and node4.example.com
. If the synchronization process finds a file named default.conf, it will not be pushed to the peers, because it’s configured as an EXCLUDE
.
There are advanced configuration parameters to configure the location of the NGINX binary, RSYNC binary, SSH binary, diff binary, lockfile location, and backup directory. There is also a parameter that utilizes sed
to template-given files. For more information about the advanced parameters, see Configuration Sharing.
Test your configuration:
$
nginx-sync.sh -h# display usage info
$
nginx-sync.sh -c node2.example.com# compare config to node2
$
nginx-sync.sh -C# compare primary config to all peers
$
nginx-sync.sh# sync the config & reload NGINX on peers
This NGINX Plus exclusive feature enables you to manage multiple NGINX Plus servers in an HA configuration by updating only the primary node and synchronizing the configuration to all other peer nodes. By automating the synchronization of configuration, you limit the risk of mistakes when transferring configurations. The nginx-sync.sh
application provides some safeguards to prevent sending bad configurations to the peers. They include testing the configuration on the primary, creating backups of the configuration on the peers, and validating the configuration on the peer before reloading. Although it’s preferable to synchronize your configuration by using configuration management tools or Docker, the NGINX Plus configuration synchronization feature is valuable if you have yet to make the big leap to managing environments in this way.
18.224.95.38