Hey,
This is a quick post for those who might need to perform HTTP health checks against a running HAProxy instance.
From my perspective, three ways of doing it:
- using the
monitor-uri
directive (you should use this one); - using a custom HTTP file with
errorfile
directive; - using a lua script.
While the first and seconds should work in any HAProxy installation, the third requires lua
, which your HAProxy binary might have support or not.
ps.: In the past, I wrote about how to install haproxy with Lua on MacOS.
The gist of it can be summarized in a single haproxy.conf
file that contains three frontends - each representing a way of doing it.
# This configuration demonstrates how several frontends
# can be created in different ways to indicate
# via HTTP that the HAProxy instance is running.
#
# The usefulness of these arise in scenarios like
# AWS NLB where no TCP health check can be specified
# and you can't modify the health check headers.
global
lua-load ./script.lua
defaults
mode http
timeout client 10000
timeout server 10000
timeout connect 1000
# The first way of doing it is via lua scripting:
# a script (which registers a service) is loaded
# and then when a request is made to a frontend
# with the directive `use-service`, the script
# does the job of responding with 200OK.
frontend status-lua
bind 127.0.0.1:8000
http-request use-service lua.status_service
# The second way is using `monitor-uri` (the
# proper way of doing since you can make the
# monitor fail in other parts of the configuration
# and there's no lua involved).
frontend status-monitor
bind 127.0.0.1:8001
monitor-uri /
#
# The third way is using a "hack": setting errorfile
# to respond with a 200OK when a 503 happens, we're
# able to indicate that HAProxy is active.
frontend status-errorfile
bind 127.0.0.1:8002
http-request set-log-level silent
errorfile 503 ./200.http
With that, we now need to tailor a script.lua
file that defines the status_service
that is used by the first frontend:
-- `core` is a static class provided by haproxy containing all
-- the haproxy methods we can use.
-- `register_init` registers a function to be executed after
-- configuration parsing.
core.register_init(function ()
core.log(core.info, "script loaded: case-200-ok")
end)
-- `register_service` registers a lua function to be executed
-- as a service. Once it's been properly registered, the service
-- can be referenced in the haproxy configuration as `lua.<svc_name>`.
--
-- Depending on the mode (tcp or http), the applet is either an
-- AppletHTTP or AppletTCP class instance.
core.register_service("status_service", "http", function (applet)
local response = "OK"
applet:set_status(200)
applet:start_response()
applet:send(response)
end)
And then, for the last frontend, tailor a 200.http
file:
HTTP/1.0 200 OK
Cache-Control: no-cache
Connection: close
Content-Type: text/plain
User-Agent: *
Allow: /
ps.: given that we’re defining the whole HTTP message, it must end with carriege return and line feed (\r\n
).
That’s it!
Load haproxy.conf
and you’re good to go.
If you have any doubts or spotted any mistakes, please let me know! I’m cirowrc on Twitter.
Have a good one!
finis