0%

用户表

user_id user_name
1 zhangsan
2 lisi
3 wangwu
4 zhaoliu

另一张money表,表示了借钱的关系

id from to how
1 1 2 100
2 3 4 100

关联查询

select m.id,u1.user_name,u2.user_name,m.how
from money as m
left outer join user u1 on u2.user_id=m.from
left outer join user u3 on u3.user_id=m.to

显示的结果

id user_name user_name how
1 zhangsan lisi 100
2 wangwu zhaoliu 100

问题

这里有个小问题,中间两列显示的名称一样,都是user_name,这样就不好辨别了,在Mybatis中如果想用

@ResultType(实体类名称.class)

来定义返回的类型,因为两个字段名一样,定义的实体类肯定不能一样,就会导致返回没有结果,怎么处理呢?

关联查询时,指定结果字段别名

select m.id,u1.user_name as user_name1,u2.user_name as user_name2,m.how
from money as m
left outer join user u1 on u2.user_id=m.from
left outer join user u3 on u3.user_id=m.to

钉钉群机器人定义

群机器人是钉钉群的高级扩展功能。群机器人可以将第三方服务的信息聚合到群聊中,实现自动化的信息同步。目前,大部分机器人在添加后,还需要进行Webhook配置,才可正常使用(配置说明详见操作流程中的帮助链接)。

例如:

  • 通过聚合GitHub,GitLab等源码管理服务,实现源码更新同步。
  • 通过聚合Trello,JIRA等项目协调服务,实现项目信息同步。
  • 另外,群机器人支持Webhook协议的自定义接入,支持更多可能性,例如:你可将运维报警通过自定义机器人聚合到钉钉群实现提醒功能。

机器人发送消息频率限制

消息发送太频繁会严重影响群成员的使用体验,大量发消息的场景(譬如系统监控报警)可以将这些信息进行整合,通过markdown消息以摘要的形式发送到群里。

每个机器人每分钟最多发送20条。如果超过20条,会限流10分钟

添加群机器人

参考官网:https://ding-doc.dingtalk.com/doc#/serverapi3/iydd5h

下载SDK简化开发

下载链接:https://ding-doc.dingtalk.com/doc#/faquestions/vzbp02

将SDK安装到本地maven仓库

mvn install:install-file -Dfile=D:/taobao-sdk-java-auto-20191203.jar -DgroupId=com.taobao -DartifactId=taobao-sdk-java-auto-20191203 -Dversion=1.0.0 -Dpackaging=jar

项目中引用

<dependency>
    <groupId>com.taobao</groupId>
    <artifactId>taobao-sdk-java-auto-20191203</artifactId>
    <version>1.0.0</version>
</dependency>

开发样例

DingTalkClient client = new DefaultDingTalkClient("https://oapi.dingtalk.com/robot/send?access_token=566cc69da782ec33e42541b09b08551f09fbe864eb8008112e994b43887");
OapiRobotSendRequest request = new OapiRobotSendRequest();
//文本类型
request.setMsgtype("text");
OapiRobotSendRequest.Text text = new OapiRobotSendRequest.Text();
text.setContent("测试文本消息");
request.setText(text);
OapiRobotSendRequest.At at = new OapiRobotSendRequest.At();
at.setAtMobiles(Arrays.asList("132xxxxxxxx"));
request.setAt(at);
 
//link类型
request.setMsgtype("link");
OapiRobotSendRequest.Link link = new OapiRobotSendRequest.Link();
link.setMessageUrl("https://www.dingtalk.com/");
link.setPicUrl("");
link.setTitle("时代的火车向前开");
link.setText("这个即将发布的新版本,创始人xx称它为“红树林”。\n" +
        "而在此之前,每当面临重大升级,产品经理们都会取一个应景的代号,这一次,为什么是“红树林");
request.setLink(link);
 
//markdown类型
request.setMsgtype("markdown");
OapiRobotSendRequest.Markdown markdown = new OapiRobotSendRequest.Markdown();
markdown.setTitle("杭州天气");
markdown.setText("#### 杭州天气 @156xxxx8827\n" +
        "> 9度,西北风1级,空气良89,相对温度73%\n\n" +
        "> ![screenshot](https://gw.alicdn.com/tfs/TB1ut3xxbsrBKNjSZFpXXcXhFXa-846-786.png)\n"  +
        "> ###### 10点20分发布 [天气](http://www.thinkpage.cn/) \n");
request.setMarkdown(markdown);
OapiRobotSendResponse response = client.execute(request);

常用的三种类型如上所示,具体参考官网类型

应答机制

自定义机器人尚不支持应答机制 (该机制指的是群里成员在聊天@机器人的时候,钉钉回调指定的服务地址,即Outgoing机器人)。

错误码

开发者每次调用接口时,可能获得正确或错误的返回码,企业可以根据返回码信息调试接口,排查错误。

注意:开发者的程序应该根据errcode来判断出错的情况,而不应该依赖errmsg来匹配,因为errmsg可能会调整。

参考官网:错误码

上文介绍了Alertmanager集成钉钉,我们还可以自己写一个webhook,用于接收Alertmanager的通知服务。

获取Alertmanager的请求内容

参考前文,我们知道Alertmanager会向配置的webhook地址发送一个POST请求,这里我们先编写一个简单的controller,用于接收Alertmanager的请求,如下:

    @RequestMapping("/test")
    public void watcher(HttpServletRequest request) throws IOException {
        System.out.println(request.getMethod());
        BufferedReader reader = new BufferedReader(new InputStreamReader(request.getInputStream()));
        String str = "";
        String wholeStr = "";
        while ((str = reader.readLine()) != null) {
            wholeStr += str;
        }
        System.out.println("body:" + wholeStr);
    }

写好上面的服务之后,修改Alertmanager中webhook地址,然后将上面打印的body分析分析。如下:

{
  "receiver":"webhook_alert",
  "status":"resolved",
  "alerts":[
    {
      "status":"resolved",
      "labels":{
        "alertname":"curl test",
        "severity":"warning"
      },
      "annotations":{
        "description":"this is a test alert from curl",
        "summary":"test alert from curl"
      },
      "startsAt":"2019-12-03T03:22:50.430372292Z",
      "endsAt":"2019-12-03T03:26:50.430372292Z",
      "generatorURL":"",
      "fingerprint":"960077177807fca5"
    }
  ],
  "groupLabels":{
    "alertname":"curl test"
  },
  "commonLabels":{
    "alertname":"curl test",
    "severity":"warning"
  },
  "commonAnnotations":{
    "description":"this is a test alert from curl",
    "summary":"test alert from curl"
  },
  "externalURL":"http://alertmanager-prometheus-operator-alertmanager-test-0:9093",
  "version":"4",
  "groupKey":"{}/{severity="warning"}:{alertname="curl test"}"
}

所有接收到的请求内容格式基本不变,标准的JSON格式,我们编写一个实体类用于接收。

编写实体类

编写内层实体类Alert.java

/**
 * @ClassName: Alert
 * @Description: TODO
 * @Author: wuzhiyong
 * @Time: 2019/12/3 11:39
 * @Version: v1.0
 **/
@Data
public class Alert {
    /**
     * 状态:firing / resolved
     */
    private String status;
    /**
     * 标签
     */
    private Map<String, String> labels;
    /**
     * 携带的其它信息
     */
    private Map<String, String> annotations;
    /**
     * 开始时间
     */
    private String startsAt;
    private String endsAt;
    /**
     * 产生的alertmanager信息
     */
    private String generatorURL;
    private String fingerprint;
 
    public Alert() {
    }
}

编写外层实体类Alerts.java

/**
 * @ClassName: Alerts
 * @Description: Alertmanager发出的告警格式
 * @Author: wuzhiyong
 * @Time: 2019/12/3 11:49
 * @Version: v1.0
 **/
@Data
public class Alerts {
    private String externalURL;
    private String version;
    private String groupKey;
    private String receiver;
    private String status;
    private List<Alert> alerts;
    private Map<String, String> groupLabels;
    private Map<String, String> commonLabels;
    private Map<String, String> commonAnnotations;
    public Alerts() {
    }
}

编写webhook

    @RequestMapping(value = "/receive", method = RequestMethod.POST)
    void receive(@RequestBody Alerts alerts) {
        log.info("new alert: {}",alerts.getCommonLabels().get("alertname"));
    }

上面接收到Alert manager的请求,只是打印了alert name的日志,我们可以根据接收到告警,做更多的事。

可以根据自身业务自行发挥。

全局配置

参考官网:https://prometheus.io/docs/prometheus/latest/configuration/configuration/#kubernetes_sd_config

global:
  # How frequently to scrape targets by default.
  [ scrape_interval:  | default = 1m ]
 
  # How long until a scrape request times out.
  [ scrape_timeout:  | default = 10s ]
 
  # How frequently to evaluate rules.
  [ evaluation_interval:  | default = 1m ]
 
  # The labels to add to any time series or alerts when communicating with
  # external systems (federation, remote storage, Alertmanager).
  external_labels:
    [ :  ... ]
 
# Rule files specifies a list of globs. Rules and alerts are read from
# all matching files.
rule_files:
  [ -  ... ]
 
# A list of scrape configurations.
scrape_configs:
  [ -  ... ]
 
# Alerting specifies settings related to the Alertmanager.
alerting:
  alert_relabel_configs:
    [ -  ... ]
  alertmanagers:
    [ -  ... ]
 
# Settings related to the remote write feature.
remote_write:
  [ -  ... ]
 
# Settings related to the remote read feature.
remote_read:
  [ -  ... ]

更改指标标签

更改标签的时机:抓取前修改、抓取后修改、告警时修改

  • 采集数据之前,通过relabel_config
  • 采集数据之后,写入存储之前,通过metric_relabel_configs
  • 在告警前修改标签,通过alert_relabel_configs

JOB配置

- job_name: prometheus
  honor_labels: false
  kubernetes_sd_configs:
  - role: endpoints
    namespaces:
      names:
      - monitoring
  scrape_interval: 30s
  relabel_configs:
  - action: keep
    source_labels:
    - __meta_kubernetes_service_label_prometheus
    regex: k8s
  - source_labels:
    - __meta_kubernetes_endpoint_address_target_kind
    - __meta_kubernetes_endpoint_address_target_name
    separator: ;
    regex: Pod;(.*)
    replacement: ${1}
    target_label: pod
  - source_labels:
    - __meta_kubernetes_namespace
    target_label: namespace
  • kubernetes_sd_configs:使用这个配置可以自动发现 k8s 中 node、service、pod、endpoint、ingress,并为其添加监控,更多的内容可以直接查看官方文档。__meta_kubernetes_xxxxx具体什么意思都可以在官网找到。
  • endpoints:采用endpoints方式采集,每创建一个 service 就会创建一个对应的 endpoint,通过endpoint方式可以将service下所有的pod都采集到。
  • 下面配置的意思是只有 service 的标签包含 prometheus=k8s,k8s 才会对其对应的 endpoint 进行采集。所以我们后面要为 Prometheus 创建一个 service,并且要为这个 service 加上 prometheus: k8s 这样的标签。
  - action: keep
    source_labels:
    - __meta_kubernetes_service_label_prometheus
    regex: k8s
  • 下面配置意识是如果 __meta_kubernetes_endpoint_address_target_kind 的值为 Pod,__meta_kubernetes_endpoint_address_target_name 的值为 prometheus-0,在它们之间加上一个 ; 之后,它们合起来就是 Pod;prometheus-0。使用正则表达式 Pod;(.*) 对其进行匹配,那么 ${1} 就是取第一个分组,它值就是 prometheus-0,最后将这个值交给 pod 这个标签。因此这一段配置就是为所有采集到的监控指标增加一个 pod=prometheus-0 的标签。如果 __meta_kubernetes_endpoint_address_target_kind 的值不是 Pod,那么不会添加任何标签。
- source_labels:
    - __meta_kubernetes_endpoint_address_target_kind
    - __meta_kubernetes_endpoint_address_target_name
  separator: ;
  regex: Pod;(.*)
  replacement: ${1}
  target_label: pod
  • 没有指定 url,Prometheus 会采集默认的 url /metrics

定义告警规则

groups:
- name: example
  rules:
  - alert: HighRequestLatency
    expr: job:request_latency_seconds:mean5m{job="myjob"} > 0.5
    for: 10m
    labels:
      severity: page
    annotations:
      summary: High request latency

参考官网: https://prometheus.io/docs/prometheus/latest/configuration/alerting_rules/

  • for:Prometheus将在每次发出警报之前检查警报在10分钟内是否继续处于活动状态
  • labels:允许指定一组附加标签来附加到警报。任何现有的冲突标签都将被覆盖。标签值可以模板化。
  • annotations:指定了一组信息标签,可用于存储更长的附加信息,例如警报说明或运行手册链接。注释值可以模板化。

模板化

标签和注释值可以使用控制台模板进行模板化。该$labels 变量保存警报实例的标签键/值对。可以通过$externalLabels变量访问已组态的外部标签。该 $value变量保存警报实例的评估值。

# To insert a firing element's label values:
{{ $labels. }}
# To insert the numeric expression value of the firing element:
{{ $value }}

例子:

groups:
- name: example
  rules:
 
  # Alert for any instance that is unreachable for >5 minutes.
  - alert: InstanceDown
    expr: up == 0
    for: 5m
    labels:
      severity: page
    annotations:
      summary: "Instance {{ $labels.instance }} down"
      description: "{{ $labels.instance }} of job {{ $labels.job }} has been down for more than 5 minutes."
 
  # Alert for any instance that has a median request latency >1s.
  - alert: APIHighRequestLatency
    expr: api_http_request_latencies_second{quantile="0.5"} > 1
    for: 10m
    annotations:
      summary: "High request latency on {{ $labels.instance }}"
      description: "{{ $labels.instance }} has a median request latency above 1s (current value: {{ $value }}s)"

Alertmanager是安装prometheus-operator时默认新增的自定义资源类型(CRD),我们可以直接在K8s中创建这样的资源。

创建alert-test.yaml

apiVersion: monitoring.coreos.com/v1
kind: Alertmanager
metadata:
  generation: 1
  labels:
    app: prometheus-operator-alertmanager
    chart: prometheus-operator-8.2.4
    heritage: Tiller
    release: prometheus-operator
  name: prometheus-operator-alertmanager-test
  namespace: monitoring
spec:
  baseImage: quay.io/prometheus/alertmanager
  version: v0.19.0
  portName: web
  replicas: 1
  retention: 120h
  routePrefix: /
  serviceAccountName: prometheus-operator-alertmanager
  affinity:
    podAntiAffinity:
      requiredDuringSchedulingIgnoredDuringExecution:
      - topologyKey: kubernetes.io/hostname
        labelSelector:
          matchLabels:
            app: alertmanager
            alertmanager: prometheus-operator-alertmanager-test
    podAntiAffinity:
      preferredDuringSchedulingIgnoredDuringExecution:
      - weight: 100
        podAffinityTerm:
          topologyKey: kubernetes.io/hostname
          labelSelector:
            matchLabels:
              app: alertmanager
              alertmanager: prometheus-operator-alertmanager-test
  storage:
    volumeClaimTemplate:
      selector: {}
      spec:
        accessModes:
        - ReadWriteOnce
        resources:
          requests:
            storage: 1Gi
        storageClassName: nfs-client

针对以上配置文件简要说明:

  • 所有配置项可以从stable/prometheus-operator/templates/alertmanager/alertmanager.yaml获取,参考前文,prometheus-operator环境是使用helm安装的,可以通过命令helm fetch stable/prometheus-operator将所有配置下载到本地,然后参考。helm安装会默认安装一个Alertmanager服务,也是通过alertmanager.yaml安装的。
  • kind类型写Alertmanager,无需多言。
  • metadata.name指定你这个Alertmanager名称,可以通过命令查询
kubectl get alertmanager -n monitoring
  • spec.baseImage/version需要指定,不然默认使用的镜像版本可能跟helm安装时使用的版本不一致,导致你需要重新下载,部署就非常慢。
  • spec.storage指定你新部署的Alertmanager存储,建议指定。
  • spec.affinity需要指定一些label,Alertmanager对象本质还是一个StatefulSet对象,后面你为Alertmanager对象创建Service时需要通过Label选择。
  • spec.portName指定你端口的名称,这个后面配置和Prometheus关联的时候需要。建议保持默认。
  • metadata.namespace指定命名空间,这个后面配置和Prometheus关联的时候需要。建议保持默认。
  • spec.routePrefix指定路径前缀,这个后面配置和Prometheus关联的时候需要。建议保持默认。

过命令或者dashborad创建Alertmanager

kubectl create -f alert-test.yaml

注意:

现在创建这个,肯定会报错,类似MountVolume.SetUp failed for volume "config-volume" : secrets "alertmanager-XXXX-xX" not found

原因:(参考:https://yunlzheng.gitbook.io/prometheus-book/part-iii-prometheus-shi-zhan/operator/use-operator-manage-monitor

这是由于Prometheus Operator通过Statefulset的方式创建的Alertmanager实例,在默认情况下,会通过alertmanager-{ALERTMANAGER_NAME}的命名规则去查找Secret配置并以文件挂载的方式,将Secret的内容作为配置文件挂载到Alertmanager实例当中。因此,需要提前为Alertmanager创建相应的配置内容。

参考前文Alertmanager配置

我们创建alertmanager.yamltemplate_1.tmpl

然后用命令创建secretsecret名称格式:alertmanager-{ALERTMANAGER_NAME},例如我们前文指定的Alertmanager名称为prometheus-operator-alertmanager-test,那么这里secret名称为alertmanager-prometheus-operator-alertmanager-test

kubectl create secret generic alertmanager-prometheus-operator-alertmanager-test -n monitoring --from-file=alertmanager.yaml --from-file=template_1.tmpl

最后创建Alertmanager

创建Alertmanager的service

这里直接指定Service类型是NodePort,便于我们访问,实际应通过Ingress来做。

apiVersion: v1
kind: Service
metadata:
  labels:
    app: prometheus-operator-alertmanager
    chart: prometheus-operator-8.2.4
    heritage: Tiller
    release: prometheus-operator
  name: prometheus-operator-alertmanager-test
  namespace: monitoring
spec:
  ports:
  - name: web
    port: 9093
    protocol: TCP
    targetPort: 9093
  selector:
    alertmanager: prometheus-operator-alertmanager-test
    app: alertmanager
  sessionAffinity: None
  type: NodePort

注意:这里通过selector来选择,和创建Alertmanager配置中保持一致。

通过命令查询Service的映射端口

kubectl get svc -n monitoring

通过命令查询Service的映射端口,即可访问我们刚刚创建的Alertmanager.

现在Alertmanager上应该还没有任何通知,原因是还没有将我们创建的Alertmanager和Prometheus关联。

关联Prometheus

如何关联Prometheus呢?首先查看下prometheus-operator创建的Prometheus的配置,prometheus-operator也是通过自定义资源类型(CRD)prometheus来创建prometheus server的,直接通过命令查看。

kubectl get Prometheus prometheus-operator-prometheus  -n monitoring -o yaml
apiVersion: monitoring.coreos.com/v1
kind: Prometheus
metadata:
  creationTimestamp: "2019-11-28T02:42:48Z"
  generation: 1
  labels:
    app: prometheus-operator-prometheus
    chart: prometheus-operator-8.2.4
    heritage: Tiller
    release: prometheus-operator
  name: prometheus-operator-prometheus
  namespace: monitoring
  resourceVersion: "6316434"
  selfLink: /apis/monitoring.coreos.com/v1/namespaces/monitoring/prometheuses/prometheus-operator-prometheus
  uid: de60d68f-6818-484d-ba30-4f381e7cb016
spec:
  alerting:
    alertmanagers:
    - name: prometheus-operator-alertmanager
      namespace: monitoring
      pathPrefix: /
      port: web
  baseImage: quay.io/prometheus/prometheus
  enableAdminAPI: false
  externalUrl: http://prom.deri.com/
  listenLocal: false
  logFormat: logfmt
  logLevel: info
  paused: false
  podMonitorNamespaceSelector: {}
  podMonitorSelector:
    matchLabels:
      release: prometheus-operator
  portName: web
  replicas: 1
  retention: 10d
  routePrefix: /
  ruleNamespaceSelector: {}
  ruleSelector:
    matchLabels:
      app: prometheus-operator
      release: prometheus-operator
  securityContext:
    fsGroup: 2000
    runAsNonRoot: true
    runAsUser: 1000
  serviceAccountName: prometheus-operator-prometheus
  serviceMonitorNamespaceSelector: {}
  serviceMonitorSelector:
    matchLabels:
      release: prometheus-operator
  storage:
    volumeClaimTemplate:
      selector: {}
      spec:
        accessModes:
        - ReadWriteOnce
        resources:
          requests:
            storage: 2Gi
        storageClassName: nfs-client
  version: v2.13.1

Prometheus配置

  • spec.alerting.alertmanagers就是指定Prometheus将告警发给哪些alertmanagers。
  • spec.ruleSelector.matchLabels通过标签关联用户创建的自定义PrometheusRule。
  • spec.serviceMonitorSelector.matchLabels通过标签关联用户创建的自定义ServiceMonitor

使用命令编辑已有的Prometheus服务配置

kubectl edit Prometheus prometheus-operator-prometheus  -n monitoring

增加一个AlertmanagerEndpoint,其中namenamespacepathPrefixport和创建Alertmanager配置保持一致。

spec:
  alerting:
    alertmanagers:
    - name: prometheus-operator-alertmanager
      namespace: monitoring
      pathPrefix: /
      port: web
    - name: prometheus-operator-alertmanager-test
      namespace: monitoring
      pathPrefix: /
      port: web

Alertmanager简介及机制

Alertmanager处理由例如Prometheus服务器等客户端发来的警报。它负责删除重复数据、分组,并将警报通过路由发送到正确的接收器,比如电子邮件、Slack等。Alertmanager还支持groups,silencing和警报抑制的机制。

分组

分组是指将同一类型的警报分类为单个通知。当许多系统同时宕机时,很有可能成百上千的警报会同时生成,这种机制特别有用。

抑制(Inhibition)

抑制是指当警报发出后,停止重复发送由此警报引发其他错误的警报的机制。(比如网络不可达,导致其他服务连接相关警报)

沉默(Silences)

Silences是一种简单的特定时间不告警的机制。

默认配置

打开Alertmanager的页面,选择status页面,可以查看到当前的Config。这是使用Helm安装prometheus-operator时默认的配置,如何修改呢?

global:
  resolve_timeout: 4m
  http_config: {}
  smtp_hello: localhost
  smtp_require_tls: true
  pagerduty_url: https://events.pagerduty.com/v2/enqueue
  hipchat_api_url: https://api.hipchat.com/
  opsgenie_api_url: https://api.opsgenie.com/
  wechat_api_url: https://qyapi.weixin.qq.com/cgi-bin/
  victorops_api_url: https://alert.victorops.com/integrations/generic/20131114/alert/
route:
  receiver: "null"
  group_by:
  - job
  routes:
  - receiver: "null"
    match:
      severity: info
  group_wait: 30s
  group_interval: 5m
  repeat_interval: 12h
receivers:
- name: "null"
templates: []

Alertmanager配置说明

参考https://www.jianshu.com/p/239b145e2acc

修改默认配置

默认配置由同命名空间下Secret挂载到POD中,所以只要修改了这个Secret就可以修改默认配置了。

alertmanager-prometheus-operator-alertmanager内容主要是alertmanager.yaml 经过Base64加密的。可以通过命令查看

kubectl edit  secret alertmanager-prometheus-operator-alertmanager -n monitoring

复制其中的alertmanager.yaml后面的字符串,然后使用命令查看原始值。

echo "Imdsb2JhbCI6IAogICJyZXNvbHZlX3RpbWVvdXQiOiAiNW0iCiJyZWNlaXZlcnMiOiAKLSAibmFtZSI6ICJudWxsIgoicm91dGUiOiAKICAiZ3JvdXBfYnkiOiAKICAtICJqb2IiCiAgImdyb3VwX2ludGVydmFsIjogIjVtIgogICJncm91cF93YWl0IjogIjMwcyIKICAicmVjZWl2ZXIiOiAibnVsbCIKICAicmVwZWF0X2ludGVydmFsIjogIjEyaCIKICAicm91dGVzIjogCiAgLSAibWF0Y2giOiAKICAgICAgImFsZXJ0bmFtZSI6ICJEZWFkTWFuc1N3aXRjaCIKICAgICJyZWNlaXZlciI6ICJudWxsIg==" | base64 -d
"global":
  "resolve_timeout": "5m"
"receivers":
- "name": "null"
"route":
  "group_by":
  - "job"
  "group_interval": "5m"
  "group_wait": "30s"
  "receiver": "null"
  "repeat_interval": "12h"
  "routes":
  - "match":
      "alertname": "DeadMansSwitch"
    "receiver": "null"

创建一个新的alertmanager.yaml文件,内容

global:
  resolve_timeout: 4m
receivers:
- name: webhook_alert
  webhook_configs:
  - send_resolved: true
    url: http://dingtalkservice:8060/dingtalk/webhook1/send 
route:
  group_by:
  - job
  - alertname
  - cluster
  - service
  group_interval: 5m
  group_wait: 30s
  receiver: webhook_alert
  repeat_interval: 12h
  routes:
  - match:
      severity: info
    receiver: webhook_alert
  - match:
      severity: warning
    receiver: webhook_alert
templates:
- '*.tmpl'

其中我们增加了webhook方式报警,配置最后增加了模板,所以我们还需要创建一个模板,如template_1.tmpl

{{ define "cluster" }}
    [错误订阅信息]{{ len .Alerts }}({{.GroupLabels.appid}}-{{.GroupLabels.service}}) 时间
    {{ range $i, $alert := .Alerts }}
        {{if eq $i 0}} 
            {{ $alert.StartsAt }}
        {{ end }}
    {{ end }}
{{ end }}
 
{{ define "alertemp.html" }}
    {{ range $i, $alert := .Alerts }}
        *报警名称:* {{ $alert.Labels.alertname }}
        *开始时间:* {{ $alert.StartsAt }}
        *错误信息:* {{ $alert.Annotations.errormessage }}
    {{ end }}
{{ end }}

上述模板参考:http://blog.microservice4.net/2018/12/05/alertmanager/

先删除原来的Secret

kubectl delete secret alertmanager-prometheus-operator-alertmanager -n monitoring

从刚刚文件创建新的Secret

kubectl create secret generic alertmanager-prometheus-operator-alertmanager -n monitoring --from-file=alertmanager.yaml --from-file=template_1.tmpl

创建完之后可以通过log命令查看后台有没有报错。

kubectl log alertmanager-prometheus-operator-alertmanager-0 alertmanager -n monitoring

也可以在Dashboard中查看日志。还可以在Alertmanager容器中查看
altermanager

最后在Alertmanager页面中查看Config是否更新。
altermanager

到此,已经完成Alertmanager默认配置的更新。

以上参考https://www.qikqiak.com/post/prometheus-operator-custom-alert/.

上述配置Webhook使用的钉钉来做通知

webhook通知机制

在Alertmanager中可以使用如下配置定义基于webhook的告警接收器receiver。一个receiver可以对应一组webhook配置。

name: 
webhook_configs:
  [ - , ... ]

每一项webhook_config的具体配置格式如下:

# Whether or not to notify about resolved alerts.
[ send_resolved:  | default = true ]
 
# The endpoint to send HTTP POST requests to.
url: 
 
# The HTTP client's configuration.
[ http_config:  | default = global.http_config ]

send_resolved用于指定是否在告警消除时发送回执消息。url则是用于接收webhook请求的地址。http_configs则是在需要对请求进行SSL配置时使用。

当用户定义webhook用于接收告警信息后,当告警被触发时,Alertmanager会按照以下格式向这些url地址发送HTTP Post请求,请求内容如下:

{
  "version": "4",
  "groupKey": <string>,    // key identifying the group of alerts (e.g. to deduplicate)
  "status": "<resolved|firing>",
  "receiver": <string>,
  "groupLabels": <object>,
  "commonLabels": <object>,
  "commonAnnotations": <object>,
  "externalURL": <string>,  // backlink to the Alertmanager.
  "alerts": [
    {
      "labels": <object>,
      "annotations": <object>,
      "startsAt": "<rfc3339>",
      "endsAt": "<rfc3339>"
    }
  ]
}

钉钉机器人

webhook机器人创建成功后,用户就可以使用任何方式向该地址发起HTTP POST请求,即可实现向该群主发送消息。目前自定义机器人支持文本(text),连接(link),markdown三种消息类型。

例如,可以向webhook地址以POST形式发送以下

{
     "msgtype": "markdown",
     "markdown": {
         "title":"Prometheus告警信息",
         "text": "#### 监控指标\n" +
                 "> 监控描述信息\n\n" +
                 "> ###### 告警时间 \n"
     },
    "at": {
        "atMobiles": [
            "156xxxx8827",
            "189xxxx8325"
        ], 
        "isAtAll": false
    }
 }

可以使用curl验证钉钉webhook是否能够成功调用:

$ curl -l -H "Content-type: application/json" -X POST -d '{"msgtype": "markdown","markdown": {"title":"Prometheus告警信息","text": "#### 监控指标\n> 监控描述信息\n\n> ###### 告警时间 \n"},"at": {"isAtAll": false}}' https://oapi.dingtalk.com/robot/send?access_token=xxxx
{"errcode":0,"errmsg":"ok"}

如果想把Alertmanager信息转到钉钉上去,需要做一个转换器。
转化器部署:可以在k8s中部署一个Deployment,然后创建一个Service给Alert manager使用。

整个报警链路

  1. 首先是Prometheus根据告警规则告警,如果增删改规则参考PrometheusRule
  2. Prometheus的告警经过Alertmanager静默、抑制、分组等配置到达Alertmanager
  3. AlterManager通过配置webhook,地址填钉钉转换器的地址。
  4. 钉钉转换器中webhook地址填写钉钉机器人webhook的地址。

Prometheus Alert 告警状态

这里说明一下 Prometheus Alert 告警状态有三种状态:InactivePendingFiring

  • Inactive:非活动状态,表示正在监控,但是还未有任何警报触发。
  • Pending:表示这个警报必须被触发。由于警报可以被分组、压抑/抑制或静默/静音,所以等待验证,一旦所有的验证都通过,则将转到 Firing 状态。
  • Firing:将警报发送到 AlertManager,它将按照配置将警报的发送给所有接收者。一旦警报解除,则将状态转到 Inactive,如此循环。

参考链接