Skip to content

HAProxy Load Balancer

Introduction

HAProxy distribue le trafic entre les services OpenStack et fournit les health checks. Avec Kolla-Ansible, HAProxy est déployé automatiquement sur chaque controller et protégé par Keepalived.

Prérequis

  • Concepts HA
  • Cluster OpenStack multi-controller
  • Compréhension des concepts de load balancing

Points à apprendre

Architecture HAProxy

graph TB
    client["Client<br/>API/Horizon"]

    subgraph ha["HA Layer"]
        vip["VIP<br/>Keepalived<br/>10.0.0.10<br/>Floating IP"]
        haproxy1["HAProxy-1<br/>Controller-1<br/>Active"]
        haproxy2["HAProxy-2<br/>Controller-2<br/>Standby"]
        haproxy3["HAProxy-3<br/>Controller-3<br/>Standby"]
    end

    subgraph backends["Backend Services"]
        keystone1["Keystone<br/>Controller-1"]
        keystone2["Keystone<br/>Controller-2"]
        keystone3["Keystone<br/>Controller-3"]
        nova1["Nova API<br/>Controller-1"]
        nova2["Nova API<br/>Controller-2"]
        nova3["Nova API<br/>Controller-3"]
    end

    client -->|"HTTPS<br/>443"| vip
    vip -->|"Forward<br/>Active"| haproxy1

    haproxy1 -->|"Round-robin<br/>5000"| keystone1
    haproxy1 --> keystone2
    haproxy1 --> keystone3

    haproxy1 -->|"Round-robin<br/>8774"| nova1
    haproxy1 --> nova2
    haproxy1 --> nova3

Configuration Kolla

# /etc/kolla/globals.yml

# HAProxy est activé par défaut avec enable_haproxy
enable_haproxy: "yes"

# VIP pour les APIs
kolla_internal_vip_address: "10.0.0.10"
kolla_external_vip_address: "203.0.113.10"

# Interface pour la VIP
network_interface: "eth0"
kolla_external_vip_interface: "eth1"

# TLS
kolla_enable_tls_internal: "yes"
kolla_enable_tls_external: "yes"

Configuration HAProxy générée

# Voir la configuration HAProxy
docker exec haproxy cat /etc/haproxy/haproxy.cfg
# /etc/haproxy/haproxy.cfg (extrait)

global
    daemon
    maxconn 40000
    log /dev/log local0
    stats socket /var/lib/kolla/haproxy/haproxy.sock mode 660 level admin

defaults
    log global
    mode http
    option httplog
    option dontlognull
    option http-server-close
    option redispatch
    retries 3
    timeout http-request 10s
    timeout queue 1m
    timeout connect 10s
    timeout client 1m
    timeout server 1m
    timeout http-keep-alive 10s
    timeout check 10s
    maxconn 10000

# Frontend Keystone
frontend keystone_public
    bind 10.0.0.10:5000 ssl crt /etc/haproxy/certs/haproxy.pem
    default_backend keystone_public_back

backend keystone_public_back
    balance roundrobin
    option httpchk GET /healthcheck
    http-check expect status 200
    server controller-1 10.0.0.11:5000 check inter 2s fall 3 rise 2
    server controller-2 10.0.0.12:5000 check inter 2s fall 3 rise 2
    server controller-3 10.0.0.13:5000 check inter 2s fall 3 rise 2

# Frontend Nova API
frontend nova_api
    bind 10.0.0.10:8774 ssl crt /etc/haproxy/certs/haproxy.pem
    default_backend nova_api_back

backend nova_api_back
    balance roundrobin
    option httpchk GET /
    server controller-1 10.0.0.11:8774 check inter 2s fall 3 rise 2
    server controller-2 10.0.0.12:8774 check inter 2s fall 3 rise 2
    server controller-3 10.0.0.13:8774 check inter 2s fall 3 rise 2

# Stats
listen stats
    bind 10.0.0.10:1984
    mode http
    stats enable
    stats uri /stats
    stats refresh 10s
    stats admin if LOCALHOST

Services exposés par HAProxy

Service Port Health Check
Keystone 5000 GET /healthcheck
Nova API 8774 GET /
Neutron 9696 GET /
Glance 9292 GET /healthcheck
Cinder 8776 GET /
Horizon 443 GET /
Placement 8778 GET /
Heat 8004 GET /
Octavia 9876 GET /

Algorithmes de load balancing

# Round-robin (défaut)
balance roundrobin

# Least connections (meilleur pour requêtes longues)
balance leastconn

# Source IP hash (sticky sessions)
balance source

# URI hash (cache optimization)
balance uri

Health checks avancés

# Check HTTP simple
option httpchk GET /healthcheck
http-check expect status 200

# Check avec header Host
option httpchk GET /healthcheck HTTP/1.1\r\nHost:\ localhost

# Paramètres de check
server controller-1 10.0.0.11:5000 check inter 2s fall 3 rise 2
# inter 2s = check toutes les 2 secondes
# fall 3 = marqué DOWN après 3 échecs
# rise 2 = marqué UP après 2 succès

Configuration personnalisée Kolla

# /etc/kolla/config/haproxy/haproxy.cfg

# Ajouter des configurations custom
# Sera inclus après la config générée

# Exemple: timeout plus long pour Heat
frontend heat_api
    timeout client 10m

backend heat_api_back
    timeout server 10m

Monitoring HAProxy

# Stats via socket
docker exec haproxy echo "show stat" | socat /var/lib/kolla/haproxy/haproxy.sock stdio

# Stats page web
curl http://10.0.0.10:1984/stats

# Métriques pour Prometheus
curl http://10.0.0.10:1984/stats\;csv

# État des backends
docker exec haproxy echo "show servers state" | \
    socat /var/lib/kolla/haproxy/haproxy.sock stdio

Diagramme de flux HAProxy

sequenceDiagram
    participant Client
    participant VIP as VIP<br/>10.0.0.10
    participant HA as HAProxy
    participant B1 as Backend-1
    participant B2 as Backend-2
    participant B3 as Backend-3

    Client->>VIP: HTTPS request<br/>(port 443)
    VIP->>HA: Forward to active<br/>HAProxy instance

    HA->>HA: SSL termination<br/>Balance algorithm

    alt Backend-1 healthy
        HA->>B1: Forward request
        B1-->>HA: Response
    else Backend-1 down
        HA->>B2: Failover to Backend-2
        B2-->>HA: Response
    end

    HA-->>VIP: Response
    VIP-->>Client: HTTPS response

Exemples pratiques

Vérifier l'état HAProxy

#!/bin/bash
# haproxy-status.sh

echo "=== HAProxy Process ==="
docker exec haproxy ps aux | grep haproxy

echo -e "\n=== Backend Status ==="
docker exec haproxy sh -c 'echo "show stat" | socat /var/lib/kolla/haproxy/haproxy.sock stdio' | \
    awk -F, '{print $1, $2, $18}' | column -t

echo -e "\n=== Connections ==="
docker exec haproxy sh -c 'echo "show info" | socat /var/lib/kolla/haproxy/haproxy.sock stdio' | \
    grep -E "(CurrConns|MaxConn|Uptime)"

echo -e "\n=== Error Rate ==="
docker exec haproxy sh -c 'echo "show stat" | socat /var/lib/kolla/haproxy/haproxy.sock stdio' | \
    awk -F, 'NR>1 {print $1, $2, "errors:", $14}' | column -t

Test de failover

# Arrêter un backend
docker stop nova_api  # Sur controller-1

# Vérifier que HAProxy détecte le DOWN
docker exec haproxy sh -c 'echo "show stat" | socat /var/lib/kolla/haproxy/haproxy.sock stdio' | \
    grep nova_api

# Les requêtes doivent continuer à fonctionner
openstack server list

# Restaurer
docker start nova_api

Gestion manuelle des backends

# Mettre un serveur en maintenance
docker exec haproxy sh -c 'echo "disable server nova_api_back/controller-1" | \
    socat /var/lib/kolla/haproxy/haproxy.sock stdio'

# Réactiver
docker exec haproxy sh -c 'echo "enable server nova_api_back/controller-1" | \
    socat /var/lib/kolla/haproxy/haproxy.sock stdio'

# Changer le poids (drain progressif)
docker exec haproxy sh -c 'echo "set server nova_api_back/controller-1 weight 0" | \
    socat /var/lib/kolla/haproxy/haproxy.sock stdio'

Ressources

Checkpoint

  • HAProxy est déployé sur tous les controllers
  • Tous les backends sont UP dans les stats
  • Le failover fonctionne lors de l'arrêt d'un backend
  • Les health checks sont configurés correctement
  • La page de stats est accessible
  • TLS est configuré pour les endpoints externes