微服务实例监控

145 阅读4分钟

微服务实例监控

1.现状&背景
1.1 背景

​ 事故一:资料微服务,双节点实例,宕机了一个实例,已经宕机了24小时了,但并未发觉,到第二天高峰期时,单节点抗压不住,导致资料列表和详情接口报大量的缓慢。

​ 事故二:计费服务,双节点实例,其中一个节点元空间溢出,节点假死,导致下载结算相关业务一直处于等待中,影响到了用户正常使用。

​ 基于以上线上事故,我们缺乏一个对服务实例级别的监控,能够监控实例的存活状态资源使用情况,在服务实例状态异常或者资源使用即将饱和时,能够提前进行预警,进行人工干预。

1.2 现状

​ 目前我们是基于Prometheus进行指标收集,已经收集了JVM相关的指标,以及基于Consul监控了实例的健康状态,但是我们目前使用的却是Grafana告警,Grafana只能针对每一个具体的实例才能添加告警,并且不支持动态变量的方式,我们的面板都是通过变量的方式动态创建的,所以Grafana告警并不适用于我们,即使适用,我们的创建告警成本很高。为了对所有服务实例进行统一的一套实例级别的告警规则,所以采用Prometheus+AlertManager+Webhook的方式进行更灵活的的告警。

2.定义监测指标

(1)告警级别

​ 告警级别暂分为:警告,严重。

(2)告警指标

​ 服务存活监控:服务宕机时间持续1min,即触发告警(严重)。

​ JVM堆内存使用率:JVM堆内存使用率持续1min超过50%(警告),JVM堆内存使用率持续1min超过80%(严重)。

​ JVM元空间使用率:JVM元空间使用率持续1min超过80%(严重)。

​ 系统CPU使用率:系统cpu使用率在连续5min内,超过80%(严重)。

3.系统架构

4.环境搭建
4.1 升级prometheus到2.31.1
cd /dataes/prometheus-2.31.1

touch start.sh

## prometheus的启动脚本
nohup ./prometheus --config.file=prometheus.yml --web.enable-lifecycle --web.max-connections=512 --storage.tsdb.retention.time=15d --query.timeout=2m --query.max-concurrency=20 --web.read-timeout=5m --web.external-url=http://10.1.25.34:9090 > ./logs/start.log 2>&1 &

## 访问地址
http://10.1.25.34:9090

## 配置重载
curl -v --request POST 'http://localhost:9090/-/reload'
4.2 升级grafana到8.3.2
cd /dataes/grafana-8.3.2

touch start.sh

## 启动grafana
nohup ./bin/grafana-server web > ./logs/start.log 2>&1 &

## 访问地址
http://10.1.25.34:3000
4.3 搭建alertmanager-0.20.0
cd /dataes/alertmanager-0.20.0

touch start.sh

## 启动告警服务
nohup ./alertmanager --config.file=alertmanager.yml  > ./logs/start.log 2>&1 &

## 访问地址
http://10.1.25.34:9093/

## 配置重载
curl -v --request POST 'http://localhost:9093/-/reload'
4.4 搭建prometheus-webhook-dingtalk-1.4.0
cd /dataes/prometheus-webhook-dingtalk-1.4.0

touch start.sh

## 启动dingtalk
nohup ./prometheus-webhook-dingtalk > ./start.log 2>&1 &
5.实施步骤
5.1 promethues.yml配置告警管理器和consul服务发现
# my global config
global: 
  scrape_interval: 15s # 设置抓取数据时间间隔为15s,不设置的话默认一分钟
  evaluation_interval: 15s # 设置分析数据时间间隔为15s,不设置的话默认一分钟
  # scrape_timeout is set to the global default (10s).

# 告警配置
alerting:
  alertmanagers:
    - static_configs:
        - targets:
          - 10.1.25.34:9093

# 告警规则配置
rule_files:
  - "rules/*.yml"
  # - "second_rules.yml"

# A scrape configuration containing exactly one endpoint to scrape:
# Here it's Prometheus itself.
# 监控数据拉取配置
scrape_configs:
  # The job name is added as a label `job=<job_name>` to any timeseries scraped from this config.
  - job_name: "prometheus"

    # metrics_path defaults to '/metrics'
    # scheme defaults to 'http'.

    static_configs:
      - targets: ["localhost:9090"]
      
# consul acl version for microservice 配置
  - job_name: 'zxxk_consul_microservice_acl'
    scrape_interval:     15s
    consul_sd_configs:
    - server: '10.1.25.52:9600'
      token: cff6f144-aa79-319d-7632-f62922536137
      datacenter: 'amc'
      refresh_interval: 5s
    relabel_configs:
    - source_labels: [__metrics_path__]
      regex: /metrics
      target_label: __metrics_path__
      replacement: /actuator/prometheus    # 必须这样否则会404
      action: replace

    - source_labels: [__meta_consul_tags]
      separator: ;
      regex: (.*)(,contextPath=)(.*)(,dubbo.metadata)(.*)
      target_label: __metrics_path__
      replacement: $3/actuator/prometheus # 必须这样否则会404
      action: replace      
# 单独openapi-settlement-admin一个应用在使用该匹配,项目下线后即可删除以下label重写
    - source_labels: [__meta_consul_tags]
      separator: ;
      regex: (.*)(,contextPath=/videoapi)(,)
      target_label: __metrics_path__
      replacement: /videoapi/actuator/prometheus # 必须这样否则会404
      action: replace

    - source_labels: [__meta_consul_tags]
      regex: (,)(.*)(,tag=)(dsp|bsp|site|app|openapi)(,)(.*)
      replacement: $4
      target_label: product

    - source_labels: [__meta_consul_tags]
      regex: (,)(.*)(,secure=false,)(.*)
      replacement: $2
      target_label: product

    - source_labels: [__meta_consul_dc]
      target_label: idc

    - source_labels: [__meta_consul_service]
      target_label: service

    - source_labels: [__meta_consul_service]
      target_label: service
      regex: .*consul.*
      action: drop

    - source_labels: [__meta_consul_service_address]
      target_label: host

    - source_labels: [__meta_consul_service_id]
      target_label: job
      
      
  # consul-self sever 配置
  - job_name: 'zxxk_linux_consul'
    scrape_interval:     30s
    metrics_path: "/v1/agent/metrics"
    params:
      format: ['prometheus']
    bearer_token: "026d869a-4d4c-91f9-e16e-4413d681d8d1"
    static_configs:
    - targets: ['10.1.1.25:9600','10.1.1.25:9500', '10.1.1.22:9600','10.1.1.22:9500','10.1.25.52:9600','10.1.1.36:9500']

5.2 编写告警规则app-rule.yml
groups:
  - name: "app"
    rules:
      # 告警名称 alertname
    - alert: "服务实例存活告警"   
      # 告警表达式,当表达式条件满足,即发送告警
      expr: up{idc="amc"} == 0
      # 等待时长,等待自动恢复的时间。
      for: 1m  
      # 此label不同于 metric中的label,发送给alertmanager之后用于管理告警项,比如匹配到那个label即触发哪种告警      
      labels:
        # key:value 皆可完全自定义
        severity: 严重   
      # 定义发送告警的内容,注意此地的labels为metric中的label
      annotations:     
         summary: "{{$labels.service}}"
         description: "{{$labels.service}}-{{$labels.instance}}:已停止运行,持续时间已超过1min"
         value: "已宕机"
         
    - alert: "CPU 使用率超过80%"
      expr: 100-(avg(rate(system_cpu_usage{idc="amc"}[5m])) by(host)* 100) > 80
      for: 1m
      labels:
        severity: 严重
      annotations:
        summary: "{{$labels.host}}"
        description: "{{$labels.host}} 宿主机5分钟内,CPU使用率超过80%,持续时间已超过1min"
        value: "{{$value}} %"
             
    - alert: "jvm堆内存使用率超过60%"
      expr: jvm_memory_used_bytes{idc="amc",area="heap"} / jvm_memory_max_bytes{idc="amc",area="heap"} * 100 >  60
      for: 1m
      labels:
        severity: 警告
      annotations:
        summary: "{{$labels.serveice}}"
        description:  "{{$labels.service}}-{{$labels.instance}} 堆内存使用率>60%, 持续时间已超过1min"
        value: "{{$value}} %"
        
    - alert: "jvm堆内存使用率超过80%"
      expr: jvm_memory_used_bytes{idc="amc",area="heap"} / jvm_memory_max_bytes{idc="amc",area="heap"} * 100 >  80
      for: 1m
      labels:
        severity: 严重
      annotations:
        summary: "{{$labels.serveice}}"
        description:  "{{$labels.service}}-{{$labels.instance}} 堆内存使用率>80%, 持续时间已超过1min"
        value: "{{$value}} %"
        
    - alert: "jvm元空间使用率超过80%"
      expr: jvm_memory_used_bytes{idc="amc",area="nonheap",id="Metaspace"} / jvm_memory_max_bytes{idc="amc",area="nonheap",id="Metaspace"} * 100 >  80
      for: 1m
      labels:
        severity: 警告
      annotations:
        summary: "{{$labels.serveice}}"
        description:  "{{$labels.service}}-{{$labels.instance}} 元空间使用率>80%, 持续时间已超过1min"
        value: "{{$value}} %"            
5.3 告警管理器alertmanager.yml配置
global:
  resolve_timeout: 5m  #每5分钟检查一次状态是否恢复
route:
  group_by: ['alertname'] #采用哪个标签来作为分组依据
  group_wait: 10s # 等待多长时间进行汇总发送
  group_interval: 5m  #相同组之间发生告警通知的时间间隔
  repeat_interval: 10m  #重复报警间隔时间
  receiver: 'web.hook'  #配置的默认的告警消息接受者信息,例如常用的 email、wechat、slack、webhook 等消息通知方式。
  #子路由,子路由的配置会覆盖默认路由,默认路由的配置会被子路由继承
  routes:
  - receiver: app_dingding

# 接收人列表      
receivers:
- name: 'app_dingding'
  webhook_configs:
  - send_resolved: true  #警报被解决之后是否通知
    url: 'http://localhost:8060/dingtalk/app-webhook/send'

# 例如:当另一个告警的级别并且告警标签中的instance值跟alertName相同,则进行抑制
inhibit_rules: # 抑制规则配置,当存在与另一组匹配的警报(源)时,抑制规则将禁用与一组匹配的警报(目标)。
  - source_match:
      alertName: 'alertName'
      severity: 'critical'
    target_match:
      severity: 'critical'
    equal: ['instance'] 
5.4 prometheus-webhook-dingtalk的config.yml配置
## Request timeout
# timeout: 5s

## Customizable templates path
templates:       
  - templates/app-dingding.tmpl

## Targets, previously was known as "profiles"
targets:
  app-webhook:
    url: https://oapi.dingtalk.com/robot/send?access_token=fe0bcdb63cb07a2946dc76fd094d081ef34c1a9961a546aaff5c72b4bf016b83
    secret: SEC351f9035d8ac2129259bdf9369639757a43476b63813dadead09de5137967304
    message:
      # Use legacy template
      #title: '{{ template "legacy.title" . }}'
      text: '{{ template "app-dingding" . }}' 
5.5 告警提示信息模板app-dingding.tmpl
{{ define "app-dingding" }}
{{ range $i, $alert :=.Alerts }}
【系统报警】
告警状态:{{   .Status }} 
告警级别:{{ $alert.Labels.severity }} 
告警应用:{{ $alert.Annotations.summary }}
告警详情:{{ $alert.Annotations.description }}
当前值:{{ $alert.Annotations.value }}
告警主机:{{ $alert.Labels.host }}
告警时间:{{ $alert.StartsAt.Format "2006-01-02 15:04:05" }}
{{ end }}
{{ end }}
6. 效果展示
(1)Prometheus的规则展示

app-rule.jpg

(2)Alertmanager告警展示

alert.jpg

(3)钉钉群消息

message-down1.jpg

message-cpu.jpg

7. 下一步计划

​ 1.Prometheus指标丰富,增加更多的关键性指标,流量预警等。

​ 2.告警路由细化,可以根据监控对象的业务标签,分组路由到不同的钉钉群。

​ 3.钉钉通知自动化,可以自动通知项目组或者业务组的主要@负责人。