kube-promethues监控告警详解(邮件、钉钉、微信、企微机器人、自研平台)

Alertmanager已经在前面Prometheus初体验(三)已经介绍过了。现在介绍一下在kube-promethues里面怎么修改alertmanager配置文件,以及怎么通过各种媒介发送信息。

一、配置 PrometheusRule(触发器)

kube-promethues把所有资源监控起来之后,就需要配置告警这一块了,而告警其实就是配置触发器。在promethues的Alert界面,已经有了很多触发器了。

 

 那么,这些报警信息是哪里来的呢?他们应该用怎样的方式通知我们呢?我们知道之前使用二进制部署的时候,是通过自定义的方式在 Prometheus 的配置文件之中指定 AlertManager 实例和 报警的 rules 文件,现在我们通过 Operator 部署的呢?我们可以在 Prometheus Dashboard 的 Config 页面下面查看关于 AlertManager 的配置:

global:
  scrape_interval: 30s
  scrape_timeout: 10s
  evaluation_interval: 30s
  external_labels:
    prometheus: monitoring/k8s
    prometheus_replica: prometheus-k8s-0
alerting:
  alert_relabel_configs:
  - separator: ;
    regex: prometheus_replica
    replacement: $1
    action: labeldrop
  alertmanagers:
  - kubernetes_sd_configs:
    - role: endpoints
      namespaces:
        names:
        - monitoring
    scheme: http
    path_prefix: /
    timeout: 10s
    api_version: v1
    relabel_configs:
    - source_labels: [__meta_kubernetes_service_name]
      separator: ;
      regex: alertmanager-main
      replacement: $1
      action: keep
    - source_labels: [__meta_kubernetes_endpoint_port_name]
      separator: ;
      regex: web
      replacement: $1
      action: keep
rule_files:
- /etc/prometheus/rules/prometheus-k8s-rulefiles-0/*.yaml

  上面 alertmanagers 实例的配置我们可以看到是通过角色为 endpoints 的 kubernetes 的服务发现机制获取的,匹配的是服务名为 alertmanager-main,端口名为 web 的 Service 服务,我们查看下 alertmanager-main 这个 Service:

[root@vm10-0-0-12 ~]# kubectl describe svc alertmanager-main -n monitoring
Name:              alertmanager-main
Namespace:         monitoring
Labels:            alertmanager=main
Annotations:       kubectl.kubernetes.io/last-applied-configuration:
                     {"apiVersion":"v1","kind":"Service","metadata":{"annotations":{},"labels":{"alertmanager":"main"},"name":"alertmanager-main","namespace":"...
Selector:          alertmanager=main,app=alertmanager
Type:              ClusterIP
IP:                10.254.160.2
Port:              web  9093/TCP
TargetPort:        web/TCP
Endpoints:         10.8.0.21:9093,10.8.1.72:9093,10.8.2.19:9093
Session Affinity:  ClientIP
Events:            <none>

  可以看到服务名正是 alertmanager-main,Port 定义的名称也是 web,符合上面的规则,所以 Prometheus 和 AlertManager 组件就正确关联上了。而对应的报警规则文件位于:/etc/prometheus/rules/prometheus-k8s-rulefiles-0/目录下面所有的 YAML 文件。我们可以进入 Prometheus 的 Pod 中验证下该目录下面是否有 YAML 文件:

$ kubectl exec -it prometheus-k8s-0 /bin/sh -n monitoring
Defaulting container name to prometheus.
Use 'kubectl describe pod/prometheus-k8s-0 -n monitoring' to see all of the containers in this pod.
/prometheus $ ls /etc/prometheus/rules/prometheus-k8s-rulefiles-0/
monitoring-prometheus-k8s-rules.yaml
/prometheus $ cat /etc/prometheus/rules/prometheus-k8s-rulefiles-0/monitoring-prometheus-k8s-rules.yaml
groups:
- name: k8s.rules
  rules:
  - expr: |
      sum(rate(container_cpu_usage_seconds_total{job="kubelet", image!="", container_name!=""}[5m])) by (namespace)
    record: namespace:container_cpu_usage_seconds_total:sum_rate
......

  这个 YAML 文件实际上就是我们之前创建的一个 PrometheusRule 文件包含的:

$ cat prometheus-rules.yaml
apiVersion: monitoring.coreos.com/v1
kind: PrometheusRule
metadata:
  labels:
    prometheus: k8s
    role: alert-rules
  name: prometheus-k8s-rules
  namespace: monitoring
spec:
  groups:
  - name: k8s.rules
    rules:
    - expr: |
        sum(rate(container_cpu_usage_seconds_total{job="kubelet", image!="", container_name!=""}[5m])) by (namespace)
      record: namespace:container_cpu_usage_seconds_total:sum_rate

  我们这里的 PrometheusRule 的 name 为 prometheus-k8s-rules,namespace 为 monitoring,我们可以猜想到我们创建一个 PrometheusRule 资源对象后,会自动在上面的 prometheus-k8s-rulefiles-0 目录下面生成一个对应的<namespace>-<name>.yaml文件,所以如果以后我们需要自定义一个报警选项的话,只需要定义一个 PrometheusRule 资源对象即可。

至于为什么 Prometheus 能够识别这个 PrometheusRule 资源对象呢?这就需要查看我们创建的 prometheus 这个资源对象了,里面有非常重要的一个属性 ruleSelector,用来匹配 rule 规则的过滤器,要求匹配具有 prometheus=k8s 和 role=alert-rules 标签的 PrometheusRule 资源对象,现在明白了吧?

cat prometheus-prometheus.yaml 

apiVersion: monitoring.coreos.com/v1
kind: Prometheus
metadata:
  labels:
    prometheus: k8s
  name: k8s
  namespace: monitoring
spec:
  alerting:
    alertmanagers:
    - name: alertmanager-main
      namespace: monitoring
      port: web
  baseImage: prom/prometheus
  nodeSelector:
    beta.kubernetes.io/os: linux
  podMonitorSelector: {}
  replicas: 2
  resources:
    requests:
      memory: 400Mi
  ruleSelector:
    matchLabels:
      prometheus: k8s
      role: alert-rules
  securityContext:
    fsGroup: 2000
    runAsNonRoot: true
    runAsUser: 1000
  serviceAccountName: prometheus-k8s
  serviceMonitorNamespaceSelector: {}
  serviceMonitorSelector: {}
  version: v2.11.0

  所以我们要想自定义一个报警规则,只需要创建一个具有 prometheus=k8s 和 role=alert-rules 标签的 PrometheusRule 对象就行了,比如现在我们添加一个 etcd 是否可用的报警,我们知道 etcd 整个集群有一半以上的节点可用的话集群就是可用的,所以我们判断如果不可用的 etcd 数量超过了一半那么就触发报警,创建文件 prometheus-etcdRules.yaml:

apiVersion: monitoring.coreos.com/v1
kind: PrometheusRule
metadata:
  labels:
    prometheus: k8s
    role: alert-rules
  name: etcd-rules
  namespace: monitoring
spec:
  groups:
  - name: etcd
    rules:
    - alert: EtcdClusterUnavailable
      annotations:
        summary: etcd cluster small
        description: If one more etcd peer goes down the cluster will be unavailable
      expr: |
        count(up{job="etcd"} == 0) > (count(up{job="etcd"}) / 2 - 1)
      for: 3m
      labels:
        severity: critical

  注意:label 标签一定至少要有 prometheus=k8s 和 role=alert-rules!

rule文件的头部都是统一的,只有spec里面不同。

创建完成后,隔一会儿再去容器中查看下 rules 文件夹:

kubectl exec -it prometheus-k8s-0 /bin/sh -n monitoring
Defaulting container name to prometheus.
Use 'kubectl describe pod/prometheus-k8s-0 -n monitoring' to see all of the containers in this pod.
/prometheus $ ls /etc/prometheus/rules/prometheus-k8s-rulefiles-0/
monitoring-etcd-rules.yaml            monitoring-prometheus-k8s-rules.yaml

  可以看到我们创建的 rule 文件已经被注入到了对应的 rulefiles 文件夹下面了,证明我们上面的设想是正确的。然后再去 Prometheus Dashboard 的 Rules页面下面就可以查看到上面我们新建的报警规则了:

 

二、配置promethuesAlert(告警媒介)

触发器配置完成后,接下来需要在kube-promethues环境里配置告警通知了。promethues支持多种告警方式:钉钉、微信、邮件、webhook。其中webhook最为灵活,可以和自研的第三方平台对接。

告警配置相关可以在alertmanager里面查看:

 

 

 这些配置信息实际上是来自于我们之前在prometheus-operator/contrib/kube-prometheus/manifests目录下面创建的 alertmanager-secret.yaml 文件:

apiVersion: v1
data:
  alertmanager.yaml: Imdsb2JhbCI6IAogICJyZXNvbHZlX3RpbWVvdXQiOiAiNW0iCiJyZWNlaXZlcnMiOiAKLSAibmFtZSI6ICJudWxsIgoicm91dGUiOiAKICAiZ3JvdXBfYnkiOiAKICAtICJqb2IiCiAgImdyb3VwX2ludGVydmFsIjogIjVtIgogICJncm91cF93YWl0IjogIjMwcyIKICAicmVjZWl2ZXIiOiAibnVsbCIKICAicmVwZWF0X2ludGVydmFsIjogIjEyaCIKICAicm91dGVzIjogCiAgLSAibWF0Y2giOiAKICAgICAgImFsZXJ0bmFtZSI6ICJEZWFkTWFuc1N3aXRjaCIKICAgICJyZWNlaXZlciI6ICJudWxsIg==
kind: Secret
metadata:
  name: alertmanager-main
  namespace: monitoring
type: Opaque

  可以将 alertmanager-secret.yaml 对应的 value 值做一个 base64 解码:

echo "Imdsb2JhbCI6IAogICJyZXNvbHZlX3RpbWVvdXQiOiAiNW0iCiJyZWNlaXZlcnMiOiAKLSAibmFtZSI6ICJudWxsIgoicm91dGUiOiAKICAiZ3JvdXBfYnkiOiAKICAtICJqb2IiCiAgImdyb3VwX2ludGVydmFsIjogIjVtIgogICJncm91cF93YWl0IjogIjMwcyIKICAicmVjZWl2ZXIiOiAibnVsbCIKICAicmVwZWF0X2ludGVydmFsIjogIjEyaCIKICAicm91dGVzIjogCiAgLSAibWF0Y2giOiAKICAgICAgImFsZXJ0bmFtZSI6ICJEZWFkTWFuc1N3aXRjaCIKICAgICJyZWNlaXZlciI6ICJudWxsIg==" | base64 -d

 

 

 也就是说,如果我们需要修改告警的主配置文件,只要修改 alertmanager-secret.yaml文件就行了。而 alertmanager-secret.yaml是一个secret,所以修改过程如下:

1、新建一个alertmanager.yaml文件

2、删除之前的secret文件(alertmanager-main)

3、新建secret文件

 

cat alertmanager.yaml 

global:
  resolve_timeout: 5m
  wechat_api_url: 'https://qyapi.weixin.qq.com/cgi-bin/'
  wechat_api_secret: '*****'
  wechat_api_corp_id: '*******'
  smtp_smarthost: 'smtp.163.com:25'
  smtp_from: '你的邮箱'
  smtp_auth_username: '邮箱用户名'
  smtp_auth_password: '密码或授权码'
  smtp_require_tls: false

templates:     ##消息模板
  - '*.tmpl'

route:
  group_by: ['alertname','job']
  group_wait: 10s
  group_interval: 10s
  repeat_interval: 12h
  receiver: 'wechat'
  routes:
  - match:
      job: 'prometheus'
    receiver: 'wechat'

receivers:
- name: 'email'
  email_configs:
  - to: '邮件接收人'
- name: 'wechat'
  wechat_configs:
  - send_resolved: true
    to_party: '2'
    agent_id: '1'
- name: 'webhook'
  webhook_configs:
#  - url: 'http://dingtalk-hook:5000'
  - url: 'http://webhook-dingtalk.monitoring.svc.cluster.local:8060/dingtalk/webhook1/send'
    send_resolved: true

  

# 先将之前的 secret 对象删除
$ kubectl delete secret alertmanager-main -n monitoring
secret "alertmanager-main" deleted

# 创建新的secret对象
$ kubectl create secret generic alertmanager-main --from-file=alertmanager.yaml -n monitoring
secret "alertmanager-main" created

  注意:这里--from-file可以使用多个,如果你使用多重告警方式的话。

以上过程执行完成后,就可以在alertmanager中看到最新的配置了:

 

 

三、配置promethuesAlert(邮件告警)

邮件告警是最简单的,只需要直接在alertmanager的config里面配置就行。

global:
  resolve_timeout: 5m
  smtp_smarthost: 'smtp.163.com:25'
  smtp_from: 'xuequn_2008@163.com'
  smtp_auth_username: 'xuequn_2008@163.com'
  smtp_auth_password: 'password'
  smtp_require_tls: false

templates:     ##消息模板
  - '*.tmpl'

route:
  group_by: ['alertname','job']
  group_wait: 10s
  group_interval: 10s
  repeat_interval: 12h
  receiver: 'wechat'
  routes:
  - match:
      job: 'prometheus'
    receiver: 'wechat'

receivers:
- name: 'email'
  email_configs:
  - to: 'xuequn_2008@163.com'

  以上是一个简单的配置,完成后,将repeat-interval设置小一点,比如1m。去邮箱查看对应的告警就行了。

 

 

 

 

 

四、配置promethuesAlert(钉钉告警)

1、注册钉钉账号->机器人管理

 

 

2、自定义(通过webhook接入自定义服务)

 

 

3、添加->复制webhook

 

 重点在webhook,复制webhook的url链接。

4、编写yaml

在/data/k8s-install/prometheus/alertmanager目录下,新建dingtalk-webhook.yaml

---
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  labels:
    run: dingtalk
  name: webhook-dingtalk
  namespace: monitoring
spec:
  replicas: 1
  template:
    metadata:
      labels:
        run: dingtalk
    spec:
      containers:
      - name: dingtalk
        image: timonwong/prometheus-webhook-dingtalk:v0.3.0
        imagePullPolicy: IfNotPresent
        # 设置钉钉群聊自定义机器人后,使用实际 access_token 替换下面 xxxxxx部分
        args:
          - --ding.profile=webhook1=https://oapi.dingtalk.com/robot/send?access_token=你的token
        ports:
        - containerPort: 8060
          protocol: TCP

---
apiVersion: v1
kind: Service
metadata:
  labels:
    run: dingtalk
  name: webhook-dingtalk
  namespace: monitoring
spec:
  ports:
  - port: 8060
    protocol: TCP
    targetPort: 8060
  selector:
    run: dingtalk
  sessionAffinity: None

  填上上面复制的webhook链接地址。

 

5、应用配置

kubectl apply -f dingtalk-webhook.yaml

  应用配置后,对应的pod和service就起来了,我们可以看到侦听的端口为8060.

6、alertmanager配置告警通知

global:
  resolve_timeout: 5m

templates:     ##消息模板
  - '*.tmpl'

route:
  group_by: ['alertname','job']
  group_wait: 10s
  group_interval: 10s
  repeat_interval: 12h
  receiver: 'webhook'

receivers:
#配置邮件告警
- name: 'email'
  email_configs:
  - to: 'xuequn_2008@163.com'

#配置钉钉告警的webhook
- name: 'webhook'
  webhook_configs:
  - url: 'http://webhook-dingtalk.monitoring.svc.cluster.local:8060/dingtalk/webhook1/send'
    send_resolved: true

  

7、更新告警文件

# 先将之前的 secret 对象删除
$ kubectl delete secret alertmanager-main -n monitoring
secret "alertmanager-main" deleted

# 创建新的secret对象
$ kubectl create secret generic alertmanager-main --from-file=alertmanager.yaml -n monitoring
secret "alertmanager-main" created

  

8、测试告警

一般情况下,没有问题的话,你就可以接收到钉钉告警拉。

 

 

五、配置promethuesAlert(微信告警)

 由于wechat的强大,所以alertmanager官方直接支持wechat告警,直接配置即可。

1、注册企业微信

找到以下几个东西:

wechat_api_secret    应用ID

wechat_api_corp_id  企业ID

to_party   中心(部门的上级)

agent_id  部门ID

 

2、配置alertmanager

global:
  resolve_timeout: 5m
  wechat_api_url: 'https://qyapi.weixin.qq.com/cgi-bin/'
  wechat_api_secret: '应用ID'
  wechat_api_corp_id: '企业ID'
  

templates:     ##消息模板
  - '*.tmpl'

route:
  group_by: ['alertname','job']
  group_wait: 10s
  group_interval: 10s
  repeat_interval: 1m
  receiver: 'wechat'

receivers:

- name: 'wechat'
  wechat_configs:
  - send_resolved: true
    to_party: '2'  #中心ID
    agent_id: '1'  #部门ID

  按照以上方式配置完成后,直接测试即可,一般没有问题的情况下,你会收到如下形式的告警:

 

六、配置promethuesAlert(微信机器人告警)

我们上面用的是企微方式,也就是你可以管理企微的情况下。如果在企业中,你不能管理企微,而只能创建企微机器人的话,就需要使用机器人来告警了。

6.1 创建企微机器人

企业微信的机器人key,需要创建群聊然后再创建机器人,机器人自带key

 

 

 6.2 安装企业微信报警插件(webhook-adapter)

这里有2种方式,1种是通过docker启动一个webhook,1种是通过k8s部署一个webhook。至于使用docker方式或K8s方式的话,却决于你自己。

方式一、docker方式部署

docker run -d --name wechat2 --restart always -p 8888:80 loveliuli/webhook-adapter --adapter=/app/prometheusalert/wx.js=/wx=https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=a079b336-abbd-4673-a6e7-1288c8d1bf

启动后检查:

 

 

 方式二、k8s方式部署

以下是以部署在腾讯云上为例:

启动参数为:

node /app/index.js --port=80 --adapter=/app/prometheusalert/wx.js=/wx=https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=0d9cb7b9-80cc-4c2d-869c-adb5c736db

  

 

 

 6.3 告警通知

 

 

 

 

七、配置promethuesAlert(自研平台)

自研平台,就是自己开发的平台。其实也是通过webhook方式和第三方对接。前提是:自研平台有对应的API接口接受告警。

比如,我们自己开发的接口如下:

curl -X POST "http://www.baibai.com/eventhub/api/v1/failure_events/" \
-H "Content-Type:application/json" \
-H "Authorization:Token 7HNSNBqqRf6EHCBaCgDdMPYHCq9VK6RE" \
-d @- << EOF
{
    "name": "告警事件名",
    "description":"事件描述",
    "project_name": "告警项目",
    "failure_type":"程序故障-通用应用程序故障-通用应用程序BUG"
}
EOF

  上面对接的是一个事件系统,有一个POST接口,可以直接接受事件告警。

因为我们希望webhook同样运行在k8s环境里,方便维护和开发,所以,我们先要制作一个对应webhook的镜像文件。

1、制作镜像

编写app

import os
import json
import requests
import datetime

from flask import Flask
from flask import request

app = Flask(__name__)


@app.route('/', methods=['POST', 'GET'])
def send():
    if request.method == 'POST':
        post_data = request.get_data()
        post_data = eval(str(post_data, encoding = "utf-8"))
        event_status = post_data.get('alerts')[0].get('status','')
        event_job = post_data.get('alerts')[0].get('labels','').get('job','')
        event_type = post_data.get('alerts')[0].get('labels','').get('alertname','')
        event_desc = post_data.get('alerts')[0].get('annotations','').get('message','')
        event_level = post_data.get('alerts')[0].get('labels','').get('severity','')
        event_time = post_data.get('alerts')[0].get('startsAt')[0:-11]
        
        new_data = {
            "alert_status": event_status,
            "alert_instance": event_job,
            "alert_type": event_type,
            "alert_desc": event_desc,
            "alert_severity": event_level,
            "alert_time": event_time
         }
        send_alert(new_data)
        return 'success'
    else:
        return 'weclome to use prometheus alertmanager events-hub webhook server!'


class ComplexEncoder(json.JSONEncoder):
    def default(self, obj):
        if isinstance(obj, datetime.datetime):
            return obj.strftime('%Y-%m-%d %H:%M:%S')
        elif isinstance(obj, bytes):
            return str(obj, encoding='utf-8')
        else:
            return json.JSONEncoder.default(self, obj)



def send_alert(data):
    url = "http://www.baibai/eventhub/api/v1/failure_events/"
    headers = {
            "Content-Type": "application/json",
            "Authorization": "Token 7HNSNBqqRf6EHCBaCgDdMPYHCq9VK6RE"
            }
    send_data = {
        "name": data.get('alert_desc',''),
        "description": data,
        "project_name": "维护支持部",
        "failure_type": "程序故障-通用应用程序故障-通用应用程序BUG"
    }
    req = requests.post(url, data=json.dumps(send_data,cls=ComplexEncoder),headers=headers)
    print(req.text)
    result = req.json()


if __name__ == '__main__':
    app.run(host='0.0.0.0', port=5000)

  

2、编写Dockerfile

cat Dockerfile 

FROM python:3.6.4

# set working directory
WORKDIR /src

# add app
ADD . /src

# install requirements
RUN pip install -r requirements.txt

# run server
CMD python app.py

  

cat requirements.txt

certifi==2018.10.15
chardet==3.0.4
Click==7.0
Flask==1.0.2
idna==2.7
itsdangerous==1.1.0
Jinja2==2.10
MarkupSafe==1.1.0
requests==2.20.1
urllib3==1.24.1
Werkzeug==0.14.1

  上面其实就是写了一个简单的flask app,通过POST方法,向第三方系统的API提交数据。

3、构建镜像

docker build  -t loveliuli/events-hub:v0.1 .

  

4、上传镜像到Dockerhub

当然,这里的前提是你得先在Dockerhub上注册了账号,并且在本地使用docker login登录。

docker push loveliuli/events-hub:v0.1

  

 

 这样就方便在任何地方都可以进行使用这个镜像了。

 

5、alertmanager编写yaml

cat dingtalk-webhook-flask.yaml

apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: dingtalk-hook
  namespace: monitoring
spec:
  template:
    metadata:
      labels:
        app: dingtalk-hook
    spec:
      containers:
      - name: dingtalk-hook
        image: loveliuli/events-hub:v0.30
        imagePullPolicy: IfNotPresent
        ports:
        - containerPort: 5000
          name: http
        resources:
          requests:
            cpu: 50m
            memory: 100Mi
          limits:
            cpu: 50m
            memory: 100Mi

---
apiVersion: v1
kind: Service
metadata:
  name: dingtalk-hook
  namespace: monitoring
spec:
  type: NodePort
  selector:
    app: dingtalk-hook
  ports:
  - name: hook
    port: 5000
    targetPort: http

  以上name命名可能有点误导,其实和钉钉毫无关系。

6、应用配置

kubectl apply -f dingtalk-webhook-flask.yaml

  应用配置后,我们即可查看启动情况:

 

 

7、配置alertmanager

global:
  resolve_timeout: 5m

templates:     ##消息模板
  - '*.tmpl'

route:
  group_by: ['alertname','job']
  group_wait: 10s
  group_interval: 10s
  repeat_interval: 1m
  receiver: 'webhook'

receivers:
- name: 'webhook'
  webhook_configs:
 - url: 'http://dingtalk-hook:5000'
    send_resolved: true

  

8、更新告警文件

# 先将之前的 secret 对象删除
$ kubectl delete secret alertmanager-main -n monitoring
secret "alertmanager-main" deleted

# 创建新的secret对象
$ kubectl create secret generic alertmanager-main --from-file=alertmanager.yaml -n monitoring
secret "alertmanager-main" created

  注意:我们每次更新alertmanager的配置文件,都必须更新告警文件,才能生成最新的配置。

 

9、测试告警

不出意外的话,你将会看到如下log信息,那就表示成功了。

 

 

第三方系统接收信息:

 

 通过第三方系统和自己企业的短信、内部系统对接,就非常简单了!

posted @ 2019-09-11 16:26  skyflask  阅读(6997)  评论(3编辑  收藏  举报