Configure comprehensive monitoring for HAProxy load balancer and Consul service discovery using Prometheus metrics collection and Grafana visualization dashboards. This tutorial covers setting up exporters, configuring scraping targets, and creating production-ready monitoring dashboards.
Prerequisites
- HAProxy 2.4+ installed and running
- Consul 1.15+ installed and configured
- Prometheus server installed
- Grafana server installed
- Root or sudo access
What this solves
HAProxy and Consul are critical infrastructure components that require comprehensive monitoring to ensure high availability and optimal performance. This tutorial shows you how to configure metrics collection from both services using Prometheus exporters and create detailed Grafana dashboards for visualization and alerting.
Step-by-step configuration
Update system packages
Start by updating your package manager to ensure you get the latest versions of all components.
sudo apt update && sudo apt upgrade -y
sudo apt install -y wget curl gnupg
Configure HAProxy metrics endpoint
Enable HAProxy's built-in statistics and metrics endpoint by modifying the main configuration file.
global
stats socket /run/haproxy/admin.sock mode 660 level admin
stats timeout 30s
defaults
stats enable
stats uri /stats
stats refresh 30s
stats admin if TRUE
frontend stats
bind *:8404
stats enable
stats uri /stats
stats refresh 5s
stats admin if TRUE
http-request use-service prometheus-exporter if { path /metrics }
frontend web_frontend
bind *:80
default_backend web_servers
backend web_servers
balance roundrobin
server web1 192.168.1.10:80 check
server web2 192.168.1.11:80 check
Install HAProxy Exporter
Download and install the official HAProxy Exporter to collect detailed metrics from HAProxy's stats socket.
cd /tmp
wget https://github.com/prometheus/haproxy_exporter/releases/download/v0.15.0/haproxy_exporter-0.15.0.linux-amd64.tar.gz
tar xzf haproxy_exporter-0.15.0.linux-amd64.tar.gz
sudo mv haproxy_exporter-0.15.0.linux-amd64/haproxy_exporter /usr/local/bin/
sudo chown root:root /usr/local/bin/haproxy_exporter
sudo chmod 755 /usr/local/bin/haproxy_exporter
Create HAProxy Exporter service
Configure HAProxy Exporter as a systemd service to ensure it starts automatically and runs reliably.
[Unit]
Description=HAProxy Exporter
Wants=network-online.target
After=network-online.target
[Service]
User=nobody
Group=nogroup
Type=simple
ExecStart=/usr/local/bin/haproxy_exporter \
--haproxy.scrape-uri=unix:/run/haproxy/admin.sock \
--web.listen-address=0.0.0.0:9101
SyslogIdentifier=haproxy_exporter
Restart=always
RestartSec=10
[Install]
WantedBy=multi-user.target
Configure Consul metrics
Enable Prometheus metrics in Consul by updating the configuration file with telemetry settings.
{
"datacenter": "dc1",
"data_dir": "/var/lib/consul",
"log_level": "INFO",
"server": true,
"ui_config": {
"enabled": true
},
"client_addr": "0.0.0.0",
"bind_addr": "0.0.0.0",
"telemetry": {
"prometheus_retention_time": "30s",
"disable_hostname": true
},
"ports": {
"grpc": 8502
},
"connect": {
"enabled": true
}
}
Install Consul Exporter
Download and configure the Consul Exporter to collect additional service discovery and health check metrics.
cd /tmp
wget https://github.com/prometheus/consul_exporter/releases/download/v0.11.0/consul_exporter-0.11.0.linux-amd64.tar.gz
tar xzf consul_exporter-0.11.0.linux-amd64.tar.gz
sudo mv consul_exporter-0.11.0.linux-amd64/consul_exporter /usr/local/bin/
sudo chown root:root /usr/local/bin/consul_exporter
sudo chmod 755 /usr/local/bin/consul_exporter
Create Consul Exporter service
Set up the Consul Exporter as a systemd service with appropriate configuration for your environment.
[Unit]
Description=Consul Exporter
Wants=network-online.target
After=network-online.target
[Service]
User=nobody
Group=nogroup
Type=simple
ExecStart=/usr/local/bin/consul_exporter \
--consul.server=localhost:8500 \
--web.listen-address=0.0.0.0:9107
SyslogIdentifier=consul_exporter
Restart=always
RestartSec=10
[Install]
WantedBy=multi-user.target
Configure Prometheus scraping targets
Add HAProxy and Consul metrics endpoints to your Prometheus configuration to start collecting metrics.
global:
scrape_interval: 15s
evaluation_interval: 15s
rule_files:
- "/etc/prometheus/rules/*.yml"
alerting:
alertmanagers:
- static_configs:
- targets:
- localhost:9093
scrape_configs:
- job_name: 'prometheus'
static_configs:
- targets: ['localhost:9090']
- job_name: 'haproxy'
static_configs:
- targets: ['localhost:9101']
scrape_interval: 5s
metrics_path: /metrics
- job_name: 'haproxy-stats'
static_configs:
- targets: ['localhost:8404']
scrape_interval: 5s
metrics_path: /metrics
- job_name: 'consul'
static_configs:
- targets: ['localhost:8500']
scrape_interval: 5s
metrics_path: /v1/agent/metrics
params:
format: ['prometheus']
- job_name: 'consul-exporter'
static_configs:
- targets: ['localhost:9107']
scrape_interval: 15s
Create alerting rules
Define Prometheus alerting rules for critical HAProxy and Consul metrics to receive notifications about issues.
groups:
- name: haproxy-alerts
rules:
- alert: HAProxyDown
expr: up{job="haproxy"} == 0
for: 1m
labels:
severity: critical
annotations:
summary: "HAProxy instance is down"
description: "HAProxy instance {{ $labels.instance }} has been down for more than 1 minute"
- alert: HAProxyBackendDown
expr: haproxy_server_up == 0
for: 30s
labels:
severity: warning
annotations:
summary: "HAProxy backend server is down"
description: "Backend server {{ $labels.server }} in {{ $labels.backend }} is down"
- alert: HAProxyHighResponseTime
expr: haproxy_server_response_time_average_seconds > 1
for: 2m
labels:
severity: warning
annotations:
summary: "HAProxy high response time"
description: "Average response time is {{ $value }}s on {{ $labels.server }}"
- name: consul-alerts
rules:
- alert: ConsulDown
expr: up{job="consul"} == 0
for: 1m
labels:
severity: critical
annotations:
summary: "Consul instance is down"
description: "Consul instance {{ $labels.instance }} has been down for more than 1 minute"
- alert: ConsulServiceUnhealthy
expr: consul_health_service_status{status!="passing"} > 0
for: 30s
labels:
severity: warning
annotations:
summary: "Consul service is unhealthy"
description: "Service {{ $labels.service_name }} is in {{ $labels.status }} state"
- alert: ConsulLeaderElection
expr: changes(consul_raft_leader[10m]) > 0
for: 0s
labels:
severity: warning
annotations:
summary: "Consul leader election occurred"
description: "Consul cluster had a leader election in the last 10 minutes"
Enable and start all services
Start and enable all the monitoring services to begin collecting metrics from HAProxy and Consul.
sudo systemctl daemon-reload
sudo systemctl enable --now haproxy-exporter
sudo systemctl enable --now consul-exporter
sudo systemctl restart haproxy
sudo systemctl restart consul
sudo systemctl restart prometheus
Import Grafana dashboards
Download and import pre-built dashboard templates for HAProxy and Consul monitoring visualization.
curl -X POST \
http://admin:admin@localhost:3000/api/dashboards/db \
-H 'Content-Type: application/json' \
-d @/tmp/haproxy-dashboard.json
curl -X POST \
http://admin:admin@localhost:3000/api/dashboards/db \
-H 'Content-Type: application/json' \
-d @/tmp/consul-dashboard.json
Create HAProxy dashboard configuration
Create a comprehensive Grafana dashboard for HAProxy metrics including frontend, backend, and server statistics.
{
"dashboard": {
"id": null,
"title": "HAProxy Metrics",
"tags": ["haproxy", "loadbalancer"],
"timezone": "browser",
"panels": [
{
"id": 1,
"title": "Frontend Requests/sec",
"type": "graph",
"targets": [
{
"expr": "rate(haproxy_frontend_http_requests_total[1m])",
"legendFormat": "{{ frontend }}"
}
],
"gridPos": {"h": 8, "w": 12, "x": 0, "y": 0}
},
{
"id": 2,
"title": "Backend Response Time",
"type": "graph",
"targets": [
{
"expr": "haproxy_server_response_time_average_seconds",
"legendFormat": "{{ server }}"
}
],
"gridPos": {"h": 8, "w": 12, "x": 12, "y": 0}
},
{
"id": 3,
"title": "Server Status",
"type": "stat",
"targets": [
{
"expr": "haproxy_server_up",
"legendFormat": "{{ server }}"
}
],
"gridPos": {"h": 8, "w": 24, "x": 0, "y": 8}
}
],
"time": {
"from": "now-1h",
"to": "now"
},
"refresh": "5s"
}
}
Create Consul dashboard configuration
Set up a detailed Grafana dashboard for monitoring Consul cluster health, service discovery, and performance metrics.
{
"dashboard": {
"id": null,
"title": "Consul Metrics",
"tags": ["consul", "servicediscovery"],
"timezone": "browser",
"panels": [
{
"id": 1,
"title": "Consul Nodes",
"type": "stat",
"targets": [
{
"expr": "consul_serf_lan_members",
"legendFormat": "Cluster Members"
}
],
"gridPos": {"h": 4, "w": 6, "x": 0, "y": 0}
},
{
"id": 2,
"title": "Registered Services",
"type": "stat",
"targets": [
{
"expr": "count(consul_catalog_service_node_healthy)",
"legendFormat": "Services"
}
],
"gridPos": {"h": 4, "w": 6, "x": 6, "y": 0}
},
{
"id": 3,
"title": "Service Health Status",
"type": "piechart",
"targets": [
{
"expr": "sum by (status) (consul_health_service_status)",
"legendFormat": "{{ status }}"
}
],
"gridPos": {"h": 8, "w": 12, "x": 12, "y": 0}
},
{
"id": 4,
"title": "Raft Commit Rate",
"type": "graph",
"targets": [
{
"expr": "rate(consul_raft_commitTime_sum[1m])",
"legendFormat": "Commit Rate"
}
],
"gridPos": {"h": 8, "w": 12, "x": 0, "y": 4}
}
],
"time": {
"from": "now-1h",
"to": "now"
},
"refresh": "10s"
}
}
Verify your setup
Check that all services are running and metrics are being collected properly.
sudo systemctl status haproxy-exporter
sudo systemctl status consul-exporter
curl http://localhost:9101/metrics | grep haproxy
curl http://localhost:9107/metrics | grep consul
curl http://localhost:8500/v1/agent/metrics?format=prometheus
prometheus --version
grafana-server --version
Common issues
| Symptom | Cause | Fix |
|---|---|---|
| HAProxy exporter connection refused | Stats socket not accessible | Check HAProxy socket permissions: sudo chmod 660 /run/haproxy/admin.sock |
| Consul metrics not appearing | Telemetry not enabled | Add telemetry configuration to consul.json and restart Consul |
| Prometheus targets down | Firewall blocking ports | Open ports 9101, 9107, 8500: sudo ufw allow 9101,9107,8500 |
| Grafana dashboard empty | Data source not configured | Add Prometheus as data source in Grafana: http://localhost:9090 |
| Exporter service fails to start | Binary permissions incorrect | Fix ownership and permissions: sudo chown root:root /usr/local/bin/exporter && sudo chmod 755 /usr/local/bin/exporter |
Next steps
- Install and configure Grafana with Prometheus for system monitoring
- Configure HAProxy with Consul for dynamic service discovery and automatic backend updates
- Set up Prometheus and Grafana monitoring stack with Docker compose
- Configure Prometheus alerting with AlertManager and notification channels
- Implement HAProxy SSL termination with Let's Encrypt certificates
Automated install script
Run this to automate the entire setup
#!/usr/bin/env bash
set -euo pipefail
# Colors for output
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m' # No Color
# Global variables
CONSUL_HOST="${1:-localhost:8500}"
HAPROXY_STATS_SOCKET="/run/haproxy/admin.sock"
TOTAL_STEPS=10
# Usage information
usage() {
echo "Usage: $0 [consul_host:port]"
echo " consul_host:port Consul server address (default: localhost:8500)"
echo "Example: $0 192.168.1.100:8500"
exit 1
}
# Print colored output
print_status() {
echo -e "${GREEN}[INFO]${NC} $1"
}
print_warning() {
echo -e "${YELLOW}[WARNING]${NC} $1"
}
print_error() {
echo -e "${RED}[ERROR]${NC} $1"
}
print_step() {
echo -e "${BLUE}[$1/$TOTAL_STEPS]${NC} $2"
}
# Cleanup function for rollback
cleanup() {
print_error "Installation failed. Cleaning up..."
systemctl stop haproxy_exporter consul_exporter 2>/dev/null || true
systemctl disable haproxy_exporter consul_exporter 2>/dev/null || true
rm -f /etc/systemd/system/haproxy_exporter.service
rm -f /etc/systemd/system/consul_exporter.service
rm -f /usr/local/bin/haproxy_exporter
rm -f /usr/local/bin/consul_exporter
systemctl daemon-reload
}
# Set trap for cleanup on error
trap cleanup ERR
# Check if running as root or with sudo
check_privileges() {
if [[ $EUID -ne 0 ]]; then
print_error "This script must be run as root or with sudo"
exit 1
fi
}
# Detect Linux distribution
detect_distro() {
if [ ! -f /etc/os-release ]; then
print_error "Cannot detect Linux distribution"
exit 1
fi
. /etc/os-release
case "$ID" in
ubuntu|debian)
PKG_MGR="apt"
PKG_INSTALL="apt install -y"
PKG_UPDATE="apt update && apt upgrade -y"
HAPROXY_CONFIG="/etc/haproxy/haproxy.cfg"
CONSUL_CONFIG="/etc/consul.d/consul.json"
;;
almalinux|rocky|centos|rhel|ol|fedora)
PKG_MGR="dnf"
PKG_INSTALL="dnf install -y"
PKG_UPDATE="dnf update -y"
HAPROXY_CONFIG="/etc/haproxy/haproxy.cfg"
CONSUL_CONFIG="/etc/consul.d/consul.json"
;;
amzn)
PKG_MGR="yum"
PKG_INSTALL="yum install -y"
PKG_UPDATE="yum update -y"
HAPROXY_CONFIG="/etc/haproxy/haproxy.cfg"
CONSUL_CONFIG="/etc/consul.d/consul.json"
;;
*)
print_error "Unsupported distribution: $ID"
exit 1
;;
esac
}
# Validate arguments
if [[ "${1:-}" == "-h" ]] || [[ "${1:-}" == "--help" ]]; then
usage
fi
print_status "Starting HAProxy and Consul monitoring setup"
check_privileges
detect_distro
print_step 1 "Updating system packages"
eval $PKG_UPDATE
eval $PKG_INSTALL wget curl gnupg tar
print_step 2 "Creating system users and directories"
useradd --system --no-create-home --shell /bin/false haproxy_exporter 2>/dev/null || true
useradd --system --no-create-home --shell /bin/false consul_exporter 2>/dev/null || true
mkdir -p /etc/consul.d /var/lib/consul /run/haproxy
chown consul:consul /var/lib/consul 2>/dev/null || chown nobody:nogroup /var/lib/consul
print_step 3 "Installing HAProxy Exporter"
cd /tmp
wget -q https://github.com/prometheus/haproxy_exporter/releases/download/v0.15.0/haproxy_exporter-0.15.0.linux-amd64.tar.gz
tar xzf haproxy_exporter-0.15.0.linux-amd64.tar.gz
mv haproxy_exporter-0.15.0.linux-amd64/haproxy_exporter /usr/local/bin/
chown root:root /usr/local/bin/haproxy_exporter
chmod 755 /usr/local/bin/haproxy_exporter
print_step 4 "Creating HAProxy Exporter systemd service"
cat > /etc/systemd/system/haproxy_exporter.service << 'EOF'
[Unit]
Description=HAProxy Exporter
Wants=network-online.target
After=network-online.target
[Service]
User=haproxy_exporter
Group=haproxy_exporter
Type=simple
ExecStart=/usr/local/bin/haproxy_exporter \
--haproxy.scrape-uri=unix:/run/haproxy/admin.sock \
--web.listen-address=0.0.0.0:9101
SyslogIdentifier=haproxy_exporter
Restart=always
RestartSec=10
ProtectSystem=strict
ProtectHome=true
NoNewPrivileges=true
[Install]
WantedBy=multi-user.target
EOF
print_step 5 "Installing Consul Exporter"
cd /tmp
wget -q https://github.com/prometheus/consul_exporter/releases/download/v0.11.0/consul_exporter-0.11.0.linux-amd64.tar.gz
tar xzf consul_exporter-0.11.0.linux-amd64.tar.gz
mv consul_exporter-0.11.0.linux-amd64/consul_exporter /usr/local/bin/
chown root:root /usr/local/bin/consul_exporter
chmod 755 /usr/local/bin/consul_exporter
print_step 6 "Creating Consul Exporter systemd service"
cat > /etc/systemd/system/consul_exporter.service << EOF
[Unit]
Description=Consul Exporter
Wants=network-online.target
After=network-online.target
[Service]
User=consul_exporter
Group=consul_exporter
Type=simple
ExecStart=/usr/local/bin/consul_exporter \
--consul.server=$CONSUL_HOST \
--web.listen-address=0.0.0.0:9107
SyslogIdentifier=consul_exporter
Restart=always
RestartSec=10
ProtectSystem=strict
ProtectHome=true
NoNewPrivileges=true
[Install]
WantedBy=multi-user.target
EOF
print_step 7 "Configuring HAProxy for metrics"
if [ ! -f "$HAPROXY_CONFIG.backup" ] && [ -f "$HAPROXY_CONFIG" ]; then
cp "$HAPROXY_CONFIG" "$HAPROXY_CONFIG.backup"
fi
cat >> "$HAPROXY_CONFIG" << 'EOF'
# Prometheus metrics configuration
global
stats socket /run/haproxy/admin.sock mode 660 level admin group haproxy
stats timeout 30s
frontend stats
bind *:8404
stats enable
stats uri /stats
stats refresh 5s
stats admin if TRUE
http-request use-service prometheus-exporter if { path /metrics }
EOF
print_step 8 "Configuring Consul for metrics"
cat > "$CONSUL_CONFIG" << 'EOF'
{
"datacenter": "dc1",
"data_dir": "/var/lib/consul",
"log_level": "INFO",
"server": true,
"ui_config": {
"enabled": true
},
"client_addr": "0.0.0.0",
"bind_addr": "0.0.0.0",
"telemetry": {
"prometheus_retention_time": "30s",
"disable_hostname": true
},
"ports": {
"grpc": 8502
},
"connect": {
"enabled": true
}
}
EOF
chown consul:consul "$CONSUL_CONFIG" 2>/dev/null || chown nobody:nogroup "$CONSUL_CONFIG"
chmod 640 "$CONSUL_CONFIG"
print_step 9 "Starting and enabling services"
systemctl daemon-reload
systemctl enable haproxy_exporter consul_exporter
systemctl restart haproxy 2>/dev/null || print_warning "HAProxy not running or not installed"
systemctl restart consul 2>/dev/null || print_warning "Consul not running or not installed"
systemctl start haproxy_exporter
systemctl start consul_exporter
print_step 10 "Verifying installation"
sleep 5
# Check services
if systemctl is-active --quiet haproxy_exporter; then
print_status "HAProxy Exporter is running"
else
print_error "HAProxy Exporter failed to start"
fi
if systemctl is-active --quiet consul_exporter; then
print_status "Consul Exporter is running"
else
print_error "Consul Exporter failed to start"
fi
# Test endpoints
if curl -s http://localhost:9101/metrics > /dev/null; then
print_status "HAProxy metrics endpoint accessible on port 9101"
else
print_warning "HAProxy metrics endpoint not accessible"
fi
if curl -s http://localhost:9107/metrics > /dev/null; then
print_status "Consul metrics endpoint accessible on port 9107"
else
print_warning "Consul metrics endpoint not accessible"
fi
# Clean up temporary files
rm -f /tmp/haproxy_exporter-*.tar.gz /tmp/consul_exporter-*.tar.gz
rm -rf /tmp/haproxy_exporter-* /tmp/consul_exporter-*
print_status "Installation completed successfully!"
echo ""
echo "Next steps:"
echo "1. Add these targets to your Prometheus configuration:"
echo " - localhost:9101 (HAProxy Exporter)"
echo " - localhost:9107 (Consul Exporter)"
echo "2. HAProxy stats available at: http://your-server:8404/stats"
echo "3. Import Grafana dashboards for HAProxy (ID: 2428) and Consul (ID: 3965)"
Review the script before running. Execute with: bash install.sh