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-uridirective (you should use this one);
- using a custom HTTP file with
- 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
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 (
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!