4 Setting Up Load Balancing by Using NGINX

This chapter describes how to configure NGINX as a load balancer and includes installation instructions and configuration directives. For an overview of NGINX, see About NGINX.

Installing NGINX

Before you can use NGINX for load balancing, you must first install the software and configure the environment.

  1. Install the nginx package on each server:

    sudo dnf install nginx

    Depending on the intended configuration, you might need to install more modules. The nginx-all-modules metapackage installs all of the packages. To display the complete listing of the available modules in the package manager, use the following command:

    sudo dnf search nginx-mod*

    Note that if you intend to do TCP/UDP load balancing, you must install the nginx-mod-stream module package.

  2. Enable access to the services or ports that you want NGINX to handle.

    For example, you would accept incoming TCP requests on port 80 as follows:

    sudo firewall-cmd --zone=zone --add-port=80/tcp
    sudo firewall-cmd --permanent --zone=zone --add-port=80/tcp
  3. If SELinux is set to enforcing mode on the system, add a rule to allow NGINX to relay HTTP traffic to any configured backend servers:

    sudo setsebool httpd_can_network_relay on
  4. Enable and start the nginx service on the server:

    sudo systemctl enable --now nginx

    If you change the NGINX configuration, reload the nginx service:

    sudo systemctl reload nginx

NGINX Configuration Directives

NGINX configuration can be spread across several files to specify different configuration directives and set the values for configuration variables. Configuration is stored in /etc/nginx. The base configuration is stored in /etc/nginx/nginx.conf, while site specific configuration tends to be created within distinct files in /etc/nginx/conf.d/. By convention, site configurations tend to use the full domain name for the file name and would have a .conf suffix.

In these examples, a configuration has the following general format:

http {
  server {
    listen 80;
    listen [::]:80;
    server_name example.com www.example.com;
    location / {
       root /usr/share/nginx/html/example.com;
       index index.html;
    }
  }
}

The previous example shows an HTTP server configuration for a web server that serves content from the web root directory at /usr/share/nginx/html/example.com.

The following configuration directives are useful for configuring load balancing:

http, https, stream

Defines the protocol for which the settings apply. Use https for TLS connections to the load balancer and stream for generic TCP/UDP traffic.

server

Defines how to handle incoming traffic from the specified ports for the chosen protocol.

To configure at least one listening port for IPv4, use the listen keyword:

listen 80;

To listen on IPv6 interfaces, prepend the [::]: directive to the port number, for example:

listen [::]:80

Note that the listen lines can be duplicated to specify more than one port for a server{} block.

Use the server_name keyword to define the hostname or domain name that the server responds to. If you don't specify this value, the configuration applies to any incoming connection, however you might need to comment out the default server configuration within /etc/nginx/nginx.conf to avoid conflicting configuration definitions.

location

The location directive defines path mappings and behavior, depending on incoming requests on the server. At minimum, you must have a value for the web root that's indicated with the value /. The behavior is defined by setting values within a location block.

For example, to configure a simple web server that serves content from a directory on the server, use the root keyword and specify the content's directory location.

The proxy_pass directive can be used to implement a reverse proxy service. Traffic is proxied onto the specified server or group of servers, as defined in an upstream directive.

For example, you would proxy inbound HTTP traffic to a website that's hosted on websrv1.example.com on port 9090 as follows:

server {
  location / {
    proxy_pass http://websvr1.example.com:9090
  }
}              

You can also specify a server group by referencing its defined upstream name.

upstream

An upstream directive is used to define a group of one or more servers where the content is stored and which can be used by the proxy_pass directive. For example, you can create an upstream group of servers called backend as follows:

upstream backend {
    server server1.example.com;
    server server2.example.com;
    server server3.example.com;
  }

To use this group, the proxy_pass directive is specified:

proxy_pass http://backend

The upstream directive is the key configuration component that's used to control load-balancing methods and algorithms. For more information, see http://nginx.org/en/docs/http/ngx_http_upstream_module.html.

Configuring Round Robin Load Balancing by Using NGINX

The default load balancing method that's used by NGINX is the round-robin method. This method proxies traffic sequentially to each server in a defined group.

Create a configuration file for the load-balancer at /etc/nginx/conf.d/example.com.conf, where example.com is the name of the external domain where inbound traffic is directed. The file would contain the following content:

http
{
  upstream backend {
    server server1.example.com;
    server server2.example.com;
    server server3.example.com;
  }

  server {
    listen 80;
    server_name example.com
                  www.example.com;
    location / {
      proxy_pass  http://backend;
    }
  }
}

In the upstream backend configuration block, list the backend servers within the environment. For example, substitute server1.example.com with the fully qualified domain name or the hostname of a web server instance.

Set the server_name directive with the domain name or names that you intend to use publicly for the load balanced service. For example, substitute example.com and www.example.com to match the company domain.

You can optionally append more failover options, such as max_fails and fail_timeout, to the end of each entry to add resilience in case any of the servers goes offline.

After ensuring that the configuration is valid, enable it by reloading NGINX on the public-facing and backend servers:

sudo systemctl reload nginx

Using Weighted Round Robin Load Balancing With NGINX

When using servers with varying physical locations or differing hardware resources, you can configure NGINX to allocate more of the traffic to servers that provide less latency and can handle more of a load. This method is referred to as the weighted round-robin method.

You can configure weighted round-robin configuration by appending a weight value to the end of each entry in the server group section of the NGINX site configuration file. Set the weight of the slowest server to 1, and then set the weight of other servers relative to that setting.

The following example shows how servers can handle multiple times the load of the base server. One server receives twice the amount of traffic, while the other server receives four times the amount:

upstream backend {
    server server1.example.com weight=1;
    server server2.example.com weight=2;
    server server3.example.com weight=4;
}      

Reload NGINX to apply the new configuration:

sudo systemctl reload nginx

Using Least-Connected Load Balancing With NGINX

The least-connected load balancing method is used to automatically control the load on application instances, mostly in situations where different inbound requests might take longer to process than other requests.

If you're using the least-connected load balancing method, NGINX always directs new incoming requests to the server with the least number of active requests. This load balancing strategy is intended to ensure that no busy servers are overloaded with new requests, while other servers that can handle the load remain idle.

You can activate the least-connected load balancing method for NGINX by specifying the least-conn directive as part of the server group configuration, for example:

upstream backend {
    least_conn;
    server server1.example.com;
    server server2.example.com;
    server server3.example.com;
}

Reload NGINX to apply the new configuration:

sudo systemctl reload nginx

Adding Session Persistence for NGINX

If you're performing load balancing of a web application, ensure that the same backend server that handled inbound requests continues to do so for the same source. This configuration is important in cases where a website or web service must preserve log-in sessions between requests, cancel an existing request, or monitor the progress of large backend transactions.

To achieve this behavior, activate the IP hash method for NGINX by specifying the ip_hash directive as part of the server group configuration, for example:

upstream backend {
    ip_hash;
    server server1.example.com;
    server server2.example.com;
    server server3.example.com;
}

Reload NGINX to apply the new configuration:

sudo systemctl reload nginx