Skip to content

Commit

Permalink
feat: standalone alertmanager library (grafana#403)
Browse files Browse the repository at this point in the history
  • Loading branch information
Duologic authored Dec 17, 2020
1 parent ba39123 commit 40ddee9
Show file tree
Hide file tree
Showing 8 changed files with 282 additions and 156 deletions.
132 changes: 132 additions & 0 deletions alertmanager/alertmanager.libsonnet
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
local kausal = import 'ksonnet-util/kausal.libsonnet';

(import 'config.libsonnet')
+ (import 'images.libsonnet')
+ {
local this = self,
local _config = self._config,
local k = kausal { _config+:: _config },

alertmanager_config+:: {
templates+: [
'/etc/alertmanager/*.tmpl',
'/etc/alertmanager/config/templates.tmpl',
],
},

local configMap = k.core.v1.configMap,

alertmanager_config_map:
configMap.new('alertmanager-config') +
configMap.withData({
'alertmanager.yml': k.util.manifestYaml(this.alertmanager_config),
'templates.tmpl': (importstr 'files/alertmanager_config.tmpl'),
}),

local container = k.core.v1.container,
local volumeMount = k.core.v1.volumeMount,

alertmanager_container::
container.new('alertmanager', self._images.alertmanager)
+ container.withPorts([
k.core.v1.containerPort.new('http-metrics', _config.alertmanager_port),
])
+ container.withArgs([
'--log.level=info',
'--config.file=/etc/alertmanager/config/alertmanager.yml',
'--web.listen-address=:%s' % _config.alertmanager_port,
'--web.external-url=%s%s' % [_config.alertmanager_external_hostname, _config.alertmanager_path],
'--storage.path=/alertmanager',
])
+ container.withEnvMixin([
container.envType.fromFieldPath('POD_IP', 'status.podIP'),
])
+ container.withVolumeMountsMixin(
volumeMount.new('alertmanager-data', '/alertmanager')
)
+ container.mixin.resources.withRequests({
cpu: '10m',
memory: '40Mi',
}),

isGossiping():: {
alertmanager_container+:
container.withPortsMixin(
[
k.core.v1.containerPort.newUDP('gossip-udp', _config.alertmanager_gossip_port),
k.core.v1.containerPort.new('gossip-tcp', _config.alertmanager_gossip_port),
]
)
+ container.withArgsMixin(
['--cluster.listen-address=[$(POD_IP)]:%s' % _config.alertmanager_gossip_port]
+ ['--cluster.peer=%s' % peer for peer in _config.alertmanager_peers]
),
},

alertmanager_watch_container::
container.new('watch', self._images.watch)
+ container.withArgs([
'-v',
'-t',
'-p=/etc/alertmanager/config',
'curl',
'-X',
'POST',
'--fail',
'-o',
'-',
'-sS',
'http://localhost:%s%s-/reload' % [
_config.alertmanager_port,
_config.alertmanager_path,
],
]) +
container.mixin.resources.withRequests({
cpu: '10m',
memory: '20Mi',
}),

local pvc = k.core.v1.persistentVolumeClaim,

alertmanager_pvc::
pvc.new('alertmanager-data')
+ pvc.mixin.spec.withAccessModes('ReadWriteOnce')
+ pvc.mixin.spec.resources.withRequests({ storage: '5Gi' }),

local statefulset = k.apps.v1.statefulSet,

alertmanager_statefulset:
statefulset.new(
'alertmanager',
_config.alertmanager_replicas,
[
self.alertmanager_container,
self.alertmanager_watch_container,
],
self.alertmanager_pvc
)
+ statefulset.mixin.spec.withServiceName('alertmanager')
+ statefulset.mixin.spec.template.metadata.withAnnotations({
'prometheus.io.path': '%smetrics' % _config.alertmanager_path,
})
+ statefulset.mixin.spec.template.spec.securityContext.withFsGroup(2000)
+ statefulset.mixin.spec.template.spec.securityContext.withRunAsUser(1000)
+ statefulset.mixin.spec.template.spec.securityContext.withRunAsNonRoot(true)
+ k.util.configVolumeMount('alertmanager-config', '/etc/alertmanager/config')
+ k.util.podPriority('critical')
,

local service = k.core.v1.service,
local servicePort = service.mixin.spec.portsType,

alertmanager_service:
k.util.serviceFor(self.alertmanager_statefulset)
+ service.mixin.spec.withPortsMixin([
servicePort.newNamed(
name='http',
port=80,
targetPort=_config.alertmanager_port,
),
]) +
service.mixin.spec.withSessionAffinity('ClientIP'),
}
18 changes: 18 additions & 0 deletions alertmanager/config.libsonnet
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
{
_config+:: {
// Cluster and environment specific overrides.
cluster_dns_tld: 'local',
cluster_dns_suffix: 'cluster.' + self.cluster_dns_tld,
cluster_name: error 'must specify cluster name',
namespace: error 'must specify namespace',

// Alertmanager config options.
alertmanager_external_hostname: 'http://alertmanager.%(namespace)s.svc.%(cluster_dns_suffix)s' % self,
alertmanager_path: '/alertmanager/',
alertmanager_port: 9093,
alertmanager_gossip_port: 9094,

alertmanager_replicas: 1,
alertmanager_peers: [],
},
}
25 changes: 25 additions & 0 deletions alertmanager/files/alertmanager_config.tmpl
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
{{ define "__alert_title" -}}
[{{ .Status | toUpper }}{{ if eq .Status "firing" }}:{{ .Alerts.Firing | len }}{{ end }}] {{ .GroupLabels.cluster }}: {{ .GroupLabels.alertname }} ({{ .GroupLabels.namespace }})
{{- end }}

{{ define "__alert_text" -}}
{{ .CommonAnnotations.summary }}
{{ if .Alerts.Firing | len }}Firing alerts:
{{ range .Alerts.Firing }}- {{ .Annotations.message }}{{ .Annotations.description }}
{{ end }}{{ end }}{{ if .Alerts.Resolved | len }}Resolved alerts:
{{ range .Alerts.Resolved }}- {{ .Annotations.message }}{{ .Annotations.description }}
{{ end }}{{ end }}
{{- end }}

# This builds the silence URL. We exclude the alertname in the range
# to avoid the issue of having trailing comma separator (%2C) at the end
# of the generated URL. Inspired from https://gist.github.com/milesbxf/e2744fc90e9c41b47aa47925f8ff6512
{{ define "__alert_silence_link" -}}
{{ .ExternalURL }}/#/silences/new?filter=%7B
{{- range .CommonLabels.SortedPairs -}}
{{- if ne .Name "alertname" -}}
{{- .Name }}%3D%22{{- .Value -}}%22%2C%20
{{- end -}}
{{- end -}}
alertname%3D%22{{ .CommonLabels.alertname }}%22%7D
{{- end }}
6 changes: 6 additions & 0 deletions alertmanager/images.libsonnet
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
_images+:: {
alertmanager: 'prom/alertmanager:v0.21.0',
watch: 'weaveworks/watch:master-5fc29a9',
},
}
15 changes: 15 additions & 0 deletions alertmanager/jsonnetfile.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
{
"version": 1,
"dependencies": [
{
"source": {
"git": {
"remote": "https://github.com/grafana/jsonnet-libs.git",
"subdir": "ksonnet-util"
}
},
"version": "master"
}
],
"legacyImports": true
}
53 changes: 53 additions & 0 deletions alertmanager/slack.libsonnet
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
{
local this = self,

_config+:: {
slack_url: 'http://slack',
slack_channel: 'general',
},

build_slack_receiver(name, slack_channel)::
{
name: name,
slack_configs: [{
api_url: this._config.slack_url,
channel: slack_channel,
send_resolved: true,
title: '{{ template "__alert_title" . }}',
text: '{{ template "__alert_text" . }}',
actions: [
{
type: 'button',
text: 'Runbook :green_book:',
url: '{{ (index .Alerts 0).Annotations.runbook_url }}',
},
{
type: 'button',
text: 'Source :information_source:',
url: '{{ (index .Alerts 0).GeneratorURL }}',
},
{
type: 'button',
text: 'Silence :no_bell:',
url: '{{ template "__alert_silence_link" . }}',
},
{
type: 'button',
text: 'Dashboard :grafana:',
url: '{{ (index .Alerts 0).Annotations.dashboard_url }}',
},
],
}],
},

alertmanager_config+:: {
route+: {
group_by: ['alertname'],
receiver: 'slack',
},

receivers+: [
this.build_slack_receiver('slack', this._config.slack_channel),
],
},
}
9 changes: 9 additions & 0 deletions prometheus-ksonnet/jsonnetfile.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,15 @@
},
"version": "master"
},
{
"source": {
"git": {
"remote": "https://github.com/grafana/jsonnet-libs.git",
"subdir": "alertmanager"
}
},
"version": "master"
},
{
"source": {
"git": {
Expand Down
Loading

0 comments on commit 40ddee9

Please sign in to comment.