Set up comprehensive Grafana alerting using both Prometheus metrics and InfluxDB time-series data to monitor your infrastructure from multiple data sources. This tutorial covers configuring data sources, creating alert rules, and setting up notification channels for production monitoring.
Prerequisites
- Grafana server with admin access
- Prometheus server running on port 9090
- InfluxDB server with monitoring database
- SMTP server access for email notifications
- Basic understanding of time-series monitoring
What this solves
Grafana alerting with multiple data sources provides comprehensive monitoring coverage for your infrastructure. By combining Prometheus metrics with InfluxDB time-series data, you can monitor both application performance and system metrics from a single dashboard with unified alerting rules.
Step-by-step configuration
Install Grafana server
First install Grafana on your system if not already present.
sudo apt update
sudo apt install -y software-properties-common
wget -q -O - https://packages.grafana.com/gpg.key | sudo apt-key add -
echo "deb https://packages.grafana.com/oss/deb stable main" | sudo tee /etc/apt/sources.list.d/grafana.list
sudo apt update
sudo apt install -y grafana
Configure Grafana service
Enable and start the Grafana service with proper permissions.
sudo systemctl enable --now grafana-server
sudo systemctl status grafana-server
Configure Prometheus data source
Access Grafana at http://your-server:3000 with admin/admin credentials and configure the Prometheus data source.
curl -X POST http://admin:admin@localhost:3000/api/datasources \
-H "Content-Type: application/json" \
-d '{
"name": "Prometheus",
"type": "prometheus",
"url": "http://localhost:9090",
"access": "proxy",
"isDefault": true
}'
Configure InfluxDB data source
Add InfluxDB as a secondary data source for time-series monitoring data.
curl -X POST http://admin:admin@localhost:3000/api/datasources \
-H "Content-Type: application/json" \
-d '{
"name": "InfluxDB",
"type": "influxdb",
"url": "http://localhost:8086",
"access": "proxy",
"database": "monitoring",
"user": "grafana",
"password": "secure_password"
}'
Create InfluxDB authentication
Set up proper authentication for the InfluxDB connection with restricted permissions.
influx -execute "CREATE USER grafana WITH PASSWORD 'secure_password'"
influx -execute "GRANT READ ON monitoring TO grafana"
influx -execute "SHOW USERS"
Configure notification channels
Set up email notifications for alert delivery using SMTP configuration.
[smtp]
enabled = true
host = smtp.example.com:587
user = alerts@example.com
password = smtp_password
skip_verify = false
from_address = alerts@example.com
from_name = Grafana Alerts
[alerting]
enabled = true
execute_alerts = true
Restart Grafana with new configuration
Apply the SMTP configuration changes by restarting the service.
sudo systemctl restart grafana-server
sudo systemctl status grafana-server
Create Slack notification channel
Add Slack integration for real-time alert notifications to your team channels.
curl -X POST http://admin:admin@localhost:3000/api/alert-notifications \
-H "Content-Type: application/json" \
-d '{
"name": "slack-alerts",
"type": "slack",
"settings": {
"url": "https://hooks.slack.com/services/YOUR/SLACK/WEBHOOK",
"channel": "#alerts",
"title": "Grafana Alert",
"text": "{{ range .Alerts }}{{ .Annotations.summary }}{{ end }}"
}
}'
Create email notification channel
Configure email notifications as a backup delivery method for critical alerts.
curl -X POST http://admin:admin@localhost:3000/api/alert-notifications \
-H "Content-Type: application/json" \
-d '{
"name": "email-alerts",
"type": "email",
"settings": {
"addresses": "ops-team@example.com;sre-team@example.com",
"subject": "[ALERT] {{ .GroupLabels.alertname }}"
}
}'
Create Prometheus CPU alert rule
Set up a CPU usage alert using Prometheus metrics with proper thresholds.
curl -X POST http://admin:admin@localhost:3000/api/ruler/grafana/api/v1/rules/alerts \
-H "Content-Type: application/json" \
-d '{
"groups": [
{
"name": "cpu-alerts",
"folder": "alerts",
"rules": [
{
"uid": "cpu-high",
"title": "High CPU Usage",
"condition": "A",
"data": [
{
"refId": "A",
"queryType": "",
"relativeTimeRange": {
"from": 300,
"to": 0
},
"datasourceUid": "prometheus-uid",
"model": {
"expr": "100 - (avg(irate(node_cpu_seconds_total{mode=\"idle\"}[5m])) * 100)",
"interval": "",
"refId": "A"
}
}
],
"noDataState": "NoData",
"execErrState": "Alerting",
"for": "5m",
"annotations": {
"summary": "CPU usage is above 80% for 5 minutes"
},
"labels": {
"severity": "warning"
}
}
]
}
]
}'
Create InfluxDB memory alert rule
Configure a memory usage alert using InfluxDB data for system monitoring.
curl -X POST http://admin:admin@localhost:3000/api/ruler/grafana/api/v1/rules/alerts \
-H "Content-Type: application/json" \
-d '{
"groups": [
{
"name": "memory-alerts",
"folder": "alerts",
"rules": [
{
"uid": "memory-high",
"title": "High Memory Usage",
"condition": "A",
"data": [
{
"refId": "A",
"queryType": "",
"relativeTimeRange": {
"from": 300,
"to": 0
},
"datasourceUid": "influxdb-uid",
"model": {
"query": "SELECT mean(\"used_percent\") FROM \"mem\" WHERE time >= now() - 5m GROUP BY time(1m)",
"refId": "A"
}
}
],
"noDataState": "NoData",
"execErrState": "Alerting",
"for": "3m",
"annotations": {
"summary": "Memory usage is above 90% for 3 minutes"
},
"labels": {
"severity": "critical"
}
}
]
}
]
}'
Create disk space alert with multi-source data
Combine Prometheus and InfluxDB data for comprehensive disk monitoring alerts.
curl -X POST http://admin:admin@localhost:3000/api/ruler/grafana/api/v1/rules/alerts \
-H "Content-Type: application/json" \
-d '{
"groups": [
{
"name": "disk-alerts",
"folder": "alerts",
"rules": [
{
"uid": "disk-space-low",
"title": "Low Disk Space",
"condition": "C",
"data": [
{
"refId": "A",
"queryType": "",
"relativeTimeRange": {
"from": 300,
"to": 0
},
"datasourceUid": "prometheus-uid",
"model": {
"expr": "100 - ((node_filesystem_avail_bytes{mountpoint=\"/\"} * 100) / node_filesystem_size_bytes{mountpoint=\"/\"})",
"refId": "A"
}
},
{
"refId": "B",
"queryType": "",
"relativeTimeRange": {
"from": 300,
"to": 0
},
"datasourceUid": "influxdb-uid",
"model": {
"query": "SELECT mean(\"used_percent\") FROM \"disk\" WHERE \"path\" = '/' AND time >= now() - 5m",
"refId": "B"
}
},
{
"refId": "C",
"queryType": "",
"expression": "$A > 85 OR $B > 85",
"conditions": [
{
"evaluator": {
"params": [85],
"type": "gt"
},
"operator": {
"type": "and"
},
"query": {
"params": ["A"]
},
"reducer": {
"type": "last"
},
"type": "query"
}
]
}
],
"noDataState": "NoData",
"execErrState": "Alerting",
"for": "2m",
"annotations": {
"summary": "Disk space usage is above 85% on root filesystem"
},
"labels": {
"severity": "warning"
}
}
]
}
]
}'
Configure alert routing and policies
Set up alert routing based on severity levels and notification preferences.
apiVersion: 1
policies:
- orgId: 1
receiver: default-receiver
group_by:
- alertname
- severity
routes:
- receiver: slack-critical
matchers:
- severity = critical
group_wait: 30s
group_interval: 5m
repeat_interval: 1h
- receiver: email-warning
matchers:
- severity = warning
group_wait: 1m
group_interval: 10m
repeat_interval: 4h
- receiver: slack-info
matchers:
- severity = info
group_wait: 5m
group_interval: 30m
repeat_interval: 12h
Set correct permissions for alerting configuration
Ensure Grafana can read the alerting configuration files with proper ownership.
sudo mkdir -p /etc/grafana/provisioning/alerting
sudo chown -R grafana:grafana /etc/grafana/provisioning
sudo chmod 755 /etc/grafana/provisioning/alerting
sudo chmod 644 /etc/grafana/provisioning/alerting/policies.yaml
Test alert configuration
Validate your alerting setup by testing notification delivery and rule evaluation.
sudo systemctl restart grafana-server
curl -X POST http://admin:admin@localhost:3000/api/ruler/grafana/api/v1/rules/test \
-H "Content-Type: application/json" \
-d '{
"expr": "up == 0",
"datasourceUid": "prometheus-uid"
}'
Configure advanced alert features
Set up alert silencing
Configure maintenance windows and alert silencing for planned downtime.
curl -X POST http://admin:admin@localhost:3000/api/alertmanager/grafana/api/v2/silences \
-H "Content-Type: application/json" \
-d '{
"matchers": [
{
"name": "instance",
"value": "203.0.113.10:9100",
"isRegex": false
}
],
"startsAt": "2024-01-01T02:00:00.000Z",
"endsAt": "2024-01-01T06:00:00.000Z",
"createdBy": "admin",
"comment": "Maintenance window for server updates"
}'
Configure alert annotations
Add detailed annotations to alerts for better troubleshooting context.
apiVersion: 1
groups:
- name: detailed-alerts
folder: monitoring
rules:
- uid: service-down
title: Service Down Alert
condition: A
data:
- refId: A
queryType: ''
relativeTimeRange:
from: 300
to: 0
datasourceUid: prometheus-uid
model:
expr: up{job="node-exporter"} == 0
annotations:
summary: "Service {{ $labels.instance }} is down"
description: "The service on {{ $labels.instance }} has been down for more than 5 minutes. Check the service status and logs."
runbook_url: "https://wiki.example.com/runbooks/service-down"
dashboard_url: "https://grafana.example.com/d/node-exporter/node-exporter-full"
labels:
team: infrastructure
service: node-exporter
Verify your setup
sudo systemctl status grafana-server
curl -s http://localhost:3000/api/health | jq
curl -s http://admin:admin@localhost:3000/api/datasources | jq '.[].name'
curl -s http://admin:admin@localhost:3000/api/alert-notifications | jq '.[].name'
curl -s http://admin:admin@localhost:3000/api/ruler/grafana/api/v1/rules | jq '.groups[].name'
Check Prometheus metrics collection:
curl -s "http://localhost:9090/api/v1/query?query=up" | jq '.data.result[] | .metric.instance'
curl -s "http://localhost:9090/api/v1/targets" | jq '.data.activeTargets[] | select(.health=="up") | .labels.instance'
Verify InfluxDB connectivity and data:
influx -execute "SHOW DATABASES"
influx -database monitoring -execute "SHOW MEASUREMENTS LIMIT 5"
influx -database monitoring -execute "SELECT * FROM cpu WHERE time > now() - 1h LIMIT 3"
Common issues
| Symptom | Cause | Fix |
|---|---|---|
| Data source connection failed | Incorrect URL or authentication | Verify service URLs and credentials: curl http://localhost:9090/metrics |
| Alert rules not evaluating | Invalid query syntax or missing data | Test queries in Explore tab: curl -X POST /api/ruler/grafana/api/v1/rules/test |
| Notifications not delivered | SMTP misconfiguration or wrong webhook URL | Check logs: sudo journalctl -u grafana-server -f and test SMTP settings |
| Permission denied on config files | Wrong ownership or permissions | Fix ownership: sudo chown -R grafana:grafana /etc/grafana/ |
| High memory usage in Grafana | Too many concurrent queries | Limit concurrent queries in /etc/grafana/grafana.ini: max_concurrent_queries = 20 |
Next steps
- Configure advanced Grafana dashboards with Prometheus integration
- Set up OpenTelemetry custom instrumentation with Prometheus
- Integrate MinIO with Prometheus monitoring for storage metrics
- Set up Grafana dashboard provisioning and automation
- Configure Prometheus Alertmanager with custom webhook integrations
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'
# Global variables
PKG_MGR=""
PKG_INSTALL=""
DISTRO=""
GRAFANA_CONFIG=""
PROMETHEUS_CONFIG=""
INFLUXDB_CONFIG=""
# Cleanup function
cleanup() {
local exit_code=$?
if [ $exit_code -ne 0 ]; then
echo -e "${RED}[ERROR] Installation failed. Cleaning up...${NC}"
systemctl stop grafana-server prometheus influxdb 2>/dev/null || true
systemctl disable grafana-server prometheus influxdb 2>/dev/null || true
fi
exit $exit_code
}
trap cleanup ERR
usage() {
echo "Usage: $0 [OPTIONS]"
echo "Options:"
echo " -h, --help Show this help message"
echo " --influxdb-password Password for InfluxDB admin user (default: randomly generated)"
echo " --grafana-port Grafana port (default: 3000)"
echo " --prometheus-port Prometheus port (default: 9090)"
echo " --influxdb-port InfluxDB port (default: 8086)"
exit 1
}
# Parse arguments
INFLUXDB_PASSWORD=""
GRAFANA_PORT="3000"
PROMETHEUS_PORT="9090"
INFLUXDB_PORT="8086"
while [[ $# -gt 0 ]]; do
case $1 in
-h|--help)
usage
;;
--influxdb-password)
INFLUXDB_PASSWORD="$2"
shift 2
;;
--grafana-port)
GRAFANA_PORT="$2"
shift 2
;;
--prometheus-port)
PROMETHEUS_PORT="$2"
shift 2
;;
--influxdb-port)
INFLUXDB_PORT="$2"
shift 2
;;
*)
echo -e "${RED}Unknown option: $1${NC}"
usage
;;
esac
done
# Generate random password if not provided
if [ -z "$INFLUXDB_PASSWORD" ]; then
INFLUXDB_PASSWORD=$(openssl rand -base64 32 | tr -d "=+/" | cut -c1-16)
fi
# Check prerequisites
check_prerequisites() {
echo -e "${BLUE}[1/8] Checking prerequisites...${NC}"
if [[ $EUID -ne 0 ]]; then
echo -e "${RED}This script must be run as root${NC}"
exit 1
fi
if ! command -v wget &> /dev/null; then
echo -e "${YELLOW}wget not found, will install it${NC}"
fi
if ! command -v openssl &> /dev/null; then
echo -e "${RED}openssl is required but not installed${NC}"
exit 1
fi
}
# Detect distribution
detect_distro() {
echo -e "${BLUE}[2/8] Detecting distribution...${NC}"
if [ -f /etc/os-release ]; then
. /etc/os-release
DISTRO="$ID"
case "$ID" in
ubuntu|debian)
PKG_MGR="apt"
PKG_INSTALL="apt install -y"
GRAFANA_CONFIG="/etc/grafana/grafana.ini"
PROMETHEUS_CONFIG="/etc/prometheus"
INFLUXDB_CONFIG="/etc/influxdb"
;;
almalinux|rocky|centos|rhel|ol|fedora)
PKG_MGR="dnf"
PKG_INSTALL="dnf install -y"
GRAFANA_CONFIG="/etc/grafana/grafana.ini"
PROMETHEUS_CONFIG="/etc/prometheus"
INFLUXDB_CONFIG="/etc/influxdb"
;;
amzn)
PKG_MGR="yum"
PKG_INSTALL="yum install -y"
GRAFANA_CONFIG="/etc/grafana/grafana.ini"
PROMETHEUS_CONFIG="/etc/prometheus"
INFLUXDB_CONFIG="/etc/influxdb"
;;
*)
echo -e "${RED}Unsupported distribution: $ID${NC}"
exit 1
;;
esac
echo -e "${GREEN}Detected: $PRETTY_NAME${NC}"
else
echo -e "${RED}Cannot detect distribution${NC}"
exit 1
fi
}
# Install Grafana
install_grafana() {
echo -e "${BLUE}[3/8] Installing Grafana...${NC}"
if [ "$PKG_MGR" = "apt" ]; then
apt update
$PKG_INSTALL software-properties-common wget
wget -q -O - https://packages.grafana.com/gpg.key | apt-key add -
echo "deb https://packages.grafana.com/oss/deb stable main" > /etc/apt/sources.list.d/grafana.list
apt update
$PKG_INSTALL grafana
else
$PKG_INSTALL wget
cat > /etc/yum.repos.d/grafana.repo << EOF
[grafana]
name=grafana
baseurl=https://packages.grafana.com/oss/rpm
repo_gpgcheck=1
enabled=1
gpgcheck=1
gpgkey=https://packages.grafana.com/gpg.key
sslverify=1
sslcacert=/etc/pki/tls/certs/ca-bundle.crt
EOF
$PKG_INSTALL grafana
fi
# Configure Grafana
sed -i "s/;http_port = 3000/http_port = $GRAFANA_PORT/" "$GRAFANA_CONFIG"
systemctl enable grafana-server
systemctl start grafana-server
}
# Install Prometheus
install_prometheus() {
echo -e "${BLUE}[4/8] Installing Prometheus...${NC}"
if [ "$PKG_MGR" = "apt" ]; then
$PKG_INSTALL prometheus
else
$PKG_INSTALL prometheus2
PROMETHEUS_CONFIG="/etc/prometheus2"
fi
# Configure Prometheus
mkdir -p "$PROMETHEUS_CONFIG"
cat > "$PROMETHEUS_CONFIG/prometheus.yml" << EOF
global:
scrape_interval: 15s
evaluation_interval: 15s
rule_files:
scrape_configs:
- job_name: 'prometheus'
static_configs:
- targets: ['localhost:$PROMETHEUS_PORT']
- job_name: 'node'
static_configs:
- targets: ['localhost:9100']
EOF
chown -R prometheus:prometheus "$PROMETHEUS_CONFIG" 2>/dev/null || true
chmod 644 "$PROMETHEUS_CONFIG/prometheus.yml"
systemctl enable prometheus
systemctl start prometheus
}
# Install InfluxDB
install_influxdb() {
echo -e "${BLUE}[5/8] Installing InfluxDB...${NC}"
if [ "$PKG_MGR" = "apt" ]; then
wget -qO- https://repos.influxdata.com/influxdb.key | apt-key add -
echo "deb https://repos.influxdata.com/debian stable main" > /etc/apt/sources.list.d/influxdb.list
apt update
$PKG_INSTALL influxdb
else
cat > /etc/yum.repos.d/influxdb.repo << EOF
[influxdb]
name = InfluxDB Repository - RHEL
baseurl = https://repos.influxdata.com/rhel/\$releasever/\$basearch/stable
enabled = 1
gpgcheck = 1
gpgkey = https://repos.influxdata.com/influxdb.key
EOF
$PKG_INSTALL influxdb
fi
# Configure InfluxDB
mkdir -p "$INFLUXDB_CONFIG"
cat > "$INFLUXDB_CONFIG/influxdb.conf" << EOF
[meta]
dir = "/var/lib/influxdb/meta"
[data]
dir = "/var/lib/influxdb/data"
engine = "tsm1"
wal-dir = "/var/lib/influxdb/wal"
[http]
enabled = true
bind-address = ":$INFLUXDB_PORT"
EOF
chown -R influxdb:influxdb "$INFLUXDB_CONFIG" 2>/dev/null || true
chown -R influxdb:influxdb /var/lib/influxdb 2>/dev/null || true
chmod 644 "$INFLUXDB_CONFIG/influxdb.conf"
systemctl enable influxdb
systemctl start influxdb
}
# Configure data sources
configure_datasources() {
echo -e "${BLUE}[6/8] Configuring Grafana data sources...${NC}"
# Wait for services to be ready
sleep 5
# Configure Prometheus data source
curl -s -X POST \
http://admin:admin@localhost:$GRAFANA_PORT/api/datasources \
-H "Content-Type: application/json" \
-d '{
"name": "Prometheus",
"type": "prometheus",
"url": "http://localhost:'$PROMETHEUS_PORT'",
"access": "proxy",
"isDefault": true
}' || echo -e "${YELLOW}Prometheus datasource may already exist${NC}"
# Configure InfluxDB data source
curl -s -X POST \
http://admin:admin@localhost:$GRAFANA_PORT/api/datasources \
-H "Content-Type: application/json" \
-d '{
"name": "InfluxDB",
"type": "influxdb",
"url": "http://localhost:'$INFLUXDB_PORT'",
"access": "proxy",
"database": "monitoring"
}' || echo -e "${YELLOW}InfluxDB datasource may already exist${NC}"
}
# Configure firewall
configure_firewall() {
echo -e "${BLUE}[7/8] Configuring firewall...${NC}"
if command -v ufw &> /dev/null; then
ufw allow $GRAFANA_PORT/tcp
ufw allow $PROMETHEUS_PORT/tcp
ufw allow $INFLUXDB_PORT/tcp
elif command -v firewall-cmd &> /dev/null; then
firewall-cmd --permanent --add-port=$GRAFANA_PORT/tcp
firewall-cmd --permanent --add-port=$PROMETHEUS_PORT/tcp
firewall-cmd --permanent --add-port=$INFLUXDB_PORT/tcp
firewall-cmd --reload
fi
}
# Verify installation
verify_installation() {
echo -e "${BLUE}[8/8] Verifying installation...${NC}"
# Check services
for service in grafana-server prometheus influxdb; do
if systemctl is-active --quiet $service; then
echo -e "${GREEN}✓ $service is running${NC}"
else
echo -e "${RED}✗ $service is not running${NC}"
exit 1
fi
done
# Check ports
for port in $GRAFANA_PORT $PROMETHEUS_PORT $INFLUXDB_PORT; do
if ss -tlnp | grep -q ":$port "; then
echo -e "${GREEN}✓ Port $port is open${NC}"
else
echo -e "${RED}✗ Port $port is not accessible${NC}"
exit 1
fi
done
}
# Main execution
main() {
check_prerequisites
detect_distro
install_grafana
install_prometheus
install_influxdb
configure_datasources
configure_firewall
verify_installation
echo -e "${GREEN}Installation completed successfully!${NC}"
echo -e "${BLUE}Access Grafana at: http://localhost:$GRAFANA_PORT${NC}"
echo -e "${BLUE}Default login: admin/admin${NC}"
echo -e "${BLUE}Prometheus: http://localhost:$PROMETHEUS_PORT${NC}"
echo -e "${BLUE}InfluxDB: http://localhost:$INFLUXDB_PORT${NC}"
echo -e "${YELLOW}InfluxDB admin password: $INFLUXDB_PASSWORD${NC}"
}
main "$@"
Review the script before running. Execute with: bash install.sh