Répartition de charge EoleSSO en mode cluster

Cette documentation a pour but de décrire la mise en place d'une configuration HAProxy afin de pouvoir mettre plusieurs services EoleSSO en cluster et de gérer la répartition de charge.

https://www.haproxy.com/fr/

Cette documentation décrit également la mise en place de 2 services pour suivre les métriques d'EoleSSO :

On suppose l’existence de 3 serveurs EoleSSO qui écoutent sur le port 443 dont les DNS sont les suivants :

  • sso-1.ac-academie.fr ;

  • sso-2.ac-academie.fr ;

  • sso-3.ac-academie.fr.

Un quatrième serveur doit héberger le service ha-proxy avec pour nom DNS sso-ha.ac-academie.fr.

Attention

Le serveur hébergeant le service ha-proxy du cluster doit avoir un nom de domaine différent de celui du cluster de serveur web même si les 2 noms de domaine pointent sur la même adresse IP.

Remarque

Pour maintenir et déployer la configuration (certificats pour stunnel, metadata, filtres, thèmes, CSS, attributs calculés) sur les différents serveurs EoleSSO il est possible d'utiliser Ansible.

Installation d'HAProxy

Sur le serveur sso-ha.ac-academie.fr :

# apt-eole install haproxy

Configuration d'HAProxy

Procéder à la configuration basique d'HAProxy (non détaillée ici).

Éditer le fichier de configuration /etc/haproxy/haproxy.cfg et ajouter les lignes suivantes :

1
global
2
	...
3
	 # Les serveurs étant gérés par vous, la vérification ssl peut être désactivée
4
	ssl-server-verify none
5
6
frontend https-in
7
     bind <IP DU SERVEUR SSO-HA>:443 ssl crt <CHEMIN DU CERTIFICAT PEM>
8
     option   forwardfor
9
     redirect scheme https if !{ ssl_fc }
10
     default_backend    sso_servers
11
12
backend sso_servers
13
     balance         roundrobin
14
     cookie SSONAME  insert indirect nocache
15
     server sso-1.ac-academie.fr   sso-1.ac-academie.fr:443 ssl cookie sso1 check
16
     server sso-2.ac-academie.fr   sso-2.ac-academie.fr:443 ssl cookie sso2 check
17
     server sso-3.ac-academie.fr   sso-3.ac-academie.fr:443 ssl cookie sso3 check

Remarque

<IP DU SERVEUR SSO-HA> : est à remplacer par l'adresse IP de votre serveur HAProxy

<CHEMIN DU CERTIFICAT PEM> : chemin du certificat + key

Attention

Penser à redémarrer le service haproxy :

# service haproxy restart

Mise en place de Prometheus et de Grafana

Il faut mettre en place un serveur Prometheus qui sera chargé de collecter les données fournies par nos serveurs EoleSSO et mettre en place Grafana pour avoir un visuel des métriques.

Pour des raisons de simplicité, des micro-services docker sont utilisés pour fournir ces deux applications, aussi il faut installer les paquets docker et docker-compose.

Remarque

Il peut être intéressant de dissocier ces services du serveur HAPproxy, car il pourrait servir à d'autres serveurs, ce serveur de monitoring porte le nom DNS monitoring.ac-academie.fr.

ExempleExemple de configuration de Prometheus

Exemple de configuration, contenu dans le fichier /shared/prometheus/monitoring-compose.yml :

1
prometheus:
2
  image: prom/prometheus
3
  ports:
4
    - 9090:9090
5
  volumes:
6
    - /shared/prometheus/etc/:/etc/prometheus/
7
    - /shared/prometheus/data/:/prometheus
8
9
grafana:
10
  image: grafana/grafana:4.1.1
11
  ports:
12
    - 3000:3000
13
  volumes:
14
    - /shared/prometheus/grafana/:/var/lib/grafana/
15
  env_file:
16
    - /shared/prometheus/grafana.config.monitoring

Configuration de Prometheus

Le fichier de configuration de prometheus /shared/prometheus/etc/prometheus.yml contient :

1
global:
2
  scrape_interval: 60s
3
4
scrape_configs:
5
  - job_name: "eole_sso"
6
    metrics_path: /metrics
7
    scheme: https
8
    tls_config:
9
      insecure_skip_verify: true
10
    static_configs:
11
        - targets:
12
            - sso-1.ac-academie.fr
13
            - sso-2.ac-academie.fr
14
            - sso-3.ac-academie.fr

Configuration de Grafana

Configuration de Grafana dans le fichier /shared/prometheus/grafana.config.monitoring

1
GF_SECURITY_ADMIN_PASSWORD=VOTRE_MOT_DE_PASSE_ADMIN
2
GF_USERS_ALLOW_SIGN_UP=false
3
http_proxy=PROXY_HOST:PROXY_PORT
4
https_proxy=PROXY_HOST:PROXY_PORT

Remarque

Modifier les valeurs de :

VOTRE_MOT_DE_PASSE_ADMIN

PROXY_HOST

PROXY_PORT

Truc & astuce

La documentation de Grafana décrit les paramètres possibles :

http://docs.grafana.org/installation/configuration/

ExempleJSON pour le tableau de bord Grafana

1
{
2
  "annotations": {
3
    "list": []
4
  },
5
  "editable": true,
6
  "gnetId": null,
7
  "graphTooltip": 0,
8
  "hideControls": false,
9
  "id": 16,
10
  "links": [],
11
  "refresh": "1m",
12
  "rows": [
13
    {
14
      "collapse": false,
15
      "height": 237,
16
      "panels": [
17
        {
18
          "aliasColors": {
19
            "sso-3": "#82B5D8",
20
            "sso-1": "#7EB26D",
21
            "sso-2": "#EAB839"
22
          },
23
          "bars": false,
24
          "datasource": null,
25
          "editable": true,
26
          "error": false,
27
          "fill": 7,
28
          "grid": {},
29
          "id": 9,
30
          "legend": {
31
            "avg": false,
32
            "current": false,
33
            "max": false,
34
            "min": false,
35
            "show": true,
36
            "total": false,
37
            "values": false
38
          },
39
          "lines": true,
40
          "linewidth": 0,
41
          "links": [],
42
          "nullPointMode": "connected",
43
          "percentage": false,
44
          "pointradius": 5,
45
          "points": false,
46
          "renderer": "flot",
47
          "seriesOverrides": [],
48
          "span": 4,
49
          "stack": true,
50
          "steppedLine": false,
51
          "targets": [
52
            {
53
              "expr": "eolesso_login_gauge",
54
              "intervalFactor": 2,
55
              "legendFormat": "{{host}}",
56
              "metric": "eolesso_login_gauge",
57
              "refId": "A",
58
              "step": 120
59
            }
60
          ],
61
          "thresholds": [],
62
          "timeFrom": null,
63
          "timeShift": null,
64
          "title": "Nombre de tickets de login (TicketCache)",
65
          "tooltip": {
66
            "msResolution": false,
67
            "shared": true,
68
            "sort": 0,
69
            "value_type": "cumulative"
70
          },
71
          "type": "graph",
72
          "xaxis": {
73
            "mode": "time",
74
            "name": null,
75
            "show": true,
76
            "values": []
77
          },
78
          "yaxes": [
79
            {
80
              "format": "short",
81
              "label": null,
82
              "logBase": 1,
83
              "max": null,
84
              "min": null,
85
              "show": true
86
            },
87
            {
88
              "format": "short",
89
              "label": null,
90
              "logBase": 1,
91
              "max": null,
92
              "min": null,
93
              "show": true
94
            }
95
          ]
96
        },
97
        {
98
          "bars": true,
99
          "datasource": null,
100
          "editable": true,
101
          "error": false,
102
          "fill": 10,
103
          "grid": {},
104
          "id": 4,
105
          "legend": {
106
            "avg": false,
107
            "current": false,
108
            "max": false,
109
            "min": false,
110
            "show": true,
111
            "total": false,
112
            "values": false
113
          },
114
          "lines": false,
115
          "linewidth": 0,
116
          "links": [],
117
          "nullPointMode": "null as zero",
118
          "percentage": false,
119
          "pointradius": 5,
120
          "points": false,
121
          "renderer": "flot",
122
          "seriesOverrides": [],
123
          "span": 4,
124
          "stack": true,
125
          "steppedLine": true,
126
          "targets": [
127
            {
128
              "expr": "(rate(eolesso_sessions_new_counter[10m]))*60*2",
129
              "intervalFactor": 2,
130
              "legendFormat": "{{host}} [{{authclass}}]",
131
              "metric": "eolesso_sessions_new_counter",
132
              "refId": "A",
133
              "step": 120
134
            }
135
          ],
136
          "thresholds": [],
137
          "timeFrom": null,
138
          "timeShift": null,
139
          "title": "Nb connexions/s",
140
          "tooltip": {
141
            "msResolution": false,
142
            "shared": true,
143
            "sort": 0,
144
            "value_type": "individual"
145
          },
146
          "type": "graph",
147
          "xaxis": {
148
            "mode": "time",
149
            "name": null,
150
            "show": true,
151
            "values": []
152
          },
153
          "yaxes": [
154
            {
155
              "format": "short",
156
              "label": null,
157
              "logBase": 1,
158
              "max": null,
159
              "min": null,
160
              "show": true
161
            },
162
            {
163
              "format": "short",
164
              "label": null,
165
              "logBase": 1,
166
              "max": null,
167
              "min": null,
168
              "show": true
169
            }
170
          ]
171
        },
172
        {
173
          "aliasColors": {
174
            "sso-3": "#82B5D8",
175
            "sso-1": "#7EB26D",
176
            "sso-2": "#EAB839"
177
          },
178
          "bars": false,
179
          "datasource": null,
180
          "editable": true,
181
          "error": false,
182
          "fill": 3,
183
          "grid": {},
184
          "id": 2,
185
          "legend": {
186
            "avg": false,
187
            "current": false,
188
            "max": false,
189
            "min": false,
190
            "show": true,
191
            "total": false,
192
            "values": false
193
          },
194
          "lines": true,
195
          "linewidth": 1,
196
          "links": [],
197
          "nullPointMode": "null",
198
          "percentage": false,
199
          "pointradius": 5,
200
          "points": false,
201
          "renderer": "flot",
202
          "seriesOverrides": [],
203
          "span": 4,
204
          "stack": true,
205
          "steppedLine": false,
206
          "targets": [
207
            {
208
              "expr": "eolesso_sessions_nb_gauge",
209
              "intervalFactor": 1,
210
              "legendFormat": "{{host}}",
211
              "metric": "eolesso_sessions_gauge",
212
              "refId": "A",
213
              "step": 60
214
            }
215
          ],
216
          "thresholds": [],
217
          "timeFrom": null,
218
          "timeShift": null,
219
          "title": "Nombre de tickets de sessions (auth)",
220
          "tooltip": {
221
            "msResolution": false,
222
            "shared": true,
223
            "sort": 0,
224
            "value_type": "cumulative"
225
          },
226
          "type": "graph",
227
          "xaxis": {
228
            "mode": "time",
229
            "name": null,
230
            "show": true,
231
            "values": []
232
          },
233
          "yaxes": [
234
            {
235
              "format": "short",
236
              "label": null,
237
              "logBase": 1,
238
              "max": null,
239
              "min": null,
240
              "show": true
241
            },
242
            {
243
              "format": "short",
244
              "label": null,
245
              "logBase": 1,
246
              "max": null,
247
              "min": null,
248
              "show": true
249
            }
250
          ]
251
        }
252
      ],
253
      "repeat": null,
254
      "repeatIteration": null,
255
      "repeatRowId": null,
256
      "showTitle": false,
257
      "title": "Row",
258
      "titleSize": "h6"
259
    },
260
    {
261
      "collapse": false,
262
      "height": "250px",
263
      "panels": [
264
        {
265
          "aliasColors": {
266
            "sso-3": "#82B5D8",
267
            "sso-1": "#7EB26D",
268
            "sso-2": "#EAB839"
269
          },
270
          "bars": false,
271
          "datasource": null,
272
          "editable": true,
273
          "error": false,
274
          "fill": 7,
275
          "grid": {},
276
          "id": 7,
277
          "legend": {
278
            "avg": false,
279
            "current": false,
280
            "max": false,
281
            "min": false,
282
            "show": true,
283
            "total": false,
284
            "values": false
285
          },
286
          "lines": true,
287
          "linewidth": 1,
288
          "links": [],
289
          "nullPointMode": "connected",
290
          "percentage": false,
291
          "pointradius": 5,
292
          "points": false,
293
          "renderer": "flot",
294
          "seriesOverrides": [],
295
          "span": 6,
296
          "stack": true,
297
          "steppedLine": true,
298
          "targets": [
299
            {
300
              "expr": "eolesso_calcdata_gauge",
301
              "intervalFactor": 2,
302
              "legendFormat": "{{host}}",
303
              "metric": "eolesso_calcdata_gauge",
304
              "refId": "A",
305
              "step": 60
306
            }
307
          ],
308
          "thresholds": [],
309
          "timeFrom": null,
310
          "timeShift": null,
311
          "title": "taille du cache des attributs calculés",
312
          "tooltip": {
313
            "msResolution": false,
314
            "shared": true,
315
            "sort": 0,
316
            "value_type": "cumulative"
317
          },
318
          "type": "graph",
319
          "xaxis": {
320
            "mode": "time",
321
            "name": null,
322
            "show": true,
323
            "values": []
324
          },
325
          "yaxes": [
326
            {
327
              "format": "decbytes",
328
              "label": "Octets",
329
              "logBase": 1,
330
              "max": null,
331
              "min": null,
332
              "show": true
333
            },
334
            {
335
              "format": "short",
336
              "label": null,
337
              "logBase": 1,
338
              "max": null,
339
              "min": null,
340
              "show": true
341
            }
342
          ]
343
        },
344
        {
345
          "aliasColors": {
346
            "sso-3": "#82B5D8",
347
            "sso-1": "#7EB26D",
348
            "sso-2": "#EAB839"
349
          },
350
          "bars": false,
351
          "datasource": null,
352
          "editable": true,
353
          "error": false,
354
          "fill": 5,
355
          "grid": {},
356
          "id": 8,
357
          "legend": {
358
            "avg": false,
359
            "current": false,
360
            "max": false,
361
            "min": false,
362
            "show": true,
363
            "total": false,
364
            "values": false
365
          },
366
          "lines": true,
367
          "linewidth": 1,
368
          "links": [],
369
          "nullPointMode": "connected",
370
          "percentage": false,
371
          "pointradius": 5,
372
          "points": false,
373
          "renderer": "flot",
374
          "seriesOverrides": [],
375
          "span": 6,
376
          "stack": true,
377
          "steppedLine": false,
378
          "targets": [
379
            {
380
              "expr": "eolesso_userdata_gauge",
381
              "intervalFactor": 2,
382
              "legendFormat": "{{host}}",
383
              "metric": "eolesso_userdata_gauge",
384
              "refId": "A",
385
              "step": 60
386
            }
387
          ],
388
          "thresholds": [],
389
          "timeFrom": null,
390
          "timeShift": null,
391
          "title": "taille du cache des attributs ldap",
392
          "tooltip": {
393
            "msResolution": false,
394
            "shared": true,
395
            "sort": 0,
396
            "value_type": "cumulative"
397
          },
398
          "type": "graph",
399
          "xaxis": {
400
            "mode": "time",
401
            "name": null,
402
            "show": true,
403
            "values": []
404
          },
405
          "yaxes": [
406
            {
407
              "format": "decbytes",
408
              "label": "Octets",
409
              "logBase": 1,
410
              "max": null,
411
              "min": null,
412
              "show": true
413
            },
414
            {
415
              "format": "short",
416
              "label": null,
417
              "logBase": 1,
418
              "max": null,
419
              "min": null,
420
              "show": true
421
            }
422
          ]
423
        }
424
      ],
425
      "repeat": null,
426
      "repeatIteration": null,
427
      "repeatRowId": null,
428
      "showTitle": false,
429
      "title": "New row",
430
      "titleSize": "h6"
431
    },
432
    {
433
      "collapse": false,
434
      "height": "250px",
435
      "panels": [
436
        {
437
          "aliasColors": {
438
            "sso.ac-reunion.fr:4430": "#82B5D8",
439
            "sso.ac-reunion.fr:4431": "#E5A8E2",
440
            "sso.ac-reunion.fr:4432": "#AEA2E0"
441
          },
442
          "bars": false,
443
          "datasource": null,
444
          "editable": true,
445
          "error": false,
446
          "fill": 0,
447
          "grid": {},
448
          "id": 3,
449
          "legend": {
450
            "alignAsTable": true,
451
            "avg": false,
452
            "current": true,
453
            "max": false,
454
            "min": false,
455
            "rightSide": true,
456
            "show": true,
457
            "total": false,
458
            "values": true
459
          },
460
          "lines": true,
461
          "linewidth": 1,
462
          "links": [],
463
          "nullPointMode": "null as zero",
464
          "percentage": false,
465
          "pointradius": 5,
466
          "points": false,
467
          "renderer": "flot",
468
          "seriesOverrides": [],
469
          "span": 6,
470
          "stack": false,
471
          "steppedLine": false,
472
          "targets": [
473
            {
474
              "expr": "process_virtual_memory_bytes{job='eole_sso'}",
475
              "intervalFactor": 2,
476
              "legendFormat": "{{instance}}",
477
              "refId": "A",
478
              "step": 60
479
            }
480
          ],
481
          "thresholds": [
482
            {
483
              "colorMode": "critical",
484
              "fill": true,
485
              "line": true,
486
              "op": "gt",
487
              "value": 1517522817
488
            }
489
          ],
490
          "timeFrom": null,
491
          "timeShift": null,
492
          "title": "Mémoire utilisée",
493
          "tooltip": {
494
            "msResolution": false,
495
            "shared": true,
496
            "sort": 0,
497
            "value_type": "individual"
498
          },
499
          "type": "graph",
500
          "xaxis": {
501
            "mode": "time",
502
            "name": null,
503
            "show": true,
504
            "values": []
505
          },
506
          "yaxes": [
507
            {
508
              "format": "bytes",
509
              "label": null,
510
              "logBase": 1,
511
              "max": null,
512
              "min": null,
513
              "show": true
514
            },
515
            {
516
              "format": "short",
517
              "label": null,
518
              "logBase": 1,
519
              "max": null,
520
              "min": null,
521
              "show": true
522
            }
523
          ]
524
        },
525
        {
526
          "aliasColors": {
527
            "sso-3": "#82B5D8",
528
            "sso-1": "#7EB26D",
529
            "sso-2": "#EAB839"
530
          },
531
          "bars": false,
532
          "datasource": null,
533
          "editable": true,
534
          "error": false,
535
          "fill": 4,
536
          "grid": {},
537
          "id": 1,
538
          "legend": {
539
            "avg": false,
540
            "current": false,
541
            "max": false,
542
            "min": false,
543
            "show": true,
544
            "total": false,
545
            "values": false
546
          },
547
          "lines": true,
548
          "linewidth": 1,
549
          "links": [],
550
          "nullPointMode": "connected",
551
          "percentage": false,
552
          "pointradius": 5,
553
          "points": false,
554
          "renderer": "flot",
555
          "seriesOverrides": [],
556
          "span": 6,
557
          "stack": true,
558
          "steppedLine": false,
559
          "targets": [
560
            {
561
              "expr": "eolesso_appticket_gauge{job='eole_sso'}",
562
              "intervalFactor": 2,
563
              "legendFormat": "{{host}}",
564
              "metric": "eolesso_appticket_gauge",
565
              "refId": "A",
566
              "step": 60
567
            }
568
          ],
569
          "thresholds": [],
570
          "timeFrom": null,
571
          "timeShift": null,
572
          "title": "Nombre de Tickets applicatifs (AppTicket)",
573
          "tooltip": {
574
            "msResolution": false,
575
            "shared": true,
576
            "sort": 0,
577
            "value_type": "cumulative"
578
          },
579
          "type": "graph",
580
          "xaxis": {
581
            "mode": "time",
582
            "name": null,
583
            "show": true,
584
            "values": []
585
          },
586
          "yaxes": [
587
            {
588
              "format": "short",
589
              "label": null,
590
              "logBase": 1,
591
              "max": null,
592
              "min": null,
593
              "show": true
594
            },
595
            {
596
              "format": "short",
597
              "label": null,
598
              "logBase": 1,
599
              "max": null,
600
              "min": null,
601
              "show": true
602
            }
603
          ]
604
        }
605
      ],
606
      "repeat": null,
607
      "repeatIteration": null,
608
      "repeatRowId": null,
609
      "showTitle": false,
610
      "title": "New row",
611
      "titleSize": "h6"
612
    }
613
  ],
614
  "schemaVersion": 14,
615
  "style": "dark",
616
  "tags": [],
617
  "templating": {
618
    "list": []
619
  },
620
  "time": {
621
    "from": "now-12h",
622
    "to": "now"
623
  },
624
  "timepicker": {
625
    "refresh_intervals": [
626
      "5s",
627
      "10s",
628
      "30s",
629
      "1m",
630
      "5m",
631
      "15m",
632
      "30m",
633
      "1h",
634
      "2h",
635
      "1d"
636
    ],
637
    "time_options": [
638
      "5m",
639
      "15m",
640
      "1h",
641
      "6h",
642
      "12h",
643
      "24h",
644
      "2d",
645
      "7d",
646
      "30d"
647
    ]
648
  },
649
  "timezone": "browser",
650
  "title": "SSO Copy",
651
  "version": 0
652
}

Monitoring

Lancer l'environnement de monitoring

# cd /shared/prometheus/

# docker-compose -f prometheus-compose.yml start

Par défaut Grafana écoute sur le port 3000 et Prometheus sur le port 9090

Pour accéder à Grafana :

http://monitoring.ac-academie.fr:3000

Pour accéder à Prometheus :

http://monitoring.ac-academie.fr:9090