-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathhaproxy-fr.txt
2891 lines (2368 loc) · 129 KB
/
haproxy-fr.txt
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
-------------------
HAProxy
Manuel de référence
-------------------
version 1.3.2
willy tarreau
2006/09/03
!!!! NOTE: CE DOCUMENT EST PERIME !!!!
Veuillez utiliser le fichier "configuration.txt" situé dans le même
répertoire, ou télécharger une version à jour à l'emplacement ci-dessous :
http://haproxy.1wt.eu/download/1.4/doc/configuration.txt
================
| Introduction |
================
HAProxy est un relais TCP/HTTP offrant des facilités d'intégration en
environnement hautement disponible. En effet, il est capable de :
- effectuer un aiguillage statique défini par des cookies ;
- effectuer une répartition de charge avec création de cookies pour assurer
la persistence de session ;
- fournir une visibilité externe de son état de santé ;
- s'arrêter en douceur sans perte brutale de service ;
- modifier/ajouter/supprimer des en-têtes dans la requête et la réponse ;
- interdire des requêtes qui vérifient certaines conditions ;
- utiliser des serveurs de secours lorsque les serveurs principaux sont hors
d'usage.
- maintenir des clients sur le bon serveur serveur d'application en fonction
de cookies applicatifs.
- fournir des rapports d'état en HTML à des utilisateurs authentifiés, à
travers des URI de l'application interceptées.
Il requiert peu de ressources, et son architecture événementielle mono-
processus lui permet facilement de gérer plusieurs milliers de connexions
simultanées sur plusieurs relais sans effondrer le système.
===========================
| Paramètres de lancement |
===========================
Les options de lancement sont peu nombreuses :
-f <fichier de configuration>
-n <nombre maximal total de connexions simultanées>
= 'maxconn' dans la section 'global'
-N <nombre maximal de connexions simultanées par instance>
= 'maxconn' dans les sections 'listen' ou 'default'
-d active le mode debug
-D passe en daemon
-Ds passe en daemon systemd
-q désactive l'affichage de messages sur la sortie standard.
-V affiche les messages sur la sortie standard, même si -q ou 'quiet' sont
spécifiés.
-c vérifie le fichier de configuration puis quitte avec un code de retour 0
si aucune erreur n'a été trouvée, ou 1 si une erreur de syntaxe a été
détectée.
-p <fichier> indique au processus père qu'il doit écrire les PIDs de ses
fils dans ce fichier en mode démon.
-sf specifie une liste de PIDs auxquels envoyer un signal FINISH
-st specifie une liste de PIDs auxquels envoyer un signal TERMINATE
-s affiche les statistiques (si option compilée)
-l ajoute des informations aux statistiques
-dk désactive l'utilisation de kqueue()
-ds désactive l'utilisation de epoll() speculatif
-de désactive l'utilisation de epoll()
-dp désactive l'utilisation de poll()
-db désactive la mise en arrière-plan (utile pour débugger)
-m <megs> applique une limitation de <megs> Mo d'utilisation mémoire
Le nombre maximal de connexion simultanées par proxy est le paramètre par
défaut pour les proxies pour lesquels ce paramètre n'est pas précisé dans le
fichier de configuration. Il s'agit du paramètre 'maxconn' dans les sections
'listen'.
Le nombre maximal total de connexions simultanées limite le nombre de
connexions TCP utilisables à un instant donné par le processus, tous proxies
confondus. Ce paramètre remplace le paramètre 'maxconn' de la section 'global'.
Le mode debug correspond à l'option 'debug' de la section 'global'. Dans ce
mode, toutes les connexions, déconnexions, et tous les échanges d'en-têtes HTTP
sont affichés.
Pour debugger, l'option '-db' est très pratique car elle désactive
temporairement le mode daemon et le mode multi-processus. Le service peut alors
être arrêté par un simple appui sur Ctrl-C, sans avoir à modifier la
configuration ni à activer le mode debug complet.
Les statistiques ne sont disponibles que si le programme a été compilé avec
l'option "STATTIME". Il s'agit principalement de données brutes n'ayant
d'utilité que lors de benchmarks par exemple, et sont amenées à disparaitre.
Les paramètres '-st' et '-sf' sont utilisés pour la reconfiguration à chaud.
Voir la section à ce sujet.
============================
| Fichier de configuration |
============================
Structure
=========
L'analyseur du fichier de configuration ignore des lignes vides, les espaces,
les tabulations, et tout ce qui est compris entre le symbole '#' (s'il n'est
pas précédé d'un '\'), et la fin de la ligne, ce qui constitue un commentaire.
Le fichier de configuration est découpé en sections répérées par des mots clés
tels que :
- 'global'
- 'listen'
- 'defaults'
Tous les paramètres font référence à la section définie par le dernier mot clé
reconnu.
1) Paramètres globaux
=====================
Il s'agit des paramètres agissant sur le processus, ou bien sur l'ensemble des
proxies. Ils sont tous spécifiés dans la section 'global'. Les paramètres
supportés sont :
- log <adresse> <catégorie> [niveau_max]
- maxconn <nombre>
- uid <identifiant>
- gid <identifiant>
- user <nom d'utilisateur>
- group <nom de groupe>
- chroot <répertoire>
- nbproc <nombre>
- daemon
- debug
- nokqueue
- noepoll
- nopoll
- quiet
- pidfile <fichier>
- ulimit-n <nombre>
- tune.maxpollevents <nombre>
1.1) Journalisation des événements
----------------------------------
La plupart des événements sont journalisés : démarrages, arrêts, disparition et
apparition de serveurs, connexions, erreurs. Tous les messages sont envoyés en
syslog vers un ou deux serveurs. La syntaxe est la suivante :
log <adresse_ip> <catégorie> [niveau_max]
Les connexions sont envoyées en niveau "info". Les démarrages de service et de
serveurs seront envoyés en "notice", les signaux d'arrêts en "warning" et les
arrêts définitifs de services et de serveurs en "alert". Ceci est valable aussi
bien pour les proxies que pour les serveurs testés par les proxies. Le
paramètre optionnel <niveau_max> définit le niveau maximal de traces émises
parmi les 8 valeurs suivantes :
emerg, alert, crit, err, warning, notice, info, debug
Par compatibilité avec les versions 1.1.16 et antérieures, la valeur par défaut
est "debug" si l'option n'est pas précisée.
Les catégories possibles sont :
kern, user, mail, daemon, auth, syslog, lpr, news,
uucp, cron, auth2, ftp, ntp, audit, alert, cron2,
local0, local1, local2, local3, local4, local5, local6, local7
Conformément à la RFC3164, les messages émis sont limités à 1024 caractères.
Exemple :
---------
global
log 192.168.2.200 local3
log 127.0.0.1 local4 notice
1.2) limitation du nombre de connexions
---------------------------------------
Il est possible et conseillé de limiter le nombre global de connexions par
processus à l'aide du mot clé global 'maxconn'. Les connexions sont comprises
au sens 'acceptation de connexion', donc il faut s'attendre en règle général à
avoir un peu plus du double de sessions TCP que le maximum de connexions fixé.
C'est important pour fixer le paramètre 'ulimit -n' avant de lancer le proxy.
Pour comptabiliser le nombre de sockets nécessaires, il faut prendre en compte
ces paramètres :
- 1 socket par connexion entrante
- 1 socket par connexion sortante
- 1 socket par couple adresse/port d'écoute par proxy
- 1 socket pour chaque serveur en cours de health-check
- 1 socket pour les logs (tous serveurs confondus)
Dans le cas où chaque proxy n'écoute que sur un couple adresse/port,
positionner la limite du nombre de descripteurs de fichiers (ulimit -n) à
(2 * maxconn + nbproxy + nbserveurs + 1). A partir des versions 1.1.32/1.2.6,
il est possible de spécifier cette limite dans la configuration à l'aide du
mot-clé global 'ulimit-n', à condition bien entendu que le proxy ait été
démarré sous le compte root (ou avec des droits suffisants pour élever le
nombre de descripteurs de fichiers). Cette solution met un terme au problème
récurrent d'incertitude de l'adéquation entre les limites systèmes lors de la
dernière relance du proxessus et les limites en nombre de connexions. Noter que
cette limite s'applique par processus.
Exemple :
---------
global
maxconn 32000
ulimit-n 65536
1.3) Diminution des privilèges
------------------------------
Afin de réduire les risques d'attaques dans le cas où une faille non identifiée
serait exploitée, il est possible de diminuer les privilèges du processus, et
de l'isoler dans un répertoire sans risque.
Dans la section 'global', le paramètre 'uid' permet de spécifier un identifiant
numérique d'utilisateur. La valeur 0, correspondant normalement au super-
utilisateur, possède ici une signification particulière car elle indique que
l'on ne souhaite pas changer cet identifiant et conserver la valeur courante.
C'est la valeur par défaut. De la même manière, le paramètre 'gid' correspond à
un identifiant de groupe, et utilise par défaut la valeur 0 pour ne rien
changer. Dans le cas où il ne serait pas possible de spécifier un identifiant
numérique pour l'uid, il est possible de spécifier un nom d'utilisateur après
le mot-clé 'user'. De la même manière, il est possible de préciser un nom de
groupe après le mot-clé 'group'.
Il est particulièrement déconseillé d'utiliser des comptes génériques tels que
'nobody' car cette pratique revient à utiliser 'root' si d'autres processus
utilisent les mêmes identifiants.
Le paramètre 'chroot' autorise à changer la racine du processus une fois le
programme lancé, de sorte que ni le processus, ni l'un de ses descendants ne
puissent remonter de nouveau à la racine. Ce type de cloisonnement (chroot) est
généralement contournable sur certains OS (Linux, Solaris) pour peu que
l'attaquant possède des droits 'root' et soit en mesure d'utiliser ou de créer
un répertoire. Aussi, il est important d'utiliser un répertoire spécifique au
service pour cet usage, et de ne pas mutualiser un même répertoire pour
plusieurs services de nature différente. Pour rendre l'isolement plus robuste,
il est conseillé d'utiliser un répertoire vide, sans aucun droit, et de changer
l'uid du processus de sorte qu'il ne puisse rien faire dans ledit répertoire.
Remarque importante :
---------------------
Dans le cas où une telle faille serait mise en évidence, il est fort probable
que les premières tentatives de son exploitation provoquent un arrêt du
programme, à cause d'un signal de type 'Segmentation Fault', 'Bus Error' ou
encore 'Illegal Instruction'. Même s'il est vrai que faire tourner le serveur
en environnement limité réduit les risques d'intrusion, il est parfois bien
utile dans ces circonstances de connaître les conditions d'apparition du
problème, via l'obtention d'un fichier 'core'. La plupart des systèmes, pour
des raisons de sécurité, désactivent la génération du fichier 'core' après un
changement d'identifiant pour le processus. Il faudra donc soit lancer le
processus à partir d'un compte utilisateur aux droits réduits (mais ne pouvant
pas effectuer le chroot), ou bien le faire en root sans réduction des droits
(uid 0). Dans ce cas, le fichier se trouvera soit dans le répertoire de
lancement, soit dans le répertoire spécifié après l'option 'chroot'. Ne pas
oublier la commande suivante pour autoriser la génération du fichier avant de
lancer le programme :
# ulimit -c unlimited
Exemple :
---------
# with uid/gid
global
uid 30000
gid 30000
chroot /var/chroot/haproxy
# with user/group
global
user haproxy
group public
chroot /var/chroot/haproxy
1.4) Modes de fonctionnement
----------------------------
Le service peut fonctionner dans plusieurs modes :
- avant- / arrière-plan
- silencieux / normal / debug
Le mode par défaut est normal, avant-plan, c'est à dire que le programme ne
rend pas la main une fois lancé. Il ne faut surtout pas le lancer comme ceci
dans un script de démarrage du système, sinon le système ne finirait pas son
initialisation. Il faut le mettre en arrière-plan, de sorte qu'il rende la main
au processus appelant. C'est ce que fait l'option 'daemon' de la section
'global', et qui est l'équivalent du paramètre '-D' de la ligne de commande.
Le paramètre de ligne de commande '-db' inhibe les options globales 'daemon'
et 'nbproc' pour faire fonctionner le processus en mode normal, avant-plan.
Par ailleurs, certains messages d'alerte sont toujours envoyés sur la sortie
standard, même en mode 'daemon'. Pour ne plus les voir ailleurs que dans les
logs, il suffit de passer en mode silencieux par l'ajout de l'option 'quiet'.
Cette option n'a pas d'équivalent en ligne de commande.
Enfin, le mode 'debug' permet de diagnostiquer les origines de certains
problèmes en affichant les connexions, déconnexions et échanges d'en-têtes HTTP
entre les clients et les serveurs. Ce mode est incompatible avec les options
'daemon' et 'quiet' pour des raisons de bon sens.
1.5) Accroissement de la capacité de traitement
-----------------------------------------------
Sur des machines multi-processeurs, il peut sembler gâché de n'utiliser qu'un
processeur pour effectuer les tâches de relayage, même si les charges
nécessaires à saturer un processeur actuel sont bien au-delà des ordres de
grandeur couramment rencontrés. Cependant, pour des besoins particuliers, le
programme sait démarrer plusieurs processus se répartissant la charge de
travail. Ce nombre de processus est spécifié par le paramètre 'nbproc' de la
section 'global'. Sa valeur par défaut est naturellement 1. Ceci ne fonctionne
qu'en mode 'daemon'. Un usage déjà rencontré pour ce paramètre fut de dépasser
la limite de nombre de descripteurs de fichiers allouée par processus sous
Solaris.
Exemple :
---------
global
daemon
quiet
nbproc 2
1.6) Simplification de la gestion des processus
-----------------------------------------------
Haproxy supporte dorénavant la notion de fichiers de pid (-> pidfiles). Si le
paramètre '-p' de ligne de commande, ou l'option globale 'pidfile' sont suivis
d'un nom de fichier, alors ce fichier sera supprimé puis recréé et contiendra
le numéro de PID des processus fils, à raison d'un par ligne (valable
uniquement en mode démon). Ce fichier n'est PAS relatif au cloisonnement chroot
afin de rester compatible avec un répertoire protégé en lecture seule. Il
appartiendra à l'utilisateur ayant lancé le processus, et disposera des droits
0644.
Exemple :
---------
global
daemon
quiet
nbproc 2
pidfile /var/run/haproxy-private.pid
# pour stopper seulement ces processus parmi d'autres :
# kill $(</var/run/haproxy-private.pid)
# pour recharger une configuration avec un impact minimal sur le service,
# et sans casser les sessions existantes :
# haproxy -f haproxy.cfg -p /var/run/haproxy-private.pid -sf $(</var/run/haproxy-private.pid)
1.7) Mécanismes de traitements des événements
---------------------------------------------
A partir de la version 1.2.5, haproxy supporte les mécanismes poll() et
epoll(). Sur les systems où select() est limité par FD_SETSIZE (comme Solaris),
poll() peut être une alternative intéressante. Des tests de performance
montrent que les performances de poll() ne décroissent pas aussi vite que le
nombre de sockets augmente, ce qui en fait une solution sûre pour les fortes
charges. Cela dit, Soalris utilise déjà poll() pour émuler select(), donc tant
que le nombre de sockets ne dépasse pas FD_SETSIZE, poll() ne devrait pas
apporter de performances supplémentaires. Sur les systèmes à base Linux
incluant le patch epoll() (ou tous les Linux 2.6), haproxy utilisera epoll()
qui est extrèmement rapide indépendamment du nombre de sockets. Les tests sur
haproxy ont montré une performance constante de 1 à 40000 sessions simultanées.
La version 1.3.9 a introduit le support de kqueue() pour FreeBSD/OpenBSD, ainsi
qu'une variante appelée "speculative epoll()" consistant à tenter d'effectuer
les opérations d'entrées/sorties avant de chaîner les événements par les appels
système.
Afin d'optimiser la latence, il est désormais possible de limiter le nombre
d'événements remontés à chaque appel. La limite par défaut est fixée à 200. Si
une latence plus petite est recherchée, il peut être justifié d'abaisser cette
limite par l'utilisation du paramètre 'tune.maxpollevents' dans la section
'global'. L'augmenter permettra d'économiser un peu le processeur en présence
de très grands nombres de connexions simultanées.
Haproxy utilisera kqueue() ou speculative epoll() lorsque ce sera disponible,
puis epoll(), et se repliera sur poll(), puis en dernier lieu sur select().
Cependant, si pour une raison quelconque il s'avérait nécessaire de désactiver
epoll() ou poll() (p.ex: à cause d'un bug ou juste pour comparer les
performances), de nouvelles options globales ont été ajoutées dans ce but :
'nokqueue', 'noepoll' et 'nopoll'.
Exemple :
---------
global
# utiliser seulement select()
noepoll
nopoll
tune.maxpollevents 100
Remarque :
----------
Dans le but d'assurer une portabilité maximale des configurations, ces options
sont acceptées et ignorées si les mécanismes poll() ou epoll() n'ont pas été
activés lors de la compilation.
Afin de simplifier la résolution de problèmes, le paramètre '-de' en ligne de
commande désactive epoll(), le paramètre '-dp' désactive poll(), '-dk' kqueue()
et '-ds' désactive speculative epoll(). Ils sont respectivement équivalents à
'noepoll', 'nopoll', et 'nokqueue'.
2) Définition d'un service en écoute
====================================
Les sections de service débutent par le mot clé "listen" :
listen <nom_instance> [ <adresse_IP>:<plage_ports>[,...] ]
- <nom_instance> est le nom de l'instance décrite. Ce nom sera envoyé dans les
logs, donc il est souhaitable d'utiliser un nom relatif au service relayé.
Aucun test n'est effectué concernant l'unicité de ce nom, qui n'est pas
obligatoire, mais fortement recommandée.
- <adresse_IP> est l'adresse IP sur laquelle le relais attend ses connexions.
L'absence d'adresse ainsi que l'adresse 0.0.0.0 signifient que les connexions
pourront s'effectuer sur toutes les adresses de la machine.
- <plage_ports> correspond soit à un port, soit à une plage de ports sur
lesquels le relais acceptera des connexions pour l'adresse IP spécifiée.
Cette plage peut être :
- soit un port numérique (ex: '80')
- soit une plage constituée de deux valeurs séparées par un tiret
(ex: '2000-2100') représentant les extrémités incluses dans la
plage.
Il faut faire attention à l'usage des plages, car chaque combinaison
<adresse_IP>:<port> consomme une socket, donc un descripteur de fichier.
Le couple <adresse_IP>:<port> doit être unique pour toutes les instances
d'une même machine. L'attachement à un port inférieur à 1024 nécessite un
niveau de privilège particulier lors du lancement du programme
(indépendamment du paramètre 'uid' de la section 'global').
- le couple <adresse_IP>:<plage_ports> peut être répété indéfiniment pour
demander au relais d'écouter également sur d'autres adresses et/ou d'autres
plages de ports. Pour cela, il suffit de séparer les couples par une virgule.
Exemples :
---------
listen http_proxy :80
listen x11_proxy 127.0.0.1:6000-6009
listen smtp_proxy 127.0.0.1:25,127.0.0.1:587
listen ldap_proxy :389,:663
Si toutes les adresses ne tiennent pas sur une ligne, il est possible d'en
rajouter à l'aide du mot clé 'bind'. Dans ce cas, il n'est même pas nécessaire
de spécifier la première adresse sur la ligne listen, ce qui facilite parfois
l'écriture de configurations :
bind [ <adresse_IP>:<plage_ports>[,...] ]
Exemples :
----------
listen http_proxy
bind :80,:443
bind 10.0.0.1:10080,10.0.0.1:10443
2.1) Inhibition d'un service
----------------------------
Un service peut être désactivé pour des besoins de maintenance, sans avoir à
commenter toute une partie du fichier. Il suffit de positionner le mot clé
"disabled" dans sa section :
listen smtp_proxy 0.0.0.0:25
disabled
Remarque: le mot clé 'enabled' permet de réactiver un service préalablement
désactivé par le mot clé 'disabled', par exemple à cause d'une
configuration par défaut.
2.2) Mode de fonctionnement
---------------------------
Un service peut fonctionner dans trois modes différents :
- TCP
- HTTP
- état de santé
Mode TCP
--------
Dans ce mode, le service relaye, dès leur établissement, les connexions TCP
vers un ou plusieurs serveurs. Aucun traitement n'est effectué sur le flux. Il
s'agit simplement d'une association
source<adresse:port> -> destination<adresse:port>.
Pour l'utiliser, préciser le mode TCP sous la déclaration du relais.
Exemple :
---------
listen smtp_proxy 0.0.0.0:25
mode tcp
Mode HTTP
---------
Dans ce mode, le service relaye les connexions TCP vers un ou plusieurs
serveurs, une fois qu'il dispose d'assez d'informations pour en prendre la
décision. Les en-têtes HTTP sont analysés pour y trouver un éventuel cookie, et
certains d'entre-eux peuvent être modifiés par le biais d'expressions
régulières. Pour activer ce mode, préciser le mode HTTP sous la déclaration du
relais.
Exemple :
---------
listen http_proxy 0.0.0.0:80
mode http
Mode supervision
----------------
Il s'agit d'un mode offrant à un composant externe une visibilité de l'état de
santé du service. Il se contente de retourner "OK" à tout client se connectant
sur son port. Il peut être utilisé avec des répartiteurs de charge évolués pour
déterminer quels sont les services utilisables. Si l'option 'httpchk' est
activée, alors la réponse changera en 'HTTP/1.0 200 OK' pour satisfaire les
attentes de composants sachant tester en HTTP. Pour activer ce mode, préciser
le mode HEALTH sous la déclaration du relais.
Exemple :
---------
# réponse simple : 'OK'
listen health_check 0.0.0.0:60000
mode health
# réponse HTTP : 'HTTP/1.0 200 OK'
listen http_health_check 0.0.0.0:60001
mode health
option httpchk
2.2.1 Supervision
-----------------
Les versions 1.1.32 et 1.2.6 apportent une nouvelle solution pour valider le
bon fonctionnement du proxy sans perturber le service. Le mot-clé 'monitor-net'
a été créé dans le butd de spécifier un réseau d'équipements qui ne PEUVENT PAS
utiliser le service pour autre chose que des tests de fonctionnement. C'est
particulièrement adapté aux proxies TCP, car cela empêche le proxy de relayer
des établissements de connexion émis par un outil de surveillance.
Lorsque c'est utilisé sur un proxy TCP, la connexion est acceptée puis refermée
et rien n'est logué. C'est suffisant pour qu'un répartiteur de charge en amont
détecte que le service est disponible.
Lorsque c'est utilisé sur un proxy HTTP, la connexion est acceptée, rien n'est
logué, puis la réponse suivante est envoyée et la session refermée :
"HTTP/1.0 200 OK". C'est normalement suffisant pour qu'un répartiteur de charge
HTTP en amont détecte le service comme opérationnel, aussi bien à travers des
tests TCP que HTTP.
Les proxies utilisant le mot-clé 'monitor-net' peuvent accessoirement se passer
de l'option 'dontlognull', ce qui permettra de loguer les connexions vides
émises depuis d'autres adresses que celles du réseau de tests.
Exemple :
---------
listen tse-proxy
bind :3389,:1494,:5900 # TSE, ICA and VNC at once.
mode tcp
balance roundrobin
server tse-farm 192.168.1.10
monitor-net 192.168.1.252/31 # L4 load-balancers on .252 and .253
Lorsque le système effectuant les tests est situé derrière un proxy, le mot-clé
'monitor-net' n'est pas utilisable du fait que haproxy verra toujours la même
adresse pour le proxy. Pour pallier à cette limitation, la version 1.2.15 a
apporté le mot-clé 'monitor-uri'. Il définit une URI qui ne sera ni retransmise
ni logée, mais pour laquelle haproxy retournera immédiatement une réponse
"HTTP/1.0 200 OK". Cela rend possibles les tests de validité d'une chaîne
reverse-proxy->haproxy en une requête HTTP. Cela peut être utilisé pour valider
une combinaision de stunnel+haproxy à l'aide de tests HTTPS par exemple. Bien
entendu, ce mot-clé n'est valide qu'en mode HTTP, sinon il n'y a pas de notion
d'URI. Noter que la méthode et la version HTTP sont simplement ignorées.
Exemple :
---------
listen stunnel_backend :8080
mode http
balance roundrobin
server web1 192.168.1.10:80 check
server web2 192.168.1.11:80 check
monitor-uri /haproxy_test
2.3) Limitation du nombre de connexions simultanées
---------------------------------------------------
Le paramètre "maxconn" permet de fixer la limite acceptable en nombre de
connexions simultanées par proxy. Chaque proxy qui atteint cette valeur cesse
d'écouter jusqu'à libération d'une connexion. Voir plus loin concernant les
limitations liées au système.
Exemple :
---------
listen tiny_server 0.0.0.0:80
maxconn 10
2.4) Arrêt en douceur
---------------------
Il est possible d'arrêter les services en douceur en envoyant un signal
SIGUSR1 au processus relais. Tous les services seront alors mis en phase
d'arrêt, mais pourront continuer d'accepter des connexions pendant un temps
défini par le paramètre 'grace' (en millisecondes). Cela permet par exemple,
de faire savoir rapidement à un répartiteur de charge qu'il ne doit plus
utiliser un relais, tout en continuant d'assurer le service le temps qu'il
s'en rende compte.
Remarque :
----------
Les connexions actives ne sont jamais cassées. Dans le pire des cas, il faudra
attendre en plus leur expiration avant l'arrêt total du processus, ou bien tuer
manuellement le processus par l'envoi d'un signal SIGTERM. La valeur par défaut
du paramètre 'grace' est 0 (pas de grâce, arrêt immédiat de l'écoute).
Exemple :
---------
# arrêter en douceur par 'killall -USR1 haproxy'
# le service tournera encore 10 secondes après la demande d'arrêt
listen http_proxy 0.0.0.0:80
mode http
grace 10000
# ce port n'est testé que par un répartiteur de charge.
listen health_check 0.0.0.0:60000
mode health
grace 0
A partir de la version 1.2.8, un nouveau mécanisme de reconfiguration à chaud
a été introduit. Il est désormais possible de mettre les proxies en "pause" en
envoyant un signal SIGTTOU aux processus. Cela désactivera les sockets d'écoute
sans casser les sessions existantes. Suite à cela, l'envoi d'un signal SIGTTIN
réactivera les sockets d'écoute. Ceci est très pratique pour tenter de charger
une nouvelle configuration ou même une nouvelle version de haproxy sans casser
les connexions existantes. Si le rechargement s'effectue correctement, il ne
reste plus qu'à envoyer un signal SIGUSR1 aux anciens processus, ce qui
provoquera leur arrêt immédiat dès que leurs connexions seront terminées ; en
revanche, si le rechargement échoue, il suffit d'envoyer un signal SIGTTIN pour
remettre les ports en écoute et rétablir le service immédiatement. Veuillez
noter que le paramètre 'grace' est ignoré pour le signal SIGTTOU ainsi que le
signal SIGUSR1 une fois le processus en pause. Aussi, il peut s'avérer très
utile de sauver le fichier de pid avant de démarrer une nouvelle instance.
Ce mécanisme est pleinement exploité à partir de la version 1.2.11 avec les
options '-st' et '-sf' (voir ci-dessous).
2.4) Reconfiguration à chaud
----------------------------
Les paramètres '-st' et '-sf' sont utilisés pour informer des processus
existants que la configuration va être rechargée. Ils recevront le signal
SIGTTOU, leur demandant de libérer les ports en écoute afin que le nouveau
processus puisse les prendre. Si quoi que ce soit se passe mal, le nouveau
processus leur enverra un signal SIGTTIN pour leur indiquer qu'ils peuvent
se remettre en écoute et continuer leur travail. En revanche, si la
configuration se charge correctement, alors ils recevront un signal de demande
de fin de travail en douceur (-sf), ou de terminaison immédiate (-st) qui
coupera les sessions en cours. Un usage typique tel que celui-ci permet de
recharger une configuration sans interruption de service :
# haproxy -p /var/run/haproxy.pid -sf $(cat /var/run/haproxy.pid)
2.5) Temps d'expiration des connexions
--------------------------------------
Il est possible de paramétrer certaines durées d'expiration au niveau des
connexions TCP. Trois temps indépendants sont configurables et acceptent des
valeurs en millisecondes. Si l'une de ces trois temporisations est dépassée, la
session est terminée à chaque extrémité.
- temps d'attente d'une donnée de la part du client, ou de la
possibilité de lui envoyer des données : "clitimeout" :
# time-out client à 2mn30.
clitimeout 150000
- temps d'attente d'une donnée de la part du serveur, ou de la
possibilité de lui envoyer des données : "srvtimeout" :
# time-out serveur à 30s.
srvtimeout 30000
- temps d'attente de l'établissement d'une connexion vers un serveur
"contimeout" :
# on abandonne si la connexion n'est pas établie après 4 secondes
contimeout 4000
Remarques :
-----------
- "contimeout" et "srvtimeout" n'ont pas d'utilité dans le cas du serveur de
type "health".
- sous de fortes charges, ou sur un réseau saturé ou défectueux, il est
possible de perdre des paquets. Du fait que la première retransmission
TCP n'ait lieu qu'au bout de 3 secoudes, fixer un timeout de connexion
inférieur à 3 secondes ne permet pas de se rattraper sur la perte
de paquets car la session aura été abandonnée avant la première
retransmission. Une valeur de 4 secondes réduira considérablement
le nombre d'échecs de connexion.
- A compter de la version 1.3.14, il est possible de spécifier les durées
d'expiration dans des unités de temps arbitraires à choisir parmi
{ us, ms, s, m, h, d }. Pour cela, la valeur entière doit être suffixée
de l'unité.
2.6) Tentatives de reconnexion
------------------------------
Lors d'un échec de connexion vers un serveur, il est possible de
retenter (potentiellement vers un autre serveur, en cas de répartition
de charge). Le nombre de nouvelles tentatives infructueuses avant
abandon est fourni par le paramètre "retries".
Exemple :
---------
# on essaie encore trois fois maxi
retries 3
Il est à noter que la tentative de reconnexion peut amener à utiliser un autre
serveur si le premier a disparu entre deux tentatives de connexion.
2.7) Adresse du serveur
-----------------------
Le serveur vers lequel sont redirigées les nouvelles connexions est défini par
le paramètre "dispatch" sous la forme <adresse_ip>:<port>. Il correspond à un
serveur d'assignation de cookie dans le cas où le service consiste à assurer
uniquement une persistence HTTP, ou bien simplement au serveur destination dans
le cas de relayage TCP simple. Cet ancien mode ne permet pas de tester l'état
du serveur distant, et il est maintenant recommandé d'utiliser de préférence
le mode 'balance'.
Exemple :
---------
# on envoie toutes les nouvelles connexions ici
dispatch 192.168.1.2:80
Remarque :
----------
Ce paramètre n'a pas d'utilité pour un serveur en mode 'health', ni en mode
'balance'.
2.8) Adresse de sortie
----------------------
Il est possible de forcer l'adresse utilisée pour établir les connexions vers
les serveurs à l'aide du paramètre "source". Il est même possible de forcer le
port, bien que cette fonctionnalité se limite à des usages très spécifiques.
C'est particulièrement utile en cas d'adressage multiple, et plus généralement
pour permettre aux serveurs de trouver le chemin de retour dans des contextes
de routage difficiles. Si l'adresse est '0.0.0.0' ou '*' ou vide, elle sera
choisie librement par le systeme. Si le port est '0' ou vide, il sera choisi
librement par le système. Il est à noter que depuis la version 1.1.18, les
tests de bon fonctionnement des serveurs seront aussi effectués à partir de la
source spécifiée par ce paramètre.
Exemples :
----------
listen http_proxy *:80
# toutes les connexions prennent l'adresse 192.168.1.200
source 192.168.1.200:0
listen rlogin_proxy *:513
# utiliser l'adresse 192.168.1.200 et le port réservé 900
source 192.168.1.200:900
2.9) Définition du nom du cookie
--------------------------------
En mode HTTP, il est possible de rechercher la valeur d'un cookie pour savoir
vers quel serveur aiguiller la requête utilisateur. Le nom du cookie est donné
par le paramètre "cookie".
Exemple :
---------
listen http_proxy :80
mode http
cookie SERVERID
On peut modifier l'utilisation du cookie pour la rendre plus intelligente
vis-à-vis des applications relayées. Il est possible, notamment de supprimer ou
réécrire un cookie retourné par un serveur accédé en direct, et d'insérer un
cookie dans une réponse HTTP adressée à un serveur sélectionné en répartition
de charge, et même de signaler aux proxies amont de ne pas cacher le cookie
inséré.
Exemples :
----------
Pour ne conserver le cookie qu'en accès indirect, donc à travers le
dispatcheur, et supprimer toutes ses éventuelles occurences lors des accès
directs :
cookie SERVERID indirect
Pour remplacer la valeur d'un cookie existant par celle attribuée à un serveur,
lors d'un accès direct :
cookie SERVERID rewrite
Pour créer un cookie comportant la valeur attribuée à un serveur lors d'un
accès en répartition de charge interne. Dans ce cas, il est souhaitable que
tous les serveurs aient un cookie renseigné. Un serveur non assigné d'un cookie
retournera un cookie vide (cookie de suppression) :
cookie SERVERID insert
Pour réutiliser un cookie applicatif et lui préfixer l'identifiant du serveur,
puis le supprimer dans les requêtes suivantes, utiliser l'option 'prefix'. Elle
permet d'insérer une instance de haproxy devant une application sans risquer
d'incompatibilités dûes à des clients qui ne supporteraient pas d'apprendre
plus d'un cookie :
cookie JSESSIONID prefix
Pour insérer un cookie, en s'assurant qu'un cache en amont ne le stockera pas,
ajouter le mot clé 'nocache' après 'insert' :
cookie SERVERID insert nocache
Pour insérer un cookie seulement suite aux requêtes de type POST, ajouter le
mot clé 'postonly' après 'insert' :
cookie SERVERID insert postonly
Remarques :
-----------
- Il est possible de combiner 'insert' avec 'indirect' ou 'rewrite' pour
s'adapter à des applications générant déjà le cookie, avec un contenu
invalide. Il suffit pour cela de les spécifier sur la même ligne.
- dans le cas où 'insert' et 'indirect' sont spécifiés, le cookie n'est jamais
transmis au serveur vu qu'il n'en a pas connaissance et ne pourrait pas le
comprendre.
- il est particulièrement recommandé d'utiliser 'nocache' en mode insertion si
des caches peuvent se trouver entre les clients et l'instance du proxy. Dans
le cas contraire, un cache HTTP 1.0 pourrait cacher la réponse, incluant le
cookie de persistence inséré, donc provoquer des changements de serveurs pour
des clients partageant le même cache.
- le mode 'prefix' ne nécessite pas d'utiliser 'indirect', 'nocache', ni
'postonly', car tout comme le mode 'rewrite', il s'appuie sur un cookie
présenté par l'application qui est censée savoir à quel moment il peut
être émis sans risque. Toutefois, comme il nécessite de rectifier le cookie
présenté par le client dans chaque requête ultérieure, il est indispensable
de s'assurer que le client et le serveur communiqueront sans "keep-alive
HTTP". Dans le doute, il est recommandé d'utiliser l'option "httpclose".
- lorsque l'application est bien connue, et que les parties nécessitant de la
persistence sont systématiquement accédées par un formulaire en mode POST,
il est plus efficace encore de combiner le mot clé "postonly" avec "insert"
et "indirect", car la page d'accueil reste cachable, et c'est l'application
qui gère le 'cache-control'.
2.10) Assignation d'un serveur à une valeur de cookie
----------------------------------------------------
En mode HTTP, il est possible d'associer des valeurs de cookie à des serveurs
par le paramètre 'server'. La syntaxe est :
server <identifiant> <adresse_ip>:<port> cookie <valeur>
- <identifiant> est un nom quelconque de serveur utilisé pour l'identifier dans la
configuration et les logs.
- <adresse_ip>:<port> est le couple adresse-port sur lequel le serveur écoute.
- <valeur> est la valeur à reconnaître ou positionner dans le cookie.
Exemple : le cookie SERVERID peut contenir server01 ou server02
---------
listen http_proxy :80
mode http
cookie SERVERID
dispatch 192.168.1.100:80
server web1 192.168.1.1:80 cookie server01
server web2 192.168.1.2:80 cookie server02
Attention : la syntaxe a changé depuis la version 1.0.
-----------
3) Répartiteur de charge autonome
=================================
Le relais peut effectuer lui-même la répartition de charge entre les différents
serveurs définis pour un service donné, en mode TCP comme en mode HTTP. Pour
cela, on précise le mot clé 'balance' dans la définition du service,
éventuellement suivi du nom d'un algorithme de répartition. Jusqu'à la version
1.2.11, seul 'roundrobin' était géré, et c'est aussi la valeur implicite par
défaut. Avec la version 1.2.12, le nouveau mot clé 'source' est apparu. La
version 1.3.10 a également apporté le mot clé 'uri'. Il est évident qu'en cas
d'utilisation du répartiteur interne, il ne faudra pas spécifier d'adresse de
dispatch, et qu'il faudra au moins un serveur.
Exemple : même que précédemment en répartition interne
---------
listen http_proxy :80
mode http
cookie SERVERID
balance roundrobin
server web1 192.168.1.1:80 cookie server01
server web2 192.168.1.2:80 cookie server02
Depuis la version 1.1.22, il est possible de déterminer automatiquement le port
du serveur vers lequel sera envoyée la connexion, en fonction du port d'écoute
sur lequel le client s'est connecté. En effet, il y a 4 possibilités pour le
champ <port> de l'adresse serveur :
- non spécifié ou nul :
la connexion sera envoyée au serveur sur le même port que celui sur
lequel le relais a reçu la connexion.
- valeur numérique (seul cas supporté pour les versions antérieures) :
le serveur recevra la connexion sur le port désigné.
- valeur numérique précédée d'un signe '+' :
la connexion sera envoyée au serveur sur le même port que celui sur
lequel le relais a reçu la connexion, auquel on ajoute la valeur désignée.
- valeur numérique précédée d'un signe '-' :
la connexion sera envoyée au serveur sur le même port que celui sur
lequel le relais a reçu la connexion, duquel on soustrait la valeur
désignée.
Exemples :
----------
# même que précédemment
listen http_proxy :80
mode http
cookie SERVERID
balance roundrobin
server web1 192.168.1.1 cookie server01
server web2 192.168.1.2 cookie server02
# relayage simultané des ports 80 et 81 et 8080-8089
listen http_proxy :80,:81,:8080-8089
mode http
cookie SERVERID
balance roundrobin
server web1 192.168.1.1 cookie server01
server web2 192.168.1.2 cookie server02
# relayage TCP des ports 25, 389 et 663 vers les ports 1025, 1389 et 1663
listen http_proxy :25,:389,:663
mode tcp
balance roundrobin
server srv1 192.168.1.1:+1000
server srv2 192.168.1.2:+1000
Comme indiqué précédemment, la version 1.2.12 apporta le nouveau mot clé
'source'. Lorsque celui-ci est utilisé, l'adresse IP du client est hachée et
distribuée de manière homogène parmi les serveurs disponibles, de sorte qu'une
même adresse IP aille toujours sur le même serveur tant qu'il n'y a aucun
changement dans le nombre de serveurs disponibles. Ceci peut être utilisé par
exemple pour attacher le HTTP et le HTTPS sur un même serveur pour un même
client. Cela peut également être utilisé pour améliorer la persistance
lorsqu'une partie de la population des clients n'accepte pas les cookies. Dans
ce cas, seuls ces derniers seront perturbés par la perte d'un serveur.
NOTE: il est important de prendre en compte le fait que beaucoup d'internautes
naviguent à travers des fermes de proxies qui assignent des adresses IP
différentes à chaque requête. D'autres internautes utilisent des liens à
la demande et obtiennent une adresse IP différente à chaque connexion. De
ce fait, le paramètre 'source' doit être utilisé avec une extrème
précaution.
Exemples :
----------
# assurer qu'une même adresse IP ira sur le même serveur pour tout service
listen http_proxy
bind :80,:443
mode http
balance source
server web1 192.168.1.1
server web2 192.168.1.2
# améliorer la persistance par l'utilisation de la source en plus du cookie :
listen http_proxy :80
mode http
cookie SERVERID
balance source
server web1 192.168.1.1 cookie server01
server web2 192.168.1.2 cookie server02
De plus, tel qu'indiqué ci-dessus, la version 1.3.10 a introduit le mot clé
'uri'. Il est très pratique dans le cas de répartition de charge entre des
reverse-proxy-caches, parce qu'il utilisera le résultat d'un hachage de l'URI
pour choisir un serveur, ce qui aura pour effet d'optimiser le taux de cache
du fait que la même URI sera toujours envoyée au même cache. Ce mot-clé n'est
autorisé qu'en mode HTTP.
Example :
---------