{"id":1688,"date":"2019-12-03T13:11:25","date_gmt":"2019-12-03T07:41:25","guid":{"rendered":"https:\/\/opstree.com\/blog\/\/?p=1688"},"modified":"2020-05-27T23:38:54","modified_gmt":"2020-05-27T18:08:54","slug":"prometheus-alertmanager-integration-with-ms-teams","status":"publish","type":"post","link":"https:\/\/opstree.com\/blog\/2019\/12\/03\/prometheus-alertmanager-integration-with-ms-teams\/","title":{"rendered":"Prometheus-Alertmanager integration with\u00a0MS-teams"},"content":{"rendered":"\n<p><p>As we know monitoring our infrastructure is one of the critical components of infrastructure management, which ensures the proper functioning of our applications and infrastructure. But it is of no use if we are not getting notifications for alarms and threats in our system. As a better practice, if we enable all of the notifications in a common work-space, it would be very helpful for our team to track the status and performance of our infrastructure.<\/p>\n<p><!--more--><\/p><\/p>\n\n\n\n<p>Last week, all of a sudden my company chose to migrate from slack to MS-teams as a common chatroom. Which meant, now, notifications would also be configured to MS-teams. If you had search a bit, you will find that there isn\u2019t any direct configuration for Ms-teams in alert manager as slack does. As a DevOps engineer I didn&#8217;t stop and looked beyond for more solutions and I found out that we need some proxy in between ALERTMANAGER and MS-teams for forwarding alerts and I proceeded to configure those.<\/p>\n\n\n\n<p>There are a couple of tools, which we can use as a proxy, but I preferred to use <a href=\"https:\/\/github.com\/bzon\/prometheus-msteams\" target=\"_blank\" rel=\"noreferrer noopener\">prometheus-msteams<\/a>, for a couple of reasons.<\/p>\n\n\n\n<ul><li>Well-structured documentation.<\/li><li>Easy to configure.<\/li><li>We have more control in hand, can customise alert notification and you can also configure to send notifications to multiple channels on MS-teams. Besides well-described documentation.<br>I still faced some challenges and took half of the day of mine.<\/li><\/ul>\n\n\n\n<p><strong>How it works<\/strong>?<\/p>\n\n\n\n<p>Firstly, Prometheus sends an alert to ALERTMANAGER on basis of rules we configured in the Prometheus server. For instance, if memory usages of the server are more than 90%, it will generate an alert, and this alert will send to ALERTMANAGER by the Prometheus server. Afterward, ALERTMANGER will send this alert to prometheus-msteams which in turn send this alert in JSON format to MS-teams\u2019s channel.<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"https:\/\/opstree.com\/blog\/\/wp-content\/uploads\/2019\/12\/e183f-1xxivs6rmpuc__xqopzylxq.png\" alt=\"\" \/><\/figure>\n\n\n\n<h4 class=\"wp-block-heading\">How to Run and Configure prometheus-msteams<\/h4>\n\n\n\n<p>We have multiple options to run prometheus-msteams<\/p>\n\n\n\n<ol><li>Running on standalone Server (Using Binary)<\/li><li>Running as a Docker Container<\/li><\/ol>\n\n\n\n<h4 class=\"wp-block-heading\">Running on&nbsp;Server<\/h4>\n\n\n\n<p>Firstly, you need to download the binary, <a href=\"https:\/\/github.com\/bzon\/prometheus-msteams\/releases\" target=\"_blank\" rel=\"noreferrer noopener\">click here<\/a> to download the binary from the latest releases.<\/p>\n\n\n\n<p>When you execute the binary with help on your system, you can see multiple options with description, which help us to run prometheus-msteams just like man-pages.<\/p>\n\n\n\n<div class=\"wp-block-group\"><div class=\"wp-block-group__inner-container is-layout-flow wp-block-group-is-layout-flow\">\n<pre class=\"wp-block-code\"><code>prometheus-msteams --help<\/code><\/pre>\n<\/div><\/div>\n\n\n\n<p>you can run promethues-msteams service as follow.<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\"><code>.\/prometheus-msteams server \\\n    -l localhost \\\n    -p 2000 \\\n    -w \"Webhook of MS-teams channel\"<\/code><\/pre>\n\n\n\n<p>Above options explanation<\/p>\n\n\n\n<ul><li>-l: On which address prometheus-msteams going to listen, the default address is \u201c0.0.0.0\u201d. In the above example, prometheus-msteams listening on the localhost.<\/li><li>-p: On which port prometheus-msteams going to listen, the default port is 2000<\/li><li>-w: The incoming webhook of MS-teams channel we are going to insert here.<\/li><\/ul>\n\n\n\n<p>Now you know how to run prometheus-msteams on the server, let\u2019s configure it with ALERTMANAGER.<\/p>\n\n\n\n<p><strong>Step 1 (Creating Incoming Webhook)<\/strong><\/p>\n\n\n\n<p>Create a channel in Ms-teams where you want to send alerts. Click on connectors(found connectors in options of the channel), and then search for \u2018incoming webhook\u2019 connector, from where you can create a webhook of this channel. Incoming webhook is used to send notification from external services to track the activities.<\/p>\n\n\n\n<p><strong>Step 2 (Run prometheus-msteams)<\/strong><\/p>\n\n\n\n<p>Till now, you have an incoming webhook of a channel where you want to send the notification. After that, you need to setup prometheus-msteams, and run it.<\/p>\n\n\n\n<p>To have more options in the future you can use config.yml to provide webhook. So that you can give multiple webhooks to send alerts to multiple channels in MS-teams in future if you need it.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>$ sudo nano \/opt\/promethues-msteams\/config.yml<\/code><\/pre>\n\n\n\n<p>Add webhooks as shown below. if you want to add another webhook, you can add right after first webhook.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>connectors:\n  - alert_channel: \"WEBHOOK URL\"<\/code><\/pre>\n\n\n\n<p>The next step is to add a template for custom notification.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>$ sudo nano \/opt\/prometheus-msteams\/card.tmpl<\/code><\/pre>\n\n\n\n<p>Copy the following content in your file, or you can modify the following template as per your requirements. This template can be customized and uses the <a href=\"https:\/\/golang.org\/pkg\/text\/template\/\" target=\"_blank\" rel=\"noreferrer noopener\">Go Templating Engine<\/a>.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>{{ define \"teams.card\" }}\n{\n  \"@type\": \"MessageCard\",\n  \"@context\": \"http:\/\/schema.org\/extensions\",\n  \"themeColor\": \"{{- if eq .Status \"resolved\" -}}2DC72D\n                 {{- else if eq .Status \"firing\" -}}\n                    {{- if eq .CommonLabels.severity \"critical\" -}}8C1A1A\n                    {{- else if eq .CommonLabels.severity \"warning\" -}}FFA500\n                    {{- else -}}808080{{- end -}}\n                 {{- else -}}808080{{- end -}}\",\n  \"summary\": \"Prometheus Alerts\",\n  \"title\": \"Prometheus Alert ({{ .Status }})\",\n  \"sections\": &#091; {{$externalUrl := .ExternalURL}}\n  {{- range $index, $alert := .Alerts }}{{- if $index }},{{- end }}\n    { \n      \"facts\": &#091;\n        {{- range $key, $value := $alert.Annotations }}\n        {\n          \"name\": \"{{ reReplaceAll \"_\" \"\\\\\\\\_\" $key }}\",\n          \"value\": \"{{ reReplaceAll \"_\" \"\\\\\\\\_\" $value }}\"\n        },\n        {{- end -}}\n        {{$c := counter}}{{ range $key, $value := $alert.Labels }}{{if call $c}},{{ end }}\n        {\n          \"name\": \"{{ reReplaceAll \"_\" \"\\\\\\\\_\" $key }}\",\n          \"value\": \"{{ reReplaceAll \"_\" \"\\\\\\\\_\" $value }}\"\n        }\n        {{- end }}\n      ],\n      \"markdown\": true\n    }\n    {{- end }}\n  ]\n}\n{{ end }}<\/code><\/pre>\n\n\n\n<p>Create prometheus-msteams user, and use <code>--no-create-home<\/code> and <code>--shell \/bin\/false<\/code> to restrict this user log into the server.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>$ sudo useradd --no-create-home --shell \/bin\/false prometheus-msteams<\/code><\/pre>\n\n\n\n<p>Now, set the user and group ownership on the prometheus-msteams directorie, and prometheus-msteams binary to the\u00a0<strong>prometheus-msteams<\/strong>\u00a0user.<\/p>\n\n\n\n<p>Create a service file to run prometheus-msteams as service with the following command.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>$ sudo nano \/etc\/systemd\/system\/prometheus-msteams.service<\/code><\/pre>\n\n\n\n<p>The service file tells systemd to run prometheus-msteams as the prometheus-msteams user, with the configuration file located \/opt\/promethues-msteams\/config.yml, and template file located in the same directory.<\/p>\n\n\n\n<p>Copy the following content into prometheus-msteams.service file.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>&#091;Unit]\nDescription=Prometheus-msteams\nWants=network-online.target\nAfter=network-online.target\n\n&#091;Service]\nUser=prometheus-msteams\nGroup=prometheus-msteams\nType=simple\nExecStart=\/usr\/local\/bin\/prometheus-msteams -config-file \/opt\/prometheus-msteams\/config.yml -template-file \/opt\/prometheus-msteams\/card.tmpl\n\n&#091;Install]\nWantedBy=multi-user.target<\/code><\/pre>\n\n\n\n<p>promethues-msteams listen on localhost on 2000 port, and you have to provide configuration file and template also.<\/p>\n\n\n\n<p>To use the newly created service, reload systemd.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>$ sudo systemctl daemon-reload<\/code><\/pre>\n\n\n\n<p>Now Start promethues-msteams.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>$ sudo systemctl start prometheus-msteams.service<\/code><\/pre>\n\n\n\n<p>Check, whether the service is running or not.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>$ sudo systemctl status prometheus-msteams<\/code><\/pre>\n\n\n\n<p>Lastly, enable the service to start on the boot.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>$ sudo systemctl enable prometheus-msteams<\/code><\/pre>\n\n\n\n<p>Now, prometheus-msteams is up and running, we can configure ALERTMANAGER to send alerts to prometheus-msteams.<\/p>\n\n\n\n<p><strong>Step 3(Configure ALERTMANAGER)<\/strong><\/p>\n\n\n\n<p>Open alertmanager.yml file in your favorite editor.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>$ sudo vim \/etc\/alertmanager\/alertmanager.yml<\/code><\/pre>\n\n\n\n<p>you can configure ALERTMANAGER as shown below.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>global:\n  resolve_timeout: 5m\n\ntemplates:\n  - '\/etc\/alertmanager\/*.tmpl'\n\nreceivers:\n- name: alert_channel\n  webhook_configs:\n  - url: 'http:\/\/localhost:2000\/alert_channel'\n    send_resolved: true\n\nroute:\n  group_by: &#091;'critical','severity']\n  group_interval: 5m\n  group_wait: 30s\n  receiver: alert_channel\n  repeat_interval: 3h<\/code><\/pre>\n\n\n\n<p>In the above configuration, ALERTMANAGER is sending alerts to prometheus-msteams, which is listening on localhost, and we pass send_resolved, which will send resolved alerts.<\/p>\n\n\n\n<p>The critical alert to MS-teams will look like below.<\/p>\n\n\n\n<div class=\"wp-block-image\"><figure class=\"aligncenter size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1638\" height=\"528\" src=\"https:\/\/opstree.com\/blog\/\/wp-content\/uploads\/2019\/10\/screenshot-2019-10-18-at-2.37.41-pm.png?w=1024\" alt=\"\" class=\"wp-image-1691\" \/><\/figure><\/div>\n\n\n\n<p>When alert resolved, it will look like below.<\/p>\n\n\n\n<div class=\"wp-block-image\"><figure class=\"aligncenter size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1684\" height=\"494\" src=\"https:\/\/opstree.com\/blog\/\/wp-content\/uploads\/2019\/10\/screenshot-2019-10-18-at-2.35.57-pm.png?w=1024\" alt=\"\" class=\"wp-image-1690\" \/><\/figure><\/div>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\"><p>Note: The logs of prometheus-msteams created in \/var\/log\/syslog file. In this file you will find every notification send by prometheus-msteams. Apart from this, if something went wrong, and you are not getting notification, you can debug in syslog file<\/p><\/blockquote>\n\n\n\n<h4 class=\"wp-block-heading\">As Docker Container<\/h4>\n\n\n\n<p>you can also run prometheus-msteams as container in your system. All configuration files of prometheus-msteams going to be the same, you just need to run the following command.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>docker run -d -p 2000:2000 \\\n    --name=\"promteams\"  \\\n    -v \/opt\/prometheus-msteams\/config.yml:\/tmp\/config.yml \\\n    -e CONFIG_FILE=\"\/tmp\/config.yml\" \\\n    -v \/opt\/prometheus-msteams\/card.tmpl:\/tmp\/card.tmpl \\\n    -e TEMPLATE_FILE=\"\/tmp\/card.tmpl\" \\\n    docker.io\/bzon\/prometheus-msteams:v1.1.4<\/code><\/pre>\n\n\n\n<p>Now that you are all set to get alerts in MS-teams channel, you can see that it isn&#8217;t as difficult as you originally thought. Ofcourse, this is not the only way to get alerts on MS-teams. You can always use different tool like prome2teams, etc. With this, I think we are ready to move ahead and explore other monitoring tools as well.<\/p>\n\n\n\n<p>I hope this blog post explains everything clearly. I would really appreciate to get feedback in comments.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>As we know monitoring our infrastructure is one of the critical components of infrastructure management, which ensures the proper functioning of our applications and infrastructure. But it is of no use if we are not getting notifications for alarms and threats in our system. As a better practice, if we enable all of the notifications &hellip; <a href=\"https:\/\/opstree.com\/blog\/2019\/12\/03\/prometheus-alertmanager-integration-with-ms-teams\/\" class=\"more-link\">Continue reading<span class=\"screen-reader-text\"> &#8220;Prometheus-Alertmanager integration with\u00a0MS-teams&#8221;<\/span><\/a><\/p>\n","protected":false},"author":173860259,"featured_media":29900,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_coblocks_attr":"","_coblocks_dimensions":"","_coblocks_responsive_height":"","_coblocks_accordion_ie_support":"","jetpack_post_was_ever_published":false,"_jetpack_newsletter_access":"","_jetpack_dont_email_post_to_subs":false,"_jetpack_newsletter_tier_id":0,"_jetpack_memberships_contains_paywalled_content":false,"_jetpack_memberships_contains_paid_content":false,"footnotes":"","jetpack_publicize_message":"","jetpack_publicize_feature_enabled":true,"jetpack_social_post_already_shared":false,"jetpack_social_options":{"image_generator_settings":{"template":"highway","enabled":false},"version":2}},"categories":[28070474,2788],"tags":[546372591,768739287,690861420],"jetpack_publicize_connections":[],"jetpack_featured_media_url":"https:\/\/opstree.com\/blog\/wp-content\/uploads\/2025\/11\/DevSecOps-1.jpg","jetpack_likes_enabled":true,"jetpack_sharing_enabled":true,"jetpack_shortlink":"https:\/\/wp.me\/pfDBOm-re","jetpack-related-posts":[],"_links":{"self":[{"href":"https:\/\/opstree.com\/blog\/wp-json\/wp\/v2\/posts\/1688"}],"collection":[{"href":"https:\/\/opstree.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/opstree.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/opstree.com\/blog\/wp-json\/wp\/v2\/users\/173860259"}],"replies":[{"embeddable":true,"href":"https:\/\/opstree.com\/blog\/wp-json\/wp\/v2\/comments?post=1688"}],"version-history":[{"count":12,"href":"https:\/\/opstree.com\/blog\/wp-json\/wp\/v2\/posts\/1688\/revisions"}],"predecessor-version":[{"id":3164,"href":"https:\/\/opstree.com\/blog\/wp-json\/wp\/v2\/posts\/1688\/revisions\/3164"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/opstree.com\/blog\/wp-json\/wp\/v2\/media\/29900"}],"wp:attachment":[{"href":"https:\/\/opstree.com\/blog\/wp-json\/wp\/v2\/media?parent=1688"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/opstree.com\/blog\/wp-json\/wp\/v2\/categories?post=1688"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/opstree.com\/blog\/wp-json\/wp\/v2\/tags?post=1688"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}