Skip to content

Commit 13f4056

Browse files
committed
feat: create ConfigMap with Alertmanager templates
1 parent ad76140 commit 13f4056

File tree

6 files changed

+210
-24
lines changed

6 files changed

+210
-24
lines changed

charts/alertmanager-config/Chart.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
apiVersion: v2
22
name: alertmanager-config
33
description: Create namespaced Alertmanager receivers and routes with AlertmanagerConfig objects.
4-
version: 1.0.0
4+
version: 1.1.0
55
maintainers:
66
77
name: Eivind Valderhaug

charts/alertmanager-config/README.md

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ _Warning: the AlertmanagerConfig CRD from Prometheus Operator is not yet stable
44

55
Specify behavior of Alertmanager with the [AlertmanagerConfig](https://prometheus-operator.dev/docs/operator/api/#monitoring.coreos.com/v1alpha1.AlertmanagerConfig) CRD from Prometheus Operator.
66

7-
This chart makes it easy to provide common default configs while allowing flexibility to override those defaults.
7+
This chart makes it easy to provide common default configs while allowing flexibility to override those defaults for example per namespace. It can also generate Alertmanager templates to be used by a global [AlertmanagerConfiguration](https://prometheus-operator.dev/docs/operator/api/#monitoring.coreos.com/v1.AlertmanagerConfiguration) (enable with `alertmanagerTemplates.enabled`).
88

99
Note: The configuration is scoped to the AlertmanagerConfig namespace; receivers and routes will automatically get a name prefix to avoid conflicts with receivers and routes configured elsewhere. Please see the related configuration options for Alertmanager and Prometheus.
1010

@@ -42,7 +42,7 @@ To support routes as dicts, which are unordered (ie. items will not be in a pred
4242

4343
Note: The `order` field is sorted using the built-in Helm function sortAlpha because there doesn't seem to be a numeric sorting function available in Helm.
4444

45-
### Example
45+
### Examples
4646
`values.yaml`:
4747
```yaml
4848
labels:
@@ -86,3 +86,19 @@ receiverDefaults:
8686
name: alertmanager-slack
8787
sendResolved: true
8888
```
89+
90+
Enable templates ConfigMap for global Alertmanager config:
91+
```yaml
92+
alertmanagerTemplates:
93+
enabled: true
94+
# templatesEnabledByDefault: false # disable all predefined templates to start from scratch with your own
95+
# slack:
96+
# enabled: false # disable individual templates
97+
# example custom template, myCustomTemplates will be the key for this template in the generated ConfigMap:
98+
myCustomTemplates:
99+
enabled: true
100+
templateString: |-
101+
{{- define "myCustomTemplates.example" -}}
102+
{{/* my custom templates */}}
103+
{{- end -}}
104+
```

charts/alertmanager-config/docs/kube-prometheus-stack-alertmanager-global-config.md

Lines changed: 25 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
1-
Example of configuring global Alertmanager config with an AlertmanagerConfig object when using the [kube-prometheus-stack](https://github.com/prometheus-community/helm-charts/tree/main/charts/kube-prometheus-stack) Helm chart.
1+
Example of global Alertmanager config for the [kube-prometheus-stack](https://github.com/prometheus-community/helm-charts/tree/main/charts/kube-prometheus-stack) Helm chart.
22

33
`alertmanager-config-values.yaml`:
44
```yaml
5-
fullnameOverride: global-config
5+
fullnameOverride: alertmanager-global-config
66
alertmanagerConfig: # https://prometheus-operator.dev/docs/operator/api/#monitoring.coreos.com/v1alpha1.AlertmanagerConfigSpec
77
receivers:
88
default:
@@ -16,14 +16,34 @@ alertmanagerConfig: # https://prometheus-operator.dev/docs/operator/api/#monitor
1616
groupWait: 10s
1717
groupInterval: 5m
1818
repeatInterval: 3h
19+
alertmanagerTemplates:
20+
enabled: true # creates ConfigMap with templates
1921
```
2022
2123
`kube-prometheus-stack-values.yaml`:
2224
```yaml
2325
alertmanager:
2426
alertmanagerSpec:
2527
alertmanagerConfiguration: # https://prometheus-operator.dev/docs/operator/api/#monitoring.coreos.com/v1.AlertmanagerConfiguration
26-
name: global-config
27-
# global: # AlertmanagerGlobalConfig: https://prometheus-operator.dev/docs/operator/api/#monitoring.coreos.com/v1.AlertmanagerGlobalConfig
28-
# templates: # SecretOrConfigMap: https://prometheus-operator.dev/docs/operator/api/#monitoring.coreos.com/v1.SecretOrConfigMap
28+
name: alertmanager-global-config
29+
global: # AlertmanagerGlobalConfig: https://prometheus-operator.dev/docs/operator/api/#monitoring.coreos.com/v1.AlertmanagerGlobalConfig
30+
# httpConfig:
31+
# authorization:
32+
# type: Bearer
33+
# credentials:
34+
# key: bot-token
35+
# name: alertmanager-slack
36+
slackApiUrl:
37+
key: api-url # https://slack.com/api/chat.postMessage
38+
name: alertmanager-slack # this secret must be manually created, eg. `kubectl create secret generic alertmanager-slack --from-literal=api-url=https://slack.com/api/chat.postMessage` # with bot-token, add: `--from-literal=bot-token=<slack bot token>`
39+
templates: # []SecretOrConfigMap: https://prometheus-operator.dev/docs/operator/api/#monitoring.coreos.com/v1.SecretOrConfigMap
40+
- configMap:
41+
key: all
42+
name: alertmanager-global-config
43+
# - configMap:
44+
# key: slack
45+
# name: alertmanager-global-config
46+
# - configMap:
47+
# key: url
48+
# name: alertmanager-global-config
2949
```

charts/alertmanager-config/templates/alertmanagerconfig.yaml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,10 @@ metadata:
44
name: {{ include "alertmanager-config.fullname" . }}
55
labels:
66
{{- include "alertmanager-config.labels" . | nindent 4 }}
7+
{{- with .Values.annotations }}
8+
annotations:
9+
{{- toYaml . | nindent 4 }}
10+
{{- end }}
711
spec:
812
{{- with (omit .Values.alertmanagerConfig "receivers" "route") }}
913
{{- toYaml . | nindent 2 }}
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
{{- if .Values.alertmanagerTemplates.enabled -}}
2+
apiVersion: v1
3+
kind: ConfigMap
4+
metadata:
5+
name: {{ include "alertmanager-config.fullname" . }}
6+
labels:
7+
{{- include "alertmanager-config.labels" . | nindent 4 }}
8+
{{- with .Values.annotations }}
9+
annotations:
10+
{{- toYaml . | nindent 4 }}
11+
{{- end }}
12+
data:
13+
all: |-
14+
{{- $templates := omit .Values.alertmanagerTemplates "enabled" "templatesEnabledByDefault" -}}
15+
{{- range $templateName, $templateValues := $templates -}}
16+
{{- if or $templateValues.enabled (and (typeIs "<nil>" $templateValues.enabled) $.Values.alertmanagerTemplates.templatesEnabledByDefault) -}}
17+
{{- with $templateValues.templateString -}}
18+
{{- . | nindent 4 }}
19+
{{- end }}
20+
{{- if $templateValues.includeHelmTemplate }}
21+
{{- include (print "alertmanager-config.templates." $templateName) $ | nindent 4 }}
22+
{{- end }}
23+
{{- end }}
24+
{{- end }}
25+
{{- range $templateName, $templateValues := $templates -}}
26+
{{- if or $templateValues.enabled (and (typeIs "<nil>" $templateValues.enabled) $.Values.alertmanagerTemplates.templatesEnabledByDefault) -}}
27+
{{- $templateName | nindent 2 }}: |-
28+
{{- with $templateValues.templateString -}}
29+
{{- . | nindent 4 }}
30+
{{- end }}
31+
{{- if $templateValues.includeHelmTemplate }}
32+
{{- include (print "alertmanager-config.templates." $templateName) $ | nindent 4 }}
33+
{{- end }}
34+
{{- end }}
35+
{{- end }}
36+
{{- end }}

charts/alertmanager-config/values.yaml

Lines changed: 126 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ nameOverride: ""
44
fullnameOverride: ""
55

66
labels:
7+
annotations:
78

89
# NOTE: the parameter names for AlertmanagerConfig objects are slightly different than in regular Alertmanager config
910
# See docs:
@@ -24,6 +25,15 @@ alertmanagerConfig:
2425
# serviceKey:
2526
# name: pagerduty
2627
# key: token
28+
# deadmanssnitch:
29+
# enabled: false
30+
# webhookConfigs:
31+
# - urlSecret:
32+
# key: url
33+
# name: deadmanssnitch
34+
# slack:
35+
# slackConfigs:
36+
# - channel: '{{ index ((index .Alerts 0).Labels) "slack_channel" }}'
2737
route:
2838
receiver: default
2939
groupBy:
@@ -49,13 +59,29 @@ alertmanagerConfig:
4959
# matchType: "="
5060
# value: critical
5161
# receiver: critical
52-
# infoInhibitor:
62+
# watchdog:
63+
# enabled: false # typically enabled for global config
5364
# order: 1
5465
# matchers:
5566
# - name: alertname
5667
# matchType: "="
68+
# value: Watchdog
69+
# receiver: void # eg. "deadmanssnitch" for global production config
70+
# repeatInterval: 1m
71+
# infoInhibitor:
72+
# order: 2
73+
# matchers:
74+
# - name: alertname
75+
# matchType: "="
5776
# value: InfoInhibitor
5877
# receiver: void
78+
# slack:
79+
# order: 3
80+
# matchers:
81+
# - name: slack_channel
82+
# matchType: "=~"
83+
# value: ^#?[a-z0-9._-]+$
84+
# receiver: slack
5985

6086
# Whether ordered routes (containing order field) are put before routes without this field.
6187
# The order field is only relevant if you use a dict/map, which is unordered, for alertmanagerConfig.route.routes.
@@ -78,27 +104,26 @@ receiverDefaults:
78104
# pagerdutyConfigs: # https://developer.pagerduty.com/docs/ZG9jOjExMDI5NTgx-send-an-alert-event
79105
# class: '{{ .CommonLabels.alertname }}'
80106
# component: '{{ with .CommonLabels }}{{ or .name .service .deployment .pod }}{{ end }}'
81-
# description: '{{ with .CommonAnnotations }}{{ or .description .summary }}{{ end }}'
82107
# details:
83108
# firing: '{{ template "pagerduty.default.instances" .Alerts.Firing }}'
84109
# resolved: '{{ template "pagerduty.default.instances" .Alerts.Resolved }}'
85110
# num_firing: '{{ .Alerts.Firing | len }}'
86111
# num_resolved: '{{ .Alerts.Resolved | len }}'
87-
# k8s_cluster: '{{ .CommonLabels.cluster }}'
88-
# namespace: '{{ .CommonLabels.namespace }}'
89-
# summary: '{{ .CommonAnnotations.summary }}'
112+
# # k8s_cluster: '{{ .CommonLabels.cluster }}'
113+
# # namespace: '{{ .CommonLabels.namespace }}'
114+
# # summary: '{{ .CommonAnnotations.summary }}'
90115
# group: '{{ .CommonLabels.namespace }}'
91116
# httpConfig: {}
92117
# links:
93-
# - href: '{{ (index .Alerts 0).Annotations.runbook_url }}'
118+
# - href: '{{ template "url.runbook" . }}'
94119
# text: Runbook
95-
# - href: '{{ (index .Alerts 0).GeneratorURL }}'
120+
# - href: '{{ template "url.query" . }}'
96121
# text: Query
97-
# - href: '{{ (index .Alerts 0).Annotations.dashboard_url }}'
122+
# - href: '{{ template "url.dashboard" . }}'
98123
# text: Dashboard
99-
# - href: '{{ (index .Alerts 0).Annotations.log_url }}'
124+
# - href: '{{ template "url.log" . }}'
100125
# text: Log
101-
# - href: '{{ template "__alert_silence_link" . }}'
126+
# - href: '{{ template "url.silence" . }}'
102127
# text: Silence
103128
# # depending on the PagerDuty integration type, use either routingKey for Events API v2 or serviceKey for integration type "Prometheus"
104129
# routingKey:
@@ -107,24 +132,25 @@ receiverDefaults:
107132
# # serviceKey:
108133
# # key: token
109134
# # name: pagerduty
110-
# severity: '{{ or .CommonLabels.severity "critical" | toLower }}' # https://support.pagerduty.com/docs/dynamic-notifications#eventalert-severity-levels
135+
# severity: '{{ or .CommonLabels.severity "error" | toLower }}' # https://support.pagerduty.com/docs/dynamic-notifications#eventalert-severity-levels
111136
# slackConfigs: # https://api.slack.com/messaging/composing/layouts#building-attachments
112137
# actions:
113138
# - text: "Runbook :green_book:"
114139
# type: button
115-
# url: '{{ (index .Alerts 0).Annotations.runbook_url }}'
140+
# url: '{{ template "url.runbook" . }}'
116141
# - text: "Query :mag:"
117142
# type: button
118-
# url: '{{ (index .Alerts 0).GeneratorURL }}'
143+
# url: '{{ template "url.query" . }}'
119144
# - text: "Dashboard :chart_with_upwards_trend:"
120145
# type: button
121-
# url: '{{ (index .Alerts 0).Annotations.dashboard_url }}'
146+
# url: '{{ template "url.dashboard" . }}'
122147
# - text: "Log :notebook:"
123148
# type: button
124-
# url: '{{ (index .Alerts 0).Annotations.log_url }}'
149+
# url: '{{ template "url.log" . }}'
125150
# - text: "Silence :no_bell:"
126151
# type: button
127-
# url: '{{ template "__alert_silence_link" . }}'
152+
# url: '{{ template "url.silence" . }}'
153+
# color: '{{ template "slack.color" . }}'
128154
# # apiURL:
129155
# # key: api-url # secret should contain webhook url or https://slack.com/api/chat.postMessage if using bot token (see also slackApiUrl in global config - https://prometheus-operator.dev/docs/operator/api/#monitoring.coreos.com/v1.AlertmanagerGlobalConfig)
130156
# # name: alertmanager-slack
@@ -149,3 +175,87 @@ receiverDefaults:
149175
# httpConfig: {}
150176
# wechatConfigs:
151177
# httpConfig: {}
178+
179+
alertmanagerTemplates:
180+
enabled: false
181+
templatesEnabledByDefault: true
182+
# <custom template name>:
183+
# enabled: true
184+
# templateString: |-
185+
# {{/* my custom templates */}}
186+
# # includeHelmTemplate: true # include Helm template "alertmanager-config.templates.<custom template name>" (only relevant if extending this chart)
187+
pagerduty:
188+
# enabled: true # overrides templatesEnabledByDefault
189+
templateString: |-
190+
{{- define "pagerduty.default.description" -}}
191+
{{- with .CommonAnnotations }}{{ or .summary .description }}{{ end -}}
192+
{{- end -}}
193+
slack:
194+
# enabled: true # overrides templatesEnabledByDefault
195+
templateString: |-
196+
{{- define "slack.color" -}}
197+
{{- if eq .Status "firing" -}}
198+
{{- if eq .CommonLabels.severity "critical" -}}
199+
danger
200+
{{- else if eq .CommonLabels.severity "warning" -}}
201+
warning
202+
{{- else -}}
203+
#439FE0
204+
{{- end -}}
205+
{{- else -}}
206+
good
207+
{{- end -}}
208+
{{- end -}}
209+
{{- /* Override default Slack templates. */}}
210+
{{- define "slack.default.text" -}}
211+
*Severity:* `{{ .CommonLabels.severity | title }}`
212+
{{- if .CommonLabels.cluster -}}
213+
{{- "\n" -}}
214+
*Cluster:* {{ .CommonLabels.cluster }}
215+
{{- end -}}
216+
{{- if (index .Alerts 0).Annotations.summary -}}
217+
{{- "\n" -}}
218+
*Summary:* {{ (index .Alerts 0).Annotations.summary -}}
219+
{{- end -}}
220+
{{- range .Alerts -}}
221+
{{- if .Annotations.description -}}
222+
{{- "\n" -}}
223+
{{- .Annotations.description -}}
224+
{{- "\n" -}}
225+
{{- end -}}
226+
{{- if .Annotations.message -}}
227+
{{- "\n" -}}
228+
{{- .Annotations.message -}}
229+
{{- "\n" -}}
230+
{{- end -}}
231+
{{- end -}}
232+
{{- end -}}
233+
{{- define "slack.default.title" -}}
234+
[{{ .Status | toUpper -}}
235+
{{ if eq .Status "firing" }}:{{ .Alerts.Firing | len }}{{- end -}}
236+
] {{ .CommonLabels.alertname }}
237+
{{- end -}}
238+
url:
239+
# enabled: true # overrides templatesEnabledByDefault
240+
templateString: |-
241+
{{- define "url.dashboard" -}}
242+
{{- (index .Alerts 0).Annotations.dashboard_url -}}
243+
{{- end -}}
244+
{{- define "url.log" -}}
245+
{{- (index .Alerts 0).Annotations.log_url -}}
246+
{{- end -}}
247+
{{- define "url.query" -}}
248+
{{- (index .Alerts 0).GeneratorURL -}}
249+
{{- end -}}
250+
{{- define "url.runbook" -}}
251+
{{- (index .Alerts 0).Annotations.runbook_url -}}
252+
{{- end -}}
253+
{{- define "url.silence" -}}
254+
{{- .ExternalURL }}/#/silences/new?filter=%7B
255+
{{- range .CommonLabels.SortedPairs -}}
256+
{{- if ne .Name "alertname" -}}
257+
{{- .Name }}%3D"{{- .Value -}}"%2C%20
258+
{{- end -}}
259+
{{- end -}}
260+
alertname%3D"{{- .CommonLabels.alertname -}}"%7D
261+
{{- end -}}

0 commit comments

Comments
 (0)