파트 IV: 텔레그램 알림
Alertmanager는 트릭을 수행하며 기본적으로 모든 주요 채널(Slack, PagerDuty, OpsGenie 등)을 지원합니다. 그러나 소규모 회사의 비즈니스 커뮤니케이션에도 다소 인기있는 Telegram은 지원하지 않습니다.
몇 가지 AWS 리소스와 간단한 Go 람다 함수로 해결해 보겠습니다.
SNS
SNS는 Alermanager가 지원하는 채널 중 하나입니다. IAM 역할이 인스턴스에 연결되어 있기 때문에 이 경우 실제로 매우 편리합니다. 자격 증명으로 번거롭게 할 필요가 없습니다.
다시 Terraform에 대해 알아보겠습니다.
resource "aws_sns_topic" "prometheus_alerts" {
name = "prometheus_alerts"
}
SQS
다음 부분은 대기열입니다. 우리는 람다를 SNS에 직접 연결할 수 있지만 SQS가 더 안정적입니다. SQS는 사실상 유일한 SNS 구독자가 되며 메시지는 추가 처리를 위해 대기합니다.
resource "aws_sqs_queue" "prometheus_alerts" {
name = "prometheus_alerts"
}
SNS 주제가 이 대기열에 메시지를 푸시할 것이기 때문에 다음도 허용해야 합니다.
resource "aws_sqs_queue_policy" "prometheus_alerts" {
queue_url = aws_sqs_queue.prometheus_alerts.id
policy = <<POLICY
{
"Version": "2012-10-17",
"Id": "sqspolicy",
"Statement": [
{
"Sid": "First",
"Effect": "Allow",
"Principal": "*",
"Action": "sqs:SendMessage",
"Resource": "${aws_sqs_queue.prometheus_alerts.arn}",
"Condition": {
"ArnEquals": {
"aws:SourceArn": "${aws_sns_topic.prometheus_alerts.arn}"
}
}
}
]
}
POLICY
}
또한 구독을 생성합니다.
resource "aws_sns_topic_subscription" "prometheus_alerts" {
topic_arn = aws_sns_topic.prometheus_alerts.arn
protocol = "sqs"
endpoint = aws_sqs_queue.prometheus_alerts.arn
}
람다 함수
다시 시작하겠습니다. Lambda에는 역할, 권한이 필요합니다. 따라서 먼저 이러한 리소스를 생성해 보겠습니다.
data "aws_caller_identity" "current" {}
data "aws_region" "current" {}
resource "aws_iam_role" "alertmanager_notify" {
name = "alertmanager_notify"
assume_role_policy = jsonencode({
Version = "2012-10-17"
Statement = [
{
Effect = "Allow"
Principal = {
Service = "lambda.amazonaws.com"
}
Action = "sts:AssumeRole"
}
]
})
}
resource "aws_iam_policy" "alertmanager_notify" {
name = "alertmanager_notify"
policy = jsonencode({
Version = "2012-10-17"
Statement = [
{
Effect = "Allow"
Action = [
"logs:CreateLogGroup",
]
Resource = [
"arn:aws:logs:${data.aws_region.current.name}:${data.aws_caller_identity.current.account_id}:log-group:/aws/lambda/alertmanager_notify",
]
},
{
Effect = "Allow"
Action = [
"logs:CreateLogStream",
"logs:PutLogEvents",
]
Resource = [
"arn:aws:logs:${data.aws_region.current.name}:${data.aws_caller_identity.current.account_id}:log-group:/aws/lambda/alertmanager_notify:*",
]
},
{
"Effect": "Allow",
"Action": [
"sqs:DeleteMessage",
"sqs:GetQueueAttributes",
"sqs:ReceiveMessage",
],
"Resource": [
aws_sqs_queue.prometheus_alerts.arn,
]
},
]
})
}
resource "aws_iam_role_policy_attachment" "alertmanager_notify" {
role = aws_iam_role.alertmanager_notify.name
policy_arn = aws_iam_policy.alertmanager_notify.arn
}
이러한 권한이 있는 경우 Lambda 함수는 SQS 대기열의 메시지를 처리하고 처리 시 삭제할 수 있습니다. Cloudwatch 부분은 매우 자명합니다. 일부 로그를 보고 싶습니다. Lambda 함수 정의 자체는 간단합니다.
resource "aws_lambda_function" "alertmanager_notify" {
filename = "${path.module}/assets/function.zip"
source_code_hash = filebase64sha256("${path.module}/assets/function.zip")
function_name = "alertmanager_notify"
role = aws_iam_role.this.arn
handler = "main"
runtime = "go1.x"
lifecycle {
ignore_changes = [
filename,
last_modified,
source_code_hash,
]
}
environment {
variables = {
TELEGRAM_TOKEN = <telegram token from bot father>
TELEGRAM_CHANNEL = <telegram group id>
}
}
}
${path.module}/assets/function.zip
, 이것은 더미 코드가 포함된 zip 파일입니다. 초기 생성을 위해서만 이 아카이브가 필요합니다. 최종 코드는 외부에서 AWS로 푸시됩니다.람다 코드
Telegram과의 통합을 위해
github.com/go-telegram-bot-api/telegram-bot-api
라이브러리를 사용할 것입니다. Telegram API에 대한 얇은 래퍼이며 이 사용 사례에 충분합니다.Please note that signatures of
handle
andsendMessage
should ideally contain interface, some sort ofTelegramSender
or so. But for the sake of simplicity we useBotAPI
directly 😊
package main
import (
"context"
"fmt"
"github.com/aws/aws-lambda-go/events"
"github.com/aws/aws-lambda-go/lambda"
tgbotapi "github.com/go-telegram-bot-api/telegram-bot-api"
log "github.com/sirupsen/logrus"
"os"
"strconv"
)
var (
telegramToken = os.Getenv("TELEGRAM_TOKEN")
telegramChannel = os.Getenv("TELEGRAM_CHANNEL")
parseMode = "HTML"
)
func init() {
log.SetFormatter(&log.JSONFormatter{})
}
func sendMessage(bot *tgbotapi.BotAPI, channel int64, message string, mode string) error {
log.Info("sending notification to Telegram")
msg := tgbotapi.NewMessage(channel, message)
msg.ParseMode = mode
_, err := bot.Send(msg)
if err != nil {
return fmt.Errorf("could not send message: %s", err)
}
return nil
}
func handle(bot *tgbotapi.BotAPI, channel int64) func(context.Context, events.SQSEvent) error {
return func(ctx context.Context, event events.SQSEvent) error {
for _, record := range event.Records {
log.
WithField("message_id", record.MessageId).
Info("processing SQS record")
err := sendMessage(bot, channel, record.Body, parseMode)
if err != nil {
log.Fatalf("could process message: %s", err)
}
}
return nil
}
}
func main() {
// create telegram client
bot, err := tgbotapi.NewBotAPI(telegramToken)
if err != nil {
log.Fatalf("could not create telegram client")
}
// parse
telegramChannelInt, err := strconv.ParseInt(telegramChannel, 10, 64)
if err != nil {
log.Fatalf("could not parse channel id")
}
lambda.Start(handle(bot, telegramChannelInt))
}
함수를 배포하자!
GOARCH=amd64 GOOS=linux go build main.go
zip function.zip main
aws lambda update-function-code --function-name alertmanager_notify --zip-file fileb://./function.zip
경보 관리자 구성
먼저 Alertmanager가 실행 중인 인스턴스에 대해 SNS 주제와의 상호 작용을 허용해야 합니다. 첫 번째 장의 IAM 정책에 다음 명령문을 추가합니다.
{
Effect = "Allow"
Action = [
"sns:Publish",
]
Resource = [
aws_sns_topic.prometheus_alerts.arn,
]
},
마지막 비트는 Alertmanager용 yaml입니다. 이것은 아마도 가장 간단한 구성일 것입니다.
global:
resolve_timeout: 1m
receivers:
- name: sns
sns_configs:
- message: |
{{ if eq .Status "firing" }}🔥 {{ end }}{{ if eq .Status "resolved" }}✅ {{ end }}[{{ .Status | toUpper }}] {{ .CommonLabels.alertname }}
{{ range .Alerts }}
<b>Alert:</b> {{ .Annotations.title }}{{ if .Labels.severity }} - `{{ .Labels.severity }}`{{ end }}
<b>Description:</b> {{ .Annotations.description }}
<b>Details:</b>
{{ range .Labels.SortedPairs }}- {{ .Name }}: <i>{{ .Value }}</i>
{{ end }}
{{ end }}
sigv4:
region: eu-west-1
topic_arn: <SNS topic ARN>
route:
group_by:
- "..."
group_interval: 30s
group_wait: 5s
receiver: sns
repeat_interval: 3h
결과
이제 Telegram 그룹에서 경고를 수신할 수 있습니다. 유사한 구성에서 가져온 다음 예를 참조하세요. 꽤 깔끔하죠?
포장하다
그리고 이것이 이 시리즈의 끝입니다. 저는 지난 두 달 동안 이 설정을 작업해 왔으며 전체적인 결과에 매우 만족합니다.
여기에 또한 마지막 면책 조항이 있습니다. Prometheus에 대한 외부 모니터링을 설정하는 것을 잊지 마십시오. Prometheus가 언제 다운되는지 알고 싶기 때문에 준비 서버의 프로브를 인터넷에 노출하고 가동 시간 로봇과 같은 도구를 사용합니다.
Do you have any questions? Ping me on twitter or ask it directly here. I'll try to do my best to help you.
Reference
이 문제에 관하여(파트 IV: 텔레그램 알림), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://dev.to/stepanvrany/part-iv-telegram-notifications-e1o텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)