监控告警

更新时间: 2023-04-12 10:06:58

ADP底座致力于帮助客户更快速更精准地发现问题,因此结合云原生应用的特性,打通了监控、告警、通知的整条链路,让客户只需要做简单的配置,就可以快速接入ADP底座的可观测能力。

功能概述

ADP底座在可观测方面提供了以下能力:

  • 提供自定义消息通道,可以设置开关、定义通知模板、是否接收已处理告警、连通性测试,内置钉钉、邮件、微信、短信等通道。

  • 提供自定义订阅组,可以选择成员、根据告警等级选择多个消息通道并设置通知有效时间。

  • 提供自定义监控指标,可以根据不同的配置模式,可视化定义监控指标,可以自动发现并转换原始prometheusRule的监控指标。

  • 提供自定义告警策略,可以根据不同的配置模式,可视化定义告警策略,可以自动发现并转换原始prometheusRule的告警规则,并能批量设置多个订阅组。

  • 提供告警消息精细化管理,关联了监控指标、告警策略、帮助信息、通知事件等信息,能够批量设置静默,还能进行诊断定位问题。

接入流程

ADP-Local在云原生应用的可观测方面,从指标采集、指标统计、指标监控与告警,通道配置及告警订阅做了良好的封装,并且记录了告警历史和通知事件,便于问题定位与溯源。

image

接下来,我们将详细介绍下涉及的各个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 }}

渲染以后的效果如下:3343434

订阅组

概念定义:订阅组通过选择通知成员,设置不同告警等级的消息通道的有效通知时间等,用于接收不同类型的告警消息。

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端口,参考

    ServiceMonitor Spec

    定义编写示例:

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

阿里云首页 云原生应用交付平台 相关技术圈