Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Max connections, stats refresh and weighted backends #29

Open
wants to merge 6 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
# Changelog

## 2022-08-25
- Add `MAXCONN` environment variable to limit max connection among backends (default to `0` - unlimited) [sauzher]
- Add `STATS_REFRESH` environment variable to enable auto refresh. (default to `0` - no refresh) [sauzher]
- Add optional weight parameter for remote backends `host:port:weight` (default to `1` - all same weight) [sauzher]

## 2021-06-14 (1.8-1.7)

- Upgrade HAProxy to 1.8.30
Expand Down
14 changes: 10 additions & 4 deletions haproxy/Readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -74,19 +74,24 @@ that served the page changes, as HAProxy switches between them.
The stats page can be accessed at http://localhost:1936 where you have to log in
using the `STATS_AUTH` authentication details (default `admin:admin`).

You may want to set `STATS_REFRESH` option to let the statistics page auto update
i.e `STATS_REFRESH="5s"` to update every five seconds (default `0s`: no refresh)

Note that it may take **up to one minute** until backends are plugged-in due to the
minimum possible `DNS_TTL`.


### Run with backends specified as environment variable

$ docker run --env BACKENDS="192.168.1.5:80 192.168.1.6:80" eeacms/haproxy
or
$ docker run --env BACKENDS="192.168.1.5:80:4 192.168.1.6:80:1" eeacms/haproxy

Using the `BACKENDS` variable is a way to quick-start the container.
The servers are written as `server_ip:server_listening_port`,
The servers are written as `server_ip:server_listening_port:weight`,
separated by spaces (and enclosed in quotes, to avoid issues).
The contents of the variable are evaluated in a python script that writes
the HAProxy configuration file automatically.
the HAProxy configuration file automatically. `weight` is optional and defaulted to `1`

If there are multiple DNS records for one or more of your `BACKENDS` (e.g. when deployed using rancher-compose),
you can use `DNS_ENABLED` environment variable. This way, haproxy will load-balance
Expand Down Expand Up @@ -128,6 +133,7 @@ either when running the container or in a `docker-compose.yml` file.

* `STATS_PORT` The port to bind statistics to - default `1936`
* `STATS_AUTH` The authentication details (written as `user:password` for the statistics page - default `admin:admin`
* `STATS_REFRESH` Refresh timing for the statistics page - default `0s` (no refresh)
* `FRONTEND_NAME` The label of the frontend - default `http-frontend`
* `FRONTEND_PORT` The port to bind the frontend to - default `5000`
* `FRONTEND_MODE` Frontend mode - default `http` or `BACKENDS_MODE` if declared
Expand All @@ -136,7 +142,7 @@ either when running the container or in a `docker-compose.yml` file.
* `COOKIES_NAME` Will be added on cookie declaration - default `SRV_ID`
* `COOKIES_PARAMS` Will be added on cookie declaration - example `indirect nocache maxidle 30m maxlife 8h` or `maxlife 24h` - documentation https://cbonte.github.io/haproxy-dconv/1.8/configuration.html#4-cookie
* `BACKEND_NAME` The label of the backend - default `http-backend`
* `BACKENDS` The list of `server_ip:server_listening_port` to be load-balanced by HAProxy, separated by space - by default it is not set
* `BACKENDS` The list of `server_ip:server_listening_port:weight` to be load-balanced by HAProxy, separated by space - by default it is not set - by default weight is 1
* `BACKENDS_PORT` Port to use when auto-discovering backends, or when `BACKENDS` are specified without port - by default `80`
* `BACKENDS_MODE` Backends mode - default `http` or `FRONTEND_MODE` if declared
* `BALANCE` The algorithm used for load-balancing - default `roundrobin`
Expand All @@ -151,12 +157,12 @@ either when running the container or in a `docker-compose.yml` file.
* `HTTPCHK` The HTTP method and uri used to check on the servers health - default `HEAD /`
* `HTTPCHK_HOST` Host Header override on http Health Check - default `localhost`
* `INTER` parameter sets the interval between two consecutive health checks. If not specified, the default value is `2s`
* `MAXCONN` parameter sets the maximum number of connection that each backend will accept and, by default, is set to `0` (no limit)
* `FAST_INTER` parameter sets the interval between two consecutive health checks when the server is any of the transition state (read above): UP - transitionally DOWN or DOWN - transitionally UP. If not set, then `INTER` is used.
* `DOWN_INTER` parameter sets the interval between two consecutive health checks when the server is in the DOWN state. If not set, then `INTER` is used.
* `RISE` number of consecutive valid health checks before considering the server as UP. Default value is `2`
* `FALL` number of consecutive invalid health checks before considering the server as DOWN. Default value is `3`


## Logging

By default the logs from haproxy are present in the docker log, by using the rsyslog inside the container (UDP port 514). No access logs are present by default, but this can be changed by setting the log level.
Expand Down
2 changes: 2 additions & 0 deletions haproxy/docker-entrypoint.sh
Original file line number Diff line number Diff line change
Expand Up @@ -51,9 +51,11 @@ if ! test -e /usr/local/etc/haproxy/haproxy.cfg; then
if [ -n "$LOG_LEVEL" ]; then echo "export LOG_LEVEL=\"$LOG_LEVEL\"" >> /etc/environment; fi
if [ -n "$PROXY_PROTOCOL_ENABLED" ]; then echo "export PROXY_PROTOCOL_ENABLED=\"$PROXY_PROTOCOL_ENABLED\"" >> /etc/environment; fi
if [ -n "$RISE" ]; then echo "export RISE=\"$RISE\"" >> /etc/environment; fi
if [ -n "$MAXCONN" ]; then echo "export MAXCONN=\"$MAXCONN\"" >> /etc/environment; fi
if [ -n "$SERVICE_NAMES" ]; then echo "export SERVICE_NAMES=\"$SERVICE_NAMES\"" >> /etc/environment; fi
if [ -n "$STATS_AUTH" ]; then echo "export STATS_AUTH=\"$STATS_AUTH\"" >> /etc/environment; fi
if [ -n "$STATS_PORT" ]; then echo "export STATS_PORT=\"$STATS_PORT\"" >> /etc/environment; fi
if [ -n "$STATS_REFRESH" ]; then echo "export STATS_REFRESH=\"$STATS_REFRESH\"" >> /etc/environment; fi
if [ -n "$TIMEOUT_CLIENT" ]; then echo "export TIMEOUT_CLIENT=\"$TIMEOUT_CLIENT\"" >> /etc/environment; fi
if [ -n "$TIMEOUT_CONNECT" ]; then echo "export TIMEOUT_CONNECT=\"$TIMEOUT_CONNECT\"" >> /etc/environment; fi
if [ -n "$TIMEOUT_SERVER" ]; then echo "export TIMEOUT_SERVER=\"$TIMEOUT_SERVER\"" >> /etc/environment; fi
Expand Down
20 changes: 15 additions & 5 deletions haproxy/src/configure.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
PROXY_PROTOCOL_ENABLED = (os.environ.get('PROXY_PROTOCOL_ENABLED', 'false').lower() == "true")
STATS_PORT = os.environ.get('STATS_PORT', '1936')
STATS_AUTH = os.environ.get('STATS_AUTH', 'admin:admin')
STATS_REFRESH = os.environ.get('STATS_REFRESH', '0s')
BACKENDS = os.environ.get('BACKENDS', '').split(' ')
BACKENDS_PORT = os.environ.get('BACKENDS_PORT', '80')
BACKENDS_MODE = os.environ.get('BACKENDS_MODE', FRONTEND_MODE)
Expand All @@ -35,6 +36,7 @@
DOWN_INTER = os.environ.get('DOWN_INTER', INTER)
RISE = os.environ.get('RISE', '2')
FALL = os.environ.get('FALL', '3')
MAXCONN = os.environ.get('MAXCONN', '2')


listen_conf = Template("""
Expand All @@ -44,6 +46,7 @@
stats uri /
stats hide-version
stats auth $auth
stats refresh $refresh
""")

frontend_conf = Template("""
Expand All @@ -62,7 +65,7 @@
backend $backend
mode $mode
balance $balance
default-server inter $inter fastinter $fastinter downinter $downinter fall $fall rise $rise
default-server inter $inter fastinter $fastinter downinter $downinter fall $fall rise $rise maxconn $maxconn
cookie $cookies_name insert $cookies_params
""")
cookies = "cookie \\\"@@value@@\\\""
Expand All @@ -74,7 +77,7 @@
backend $backend
mode $mode
balance $balance
default-server inter $inter fastinter $fastinter downinter $downinter fall $fall rise $rise
default-server inter $inter fastinter $fastinter downinter $downinter fall $fall rise $rise maxconn $maxconn
cookie $cookies_name prefix $cookies_params
""")
cookies = ""
Expand All @@ -87,7 +90,7 @@
""")

backend_conf_plus = Template("""
server $name-$index $host:$port $cookies check
server $name-$index $host:$port $cookies check weight $weight
""")

health_conf = """
Expand All @@ -105,7 +108,8 @@
fall=FALL,
rise=RISE,
cookies_name=COOKIES_NAME,
cookies_params=COOKIES_PARAMS
cookies_params=COOKIES_PARAMS,
maxconn=MAXCONN
)

if BACKENDS_MODE == 'http':
Expand Down Expand Up @@ -142,6 +146,7 @@
index=ip.replace(".", "-"),
host=ip,
port=port,
weight=1,
cookies=cookies.replace('@@value@@', ip))

################################################################################
Expand All @@ -153,11 +158,13 @@
server_port = backend_server.split(':')
host = server_port[0]
port = server_port[1] if len(server_port) > 1 else BACKENDS_PORT
weight = server_port[2] if len(server_port) > 2 else 1
backend_conf += backend_conf_plus.substitute(
name=host.replace(".", "-"),
index=index,
host=host,
port=port,
weight=weight,
cookies=cookies.replace('@@value@@', host))

################################################################################
Expand Down Expand Up @@ -208,6 +215,7 @@
index=index,
host=host_ip,
port=host_port,
weight=1,
cookies=cookies.replace('@@value@@', host_ip)
)
index += 1
Expand Down Expand Up @@ -235,7 +243,9 @@

configuration.write(
listen_conf.substitute(
port=STATS_PORT, auth=STATS_AUTH
port=STATS_PORT,
auth=STATS_AUTH,
refresh=STATS_REFRESH
)
)

Expand Down