Deploy a production-grade Jaeger distributed tracing cluster with Elasticsearch backend, load-balanced collectors, and automatic failover for enterprise-scale microservices monitoring.
Prerequisites
- Root or sudo access
- Minimum 8GB RAM
- Java 11+ installed
- Network access for package downloads
- Multiple servers for true HA (optional)
What this solves
A single Jaeger instance creates a bottleneck and single point of failure for distributed tracing in production environments. This tutorial sets up a high-availability Jaeger cluster with multiple collectors behind a load balancer, Elasticsearch backend storage, and automatic failover to ensure continuous tracing collection even when individual components fail.
Step-by-step installation
Update system packages and install dependencies
Start by updating your package manager and installing required dependencies for the Jaeger cluster setup.
sudo apt update && sudo apt upgrade -y
sudo apt install -y wget curl openjdk-11-jre-headless systemd
Create Jaeger system user and directories
Create a dedicated system user for Jaeger components and set up the necessary directory structure with proper permissions.
sudo useradd --system --shell /bin/false --home-dir /opt/jaeger jaeger
sudo mkdir -p /opt/jaeger/{bin,config,logs,data}
sudo mkdir -p /etc/jaeger
sudo chown -R jaeger:jaeger /opt/jaeger
sudo chmod 755 /opt/jaeger/{bin,config}
sudo chmod 775 /opt/jaeger/{logs,data}
Download and install Jaeger binaries
Download the latest Jaeger release and extract the binaries to the appropriate directories.
cd /tmp
wget https://github.com/jaegertracing/jaeger/releases/download/v1.53.0/jaeger-1.53.0-linux-amd64.tar.gz
tar -xzf jaeger-1.53.0-linux-amd64.tar.gz
sudo cp jaeger-1.53.0-linux-amd64/jaeger-collector /opt/jaeger/bin/
sudo cp jaeger-1.53.0-linux-amd64/jaeger-query /opt/jaeger/bin/
sudo cp jaeger-1.53.0-linux-amd64/jaeger-agent /opt/jaeger/bin/
sudo chown jaeger:jaeger /opt/jaeger/bin/*
sudo chmod 755 /opt/jaeger/bin/*
Install and configure Elasticsearch cluster
Set up Elasticsearch as the backend storage for Jaeger traces. This provides persistence and enables distributed storage across multiple nodes.
wget -qO - https://artifacts.elastic.co/GPG-KEY-elasticsearch | sudo gpg --dearmor -o /usr/share/keyrings/elasticsearch-keyring.gpg
echo "deb [signed-by=/usr/share/keyrings/elasticsearch-keyring.gpg] https://artifacts.elastic.co/packages/8.x/apt stable main" | sudo tee /etc/apt/sources.list.d/elastic-8.x.list
sudo apt update
sudo apt install -y elasticsearch
Configure Elasticsearch for Jaeger
Configure Elasticsearch with optimized settings for Jaeger workloads, including cluster discovery and memory allocation.
cluster.name: jaeger-cluster
node.name: jaeger-es-01
path.data: /var/lib/elasticsearch
path.logs: /var/log/elasticsearch
network.host: 0.0.0.0
http.port: 9200
discovery.type: single-node
xpack.security.enabled: false
xpack.monitoring.collection.enabled: false
action.destructive_requires_name: false
indices.query.bool.max_clause_count: 10000
bootstrap.memory_lock: true
-Xms2g
-Xmx2g
sudo systemctl enable elasticsearch
sudo systemctl start elasticsearch
Install and configure HAProxy for load balancing
Set up HAProxy to load balance traffic across multiple Jaeger collectors with health checks and automatic failover.
sudo apt install -y haproxy
For more advanced HAProxy configuration patterns, see our tutorial on HAProxy high availability load balancing.
Configure HAProxy for Jaeger collector load balancing
Configure HAProxy with health checks and failover for the Jaeger collector cluster.
global
daemon
chroot /var/lib/haproxy
stats socket /run/haproxy/admin.sock mode 660 level admin
stats timeout 30s
user haproxy
group haproxy
defaults
mode http
timeout connect 5000ms
timeout client 50000ms
timeout server 50000ms
option httplog
option dontlognull
option redispatch
retries 3
frontend jaeger-collector-grpc
bind *:14250
mode tcp
default_backend jaeger-collectors-grpc
frontend jaeger-collector-http
bind *:14268
mode http
default_backend jaeger-collectors-http
frontend jaeger-query
bind *:16686
mode http
default_backend jaeger-query-servers
backend jaeger-collectors-grpc
mode tcp
balance roundrobin
option tcp-check
tcp-check connect port 14250
server collector1 127.0.0.1:14251 check
server collector2 127.0.0.1:14252 check
server collector3 127.0.0.1:14253 check
backend jaeger-collectors-http
mode http
balance roundrobin
option httpchk GET /
server collector1 127.0.0.1:14269 check
server collector2 127.0.0.1:14270 check
server collector3 127.0.0.1:14271 check
backend jaeger-query-servers
mode http
balance roundrobin
option httpchk GET /
server query1 127.0.0.1:16687 check
server query2 127.0.0.1:16688 check
listen stats
bind *:8404
stats enable
stats uri /stats
stats refresh 30s
stats admin if TRUE
Create Jaeger collector configuration
Configure multiple Jaeger collectors with Elasticsearch backend and different ports for high availability.
collector:
grpc-server:
host-port: 127.0.0.1:14251
http-server:
host-port: 127.0.0.1:14269
queue:
size: 2000
workers: 50
span-storage:
type: elasticsearch
elasticsearch:
server-urls: http://localhost:9200
index-prefix: jaeger
create-index-templates: true
log-level: info
collector:
grpc-server:
host-port: 127.0.0.1:14252
http-server:
host-port: 127.0.0.1:14270
queue:
size: 2000
workers: 50
span-storage:
type: elasticsearch
elasticsearch:
server-urls: http://localhost:9200
index-prefix: jaeger
create-index-templates: true
log-level: info
collector:
grpc-server:
host-port: 127.0.0.1:14253
http-server:
host-port: 127.0.0.1:14271
queue:
size: 2000
workers: 50
span-storage:
type: elasticsearch
elasticsearch:
server-urls: http://localhost:9200
index-prefix: jaeger
create-index-templates: true
log-level: info
Create Jaeger query configuration
Configure multiple Jaeger query instances for the web UI with load balancing and failover support.
query:
base-path: /
static-files: /usr/share/jaeger/
ui-config: /etc/jaeger/ui.json
http-server:
host-port: 127.0.0.1:16687
span-storage:
type: elasticsearch
elasticsearch:
server-urls: http://localhost:9200
index-prefix: jaeger
log-level: info
query:
base-path: /
static-files: /usr/share/jaeger/
ui-config: /etc/jaeger/ui.json
http-server:
host-port: 127.0.0.1:16688
span-storage:
type: elasticsearch
elasticsearch:
server-urls: http://localhost:9200
index-prefix: jaeger
log-level: info
{
"monitor": {
"menuEnabled": true
},
"dependencies": {
"menuEnabled": true
},
"archiveEnabled": true
}
Create systemd services for Jaeger collectors
Create systemd service files for each Jaeger collector instance with proper resource limits and restart policies.
[Unit]
Description=Jaeger Collector 01
After=network.target elasticsearch.service
Requires=elasticsearch.service
[Service]
Type=simple
User=jaeger
Group=jaeger
ExecStart=/opt/jaeger/bin/jaeger-collector --config-file=/etc/jaeger/collector-01.yaml
Restart=always
RestartSec=5
LimitNOFILE=65536
WorkingDirectory=/opt/jaeger
StandardOutput=journal
StandardError=journal
[Install]
WantedBy=multi-user.target
[Unit]
Description=Jaeger Collector 02
After=network.target elasticsearch.service
Requires=elasticsearch.service
[Service]
Type=simple
User=jaeger
Group=jaeger
ExecStart=/opt/jaeger/bin/jaeger-collector --config-file=/etc/jaeger/collector-02.yaml
Restart=always
RestartSec=5
LimitNOFILE=65536
WorkingDirectory=/opt/jaeger
StandardOutput=journal
StandardError=journal
[Install]
WantedBy=multi-user.target
[Unit]
Description=Jaeger Collector 03
After=network.target elasticsearch.service
Requires=elasticsearch.service
[Service]
Type=simple
User=jaeger
Group=jaeger
ExecStart=/opt/jaeger/bin/jaeger-collector --config-file=/etc/jaeger/collector-03.yaml
Restart=always
RestartSec=5
LimitNOFILE=65536
WorkingDirectory=/opt/jaeger
StandardOutput=journal
StandardError=journal
[Install]
WantedBy=multi-user.target
Create systemd services for Jaeger query instances
Create systemd service files for the Jaeger query web UI instances.
[Unit]
Description=Jaeger Query 01
After=network.target elasticsearch.service
Requires=elasticsearch.service
[Service]
Type=simple
User=jaeger
Group=jaeger
ExecStart=/opt/jaeger/bin/jaeger-query --config-file=/etc/jaeger/query-01.yaml
Restart=always
RestartSec=5
LimitNOFILE=65536
WorkingDirectory=/opt/jaeger
StandardOutput=journal
StandardError=journal
[Install]
WantedBy=multi-user.target
[Unit]
Description=Jaeger Query 02
After=network.target elasticsearch.service
Requires=elasticsearch.service
[Service]
Type=simple
User=jaeger
Group=jaeger
ExecStart=/opt/jaeger/bin/jaeger-query --config-file=/etc/jaeger/query-02.yaml
Restart=always
RestartSec=5
LimitNOFILE=65536
WorkingDirectory=/opt/jaeger
StandardOutput=journal
StandardError=journal
[Install]
WantedBy=multi-user.target
Set proper file ownership and permissions
Ensure all configuration files have the correct ownership and minimal required permissions.
sudo chown jaeger:jaeger /etc/jaeger/.yaml /etc/jaeger/.json
sudo chmod 644 /etc/jaeger/.yaml /etc/jaeger/.json
sudo chown root:root /etc/systemd/system/jaeger-*.service
sudo chmod 644 /etc/systemd/system/jaeger-*.service
Configure firewall rules
Open the necessary firewall ports for Jaeger cluster communication and external access.
sudo ufw allow 14250/tcp comment "Jaeger Collector gRPC"
sudo ufw allow 14268/tcp comment "Jaeger Collector HTTP"
sudo ufw allow 16686/tcp comment "Jaeger Query UI"
sudo ufw allow 8404/tcp comment "HAProxy Stats"
sudo ufw allow 9200/tcp comment "Elasticsearch HTTP"
sudo ufw reload
Enable and start all services
Start the Elasticsearch backend, Jaeger components, and HAProxy load balancer with proper startup order.
sudo systemctl daemon-reload
sudo systemctl enable --now elasticsearch
sudo systemctl enable --now jaeger-collector-01 jaeger-collector-02 jaeger-collector-03
sudo systemctl enable --now jaeger-query-01 jaeger-query-02
sudo systemctl enable --now haproxy
Create monitoring script for cluster health
Set up automated monitoring to check the health of all cluster components and alert on failures.
#!/bin/bash
set -euo pipefail
ELASTICSEARCH_URL="http://localhost:9200"
HAPROXY_STATS="http://localhost:8404/stats;csv"
LOG_FILE="/opt/jaeger/logs/health-check.log"
log() {
echo "[$(date '+%Y-%m-%d %H:%M:%S')] $1" | tee -a "$LOG_FILE"
}
Check Elasticsearch
if ! curl -s "$ELASTICSEARCH_URL/_cluster/health" | jq -e '.status == "green" or .status == "yellow"' > /dev/null; then
log "ERROR: Elasticsearch cluster unhealthy"
exit 1
fi
Check HAProxy backends
if ! curl -s "$HAPROXY_STATS" | grep -q "jaeger-collectors-grpc,collector1,.*,UP"; then
log "WARNING: Collector 1 is down"
fi
Check collector services
for i in {01..03}; do
if ! systemctl is-active --quiet "jaeger-collector-$i"; then
log "ERROR: jaeger-collector-$i service is not running"
systemctl restart "jaeger-collector-$i"
fi
done
Check query services
for i in {01..02}; do
if ! systemctl is-active --quiet "jaeger-query-$i"; then
log "ERROR: jaeger-query-$i service is not running"
systemctl restart "jaeger-query-$i"
fi
done
log "Health check completed successfully"
sudo chmod 755 /opt/jaeger/bin/health-check.sh
sudo chown jaeger:jaeger /opt/jaeger/bin/health-check.sh
Set up automated health monitoring with cron
Schedule regular health checks to monitor cluster status and automatically restart failed components.
sudo crontab -u jaeger -e
Add the following line to run health checks every 5 minutes:
/5 * /opt/jaeger/bin/health-check.sh
Configure high availability and failover
Configure Elasticsearch index lifecycle management
Set up index lifecycle policies to manage Jaeger trace data retention and optimize storage performance. For detailed ILM configuration, see our tutorial on Elasticsearch index lifecycle management.
curl -X PUT "localhost:9200/_ilm/policy/jaeger-ilm-policy" -H "Content-Type: application/json" -d'
{
"policy": {
"phases": {
"hot": {
"actions": {
"rollover": {
"max_size": "1GB",
"max_age": "1d"
},
"set_priority": {
"priority": 100
}
}
},
"warm": {
"min_age": "2d",
"actions": {
"set_priority": {
"priority": 50
},
"allocate": {
"number_of_replicas": 0
}
}
},
"delete": {
"min_age": "7d",
"actions": {
"delete": {}
}
}
}
}
}'
Configure Jaeger span sampling strategies
Set up dynamic sampling strategies to manage trace volume and ensure consistent performance under high load.
{
"service_strategies": [
{
"service": "frontend",
"type": "probabilistic",
"param": 1.0
},
{
"service": "backend",
"type": "probabilistic",
"param": 0.5
}
],
"default_strategy": {
"type": "probabilistic",
"param": 0.1
}
}
Update collector configurations to use sampling strategies:
echo "sampling:
strategies-file: /etc/jaeger/sampling.json" | sudo tee -a /etc/jaeger/collector-01.yaml
echo "sampling:
strategies-file: /etc/jaeger/sampling.json" | sudo tee -a /etc/jaeger/collector-02.yaml
echo "sampling:
strategies-file: /etc/jaeger/sampling.json" | sudo tee -a /etc/jaeger/collector-03.yaml
Verify your setup
Check that all components are running and the cluster is operational:
# Check Elasticsearch cluster health
curl -s http://localhost:9200/_cluster/health | jq '.status'
Check all Jaeger services
sudo systemctl status jaeger-collector-01 jaeger-collector-02 jaeger-collector-03
sudo systemctl status jaeger-query-01 jaeger-query-02
sudo systemctl status haproxy
Test load balancer endpoints
curl -f http://localhost:14268/api/traces
curl -f http://localhost:16686/
Check HAProxy stats
curl -s http://localhost:8404/stats
Verify Elasticsearch indices
curl -s http://localhost:9200/_cat/indices/jaeger*
Access the Jaeger UI at http://your-server-ip:16686 and verify that traces are being collected and stored properly.
Monitor cluster health and performance
Set up Prometheus metrics collection
Configure Jaeger components to expose Prometheus metrics for monitoring and alerting.
echo "metrics-backend: prometheus" | sudo tee -a /etc/jaeger/collector-01.yaml
echo "metrics-backend: prometheus" | sudo tee -a /etc/jaeger/collector-02.yaml
echo "metrics-backend: prometheus" | sudo tee -a /etc/jaeger/collector-03.yaml
echo "metrics-backend: prometheus" | sudo tee -a /etc/jaeger/query-01.yaml
echo "metrics-backend: prometheus" | sudo tee -a /etc/jaeger/query-02.yaml
For comprehensive monitoring setup, see our tutorial on Prometheus and Grafana monitoring.
Create performance monitoring dashboard
Set up key performance indicators to monitor cluster throughput and latency.
#!/bin/bash
set -euo pipefail
METRICS_FILE="/opt/jaeger/logs/performance.log"
Collect performance metrics
TIMESTAMP=$(date '+%Y-%m-%d %H:%M:%S')
SPAN_COUNT=$(curl -s "http://localhost:9200/jaeger-span-*/_count" | jq '.count')
INDEX_SIZE=$(curl -s "http://localhost:9200/_cat/indices/jaeger*" | awk '{sum+=$8} END {print sum}')
echo "$TIMESTAMP,spans=$SPAN_COUNT,index_size_bytes=$INDEX_SIZE" >> "$METRICS_FILE"
Check for performance issues
if [ "$SPAN_COUNT" -gt 1000000 ]; then
logger "WARNING: High span count detected: $SPAN_COUNT"
fi
sudo chmod 755 /opt/jaeger/bin/performance-monitor.sh
sudo chown jaeger:jaeger /opt/jaeger/bin/performance-monitor.sh
Common issues
| Symptom | Cause | Fix |
|---|---|---|
| Collector not starting | Elasticsearch not accessible | Check Elasticsearch service: sudo systemctl status elasticsearch |
| HAProxy backend servers down | Collector ports not listening | Verify collector binds: sudo netstat -tlnp | grep 142 |
| High memory usage | Large trace volumes | Adjust sampling rates in /etc/jaeger/sampling.json |
| Spans not appearing in UI | Index template not created | Check Elasticsearch logs and recreate templates |
| Query timeout errors | Large time range queries | Limit query time ranges and add more query replicas |
| Disk space filling up | No index lifecycle policy | Configure ILM policy to auto-delete old indices |
Next steps
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'
NC='\033[0m'
# Configuration
JAEGER_VERSION="${JAEGER_VERSION:-1.53.0}"
ELASTICSEARCH_VERSION="${ELASTICSEARCH_VERSION:-8.x}"
CLUSTER_NAME="${1:-jaeger-cluster}"
# Check prerequisites
if [[ $EUID -ne 0 ]]; then
echo -e "${RED}Error: This script must be run as root${NC}"
exit 1
fi
# Auto-detect distro
if [ -f /etc/os-release ]; then
. /etc/os-release
case "$ID" in
ubuntu|debian)
PKG_MGR="apt"
PKG_INSTALL="apt install -y"
PKG_UPDATE="apt update && apt upgrade -y"
JAVA_PKG="openjdk-11-jre-headless"
;;
almalinux|rocky|centos|rhel|ol|fedora)
PKG_MGR="dnf"
PKG_INSTALL="dnf install -y"
PKG_UPDATE="dnf update -y"
JAVA_PKG="java-11-openjdk-headless"
;;
amzn)
PKG_MGR="yum"
PKG_INSTALL="yum install -y"
PKG_UPDATE="yum update -y"
JAVA_PKG="java-11-openjdk-headless"
;;
*)
echo -e "${RED}Error: Unsupported distro: $ID${NC}"
exit 1
;;
esac
else
echo -e "${RED}Error: Cannot detect OS distribution${NC}"
exit 1
fi
# Cleanup on error
cleanup() {
echo -e "${RED}Installation failed. Cleaning up...${NC}"
systemctl stop jaeger-collector jaeger-query haproxy elasticsearch 2>/dev/null || true
userdel jaeger 2>/dev/null || true
rm -rf /opt/jaeger /etc/jaeger 2>/dev/null || true
}
trap cleanup ERR
echo -e "${GREEN}[1/12] Updating system packages and installing dependencies${NC}"
$PKG_UPDATE
$PKG_INSTALL wget curl $JAVA_PKG systemd haproxy
echo -e "${GREEN}[2/12] Creating Jaeger system user and directories${NC}"
useradd --system --shell /bin/false --home-dir /opt/jaeger jaeger 2>/dev/null || true
mkdir -p /opt/jaeger/{bin,config,logs,data}
mkdir -p /etc/jaeger
chown -R jaeger:jaeger /opt/jaeger
chmod 755 /opt/jaeger/{bin,config}
chmod 750 /opt/jaeger/{logs,data}
echo -e "${GREEN}[3/12] Downloading and installing Jaeger binaries${NC}"
cd /tmp
wget -q "https://github.com/jaegertracing/jaeger/releases/download/v${JAEGER_VERSION}/jaeger-${JAEGER_VERSION}-linux-amd64.tar.gz"
tar -xzf "jaeger-${JAEGER_VERSION}-linux-amd64.tar.gz"
cp "jaeger-${JAEGER_VERSION}-linux-amd64/jaeger-collector" /opt/jaeger/bin/
cp "jaeger-${JAEGER_VERSION}-linux-amd64/jaeger-query" /opt/jaeger/bin/
cp "jaeger-${JAEGER_VERSION}-linux-amd64/jaeger-agent" /opt/jaeger/bin/
chown jaeger:jaeger /opt/jaeger/bin/*
chmod 755 /opt/jaeger/bin/*
echo -e "${GREEN}[4/12] Installing Elasticsearch${NC}"
if [[ "$PKG_MGR" == "apt" ]]; then
wget -qO - https://artifacts.elastic.co/GPG-KEY-elasticsearch | gpg --dearmor -o /usr/share/keyrings/elasticsearch-keyring.gpg
echo "deb [signed-by=/usr/share/keyrings/elasticsearch-keyring.gpg] https://artifacts.elastic.co/packages/${ELASTICSEARCH_VERSION}/apt stable main" > /etc/apt/sources.list.d/elastic-${ELASTICSEARCH_VERSION}.list
apt update
$PKG_INSTALL elasticsearch
else
rpm --import https://artifacts.elastic.co/GPG-KEY-elasticsearch
cat > /etc/yum.repos.d/elasticsearch.repo << EOF
[elasticsearch]
name=Elasticsearch repository for ${ELASTICSEARCH_VERSION} packages
baseurl=https://artifacts.elastic.co/packages/${ELASTICSEARCH_VERSION}/yum
gpgcheck=1
gpgkey=https://artifacts.elastic.co/GPG-KEY-elasticsearch
enabled=0
autorefresh=1
type=rpm-md
EOF
$PKG_INSTALL --enablerepo=elasticsearch elasticsearch
fi
echo -e "${GREEN}[5/12] Configuring Elasticsearch${NC}"
cat > /etc/elasticsearch/elasticsearch.yml << EOF
cluster.name: $CLUSTER_NAME
node.name: \${HOSTNAME}
network.host: 0.0.0.0
http.port: 9200
discovery.type: single-node
xpack.security.enabled: false
xpack.security.enrollment.enabled: false
xpack.security.http.ssl.enabled: false
xpack.security.transport.ssl.enabled: false
action.destructive_requires_name: true
EOF
echo -e "${GREEN}[6/12] Creating Jaeger configuration files${NC}"
cat > /etc/jaeger/collector.yml << EOF
es:
server-urls: http://localhost:9200
index-prefix: jaeger
collector:
grpc:
host-port: 0.0.0.0:14250
http:
host-port: 0.0.0.0:14268
zipkin:
host-port: 0.0.0.0:9411
log-level: info
EOF
cat > /etc/jaeger/query.yml << EOF
es:
server-urls: http://localhost:9200
index-prefix: jaeger
query:
base-path: /
grpc:
host-port: 0.0.0.0:16685
http:
host-port: 0.0.0.0:16686
log-level: info
EOF
echo -e "${GREEN}[7/12] Creating systemd service files${NC}"
cat > /etc/systemd/system/jaeger-collector.service << EOF
[Unit]
Description=Jaeger Collector
After=network.target elasticsearch.service
Requires=elasticsearch.service
[Service]
Type=simple
User=jaeger
Group=jaeger
ExecStart=/opt/jaeger/bin/jaeger-collector --config-file=/etc/jaeger/collector.yml
Restart=always
RestartSec=10
StandardOutput=journal
StandardError=journal
[Install]
WantedBy=multi-user.target
EOF
cat > /etc/systemd/system/jaeger-query.service << EOF
[Unit]
Description=Jaeger Query
After=network.target elasticsearch.service
Requires=elasticsearch.service
[Service]
Type=simple
User=jaeger
Group=jaeger
ExecStart=/opt/jaeger/bin/jaeger-query --config-file=/etc/jaeger/query.yml
Restart=always
RestartSec=10
StandardOutput=journal
StandardError=journal
[Install]
WantedBy=multi-user.target
EOF
echo -e "${GREEN}[8/12] Configuring HAProxy for load balancing${NC}"
cat > /etc/haproxy/haproxy.cfg << EOF
global
log stdout local0
chroot /var/lib/haproxy
stats socket /run/haproxy/admin.sock mode 660 level admin
stats timeout 30s
user haproxy
group haproxy
daemon
defaults
mode http
log global
option httplog
option dontlognull
option log-health-checks
timeout connect 5000
timeout client 50000
timeout server 50000
errorfile 400 /etc/haproxy/errors/400.http
errorfile 403 /etc/haproxy/errors/403.http
errorfile 408 /etc/haproxy/errors/408.http
errorfile 500 /etc/haproxy/errors/500.http
errorfile 502 /etc/haproxy/errors/502.http
errorfile 503 /etc/haproxy/errors/503.http
errorfile 504 /etc/haproxy/errors/504.http
frontend jaeger-collector
bind *:14268
default_backend jaeger-collectors
backend jaeger-collectors
balance roundrobin
option httpchk GET /
server collector1 127.0.0.1:14268 check
frontend jaeger-query
bind *:80
default_backend jaeger-queries
backend jaeger-queries
balance roundrobin
option httpchk GET /
server query1 127.0.0.1:16686 check
EOF
echo -e "${GREEN}[9/12] Creating monitoring script${NC}"
cat > /opt/jaeger/bin/performance-monitor.sh << 'EOF'
#!/bin/bash
METRICS_FILE="/opt/jaeger/logs/metrics.log"
SPAN_COUNT=$(curl -s "http://localhost:9200/jaeger-span-*/_count" | grep -o '"count":[0-9]*' | cut -d':' -f2 || echo "0")
echo "$(date): Span count: $SPAN_COUNT" >> "$METRICS_FILE"
if [ "$SPAN_COUNT" -gt 1000000 ]; then
logger "WARNING: High span count detected: $SPAN_COUNT"
fi
EOF
chmod 755 /opt/jaeger/bin/performance-monitor.sh
chown jaeger:jaeger /opt/jaeger/bin/performance-monitor.sh
echo -e "${GREEN}[10/12] Configuring firewall${NC}"
if command -v ufw >/dev/null 2>&1; then
ufw --force enable
ufw allow 80/tcp
ufw allow 14268/tcp
ufw allow 16686/tcp
elif command -v firewall-cmd >/dev/null 2>&1; then
systemctl enable --now firewalld
firewall-cmd --permanent --add-port=80/tcp
firewall-cmd --permanent --add-port=14268/tcp
firewall-cmd --permanent --add-port=16686/tcp
firewall-cmd --reload
fi
echo -e "${GREEN}[11/12] Starting services${NC}"
systemctl daemon-reload
systemctl enable --now elasticsearch
sleep 10
systemctl enable --now jaeger-collector
systemctl enable --now jaeger-query
systemctl enable --now haproxy
echo -e "${GREEN}[12/12] Verifying installation${NC}"
sleep 5
# Check services
for service in elasticsearch jaeger-collector jaeger-query haproxy; do
if systemctl is-active --quiet $service; then
echo -e "${GREEN}✓ $service is running${NC}"
else
echo -e "${RED}✗ $service failed to start${NC}"
exit 1
fi
done
# Check endpoints
if curl -sf http://localhost:16686 >/dev/null; then
echo -e "${GREEN}✓ Jaeger UI accessible at http://localhost:16686${NC}"
else
echo -e "${YELLOW}⚠ Jaeger UI not yet accessible, may need more time to start${NC}"
fi
if curl -sf http://localhost:9200 >/dev/null; then
echo -e "${GREEN}✓ Elasticsearch accessible${NC}"
else
echo -e "${RED}✗ Elasticsearch not accessible${NC}"
exit 1
fi
echo -e "${GREEN}Jaeger HA cluster installation completed successfully!${NC}"
echo -e "${YELLOW}Access Jaeger UI at: http://$(hostname -I | awk '{print $1}'):16686${NC}"
echo -e "${YELLOW}Send traces to: http://$(hostname -I | awk '{print $1}'):14268${NC}"
Review the script before running. Execute with: bash install.sh