From 589548b70ccdd4fecddbcc51e6b4c3a81db36036 Mon Sep 17 00:00:00 2001 From: Tristan PILAT Date: Thu, 9 Jan 2020 18:09:05 +0100 Subject: [PATCH] =?UTF-8?q?Ajout=20ajustement=20dynamique=20du=20poids=20e?= =?UTF-8?q?t=20des=20=C3=A9tats=20via=20agent-check?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- HowtoHaproxy.md | 86 ++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 85 insertions(+), 1 deletion(-) diff --git a/HowtoHaproxy.md b/HowtoHaproxy.md index 81d131d7..1e109f20 100644 --- a/HowtoHaproxy.md +++ b/HowtoHaproxy.md @@ -274,7 +274,9 @@ CREATE USER haproxy_check@IP_OF_HAPROXY; #### Mode avancé -La version avancée consiste à utiliser un check http pour déterminer l'état du serveur. +## Check HTTP + +Cela consiste à utiliser un check http pour déterminer l'état du serveur. ~~~ frontend fe_mysql @@ -352,6 +354,88 @@ On redémarre xinetd (surveiller `/var/log/syslog` pour d'éventuelles erreurs) Il est également possible d'utiliser tout programme ou script, pourvu qu'au final il puisse être accessible en HTTP. +## Ajustement dynamique + +Le propos est d'utiliser l'option `agent-check` pour pouvoir ajuster dynamiquement le poids ou les états des membres d'un backend. + +On utilisera ici `xinetd` pour pouvoir interroger la charge de chacun des membres à intervale régulier + +~~~ +frontend fe_www + bind :80 + bind :443 ssl crt /etc/ssl/haproxy/ alpn h2,http/1.1 + option forwardfor + default_backend be_www + +backend be_www + balance roundrobin + option httpchk OPTIONS * + server www01 192.0.2.1:80 check agent-check agent-inter 5s agent-addr 192.0.2.1 agent-port 9999 + server www02 192.0.2.2:80 check agent-check agent-inter 5s agent-addr 192.0.2.2 agent-port 9999 + server www03 192.0.2.3:80 check agent-check agent-inter 5s agent-addr 192.0.2.3 agent-port 9999 +~~~ + +Un moyen simple (inspiré de ce [blog post](https://icicimov.github.io/blog/server/HAProxy-dynamically-adjust-server-weight-using-external-agent/)) est de créer un script qui sera déclenché par **xinetd**. + +~~~ +# apt install xinetd +~~~ + +On ajoute un service à xinetd, dans `/etc/xinetd.d/haproxy-agent-check` (droits: root:root 0644) : + +~~~ +service haproxy-agent-check +{ + disable = no + flags = REUSE + socket_type = stream + port = 9999 + wait = no + user = nobody + server = /usr/local/bin/haproxy-agent-check + log_on_failure += USERID + only_from = 192.0.2.0/27 + per_source = UNLIMITED +} +~~~ + +Il faut penser à ajuster la liste d'adresses IP autorisées dans `only_from`. + +On ajoute la ligne suivante dans `/etc/services` : + +~~~ +haproxy-agent-check 9999/tcp # haproxy-agent-check +~~~ + +On crée le script à exécuter dans `/usr/local/bin/haproxy-agent-check` (droits: root:root 0755) : + +~~~{.bash} +#!/bin/bash +LMAX=90 + +load=$(uptime | grep -E -o 'load average[s:][: ].*' | sed 's/,//g' | cut -d' ' -f3-5) +cpus=$(grep processor /proc/cpuinfo | wc -l) + +while read -r l1 l5 l15; do { + l5util=$(echo "$l5/$cpus*100" | bc -l | cut -d"." -f1); + [[ $l5util -lt $LMAX ]] && echo "up 100%" && exit 0; + [[ $l5util -gt $LMAX ]] && [[ $l5util -lt 100 ]] && echo "up 50%" && exit 0; + echo "drain"; +}; done < <(echo $load) + +exit 0 +~~~ + +On redémarre xinetd (surveiller `/var/log/syslog` pour d'éventuelles erreurs) et on pense à autoriser le port 9999 au niveau firewall depuis les IP concernées. + +Les valeurs renvoyées peuvent être les suivantes : + +- Un % entier (ex 75%) pour l'ajustement du poids +- La chaîne `maxconn:` suivie d'un entier pour spécifier le nombre max de connexions +- Les mot `ready`, `drain`, `maint`, `down` et `up` pour modifier les états + +On notera que seuls les algorithmes d'équilibrage dynamiques (roundrobin et leastconn) permettront l'ajustement du poids via `agent-check`. Dans le cas de l'utilisation d'un algorithme statique comme `source` par exemple, seules des opérations telles que le passage en DRAIN, DOWN, MAINT et UP seront possibles. + ### HTTP basic authentication Pour mettre en place une authentification HTTP basique au niveau d'HAProxy, définir dans la section globale une liste d'utilisateur, soit avec un mot de passe en clair soit avec un mot de passe chiffré :