Properly testing your HAProxy configuration file is a simple, yet crucial part of administering your load balancer. Remembering to run one simple command after making a change to your configuration file can save you from unintentionally stopping your load balancer and bringing down your services.
For the impatient, here’s a simple command to test a configuration file:
$ haproxy -f /path/to/haproxy.cfg -c |
The flag ‘-c
‘, enables “check mode” and is the flag that tells HAProxy to test, without actually starting or restarting HAProxy.
#Tell Me More
How is this different from using the configuration check that’s built into the systemd reload command?
Invoking HAProxy in check mode has no effect upon the load balancer’s state. If your HAProxy is not running, testing the file in this manner will not start it, even momentarily. If your load balancer is running, it will not interrupt it. This lets you perform ad hoc tests of changes you’d like to make, without interfering with or interrupting your services.
Let’s look at what happens when you use the different ways systemd starts and restarts HAProxy:
$ sudo systemctl start haproxy | On startup, the HAProxy process reads your configuration file one time and stores its parameters in memory. After that, it doesn’t touch the file again until you tell it to. Not needing to refer to the file on disk lets HAProxy run incredibly fast. | |
$ sudo systemctl restart haproxy | HAProxy stops immediately, killing any active connections. It then attempts to start HAProxy with the specified configuration file. If that file has errors, HAProxy will not start. This is probably not what you want to happen. | |
$ sudo systemctl reload haproxy | Hitless reloads let the active connections gracefully finish using the old configuration while bringing up new connections with the new config. If you attempt a reload with a broken config, it will give an error, but will not interrupt the previously running service. | |
$ sudo systemctl stop haproxy | HAProxy stops. The configuration file is not read. |
Getting into the habit of using hitless reloads when you roll in a new config goes a long way towards avoiding unintended interruptions, but having check mode at your disposal adds a layer of fine-grained control, especially if you are incorporating external scripts.
#Calling HAProxy Directly
Any user can start an HAProxy process to create a load balancer, as long as the configuration file isn’t trying to access any privileged ports, files, or sockets. Let’s create a configuration with a simple typo, to see what HAProxy does when it encounters an error.
Paste the following into a file called test.cfg in your server’s /tmp directory:
defaults | |
mode http | |
timeout client 10000ms | |
timeout connect 3000ms | |
timeout server 10000ms | |
frontend fe_test | |
bind *:8080 | |
default_backend be_test | |
backend be_test | |
server my_server 127.0.0.1:8000 chekc |
Test this with:
$ haproxy -f /tmp/test.cfg -c |
You’ll get the following error message:
[NOTICE] (14686) : haproxy version is 2.4.2-1ppa1~focal | |
[NOTICE] (14686) : path to executable is /usr/sbin/haproxy | |
[ALERT] (14686) : parsing [/tmp/test.cfg:12] : ‘server server1’ : unknown keyword ‘chekc’; did you mean ‘check’ maybe ?. | |
[ALERT] (14686) : Error(s) found in configuration file : /tmp/test.cfg | |
[ALERT] (14686) : Fatal errors found in configuration. | |
As you can see from the output, it tells you the line number of the first fatal error it encountered, [./haproxy.cfg:12], where it broke on “unknown keyword ‘chekc’”. Recent versions of HAProxy will even suggest a correction: “did you mean ‘check’ maybe?”
#Testing a Running Proxy’s Config
Testing a throwaway config is one thing, but when you make a change to a running service’s configuration file, how should you test it? The procedure is exactly the same:
$ haproxy -f /etc/haproxy/haproxy.cfg -c | |
Configuration file is valid |
This will have no effect on the running HAProxy process, as long as you have the check mode (-c) flag in place.