返回

告别告警盲区:用Go语言+飞书打造告警通知系统

后端

Alertmanager告警通知:通过飞书实时掌控系统健康状况

引言

在当今数字化时代,企业依赖复杂的IT系统来运营其业务。然而,这些系统经常会遇到故障或性能瓶颈,如果不及时解决,可能会导致严重的业务损失。为了避免这种情况,告警通知系统是至关重要的。

Alertmanager与Prometheus:告警监控的基石

Alertmanager和Prometheus是业界领先的告警监控解决方案。Prometheus负责收集和存储系统指标数据,而Alertmanager则对这些数据进行分析,并根据预定义的规则生成告警信息。然而,Alertmanager默认只能通过电子邮件或PagerDuty等方式发送告警信息,这对于需要在手机上接收告警的人员来说不够方便。

飞书集成:实时接收告警,及时响应

为了解决这个问题,我们可以使用Go语言编写一个web服务,用于接受Alertmanager的webhook请求,并调用飞书的web服务发送告警信息。通过这种方式,我们可以直接在飞书APP上接收告警信息,并立即采取行动。

实现步骤

1. 创建Go语言Web服务

package main

import (
    "encoding/json"
    "fmt"
    "io/ioutil"
    "log"
    "net/http"
    "os"

    "github.com/feishu/go-sdk/v4/bot"
)

const (
    feishuWebhookURL = "https://open.feishu.cn/open-apis/bot/v2/hook/xxxxxxx"
    feishuSecretKey = "xxxxxxxx"
)

func main() {
    http.HandleFunc("/webhook", webhookHandler)

    port := os.Getenv("PORT")
    if port == "" {
        port = "8080"
    }

    log.Printf("Listening on port %s", port)
    if err := http.ListenAndServe(":"+port, nil); err != nil {
        log.Fatal(err)
    }
}

func webhookHandler(w http.ResponseWriter, r *http.Request) {
    defer r.Body.Close()

    body, err := ioutil.ReadAll(r.Body)
    if err != nil {
        log.Printf("Error reading request body: %v", err)
        http.Error(w, "Bad Request", http.StatusBadRequest)
        return
    }

    var alertmanagerAlert AlertmanagerAlert
    if err := json.Unmarshal(body, &alertmanagerAlert); err != nil {
        log.Printf("Error parsing request body: %v", err)
        http.Error(w, "Bad Request", http.StatusBadRequest)
        return
    }

    feishuMessage := bot.Message{
        MsgType: "text",
        Content: bot.Text{
            Text: fmt.Sprintf("告警级别:%s\n告警名称:%s\n告警%s", alertmanagerAlert.CommonAnnotations["level"], alertmanagerAlert.CommonLabels["alertname"], alertmanagerAlert.CommonAnnotations["description"]),
        },
    }

    client, err := bot.NewClient(feishuWebhookURL, feishuSecretKey)
    if err != nil {
        log.Printf("Error creating Feishu client: %v", err)
        http.Error(w, "Internal Server Error", http.StatusInternalServerError)
        return
    }

    if _, err := client.Send(feishuMessage); err != nil {
        log.Printf("Error sending Feishu message: %v", err)
        http.Error(w, "Internal Server Error", http.StatusInternalServerError)
        return
    }

    w.WriteHeader(http.StatusOK)
}

type AlertmanagerAlert struct {
    CommonAnnotations map[string]string `json:"commonAnnotations"`
    CommonLabels     map[string]string `json:"commonLabels"`
}

2. 配置Alertmanager

route:
  receiver: 'webhook-feishu'
receivers:
- name: 'webhook-feishu'
  webhook_configs:
  - send_resolved: true
    url: 'http://localhost:8080/webhook'

3. 运行Web服务

go run main.go

4. 测试告警通知功能

触发一个告警,例如:

- alert: MyAlert
  expr: node_memory_MemFree < 100e6
  for: 10m
  labels:
    severity: critical
  annotations:
    summary: "Node {{ $labels.instance }} is running out of memory"
    description: "The free memory on node {{ $labels.instance }} is below 100MB."

然后,我们应该可以在飞书APP上收到告警信息。

结论

通过使用Go语言编写web服务,我们可以轻松地将Alertmanager的告警信息发送到飞书APP上。这使得我们可以更方便地接收和处理告警信息,从而确保系统稳定运行,最大程度地减少业务损失。

常见问题解答

1. 如何自定义飞书消息?

可以通过修改feishuMessage对象中的Text字段来自定义飞书消息。例如,我们可以添加Markdown格式或嵌入图片。

2. 如何配置多个接收者?

Alertmanager允许配置多个接收者。我们可以创建多个webhook_configs对象,每个对象对应一个接收者。

3. 如何处理已解决的告警?

可以通过设置send_resolved: true来配置webhook_config,以在告警已解决时发送通知。

4. 如何保护飞书webhook的安全性?

feishuWebhookURL和feishuSecretKey是敏感信息。我们应该将其存储在安全的地方,例如Vault或Kubernetes Secret。

5. 是否可以将此解决方案扩展到其他告警系统?

是的。虽然本解决方案是为Alertmanager设计的,但相同的方法可以应用于其他支持webhook集成的告警系统。