Slack Integration
Introduction
In a monitoring setup, getting alerts is only half the battle - you need to ensure these alerts reach the right people at the right time. Slack has become one of the most popular communication platforms for development and operations teams. By integrating Prometheus Alertmanager with Slack, you can receive real-time notifications about critical issues directly in your team's Slack channels.
This guide will walk you through the process of setting up a Slack integration for your Prometheus alerting system, enabling your team to respond quickly to incidents and minimize downtime.
Prerequisites
Before we begin, you should have:
- A running Prometheus instance
- Alertmanager configured and connected to Prometheus
- A Slack workspace with administrative access or permission to create applications
Understanding the Integration Flow
The process of sending Prometheus alerts to Slack follows this path:
Prometheus fires alerts based on the conditions you've defined. These alerts are sent to Alertmanager, which processes them according to your routing configurations. For alerts that should be sent to Slack, Alertmanager uses a webhook URL to post messages directly to your specified Slack channels.
Step 1: Create a Slack App and Webhook
First, we need to create a Slack app and generate an incoming webhook:
- Go to https://api.slack.com/apps and click "Create New App"
- Choose "From scratch" and give your app a name (e.g., "Prometheus Alerts")
- Select the workspace where you want to install the app
- In the left sidebar, click on "Incoming Webhooks"
- Toggle "Activate Incoming Webhooks" to On
- Click "Add New Webhook to Workspace"
- Select the channel where you want the alerts to be posted
- Copy the webhook URL that Slack provides - you'll need this for Alertmanager configuration
Step 2: Configure Alertmanager
Now that we have our Slack webhook, we need to configure Alertmanager to use it. Let's modify the Alertmanager configuration file:
global:
resolve_timeout: 5m
route:
group_by: ['alertname']
group_wait: 10s
group_interval: 10s
repeat_interval: 1h
receiver: 'slack-notifications'
receivers:
- name: 'slack-notifications'
slack_configs:
- api_url: 'https://hooks.slack.com/services/T00000000/B00000000/XXXXXXXXXXXXXXXXXXXXXXXX' # Replace with your webhook URL
channel: '#alerts' # Optional: override the channel
send_resolved: true
title: '{{ .Status | toUpper }}{{ if eq .Status "firing" }}:{{ .Alerts.Firing | len }}{{ end }} - {{ .CommonLabels.alertname }}'
text: >-
{{ range .Alerts -}}
*Alert:* {{ .Annotations.summary }}
*Description:* {{ .Annotations.description }}
*Severity:* {{ .Labels.severity }}
*Started:* {{ .StartsAt.Format "2006-01-02 15:04:05" }}
{{ if ne .Status "firing" -}}
*Resolved:* {{ .EndsAt.Format "2006-01-02 15:04:05" }}
{{ end -}}
{{ end }}
In this configuration:
- We're creating a route that directs all alerts to our Slack receiver
- The
slack_configs
section specifies how to format and send alerts to Slack - Replace the
api_url
with your actual webhook URL - The
title
andtext
fields use Go templating to format the message send_resolved: true
ensures you get notifications when alerts are resolved
Step 3: Apply the Configuration
Save your Alertmanager configuration to a file (typically alertmanager.yml
) and restart Alertmanager to apply the changes:
# If running Alertmanager directly
alertmanager --config.file=alertmanager.yml
# If using Docker
docker restart alertmanager
# If using Kubernetes
kubectl apply -f alertmanager-config.yaml
kubectl rollout restart deployment alertmanager
Step 4: Customizing Alert Appearance
You can enhance your Slack notifications by customizing their appearance. Alertmanager supports Slack's message formatting options, including colors, attachments, and icons.
Here's an enhanced configuration example that uses colors based on alert severity:
receivers:
- name: 'slack-notifications'
slack_configs:
- api_url: 'https://hooks.slack.com/services/T00000000/B00000000/XXXXXXXXXXXXXXXXXXXXXXXX'
channel: '#alerts'
send_resolved: true
icon_emoji: ':prometheus:'
title: '{{ .Status | toUpper }}{{ if eq .Status "firing" }}:{{ .Alerts.Firing | len }}{{ end }} - {{ .CommonLabels.alertname }}'
text: >-
{{ range .Alerts -}}
*Alert:* {{ .Annotations.summary }}
*Description:* {{ .Annotations.description }}
*Severity:* {{ .Labels.severity }}
*Started:* {{ .StartsAt.Format "2006-01-02 15:04:05" }}
{{ if ne .Status "firing" -}}
*Resolved:* {{ .EndsAt.Format "2006-01-02 15:04:05" }}
{{ end -}}
{{ end }}
color: '{{ if eq .Status "firing" }}{{ if eq .CommonLabels.severity "critical" }}#FF0000{{ else if eq .CommonLabels.severity "warning" }}#FFA500{{ else }}#FFFF00{{ end }}{{ else }}#00FF00{{ end }}'
With this configuration:
- Critical alerts will appear with a red side border
- Warning alerts will be orange
- Other alerts will be yellow
- Resolved alerts will have a green border
Real-World Example: Complete Setup
Let's walk through a complete real-world example that includes alert rules, Alertmanager configuration, and integration with Slack.
1. Define Prometheus Alert Rules
First, create a file named alert_rules.yml
with the following content:
groups:
- name: example
rules:
- alert: HighCPULoad
expr: 100 - (avg by(instance) (irate(node_cpu_seconds_total{mode="idle"}[5m])) * 100) > 80
for: 5m
labels:
severity: warning
annotations:
summary: "High CPU load (instance {{ $labels.instance }})"
description: "CPU load is above 80%
VALUE = {{ $value }}
LABELS = {{ $labels }}"
- alert: MemoryUsageHigh
expr: (node_memory_MemTotal_bytes - node_memory_MemAvailable_bytes) / node_memory_MemTotal_bytes * 100 > 90
for: 5m
labels:
severity: critical
annotations:
summary: "High memory usage (instance {{ $labels.instance }})"
description: "Memory usage is above 90%
VALUE = {{ $value }}
LABELS = {{ $labels }}"
2. Configure Prometheus to load the rules
In your prometheus.yml
file:
global:
scrape_interval: 15s
evaluation_interval: 15s
rule_files:
- "alert_rules.yml"
alerting:
alertmanagers:
- static_configs:
- targets:
- alertmanager:9093
scrape_configs:
- job_name: 'prometheus'
static_configs:
- targets: ['localhost:9090']
- job_name: 'node_exporter'
static_configs:
- targets: ['node-exporter:9100']
3. Set up Alertmanager with Slack integration
Create an alertmanager.yml
file:
global:
resolve_timeout: 5m
route:
group_by: ['alertname', 'instance']
group_wait: 30s
group_interval: 5m
repeat_interval: 4h
receiver: 'slack-notifications'
routes:
- match:
severity: critical
receiver: 'slack-critical'
continue: true
- match:
severity: warning
receiver: 'slack-warnings'
receivers:
- name: 'slack-notifications'
slack_configs:
- api_url: 'https://hooks.slack.com/services/T00000000/B00000000/XXXXXXXXXXXXXXXXXXXXXXXX'
channel: '#alerts-all'
send_resolved: true
title: '{{ .Status | toUpper }} {{ .CommonLabels.alertname }}'
text: >-
{{ range .Alerts -}}
*Alert:* {{ .Annotations.summary }}
*Description:* {{ .Annotations.description }}
*Severity:* {{ .Labels.severity }}
*Started:* {{ .StartsAt.Format "2006-01-02 15:04:05" }}
{{ if ne .Status "firing" -}}
*Resolved:* {{ .EndsAt.Format "2006-01-02 15:04:05" }}
{{ end -}}
{{ end }}
- name: 'slack-critical'
slack_configs:
- api_url: 'https://hooks.slack.com/services/T00000000/B00000000/XXXXXXXXXXXXXXXXXXXXXXXX'
channel: '#alerts-critical'
send_resolved: true
icon_emoji: ':red-siren:'
title: '🚨 CRITICAL ALERT: {{ .CommonLabels.alertname }} 🚨'
text: >-
{{ range .Alerts -}}
*Alert:* {{ .Annotations.summary }}
*Description:* {{ .Annotations.description }}
*Severity:* {{ .Labels.severity }}
*Started:* {{ .StartsAt.Format "2006-01-02 15:04:05" }}
{{ if ne .Status "firing" -}}
*Resolved:* {{ .EndsAt.Format "2006-01-02 15:04:05" }}
{{ end -}}
{{ end }}
color: '#FF0000'
- name: 'slack-warnings'
slack_configs:
- api_url: 'https://hooks.slack.com/services/T00000000/B00000000/XXXXXXXXXXXXXXXXXXXXXXXX'
channel: '#alerts-warnings'
send_resolved: true
icon_emoji: ':warning:'
title: '⚠️ WARNING: {{ .CommonLabels.alertname }}'
text: >-
{{ range .Alerts -}}
*Alert:* {{ .Annotations.summary }}
*Description:* {{ .Annotations.description }}
*Severity:* {{ .Labels.severity }}
*Started:* {{ .StartsAt.Format "2006-01-02 15:04:05" }}
{{ if ne .Status "firing" -}}
*Resolved:* {{ .EndsAt.Format "2006-01-02 15:04:05" }}
{{ end -}}
{{ end }}
color: '#FFA500'
This configuration:
- Routes alerts to different Slack channels based on severity
- Uses different formatting for critical vs. warning alerts
- Makes critical alerts stand out with red color and emoji
Testing Your Integration
After setting up your integration, you should test it to ensure everything works correctly:
- Temporarily modify an alert threshold to trigger an alert
- Wait for the alert to fire (considering the
for
duration in your alert rule) - Check if the notification appears in your Slack channel
- Verify the formatting and content of the message
- Resolve the alert condition and confirm you receive a resolution notification
Troubleshooting Tips
If you're not receiving alerts in Slack:
-
Check the Alertmanager logs for any errors:
bashdocker logs alertmanager
# Or for Kubernetes
kubectl logs -l app=alertmanager -
Verify the webhook URL is correct and hasn't been revoked
-
Test the webhook directly using curl:
bashcurl -X POST -H 'Content-type: application/json' --data '{"text":"Hello, this is a test from Prometheus Alertmanager"}' YOUR_WEBHOOK_URL
-
Ensure your alert rules are correctly defined and firing
Advanced Configuration: Routing by Team
In larger organizations, you might want to route different types of alerts to different teams. Here's how to set up more sophisticated routing:
route:
group_by: ['alertname', 'instance']
group_wait: 30s
group_interval: 5m
repeat_interval: 4h
receiver: 'slack-default'
routes:
- match:
team: infrastructure
receiver: 'slack-infrastructure'
- match:
team: database
receiver: 'slack-database'
- match:
team: application
receiver: 'slack-application'
receivers:
- name: 'slack-default'
slack_configs:
- api_url: 'https://hooks.slack.com/services/T00000000/B00000000/XXXXXXXXXXXXXXXXXXXXXXXX'
channel: '#alerts-general'
- name: 'slack-infrastructure'
slack_configs:
- api_url: 'https://hooks.slack.com/services/T00000000/B00000000/XXXXXXXXXXXXXXXXXXXXXXXX'
channel: '#alerts-infra'
- name: 'slack-database'
slack_configs:
- api_url: 'https://hooks.slack.com/services/T00000000/B00000000/XXXXXXXXXXXXXXXXXXXXXXXX'
channel: '#alerts-db'
- name: 'slack-application'
slack_configs:
- api_url: 'https://hooks.slack.com/services/T00000000/B00000000/XXXXXXXXXXXXXXXXXXXXXXXX'
channel: '#alerts-app'
To use this configuration, add a team
label to your alert rules:
- alert: HighDatabaseLatency
expr: pg_stat_activity_max_tx_duration{datname="production"} > 120
for: 5m
labels:
severity: critical
team: database
annotations:
summary: "Database transaction taking too long"
description: "A database transaction has been running for more than 2 minutes"
Best Practices for Slack Alerts
To make the most of your Slack integration, follow these best practices:
- Be selective: Only send important alerts to Slack to avoid alert fatigue
- Use different channels: Separate critical alerts from warnings
- Include actionable information: Make sure alerts include enough context to start troubleshooting
- Use clear titles: Make alert titles descriptive and easy to understand at a glance
- Add runbooks: Include links to runbooks or documentation in your alert templates
- Set up escalation paths: Configure fallback notification methods for critical alerts that go unacknowledged
- Test regularly: Periodically verify your alerting pipeline works end-to-end
Summary
Integrating Prometheus Alertmanager with Slack provides a powerful way to ensure your team gets notified about important events in your infrastructure. In this guide, we've covered:
- Setting up a Slack app and webhook
- Configuring Alertmanager to send notifications to Slack
- Customizing alert appearance and formatting
- Implementing sophisticated routing based on alert severity and team ownership
- Testing and troubleshooting your integration
- Best practices for effective Slack alerts
By following these steps, you can create a robust alerting system that keeps your team informed without causing alert fatigue.
Additional Resources
- Alertmanager Configuration Documentation
- Slack API Documentation for Incoming Webhooks
- Go Templates Documentation (used for customizing alert messages)
Exercises
- Create a simple alert rule that triggers when a service goes down, and configure it to send notifications to Slack.
- Modify the Slack message template to include links to your monitoring dashboards.
- Set up separate channels for different environments (production, staging, development).
- Implement a "maintenance mode" using Alertmanager's inhibition rules to prevent alerts during planned maintenance.
- Create a custom alert that includes a graph image of the metric that triggered the alert.
If you spot any mistakes on this website, please let me know at [email protected]. I’d greatly appreciate your feedback! :)