From 4bb9b00a4ac2eda1ddcd1b23bd15ea0dae5e750e Mon Sep 17 00:00:00 2001 From: kklinch0 Date: Tue, 23 Sep 2025 21:47:34 +0300 Subject: [PATCH] feature/add slack alerts Signed-off-by: kklinch0 --- packages/extra/monitoring/Chart.yaml | 2 +- packages/extra/monitoring/README.md | 46 ++-- .../monitoring/templates/alerta/alerta.yaml | 50 ++++- packages/extra/monitoring/values.schema.json | 205 ++++++++++++++++-- packages/extra/monitoring/values.yaml | 29 +++ packages/extra/versions_map | 3 +- 6 files changed, 298 insertions(+), 37 deletions(-) diff --git a/packages/extra/monitoring/Chart.yaml b/packages/extra/monitoring/Chart.yaml index 5c6c5a68..1733f5ff 100644 --- a/packages/extra/monitoring/Chart.yaml +++ b/packages/extra/monitoring/Chart.yaml @@ -3,4 +3,4 @@ name: monitoring description: Monitoring and observability stack icon: /logos/monitoring.svg type: application -version: 1.13.1 +version: 1.14.0 diff --git a/packages/extra/monitoring/README.md b/packages/extra/monitoring/README.md index c97b13de..522cded6 100644 --- a/packages/extra/monitoring/README.md +++ b/packages/extra/monitoring/README.md @@ -48,30 +48,40 @@ | ---------------------------------- | ----------------------------------------------------- | ---------- | ------------ | | `logsStorages` | Configuration of logs storage instances | `[]object` | `[...]` | | `logsStorages[i].name` | Name of the storage instance | `string` | `""` | -| `logsStorages[i].retentionPeriod` | Retention period for the logs in the storage instance | `string` | `1` | +| `logsStorages[i].retentionPeriod` | Retention period for the logs in the storage instance | `string` | `{}` | | `logsStorages[i].storage` | Persistent Volume size for the storage instance | `string` | `10Gi` | | `logsStorages[i].storageClassName` | StorageClass used to store the data | `*string` | `replicated` | ### Alerta configuration -| Name | Description | Type | Value | -| ----------------------------------------- | ----------------------------------------------------------------------------------- | ----------- | ------- | -| `alerta` | Configuration for Alerta service | `object` | `{}` | -| `alerta.storage` | Persistent Volume size for the database | `*string` | `10Gi` | -| `alerta.storageClassName` | StorageClass used to store the data | `*string` | `""` | -| `alerta.resources` | Resources configuration | `*object` | `null` | -| `alerta.resources.requests` | | `*object` | `null` | -| `alerta.resources.requests.cpu` | CPU request (minimum available CPU) | `*quantity` | `100m` | -| `alerta.resources.requests.memory` | Memory request (minimum available memory) | `*quantity` | `256Mi` | -| `alerta.resources.limits` | | `*object` | `null` | -| `alerta.resources.limits.cpu` | CPU limit (maximum available CPU) | `*quantity` | `1` | -| `alerta.resources.limits.memory` | Memory limit (maximum available memory) | `*quantity` | `1Gi` | -| `alerta.alerts` | Configuration for alerts | `*object` | `null` | -| `alerta.alerts.telegram` | Configuration for Telegram alerts | `*object` | `null` | -| `alerta.alerts.telegram.token` | Telegram token for your bot | `string` | `""` | -| `alerta.alerts.telegram.chatID` | Specify multiple ID's separated by comma. Get yours in https://t.me/chatid_echo_bot | `string` | `""` | -| `alerta.alerts.telegram.disabledSeverity` | List of severity without alerts, separated by comma like: "informational,warning" | `string` | `""` | +| Name | Description | Type | Value | +| ----------------------------------------- | ----------------------------------------------------------------------------------------------------------- | ------------------------------ | ------- | +| `alerta` | Configuration for Alerta service | `object` | `{}` | +| `alerta.storage` | Persistent Volume size for the database | `*string` | `10Gi` | +| `alerta.storageClassName` | StorageClass used to store the data | `*string` | `""` | +| `alerta.resources` | Resources configuration | `*object` | `null` | +| `alerta.resources.requests` | | `*object` | `null` | +| `alerta.resources.requests.cpu` | CPU request (minimum available CPU) | `*quantity` | `100m` | +| `alerta.resources.requests.memory` | Memory request (minimum available memory) | `*quantity` | `256Mi` | +| `alerta.resources.limits` | | `*object` | `null` | +| `alerta.resources.limits.cpu` | CPU limit (maximum available CPU) | `*quantity` | `1` | +| `alerta.resources.limits.memory` | Memory limit (maximum available memory) | `*quantity` | `1Gi` | +| `alerta.alerts` | Configuration for alerts | `*object` | `null` | +| `alerta.alerts.telegram` | Configuration for Telegram alerts | `*object` | `null` | +| `alerta.alerts.telegram.token` | Telegram token for your bot | `string` | `""` | +| `alerta.alerts.telegram.chatID` | Specify multiple ID's separated by comma. Get yours in https://t.me/chatid_echo_bot | `string` | `""` | +| `alerta.alerts.telegram.disabledSeverity` | List of severity without alerts, separated by comma like: "informational,warning" | `string` | `""` | +| `alerta.alerts.slack` | Configuration for Slack alerts | `*object` | `null` | +| `alerta.alerts.slack.webhookURL` | Incoming Webhook URL for Slack (example: 'https://hooks.slack.com/services/T000/B000/XXXXX') | `string` | `""` | +| `alerta.alerts.slack.channel` | Default Slack channel (e.g. "#alerts"). If empty, channel from webhook configuration is used. | `string` | `""` | +| `alerta.alerts.slack.attachments` | Whether to include attachments in Slack messages (default: false) | `bool` | `false` | +| `alerta.alerts.slack.channelEnvMap` | Mapping of environment name to Slack channel. Example: { Production: "#alert-prod" } | `map[string]string` | `{}` | +| `alerta.alerts.slack.channelEventMap` | Mapping of event name to Slack channel. Example: { "Node offline": "#critical-alerts" } | `map[string]string` | `{}` | +| `alerta.alerts.slack.channelSeverityMap` | Mapping of severity to Slack channel. Example: { critical: "#critical-alerts" } | `map[string]string` | `{}` | +| `alerta.alerts.slack.channelMap` | Nested mapping of environment -> severity -> channel. Example: { Production: { critical: "#prod-alerts" } } | `map[string]map[string]string` | `{}` | +| `alerta.alerts.slack.iconEmoji` | Emoji to use as an icon for messages (e.g. ":warning:") | `string` | `""` | +| `alerta.alerts.slack.alertaUsername` | Username to use for messages from Alerta (default: "alerta") | `string` | `""` | ### Grafana configuration diff --git a/packages/extra/monitoring/templates/alerta/alerta.yaml b/packages/extra/monitoring/templates/alerta/alerta.yaml index 13c37788..8fc5a9c4 100644 --- a/packages/extra/monitoring/templates/alerta/alerta.yaml +++ b/packages/extra/monitoring/templates/alerta/alerta.yaml @@ -10,7 +10,8 @@ {{- if $existingSecret }} {{- $apiKey = index $existingSecret.data "alerta-api-key" | b64dec }} {{- end }} ---- +{{- /* build list of plugins to enable */}} +{{- $plugins := list }} apiVersion: v1 kind: Secret metadata: @@ -110,8 +111,7 @@ spec: value: "True" {{- if and .Values.alerta.alerts.telegram.chatID .Values.alerta.alerts.telegram.token }} - - name: "PLUGINS" - value: "telegram" + {{- $plugins = append $plugins "telegram" }} - name: TELEGRAM_CHAT_ID value: "{{ .Values.alerta.alerts.telegram.chatID }}" - name: TELEGRAM_TOKEN @@ -122,6 +122,50 @@ spec: value: "{{ .Values.alerta.alerts.telegram.disabledSeverity }}" {{- end }} + {{- if .Values.alerta.alerts.slack.webhookURL }} + {{- $plugins = append $plugins "slack" }} + - name: SLACK_WEBHOOK_URL + value: "{{ .Values.alerta.alerts.slack.webhookURL }}" + {{- end }} + {{- if .Values.alerta.alerts.slack.channel }} + - name: SLACK_CHANNEL + value: "{{ .Values.alerta.alerts.slack.channel }}" + {{- end }} + {{- if .Values.alerta.alerts.slack.attachments }} + - name: SLACK_ATTACHMENTS + value: "{{ .Values.alerta.alerts.slack.attachments }}" + {{- end }} + {{- if .Values.alerta.alerts.slack.channelEnvMap }} + - name: SLACK_CHANNEL_ENV_MAP + value: '{{ toJson .Values.alerta.alerts.slack.channelEnvMap }}' + {{- end }} + {{- if .Values.alerta.alerts.slack.channelEventMap }} + - name: SLACK_CHANNEL_EVENT_MAP + value: '{{ toJson .Values.alerta.alerts.slack.channelEventMap }}' + {{- end }} + {{- if .Values.alerta.alerts.slack.channelSeverityMap }} + - name: SLACK_CHANNEL_SEVERITY_MAP + value: '{{ toJson .Values.alerta.alerts.slack.channelSeverityMap }}' + {{- end }} + {{- if .Values.alerta.alerts.slack.channelMap }} + - name: SLACK_CHANNEL_MAP + value: '{{ toJson .Values.alerta.alerts.slack.channelMap }}' + {{- end }} + {{- if .Values.alerta.alerts.slack.iconEmoji }} + - name: ICON_EMOJI + value: "{{ .Values.alerta.alerts.slack.iconEmoji }}" + {{- end }} + {{- if .Values.alerta.alerts.slack.alertaUsername }} + - name: ALERTA_USERNAME + value: "{{ .Values.alerta.alerts.slack.alertaUsername }}" + {{- end }} + {{- end }} + + {{- if gt (len $plugins) 0 }} + - name: PLUGINS + value: "{{ join "," $plugins }}" + {{- end }} + ports: - name: http containerPort: 8080 diff --git a/packages/extra/monitoring/values.schema.json b/packages/extra/monitoring/values.schema.json index 36f1c0c3..455b02b8 100644 --- a/packages/extra/monitoring/values.schema.json +++ b/packages/extra/monitoring/values.schema.json @@ -5,17 +5,149 @@ "alerta": { "description": "Configuration for Alerta service", "type": "object", - "default": {}, + "default": { + "alerts": { + "slack": { + "alertaUsername": "", + "attachments": false, + "channel": "", + "channelEnvMap": {}, + "channelEventMap": {}, + "channelMap": {}, + "channelSeverityMap": {}, + "iconEmoji": "", + "webhookURL": "" + }, + "telegram": { + "chatID": "", + "disabledSeverity": "", + "token": "" + } + }, + "resources": { + "limits": { + "cpu": "1", + "memory": "1Gi" + }, + "requests": { + "cpu": "100m", + "memory": "256Mi" + } + }, + "storage": "10Gi", + "storageClassName": "" + }, "properties": { "alerts": { "description": "Configuration for alerts", "type": "object", - "default": {}, + "default": { + "slack": { + "alertaUsername": "", + "attachments": false, + "channel": "", + "channelEnvMap": {}, + "channelEventMap": {}, + "channelMap": {}, + "channelSeverityMap": {}, + "iconEmoji": "", + "webhookURL": "" + }, + "telegram": { + "chatID": "", + "disabledSeverity": "", + "token": "" + } + }, "properties": { + "slack": { + "description": "Configuration for Slack alerts", + "type": "object", + "default": { + "alertaUsername": "", + "attachments": false, + "channel": "", + "channelEnvMap": {}, + "channelEventMap": {}, + "channelMap": {}, + "channelSeverityMap": {}, + "iconEmoji": "", + "webhookURL": "" + }, + "required": [ + "alertaUsername", + "attachments", + "channel", + "iconEmoji", + "webhookURL" + ], + "properties": { + "alertaUsername": { + "description": "Username to use for messages from Alerta (default: \"alerta\")", + "type": "string" + }, + "attachments": { + "description": "Whether to include attachments in Slack messages (default: false)", + "type": "boolean", + "default": false + }, + "channel": { + "description": "Default Slack channel (e.g. \"#alerts\"). If empty, channel from webhook configuration is used.", + "type": "string" + }, + "channelEnvMap": { + "description": "Mapping of environment name to Slack channel. Example: { Production: \"#alert-prod\" }", + "type": "object", + "default": {}, + "additionalProperties": { + "type": "string" + } + }, + "channelEventMap": { + "description": "Mapping of event name to Slack channel. Example: { \"Node offline\": \"#critical-alerts\" }", + "type": "object", + "default": {}, + "additionalProperties": { + "type": "string" + } + }, + "channelMap": { + "description": "Nested mapping of environment -\u003e severity -\u003e channel. Example: { Production: { critical: \"#prod-alerts\" } }", + "type": "object", + "default": {}, + "additionalProperties": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "channelSeverityMap": { + "description": "Mapping of severity to Slack channel. Example: { critical: \"#critical-alerts\" }", + "type": "object", + "default": {}, + "additionalProperties": { + "type": "string" + } + }, + "iconEmoji": { + "description": "Emoji to use as an icon for messages (e.g. \":warning:\")", + "type": "string" + }, + "webhookURL": { + "description": "Incoming Webhook URL for Slack (example: 'https://hooks.slack.com/services/T000/B000/XXXXX')", + "type": "string" + } + } + }, "telegram": { "description": "Configuration for Telegram alerts", "type": "object", - "default": {}, + "default": { + "chatID": "", + "disabledSeverity": "", + "token": "" + }, "required": [ "chatID", "disabledSeverity", @@ -41,11 +173,23 @@ "resources": { "description": "Resources configuration", "type": "object", - "default": {}, + "default": { + "limits": { + "cpu": "1", + "memory": "1Gi" + }, + "requests": { + "cpu": "100m", + "memory": "256Mi" + } + }, "properties": { "limits": { "type": "object", - "default": {}, + "default": { + "cpu": "1", + "memory": "1Gi" + }, "properties": { "cpu": { "description": "CPU limit (maximum available CPU)", @@ -79,7 +223,10 @@ }, "requests": { "type": "object", - "default": {}, + "default": { + "cpu": "100m", + "memory": "256Mi" + }, "properties": { "cpu": { "description": "CPU request (minimum available CPU)", @@ -127,12 +274,28 @@ "grafana": { "description": "Configuration for Grafana", "type": "object", - "default": {}, + "default": { + "db": { + "size": "10Gi" + }, + "resources": { + "limits": { + "cpu": "1", + "memory": "1Gi" + }, + "requests": { + "cpu": "100m", + "memory": "256Mi" + } + } + }, "properties": { "db": { "description": "Database configuration", "type": "object", - "default": {}, + "default": { + "size": "10Gi" + }, "properties": { "size": { "description": "Persistent Volume size for the database", @@ -144,11 +307,23 @@ "resources": { "description": "Resources configuration", "type": "object", - "default": {}, + "default": { + "limits": { + "cpu": "1", + "memory": "1Gi" + }, + "requests": { + "cpu": "100m", + "memory": "256Mi" + } + }, "properties": { "limits": { "type": "object", - "default": {}, + "default": { + "cpu": "1", + "memory": "1Gi" + }, "properties": { "cpu": { "description": "CPU limit (maximum available CPU)", @@ -182,7 +357,10 @@ }, "requests": { "type": "object", - "default": {}, + "default": { + "cpu": "100m", + "memory": "256Mi" + }, "properties": { "cpu": { "description": "CPU request (minimum available CPU)", @@ -247,8 +425,7 @@ }, "retentionPeriod": { "description": "Retention period for the logs in the storage instance", - "type": "string", - "default": "1" + "type": "string" }, "storage": { "description": "Persistent Volume size for the storage instance", @@ -538,4 +715,4 @@ } } } -} \ No newline at end of file +} diff --git a/packages/extra/monitoring/values.yaml b/packages/extra/monitoring/values.yaml index 02155ce0..e1da531a 100644 --- a/packages/extra/monitoring/values.yaml +++ b/packages/extra/monitoring/values.yaml @@ -90,6 +90,16 @@ logsStorages: ## @field telegramAlerts.token {string} Telegram token for your bot ## @field telegramAlerts.chatID {string} Specify multiple ID's separated by comma. Get yours in https://t.me/chatid_echo_bot ## @field telegramAlerts.disabledSeverity {string} List of severity without alerts, separated by comma like: "informational,warning" +## @field alerts.slack {*slackAlerts} Configuration for Slack alerts +## @field slackAlerts.webhookURL {string} Incoming Webhook URL for Slack (example: 'https://hooks.slack.com/services/T000/B000/XXXXX') +## @field slackAlerts.channel {string} Default Slack channel (e.g. "#alerts"). If empty, channel from webhook configuration is used. +## @field slackAlerts.attachments {bool} Whether to include attachments in Slack messages (default: false) +## @field slackAlerts.channelEnvMap {map[string]string} Mapping of environment name to Slack channel. Example: { Production: "#alert-prod" } +## @field slackAlerts.channelEventMap {map[string]string} Mapping of event name to Slack channel. Example: { "Node offline": "#critical-alerts" } +## @field slackAlerts.channelSeverityMap {map[string]string} Mapping of severity to Slack channel. Example: { critical: "#critical-alerts" } +## @field slackAlerts.channelMap {map[string]map[string]string} Nested mapping of environment -> severity -> channel. Example: { Production: { critical: "#prod-alerts" } } +## @field slackAlerts.iconEmoji {string} Emoji to use as an icon for messages (e.g. ":warning:") +## @field slackAlerts.alertaUsername {string} Username to use for messages from Alerta (default: "alerta") alerta: storage: 10Gi storageClassName: "" @@ -111,6 +121,25 @@ alerta: token: "" chatID: "" disabledSeverity: "" + slack: + # Incoming Webhook URL for Slack. If set, the slack plugin will be enabled. + webhookURL: "" + # Optional channel (e.g. "#alerts") + channel: "" + # Whether to include attachments in Slack messages (default: false) + attachments: false + # Optional mapping of environment name -> channel. Example: { Production: "#alert-prod" } + channelEnvMap: {} + # Optional mapping of event name -> channel. Example: { "Node offline": "#critical-alerts" } + channelEventMap: {} + # Optional mapping of severity -> channel. Example: { critical: "#critical-alerts" } + channelSeverityMap: {} + # Optional nested mapping of environment -> (severity -> channel). Example: { Production: { critical: "#prod-alerts" } } + channelMap: {} + # Optional emoji to use as an icon (e.g. ":warning:") + iconEmoji: "" + # Optional username for messages from Alerta (default: alerta) + alertaUsername: "" ## @section Grafana configuration diff --git a/packages/extra/versions_map b/packages/extra/versions_map index b0f3c742..c135934a 100644 --- a/packages/extra/versions_map +++ b/packages/extra/versions_map @@ -57,7 +57,8 @@ monitoring 1.11.0 4369b031 monitoring 1.12.0 0e47e1e8 monitoring 1.12.1 c02a3818 monitoring 1.13.0 87b23161 -monitoring 1.13.1 HEAD +monitoring 1.13.1 53fbe7c2 +monitoring 1.14.0 HEAD seaweedfs 0.1.0 71514249 seaweedfs 0.2.0 5fb9cfe3 seaweedfs 0.2.1 fde4bcfa