Return HTTP status codes based on an arbitrary script

3 min read

Sometimes we need a way of telling using a HTTP endpoint the "readiness" of the service but the service does not provide any of this: For example, a MySQL replica that we need to get in and out of the pool depending on how "lagged" it is, or a worker node that we want to remove from that pool depending on it's CPU usage...

If we have a command that will tell us whether the service is ready to accept connections, we can use healthcheckd to create a HTTP endpoint to publish it.

This tool is something that we can install easily on any server or container, the only dependencies are pid (for handling the creation of a PIDfile) and configparser (to read the ini config file). It uses python's http.server to handle the HTTP requests.

To configure it we just need to create a config file with the command we want to use, for example if we use the following command that will return 0 only if the last digit of the bash's RANDOM variable is greater than 5:

test ${RANDOM: -1} -ge 5

We can configure it like so:

[healthcheckd]

pidfile = demo.pid
port = 9999
command = "test ${RANDOM: -1} -ge 5"

And finally run the webserver using this config

python3 healthcheckd.py ./random_example.config

Now we we use run curl to localhost using the configured port we will get a different result depending the value of the RANDOM variable:

$ curl -I localhost:9999
HTTP/1.0 200 OK
Server: BaseHTTP/0.6 Python/3.8.10
Date: Tue, 26 Oct 2021 15:41:04 GMT
Content-type: text/html

$ curl -I localhost:9999
HTTP/1.0 503 Service Unavailable
Server: BaseHTTP/0.6 Python/3.8.10
Date: Tue, 26 Oct 2021 15:41:05 GMT
Content-type: text/html

$ curl -I localhost:9999
HTTP/1.0 200 OK
Server: BaseHTTP/0.6 Python/3.8.10
Date: Tue, 26 Oct 2021 15:41:06 GMT
Content-type: text/html

$ curl -I localhost:9999
HTTP/1.0 503 Service Unavailable
Server: BaseHTTP/0.6 Python/3.8.10
Date: Tue, 26 Oct 2021 15:41:06 GMT
Content-type: text/html

$ curl -I localhost:9999
HTTP/1.0 503 Service Unavailable
Server: BaseHTTP/0.6 Python/3.8.10
Date: Tue, 26 Oct 2021 15:41:07 GMT
Content-type: text/html

(...)

To have a health endpoint we just need to change the script to run to something that returns 0 when we want to accept connections or any other return code when we don't.


Posted on 27/10/2021

Categories