From 714e2bc2abe11e4b140c052966cb8e09910d9e7d Mon Sep 17 00:00:00 2001 From: Gabriel Radureau Date: Wed, 8 Jul 2026 23:20:00 +0200 Subject: [PATCH] feat(alerting): livraison Telegram des alertes via Alertmanager MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Les règles d'alerte `prospection` s'évaluaient déjà dans Prometheus mais ne notifiaient nulle part. On câble Alertmanager pour livrer les alertes sur le bot Telegram de prospection, via `telegram_configs` natif d'Alertmanager. - iac Vault : policy read-only `alertmanager-telegram` sur kvv2/data/prospection/telegram + rôle k8s `alertmanager` (SA prometheus-alertmanager, ns tools). - VSO : VaultAuth + VaultStaticSecret resynchronisent kvv2/prospection/telegram vers un Secret `alertmanager-telegram` dans le ns tools (le Secret prospection est namespace-scoped, non réutilisable). rolloutRestartTargets sur le StatefulSet Alertmanager. - prometheus values : lien server -> Alertmanager (prometheus-alertmanager:9093), route + receiver `telegram` (bot_token_file monté, chat_id inline, parse_mode HTML, send_resolved), et montage du Secret via extraSecretMounts. Additif : ni grafana ni les règles d'alerte existantes ne sont touchés. Co-Authored-By: Claude Opus 4.8 --- hashicorp-vault/iac/main.tf | 23 +++++++++++++ prometheus/templates/vault-telegram.yaml | 44 ++++++++++++++++++++++++ prometheus/values.yaml | 37 ++++++++++++++++++-- 3 files changed, 102 insertions(+), 2 deletions(-) create mode 100644 prometheus/templates/vault-telegram.yaml diff --git a/hashicorp-vault/iac/main.tf b/hashicorp-vault/iac/main.tf index f00c6db..6100c15 100644 --- a/hashicorp-vault/iac/main.tf +++ b/hashicorp-vault/iac/main.tf @@ -74,6 +74,29 @@ resource "vault_kubernetes_auth_backend_role" "vso" { alias_name_source = "serviceaccount_name" } +# Alertmanager (ns tools) doit lire le token du bot Telegram de prospection +# pour livrer les alertes. Rôle k8s dédié + policy read-only sur kvv2/prospection/telegram. +data "vault_policy_document" "alertmanager_telegram" { + rule { + path = "kvv2/data/prospection/telegram" + capabilities = ["read"] + } +} +resource "vault_policy" "alertmanager_telegram" { + name = "alertmanager-telegram" + policy = data.vault_policy_document.alertmanager_telegram.hcl +} +resource "vault_kubernetes_auth_backend_role" "alertmanager" { + backend = vault_auth_backend.kubernetes.path + role_name = "alertmanager" + bound_service_account_names = ["prometheus-alertmanager"] + bound_service_account_namespaces = ["tools"] + token_ttl = 3600 + token_policies = ["default", vault_policy.alertmanager_telegram.name] + audience = "vault" + alias_name_source = "serviceaccount_name" +} + module "app_policies" { source = "./modules/app_policy" for_each = { for app in var.applications : app.name => app } diff --git a/prometheus/templates/vault-telegram.yaml b/prometheus/templates/vault-telegram.yaml new file mode 100644 index 0000000..85c8e0f --- /dev/null +++ b/prometheus/templates/vault-telegram.yaml @@ -0,0 +1,44 @@ +# Livraison des alertes Prometheus vers Telegram (bot prospection). +# +# Alertmanager tourne dans le namespace `tools`, mais le token du bot vit dans Vault +# (kvv2/prospection/telegram). Le Secret `prospection-telegram` synchronisé par VSO est +# namespace-scoped (prospection) et non réutilisable ici. On resynchronise donc le même +# chemin kvv2 vers un Secret `alertmanager-telegram` dans `tools`, via un VaultAuth dédié +# (rôle k8s `alertmanager`, provisionné par hashicorp-vault/iac). +# +# NB: ce chart prometheus est en mode `tool.kind: SubChart`, donc les templates +# helm-chart*.yaml ne rendent rien ; ce fichier, lui, est rendu tel quel et appliqué par +# ArgoCD (app `prometheus`, destination namespace `tools`). +apiVersion: secrets.hashicorp.com/v1beta1 +kind: VaultAuth +metadata: + name: alertmanager-telegram + namespace: tools +spec: + method: kubernetes + mount: kubernetes + kubernetes: + role: alertmanager + serviceAccount: prometheus-alertmanager + audiences: + - vault +--- +apiVersion: secrets.hashicorp.com/v1beta1 +kind: VaultStaticSecret +metadata: + name: alertmanager-telegram + namespace: tools +spec: + type: kv-v2 + mount: kvv2 + path: prospection/telegram + destination: + name: alertmanager-telegram + create: true + refreshAfter: 1h + vaultAuthRef: alertmanager-telegram + # Alertmanager lit le token depuis un fichier monté au démarrage et ne recharge pas à + # chaud un secret monté : on redémarre le StatefulSet quand le token change dans Vault. + rolloutRestartTargets: + - kind: StatefulSet + name: prometheus-alertmanager diff --git a/prometheus/values.yaml b/prometheus/values.yaml index eba525a..9b6a321 100644 --- a/prometheus/values.yaml +++ b/prometheus/values.yaml @@ -612,8 +612,11 @@ prometheus: &prometheus_config podLabels: {} ## Prometheus AlertManager configuration - ## - alertmanagers: [] + ## Lien Prometheus -> Alertmanager (service du sous-chart, ns tools). + alertmanagers: + - static_configs: + - targets: + - prometheus-alertmanager:9093 ## Use a StatefulSet if replicaCount needs to be greater than 1 (see below) ## @@ -1233,6 +1236,36 @@ prometheus: &prometheus_config ## enabled: true + ## Configuration Alertmanager : livraison native Telegram (bot prospection). + ## Le token est lu depuis le fichier monté via extraSecretMounts (Secret + ## alertmanager-telegram, synchronisé par VSO — cf. templates/vault-telegram.yaml). + ## chat_id est public (non sensible), donc inline. + config: + enabled: true + global: {} + templates: + - /etc/alertmanager/*.tmpl + route: + group_by: ["alertname", "app"] + group_wait: 30s + group_interval: 5m + repeat_interval: 3h + receiver: telegram + receivers: + - name: telegram + telegram_configs: + - bot_token_file: /etc/alertmanager/telegram/BOT_TOKEN + chat_id: 7497777082 + parse_mode: HTML + send_resolved: true + + ## Montage du token du bot dans le pod Alertmanager (fichier BOT_TOKEN). + extraSecretMounts: + - name: telegram + mountPath: /etc/alertmanager/telegram + secretName: alertmanager-telegram + readOnly: true + persistence: ## If true, storage will create or use Persistence Volume ## If false, storage will use emptyDir