Управление правилами Prometheus с помощью Terraform
Правила Prometheus в Knowledge Graph позволяют определять пользовательские правила записи и алертинга, которые вычисляются по данным ваших метрик. Правила записи предварительно вычисляют часто используемые или ресурсоёмкие выражения и сохраняют результаты в виде новых временных рядов. Правила алертинга задают условия, при выполнении которых срабатывают алерты.
С помощью ресурса grafana_asserts_prom_rule_file вы можете управлять этими правилами как кодом, что обеспечивает версионирование, процессы review и согласованные развёртывания в разных средах.
Прежде чем начать
Чтобы управлять правилами Prometheus с помощью Terraform, вам потребуется:
- Стек Grafana Cloud с включённым Knowledge Graph
- Terraform, настроенный для Knowledge Graph
- Понимание PromQL и концепций правил Prometheus
Создание базового правила записи
Правила записи позволяют предварительно вычислять выражения PromQL и сохранять результаты в виде новых метрик. Это полезно для ресурсоёмких запросов, которые вы выполняете часто.
Создайте файл с именем prom-rules.tf и добавьте следующее:
# Basic recording rule for request rate
resource "grafana_asserts_prom_rule_file" "request_rates" {
provider = grafana.asserts
name = "request-rates"
active = true
group {
name = "request_rate_rules"
interval = "30s"
rule {
record = "job:http_requests_total:rate5m"
expr = "sum(rate(http_requests_total[5m])) by (job)"
labels = {
aggregation = "job"
source = "custom"
}
}
}
}
Создание правил алертинга
Правила алертинга задают условия, при выполнении которых срабатывают алерты. Используйте поле alert вместо record, чтобы определить правило алертинга.
# Alerting rules for service health
resource "grafana_asserts_prom_rule_file" "service_alerts" {
provider = grafana.asserts
name = "service-health-alerts"
active = true
group {
name = "service_health"
interval = "1m"
rule {
alert = "HighErrorRate"
expr = "sum(rate(http_requests_total{code=~\"5..\"}[5m])) / sum(rate(http_requests_total[5m])) > 0.05"
duration = "5m"
labels = {
severity = "critical"
team = "platform"
}
annotations = {
summary = "High error rate detected"
description = "Error rate is above 5% for the last 5 minutes"
runbook_url = "https://docs.example.com/runbooks/high-error-rate"
}
}
rule {
alert = "ServiceDown"
expr = "up == 0"
duration = "2m"
labels = {
severity = "critical"
}
annotations = {
summary = "Service is down"
description = "{{ $labels.job }} has been down for more than 2 minutes"
}
}
}
}
Создание нескольких групп правил
Объединяйте связанные правила в группы с собственными интервалами вычисления:
# Multiple rule groups for comprehensive monitoring
resource "grafana_asserts_prom_rule_file" "comprehensive_rules" {
provider = grafana.asserts
name = "comprehensive-monitoring"
active = true
# Latency recording rules
group {
name = "latency_recording"
interval = "30s"
rule {
record = "job:http_request_duration_seconds:p99"
expr = "histogram_quantile(0.99, sum(rate(http_request_duration_seconds_bucket[5m])) by (job, le))"
labels = {
quantile = "0.99"
}
}
rule {
record = "job:http_request_duration_seconds:p95"
expr = "histogram_quantile(0.95, sum(rate(http_request_duration_seconds_bucket[5m])) by (job, le))"
labels = {
quantile = "0.95"
}
}
rule {
record = "job:http_request_duration_seconds:p50"
expr = "histogram_quantile(0.50, sum(rate(http_request_duration_seconds_bucket[5m])) by (job, le))"
labels = {
quantile = "0.50"
}
}
}
# Latency alerting rules
group {
name = "latency_alerts"
interval = "1m"
rule {
alert = "HighP99Latency"
expr = "job:http_request_duration_seconds:p99 > 1"
duration = "5m"
labels = {
severity = "warning"
}
annotations = {
summary = "High P99 latency detected"
description = "P99 latency for {{ $labels.job }} is above 1 second"
}
}
rule {
alert = "CriticalLatency"
expr = "job:http_request_duration_seconds:p99 > 5"
duration = "2m"
labels = {
severity = "critical"
}
annotations = {
summary = "Critical latency detected"
description = "P99 latency for {{ $labels.job }} is above 5 seconds"
}
}
}
# Throughput rules
group {
name = "throughput_rules"
interval = "1m"
rule {
record = "job:http_requests:rate1m"
expr = "sum(rate(http_requests_total[1m])) by (job)"
}
rule {
alert = "LowThroughput"
expr = "job:http_requests:rate1m < 10"
duration = "10m"
labels = {
severity = "warning"
}
annotations = {
summary = "Low throughput detected"
description = "Request rate for {{ $labels.job }} is below 10 requests per second"
}
}
}
}
Создание правил использования ресурсов
Определите правила для мониторинга использования ресурсов в вашей инфраструктуре:
# Resource utilization monitoring rules
resource "grafana_asserts_prom_rule_file" "resource_utilization" {
provider = grafana.asserts
name = "resource-utilization"
active = true
group {
name = "cpu_rules"
interval = "30s"
rule {
record = "instance:cpu_utilization:avg5m"
expr = "1 - avg(rate(node_cpu_seconds_total{mode=\"idle\"}[5m])) by (instance)"
}
rule {
alert = "HighCPUUtilization"
expr = "instance:cpu_utilization:avg5m > 0.85"
duration = "10m"
labels = {
severity = "warning"
resource = "cpu"
}
annotations = {
summary = "High CPU utilization"
description = "CPU utilization on {{ $labels.instance }} is above 85%"
}
}
rule {
alert = "CriticalCPUUtilization"
expr = "instance:cpu_utilization:avg5m > 0.95"
duration = "5m"
labels = {
severity = "critical"
resource = "cpu"
}
annotations = {
summary = "Critical CPU utilization"
description = "CPU utilization on {{ $labels.instance }} is above 95%"
}
}
}
group {
name = "memory_rules"
interval = "30s"
rule {
record = "instance:memory_utilization:ratio"
expr = "1 - (node_memory_MemAvailable_bytes / node_memory_MemTotal_bytes)"
}
rule {
alert = "HighMemoryUtilization"
expr = "instance:memory_utilization:ratio > 0.85"
duration = "10m"
labels = {
severity = "warning"
resource = "memory"
}
annotations = {
summary = "High memory utilization"
description = "Memory utilization on {{ $labels.instance }} is above 85%"
}
}
}
group {
name = "disk_rules"
interval = "1m"
rule {
record = "instance:disk_utilization:ratio"
expr = "1 - (node_filesystem_avail_bytes{mountpoint=\"/\"} / node_filesystem_size_bytes{mountpoint=\"/\"})"
}
rule {
alert = "DiskSpaceLow"
expr = "instance:disk_utilization:ratio > 0.80"
duration = "15m"
labels = {
severity = "warning"
resource = "disk"
}
annotations = {
summary = "Disk space running low"
description = "Disk utilization on {{ $labels.instance }} is above 80%"
}
}
}
}
Создание правил для Kubernetes
Определите правила для мониторинга рабочих нагрузок Kubernetes:
# Kubernetes workload monitoring rules
resource "grafana_asserts_prom_rule_file" "kubernetes_rules" {
provider = grafana.asserts
name = "kubernetes-workloads"
active = true
group {
name = "kubernetes_pod_rules"
interval = "30s"
rule {
record = "namespace:pod_restarts:rate1h"
expr = "sum(increase(kube_pod_container_status_restarts_total[1h])) by (namespace)"
}
rule {
alert = "PodCrashLooping"
expr = "rate(kube_pod_container_status_restarts_total[15m]) * 60 * 15 > 3"
duration = "5m"
labels = {
severity = "warning"
}
annotations = {
summary = "Pod is crash looping"
description = "Pod {{ $labels.namespace }}/{{ $labels.pod }} is restarting frequently"
}
}
rule {
alert = "PodNotReady"
expr = "kube_pod_status_ready{condition=\"true\"} == 0"
duration = "10m"
labels = {
severity = "warning"
}
annotations = {
summary = "Pod not ready"
description = "Pod {{ $labels.namespace }}/{{ $labels.pod }} has been in a non-ready state for more than 10 minutes"
}
}
}
group {
name = "kubernetes_deployment_rules"
interval = "1m"
rule {
record = "deployment:replicas_unavailable:count"
expr = "kube_deployment_status_replicas_unavailable"
}
rule {
alert = "DeploymentReplicasMismatch"
expr = "kube_deployment_spec_replicas != kube_deployment_status_replicas_available"
duration = "10m"
labels = {
severity = "warning"
}
annotations = {
summary = "Deployment replicas mismatch"
description = "Deployment {{ $labels.namespace }}/{{ $labels.deployment }} has not matched the expected number of replicas for more than 10 minutes"
}
}
}
group {
name = "kubernetes_node_rules"
interval = "1m"
rule {
alert = "NodeNotReady"
expr = "kube_node_status_condition{condition=\"Ready\",status=\"true\"} == 0"
duration = "5m"
labels = {
severity = "critical"
}
annotations = {
summary = "Kubernetes node not ready"
description = "Node {{ $labels.node }} has been unready for more than 5 minutes"
}
}
rule {
alert = "NodeMemoryPressure"
expr = "kube_node_status_condition{condition=\"MemoryPressure\",status=\"true\"} == 1"
duration = "5m"
labels = {
severity = "warning"
}
annotations = {
summary = "Node under memory pressure"
description = "Node {{ $labels.node }} is under memory pressure"
}
}
}
}
Условное отключение правил
Отключайте отдельные правила в определённых группах с помощью поля disable_in_groups:
# Rules with conditional disabling
resource "grafana_asserts_prom_rule_file" "conditional_rules" {
provider = grafana.asserts
name = "conditional-alerting"
active = true
group {
name = "production_alerts"
interval = "1m"
rule {
alert = "HighErrorRate"
expr = "sum(rate(http_requests_total{code=~\"5..\"}[5m])) / sum(rate(http_requests_total[5m])) > 0.01"
duration = "5m"
labels = {
severity = "critical"
environment = "production"
}
annotations = {
summary = "High error rate in production"
description = "Error rate is above 1% for the last 5 minutes"
}
# Disable this rule in staging group
disable_in_groups = ["staging_alerts"]
}
}
group {
name = "staging_alerts"
interval = "1m"
rule {
alert = "HighErrorRate"
expr = "sum(rate(http_requests_total{code=~\"5..\"}[5m])) / sum(rate(http_requests_total[5m])) > 0.10"
duration = "10m"
labels = {
severity = "warning"
environment = "staging"
}
annotations = {
summary = "High error rate in staging"
description = "Error rate is above 10% for the last 10 minutes"
}
}
}
}
Управление неактивными файлами правил
Временно отключите весь файл правил, не удаляя его:
# Inactive rules file (not evaluated)
resource "grafana_asserts_prom_rule_file" "experimental_rules" {
provider = grafana.asserts
name = "experimental-rules"
active = false # Rules are not evaluated
group {
name = "experimental_alerts"
interval = "1m"
rule {
alert = "ExperimentalAlert"
expr = "some_experimental_metric > 100"
duration = "5m"
labels = {
severity = "info"
}
annotations = {
summary = "Experimental alert triggered"
}
}
}
}
Справочник по ресурсам
grafana_asserts_prom_rule_file
Управляйте правилами записи и алертинга Prometheus через Knowledge Graph API. Этот ресурс позволяет создавать пользовательские правила Prometheus, которые вычисляются по данным ваших метрик, и управлять ими.
Аргументы
Блок group
Каждый блок group содержит набор связанных правил с общим интервалом вычисления:
Блок rule
Каждый блок rule определяет правило записи или алертинга. Необходимо указать либо record, либо alert, но не оба одновременно:
Пример
resource "grafana_asserts_prom_rule_file" "example" {
provider = grafana.asserts
name = "example-rules"
active = true
group {
name = "example_group"
interval = "1m"
# Recording rule
rule {
record = "job:http_requests:rate5m"
expr = "sum(rate(http_requests_total[5m])) by (job)"
}
# Alerting rule
rule {
alert = "HighErrorRate"
expr = "job:http_errors:rate5m > 0.05"
duration = "5m"
labels = {
severity = "critical"
}
annotations = {
summary = "High error rate detected"
description = "Error rate for {{ $labels.job }} is above 5%"
}
}
}
}
Рекомендации
При управлении правилами Prometheus с помощью Terraform учитывайте следующие рекомендации.
Организация правил
- Объединяйте связанные правила в одну группу правил
- Используйте описательные имена правил, отражающие их назначение
- Разделяйте правила записи и правила алертинга на разные группы, если у них разные потребности в вычислении
- Используйте согласованные соглашения об именовании записываемых метрик, например
level:metric:operation
Правила записи
- Используйте правила записи для ресурсоёмких запросов, которые выполняются часто
- Предварительно вычисляйте агрегации, используемые несколькими дашбордами или алертами
- Выбирайте подходящие интервалы вычисления в зависимости от частоты изменения данных
- Следуйте соглашениям об именовании Prometheus, например
job:metric:aggregation
Правила алертинга
- Устанавливайте подходящие значения
duration, чтобы избежать «дребезжащих» алертов - Включайте осмысленные метки, такие как
severityиteam, для маршрутизации - Предоставляйте подробные аннотации, включая
summary,descriptionиrunbook_url - Используйте переменные шаблонов в аннотациях, такие как
{{ $labels.job }}, чтобы передать контекст
Вопросы производительности
- Избегайте чрезмерно сложных выражений PromQL, которые могут завершиться по тайм-ауту
- Используйте подходящие интервалы вычисления; не вычисляйте чаще, чем необходимо
- Тестируйте запросы PromQL в Grafana, прежде чем добавлять их в Terraform
- Учитывайте влияние на кардинальность правил записи, создающих новые временные ряды
Тестирование и проверка
- Тестируйте правила в среде, отличной от производственной, прежде чем развёртывать их в production
- Используйте флаг
active = false, чтобы подготовить правила без их вычисления - Отслеживайте влияние новых правил на производительность после развёртывания
- Регулярно проверяйте и удаляйте неиспользуемые правила
Проверка
После применения конфигурации Terraform убедитесь, что:
- Файлы правил созданы и видны в конфигурации правил Knowledge Graph
- Правила записи создают ожидаемые временные ряды
- Правила алертинга вычисляются корректно
- Пороги алертов запускают уведомления как ожидается
- Время вычисления правил находится в допустимых пределах
- В журналах вычисления правил не появляется ошибок
Устранение неполадок
Правила не вычисляются
Если ваши правила не вычисляются:
- Убедитесь, что для файла правил установлено
active = true - Проверьте, что имя файла правил соответствует правилам валидации имён (буквенно-цифровые символы, дефисы, подчёркивания)
- Убедитесь, что выражение PromQL корректно, проверив его в Grafana
Правило записи не создаёт данные
Если правило записи не создаёт данные:
- Убедитесь, что исходные метрики существуют и содержат данные
- Проверьте, что выражение PromQL возвращает результаты
- Убедитесь, что интервал вычисления подходит
- Проверьте журналы вычисления правил на наличие ошибок
Алерты не срабатывают
Если правила алертинга не срабатывают:
- Убедитесь, что условие фактически выполнено, запросив выражение вручную
- Проверьте, что период
durationистёк - Убедитесь, что система алертинга правильно настроена для получения алертов
- Проверьте шаблоны аннотаций на синтаксические ошибки
Ошибка импорта при пересоздании правил
Если при пересоздании правил возникают ошибки:
- Поле
nameнеизменяемо и вызывает пересоздание ресурса при изменении - Убедитесь, что не существует конфликтующих файлов правил с тем же именем
- При необходимости используйте
terraform importдля импорта существующих ресурсов