监控告警
ADP底座致力于帮助客户更快速更精准地发现问题,因此结合云原生应用的特性,打通了监控、告警、通知的整条链路,让客户只需要做简单的配置,就可以快速接入ADP底座的可观测能力。
功能概述
ADP底座在可观测方面提供了以下能力:
提供自定义消息通道,可以设置开关、定义通知模板、是否接收已处理告警、连通性测试,内置钉钉、邮件、微信、短信等通道。
提供自定义订阅组,可以选择成员、根据告警等级选择多个消息通道并设置通知有效时间。
提供自定义监控指标,可以根据不同的配置模式,可视化定义监控指标,可以自动发现并转换原始prometheusRule的监控指标。
提供自定义告警策略,可以根据不同的配置模式,可视化定义告警策略,可以自动发现并转换原始prometheusRule的告警规则,并能批量设置多个订阅组。
提供告警消息精细化管理,关联了监控指标、告警策略、帮助信息、通知事件等信息,能够批量设置静默,还能进行诊断定位问题。
接入流程
ADP-Local在云原生应用的可观测方面,从指标采集、指标统计、指标监控与告警,通道配置及告警订阅做了良好的封装,并且记录了告警历史和通知事件,便于问题定位与溯源。
接下来,我们将详细介绍下涉及的各个CR的定义格式。
消息通道
概念定义:用于定义不同的告警消息发送方式,目前包括邮箱、钉钉机器人、Webhook、钉钉工作通知、企业微信通知、阿里云SMS等,并且可以根据业务场景扩展其他消息通道方式。
通道类型
邮箱
邮箱消息通道定义:
apiVersion: adp.aliyun.com/v1
kind: NotificationChannel
metadata:
name: adp-email
spec:
type: Email
title: "邮件"
enable: true # 是否开启消息通知
sendResolved: true # 是否接收已处理告警消息
description: "通过配置邮箱服务器,将告警信息以邮件的形式发送到个人邮箱"
emailConfig:
host: smtp.163.com # 邮件服务器地址
port: 465 # 邮件服务器端口
username: username@example.com # 发送邮箱
password: # 密码不能明文配置,需要引用secret文件中的数据
secretRef:
key: adp-email-password
name: adp-channel
namespace: acs-system
requireTLS: false
template: # 邮件模板
contentType: text/html # 邮件类型
title: "" # 邮件标题,go template模板可渲染
content: "" # 邮件内容,go template模板可渲染
钉钉机器人
钉钉机器人消息通道定义,可以配置多个机器人
apiVersion: adp.aliyun.com/v1
kind: NotificationChannel
metadata:
name: adp-dingtalkrobot
spec:
title: 钉钉机器人
type: DingTalkRobot
enable: true # 是否开启消息通知
sendResolved: true # 是否接收已处理告警消息
description: 通过配置钉钉群助手(自定义机器人),将告警信息推送到钉钉群内
dingTalkRobotConfig:
robots: # 钉钉机器人,可以配置多个
- name: test # 机器人名称
secret: # 机器人加签密钥
secretRef: {}
webhook: https://oapi.dingtalk.com/robot/send?xxx # 机器人webhook链接
template: # 选择其中一个模板类型
# markdown
msgType: markdown
title: "" # 通知标题,go template模板可渲染
content: "" # 通知内容,go template模板可渲染
# actionCard
msgType: actionCard
title: # 通知标题,go template模板可渲染
content: "" # 通知内容,go template模板可渲染
btnText: "" # 按钮标题
btnURL: "" # 按钮地址,go template模板可渲染
# text
msgType: text
title: # 通知标题,go template模板可渲染
content: "" # 通知内容,go template模板可渲染
钉钉工作通知
钉钉工作通知消息定义,通知模板类似于钉钉机器人
apiVersion: adp.aliyun.com/v1
kind: NotificationChannel
metadata:
name: adp-dingtalknotice
spec:
type: DingTalkNotice
title: "钉钉通知"
enable: false
sendResolved: true
description: "通过配置钉钉功能号,将告警信息以消息通知的形式发送到企业内的钉钉号"
dingTalkNoticeConfig:
apiURL: "https://u-api.alibaba-inc.com" #钉钉服务器地址
appKey: "snow-abc"
agentID: "192657317"
appSecret:
secretRef:
key: adp-email-password
name: adp-channel
namespace: acs-system
template: # 类似钉钉机器人的模板配置
msgType: markdown
title: "" # 通知标题 ,go template模板可渲染
content: "" # 告警内容 ,go template模板可渲染
企业微信通知
企业微信通知消息通道定义:
apiVersion: adp.aliyun.com/v1
kind: NotificationChannel
metadata:
name: adp-wechatnotice
spec:
type: WeChatNotice
title: "企业微信通知"
enable: true # 是否开启消息通知
sendResolved: true # 是否接收已处理告警消息
description: "通过配置企业微信服务商助手,将告警信息以消息通知的形式发送到企业微信号"
weChatNoticeConfig:
apiURL: ""
corpID: ""
agentID: ""
corpSecret:
value: ""
template:
msgType: textcard # 模板类型,text/markdown/actionCard
title: "" # 通知标题 ,go template模板可渲染
content: "" # 告警内容 ,go template模板可渲染
Webhook
自定义Webhook消息通道定义,可以配置多个webhook:
apiVersion: adp.aliyun.com/v1
kind: NotificationChannel
metadata:
name: adp-webhook
spec:
type: Webhook
title: "Webhook"
enable: true # 是否开启消息通知
sendResolved: true # 是否接收已处理告警消息
description: "将告警信息推送到指定的Webhook地址"
webhookConfig:
webhooks:
- name: "" # webhook名字
url: "" # webhook url 地址
requireTLS: false # 是否TLS认证
template: "" # 消息通知模板内容,go template模板可渲染
阿里云SMS
阿里云SMS消息通道定义:
apiVersion: adp.aliyun.com/v1
kind: NotificationChannel
metadata:
name: adp-aliyunsms
spec:
type: AliyunSMS
title: "阿里云SMS"
enable: true # 是否开启消息通知
sendResolved: true # 是否接收已处理告警消息
description: "通过配置阿里云SMS服务,将告警信息以短信的形式发送到个人手机"
aliyunSMSConfig:
signName: "" # 短信签名
templateCode: "" # 短信模板代号
accessKeyID:
secretRef: {}
accessKeySecret:
secretRef: {}
template: "" # 短信内容 ,go template模板可渲染
通知模板
ADP底座接收到告警消息后,如果确定要发送消息通知,告警消息会渲染钉钉、邮件等消息通道中的go template模板数据(通知标题或者通知内容),然后再通过钉钉、邮件等发送给用户。
告警消息的数据结构如下:
type AlertData struct {
Alert
AlertName string `json:"alertName"`
Title string `json:"title,omitempty"`
Runbook string `json:"runbook,omitempty"`
Description string `json:"description,omitempty"`
SubscribeGroups []string `json:"subscribeGroups,omitempty"`
Users []v1.User `json:"users,omitempty"`
ChannelRef string `json:"channelRef"`
SimilarAlerts []Alert `json:"similarAlerts,omitempty"`
Params map[string]string `json:"params,omitempty"`
}
type Alert struct {
Fingerprint string `json:"fingerprint"`
Severity v1.AlertSeverity `json:"severity"`
Summary string `json:"summary,omitempty"`
StartsAt time.Time `json:"startsAt"`
EndsAt time.Time `json:"endsAt"`
UpdatedAt time.Time `json:"updatedAt"`
Status AlertStatus `json:"status"`
Labels map[string]string `json:"labels,omitempty"`
Annotations map[string]string `json:"annotations,omitempty"`
}
引用格式: 取AlertData结构体的字段,例如告警标题 {{ .Title }}
ADP底座的通知模板都是go template模板,可以渲染通知标题或者通知内容,在通知模板中可以通过AlertData引用告警消息数据,例如钉钉消息通知模板:
template:
msgType: markdown
title: 告警通知
content: |
**【{{ if eq .Severity "critical" }}紧急告警{{ else if eq .Severity "warning" }}严重告警{{ else }}一般告警{{ end }} - {{ .Title }}】{{ if eq .Status "active" }}正在告警中{{ else }}告警已处理{{ end }}**
**告警名称** : {{ .AlertName }}
**告警状态** : {{ .Status }}
**最近触发** : {{ .UpdatedAt.Format "2006-01-02 15:04:05" }}
**开始触发** : {{ .StartsAt.Format "2006-01-02 15:04:05" }}
**相似告警** : {{ len .SimilarAlerts }}
**告警摘要** : {{ .Summary }}
**处理人员** :
{{ range $val := .Users }}{{ if $val.Mobile }}@{{ $val.Mobile }}{{ else if $val.DingDing }}@{{ $val.DingDing }}{{ else }}{{ $val.Account }}{{ end}} {{ end}}
**告警标签** :
{{ range $key,$val := .Labels }}
- {{ $key }}: {{ $val }}
{{ end}}
**告警描述** :
{{ .Description }}
{{ if .Params.dashboardurl }}
[查看详情]({{ .Params.dashboardurl }}/adp/notifyMessages/{{ .Fingerprint }})
{{ else }}
**查看详情** :
{Local控制台}/adp/notifyMessages/{{ .Fingerprint }}
{{ end }}
渲染以后的效果如下:
订阅组
概念定义:订阅组通过选择通知成员,设置不同告警等级的消息通道的有效通知时间等,用于接收不同类型的告警消息。
apiVersion: adp.aliyun.com/v1
kind: SubscribeGroup
metadata:
name: admin
spec:
title: 默认订阅组 # 订阅组标题
users: #
- account: admin # 用户账号
email: adp@163.com # 用户邮箱
mobile: xxx # 手机
dingDing: 80213 # 钉钉号
weChat: 433 # 微信号
notifications: # 按告警等级分多个通知组
- severity: critical # 告警等级
channels:
- channelRef: adp-email # 消息通道引用名称
effectiveStart: "09:00:00" # 有效通知时间段开始时间
effectiveEnd: "23:59:59" # 有效通知时间段结束时间
- channelRef: adp-dingtalkrobot/test
effectiveStart: "00:00:00"
effectiveEnd: "23:59:59"
监控大盘
ADP底座的监控大盘采用Grafana进行配置,然后导出到ConfigMap部署到Kubernetes中,ADP底座会根据以下规则,自动识别并发现Grafana监控大盘并展示到ADP-Local中。监控大盘的识别规则如下:
识别ConfigMap为Grafana监控大盘,需要配置label:
grafana_dashboard: '1'
识别Grafana监控大盘为某一个组件的监控大盘,有两种方法:
组件的监控大盘ConfigMap和组件在同一个Helm包中,无需做任何配置;
组件的监控大盘ConfigMap和组件不在同一个Helm包中,例如MySQL实例的监控大盘是放在mysql-operator组件中的,需要配置如下标签:
adp.aliyuncs.com/scope-component-type: mysql.mysql # 组件类型
adp.aliyuncs.com/scope-level: component # 表明是哪些级别的监控大盘,目前包括cluster/node/product/component
adp.aliyuncs.com/scope-provider: harmonycloud.cn # 该监控大盘的提供商
下面以MySQL监控大盘来举个例子:
apiVersion: v1
kind: ConfigMap
metadata:
labels:
grafana_dashboard: '1'
adp.aliyuncs.com/scope-component-type: mysql.mysql
adp.aliyuncs.com/scope-level: component
adp.aliyuncs.com/scope-provider: harmonycloud.cn
data:
MySQL.json: |-
{
"title": "MySQL Overview",
"uid": "uaKUl7_Mk",
"annotations": {
"list": [
{
"builtIn": 1,
"datasource": "-- Grafana --",
"enable": true,
"hide": true,
"iconColor": "rgba(0, 211, 255, 1)",
"name": "Annotations & Alerts",
"type": "dashboard"
}
]
},
"description": "Dashboard from Percona Monitoring and Management project. ",
"editable": true,
"style": "dark",
"tags": [
"Percona",
"MySQL"
],
"time": {
"from": "now-12h",
"to": "now"
}
"links": [],
"panels": [],
"templating": {},
监控指标
基础指标
基础指标概念定义:就是通过prometheus exporter,loki collector等采集的原始指标,不可分解。
我们可以利用Prometheus SDK编写业务指标,并暴露metrics端口,供Prometheus Server进行采集并存储到Prometheus TSDB中,然后用于监控分析。具体流程如下:
在业务应用中或者创建一个Exporter应用,然后利用Prometheus SDK编写Prometheus Metrics,各语言SDK如下:
配置K8s ServiceMonitor,用于发现需要采集的Metrics端口,参考
定义编写示例:
apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:
name: myapp-svc
spec:
endpoints:
- interval: 15s
port: http-metrics
scheme: http
selector:
matchLabels:
app: myapp
最终采集到的数据可以在Prometheus控制台查询到:
复合指标
复合指标概念定义:利用PromQL对基础指标进行计算和加工的新指标。
MetricDefinition
概念定义:通过各种极简配置模式,设置Prometheus监控指标和Loki监控指标。
apiVersion: adp.aliyun.com/v1
kind: MetricDefinition
metadata:
labels:
adp.aliyuncs.com/application-name: demo # 产品名称
adp.aliyuncs.com/component-name: mysql-mysql # 组件名称
adp.aliyuncs.com/scope-level: component # 告警级别
name: mysql-mysql
namespace: default
spec:
groups:
- name: mysql-cluster # 分组名称
configRef: # 监控指标存储的配置文件
type: Prometheus # 配置类型,Prometheus/Loki
name: mysql-mysql
namespace: default
items:
- name: mysql_slave_lag_seconds # 指标名称
title: mysql_slave_lag_seconds # 指标标题
description: "" # 指标描述
mode: Expr # 配置模式,PromExpr:PromQL指标表达式/LogExpr:LogQL日志表达式/MetricFormula:指标计算公式
expr: "" # PromQL表达式
labels: # 标签
product: harmonycloud
uid: xxx # 指标项唯一ID
creationTimestamp: "2022-05-18T11:22:26Z" # 指标项创建时间
指标项包括三种配置方式:
Expr:promQL表达式
name: cluster:cpu_usage:ratio
title: '集群CPU使用率'
type: Gauge
description: '集群CPU使用率=集群CPU使用量/集群CPU总量'
mode: Expr
expr: >
round(cluster:cpu_usage:rate5m / cluster:cpu_total:sum, 0.001)
LogExpr:LogQL表达式
mode: LogExpr
expr: >
rate({app="cn-app-operator"}[1m])
MetricFormula: 指标公式
name: product:storage_total:sum
title: '产品存储总量'
type: Gauge
unit: 'Byte'
description: '产品中所有的Pod持久卷(PersistentVolume)的容量总和'
mode: MetricFormula
metric: component:storage_available:sum # 用于计算的指标
function: sum # 用于计算的函数
dimensions: # 用于计算分组的维度
- product
digits: 3 # 保留的小数位数,如果不处理,默认-1
按此方式配置的记录规则表达式如下:
round(sum by (product) (component:storage_available:sum), 0.001)
Prometheus Recording Rule
你也可以在PrometheusRule定义记录规则,ADP-Local可以自动发现并生成MetricDefinition。
apiVersion: monitoring.coreos.com/v1
kind: PrometheusRule
metadata:
name: mysql-mysql
namespace: default
spec:
groups:
- name: mysql-cluster
rules:
- expr: mysql_slave_status_seconds_behind_master{service='mysql-mysql'} - mysql_slave_status_sql_delay{service='mysql-mysql'}
labels:
severity: warning
record: mysql_slave_lag_seconds
Loki Recording Rule
Loki的监控规则配置是存储在configmap/acs-system/loki-stack-alerting-rules.yaml 文件中:
apiVersion: v1
kind: ConfigMap
metadata:
name: loki-stack-alerting-rules
namespace: acs-system
data:
loki-stack-alerting-rules.yaml: |-
groups:
- name: loki-server
rules:
- record: throughputLogStreams
expr: sum by(container) (rate({job=~".*/loki"}[1m]))
告警策略
AlertStrategy
概念定义:通过各种极简配置模式,设置Prometheus告警规则,并且可以设置订阅组等。
apiVersion: adp.aliyun.com/v1
kind: AlertStrategy
metadata:
labels:
adp.aliyuncs.com/application-name: demo # 产品名称
adp.aliyuncs.com/component-name: mysql-mysql # 组件名称
adp.aliyuncs.com/scope-level: component # 告警级别
name: mysql-mysql
namespace: default
spec:
groups:
- name: mysql-cluster
configRef: # 告警规则存储的配置文件
name: mysql-mysql
namespace: default
items:
- name: MySQLReplicationNotRunning # 告警名称
title: MySQLReplicationNotRunning # 告警标题
description: "" # 告警描述,go template模板,可以传入告警消息渲染
mode: Expr # 配置模式,Expr:告警表达式/MetricFormula:告警指标公式/ValueFormula:告警值公式
rules: # 告警规则,按告警等级设置多条告警
- expr: "" # PromQL表达式
interval: 2m # 阈值不达标持续多久才告警
severity: critical # 告警等级
summary: Slave replication is not running # 概要信息
labels: # 标签
product: harmonycloud
annotations: # 注释
product: harmonycloud
subscribeGroups: # 订阅组,可以设置多个
- admin
uid: f91fc2bee27674478635330bb34175ef # 告警项唯一ID
creationTimestamp: "2022-05-18T11:22:26Z" # 告警项创建时间
告警项包括三种配置方式:
Expr:告警表达式
name: node:storage_usage_ratio:high
title: '节点存储使用率过高'
description: '节点{{ $labels.node }}的存储使用率{{ $value }}将达到最大限制'
mode: Expr
rules:
- severity: warning
summary: '节点{{ $labels.node }}的存储使用率{{ $value }}过高'
interval: '2m'
expr: >
round(node:disk_size_usage:sum / node:disk_size_total:sum, 0.001) > 0.9
ValueFormula:告警值公式
name: node:storage_usage_ratio:high
title: '节点存储使用率过高'
description: '节点{{ $labels.node }}的存储使用率{{ $value }}将达到最大限制'
mode: ValueFormula
valueExpr: >
round(node:disk_size_usage:sum / node:disk_size_total:sum, 0.001)
rules:
- severity: warning
summary: '节点{{ $labels.node }}的存储使用率{{ $value }}过高'
interval: '2m'
algorithm: CurrentValue
operator: '>'
threshold: '0.9'
按此方式配置的告警表达式如下:
round(node:disk_size_usage:sum / node:disk_size_total:sum, 0.001) > 0.9
MetricFormula:指标公式
name: cluster:license_status:invalid
title: 'license状态无效'
description: '产品{{ $labels.product }}的license授权状态无效,会影响应用启动,请尽快注册'
mode: MetricFormula
metric: 'adp_licenses_counter'
filters:
- name: 'status'
operator: '='
value: 'Valid'
rules:
- severity: critical
summary: '产品{{ $labels.product }}持续2分钟license授权状态无效'
interval: 2m
algorithm: CurrentValue
operator: '>'
threshold: '0'
按此方式配置的告警表达式如下:
adp_licenses_counter{status="Valid"} > 0
Prometheus Alerting Rule
你可以定义PrometheusRule告警规则,ADP-Local可以自动发现并生成AlertStrategy:
apiVersion: monitoring.coreos.com/v1
kind: PrometheusRule
metadata:
name: mysql-mysql
namespace: default
spec:
groups:
- name: mysql-stats
rules:
- alert: MySQLThreadStackSizeTooSmall
annotations:
description: Thread stack size is too small. This can cause problems when
you use Stored Language constructs for example. A typical is 256k for thread_stack_size.
metric: mysql_global_variables_thread_stack
product: harmonycloud
runbook_url: ""
service: metrics
subscribegroups: admin
summary: Instance {{$labels.instance}} Thread stack size is too small
title: MySQLThreadStackSizeTooSmall
expr: mysql_global_variables_thread_stack{service='mysql-mysql'} <196608
for: 1m
labels:
severity: warning