写点什么

BAT 大厂大佬教你:Docker 部署 Prometheus+Grafana 监控系统

  • 2022 年 4 月 19 日
  • 本文字数:6867 字

    阅读完需:约 23 分钟

可以看到,Prometheus 添加的 cadvisor 状态为 UP,说明正常接收数据。


部署 Redis 监控组件

容器部署 Redis 服务监控组件 redis_exporter,--redis.passwd 指定认证口令,如果你的 redis 访问没有密码那么就无需指定后面参数。


$ docker run -d -h redis_exporter139-218 --name redis_exporter139-218 --network trust139 --ip=10.1.139.218 -m 8g --cpus=4 oliver006/redis_exporter --redis.passwd 123456


在 prometheus.yml 添加 redis-exporter




  • job_name: 'Redis-exporter' #exporter 地址 static_configs:

  • targets: ['10.2.139.218:9121'']labels:appname: 'redis-exporter'

  • job_name: 'RedisProxy' #需要监控的 redis 地址 static_configs:

  • targets:

  • redis://10.2.139.70:6379

  • redis://10.2.139.71:6379labels:appname: RedisProxymetrics_path: /scraperelabel_configs:

  • source_labels: [address]target_label: __param_target

  • source_labels: [__param_target]target_label: instance

  • target_label: addressreplacement: 10.2.139.218:9121


然后热加载更新,步骤同上。

部署应用监控组件

中间件部署 JVM 监控组件 jmx_exporter, 这种方式是适用于代码中没有暴露应用 metrics 信息的服务,无需进行代码改动,在应用启动时调用该 jar 包暴露 jmx 信息,然后在 Prometheus 分别指定应用的地址即可。


首先下载 jar :https://github.com/prometheus/jmx_exporter(jmx_prometheus_javaagent-0.11.0.jar )


下载配置文件,有 tomcat 和 weblogic 注意区分:https://github.com/prometheus/jmx_exporter/tree/master/example_configs


然后在中间件启动参数添加以下内容,指定配置文件和 jar 包的路径:


CATALINA_OPTS="-javaagent:/app/tomcat-8.5.23/lib/jmx_prometheus_javaagent-0.11.0.jar=12345:/app/tomcat-8.5.23/conf/config.yaml"


上面我指定暴露 metrics 信息的端口为 12345,所以我们在 prometheus.yml 文件中添加即可:




  • job_name: 'MIDL'static_configs:

  • targets: ['192.168.166.18:12345','192.168.166.19:12345']labels:appname: 'ORDER'

  • targets: ['10.2.139.111:12345','10.2.139.112:12345']labels:appname: 'WEB'


其他步骤同上,Prometheus 热加载更新即可。

部署进程监控组件

因为我们容器是使用单独的网络部署的,相当于胖容器的方式,所以需要在监控的容器中部署 process-exporter 进程监控组件来监控容器的进程,


软件包下载:


wget https://github.com/ncabatoff/process-exporter/releases/download/v0.5.0/process-exporter-0.5.0.linux-amd64.tar.gz


配置文件:process-name.yaml


process_names:


  • name: "{{.Matches}}"


cmdline:


  • 'redis-shake' #匹配进程,支持正则


启动参数:


$ nohup ./process-exporter -config.path process-name.yaml &


在 Prometheus.yml 添加该容器的 IP 地址,端口号为 9256




  • job_name: 'process'static_configs:

  • targets: [ '10.2.139.186:9256']labels:appname: 'Redis-shake'


ok,现在我们热加载更新 Prometheus 的主机文件


$ curl -X POSThttp://10.2.139.210:9090/-/reload

部署 Alertmanager 报警组件

Alertmanager 概述 Alertmanager 处理客户端应用程序(如 Prometheus 服务器)发送的告警。它负责对它们进行重复数据删除,分组和路由,以及正确的接收器集成,例如电子邮件,PagerDuty 或 OpsGenie。它还负责警报的静默和抑制。


以下描述了 Alertmanager 实现的核心概念。请参阅配置文档以了解如何更详细地使用它们。


1.分组(Grouping)


  • 分组将类似性质的告警分类为单个通知。这在大型中断期间尤其有用,因为许多系统一次失败,并且可能同时发射数百到数千个警报。

  • 示例:发生网络分区时,群集中正在运行数十或数百个服务实例。一半的服务实例无法再访问数据库。Prometheus 中的告警规则配置为在每个服务实例无法与数据库通信时发送告警。结果,数百个告警被发送到 Alertmanager。

  • 作为用户,只能想要获得单个页面,同时仍能够确切地看到哪些服务实例受到影响。因此,可以将 Alertmanager 配置为按群集和 alertname 对警报进行分组,以便发送单个紧凑通知。

  • 这些通知的接收器通过配置文件中的路由树配置告警的分组,定时的进行分组通知。


2.抑制(Inhibition)


  • 如果某些特定的告警已经触发,则某些告警需要被抑制。

  • 示例:如果某个告警触发,通知无法访问整个集群。Alertmanager 可以配置为在该特定告警触发时将与该集群有关的所有其他告警静音。这可以防止通知数百或数千个与实际问题无关的告警触发。


3.静默(SILENCES)


  • 静默是在给定时间内简单地静音告警的方法。基于匹配器配置静默,就像路由树一样。检查告警是否匹配或者正则表达式匹配静默。如果匹配,则不会发送该告警的通知。在 Alertmanager 的 Web 界面中可以配置静默。


4.客户端行为(Client behavior)


  • Alertmanager 对其客户的行为有特殊要求。这些仅适用于不使用 Prometheus 发送警报的高级用例。#制作镜像方式和 Prometheus 类似,稍作更改即可,此步省略。


设置警报和通知的主要步骤如下:


  • 设置并配置 Alertmanager;

  • 配置 Prometheus 对 Alertmanager 访问;

  • 在普罗米修斯创建警报规则;

部署 Alertmanager 组件

首先需要创建 Alertmanager 的报警通知文件,我这里使用企业微信报警,其中企业微信需要申请账号认证,方式如下:


  • 访问网站注册企业微信账号(不需要企业认证)。

  • 访问 apps 创建第三方应用,点击创建应用按钮 -> 填写应用信息:

  • 创建报警组,获取组 ID:

  • 新建 alertmanager.yml 报警通知文件


global:resolve_timeout: 2msmtp_smarthost: smtp.163.com:25smtp_from: 15xxx@163.comsmtp_auth_username: 15xxxx@163.comsmtp_auth_password: zxxx


templates:


  • '/data/alertmanager/conf/template/wechat.tmpl'route:group_by: ['alertname_wechat']group_wait: 1sgroup_interval: 1sreceiver: 'wechat'repeat_interval: 1hroute Java 开源项目【ali1024.coding.net/public/P7/Java/git】 s:

  • receiver: wechatmatch_re:serverity: wechatreceivers:

  • name: 'email'email_configs:

  • to: '8xxxxx@qq.com'send_resolved: true

  • name: 'wechat'wechat_configs:

  • corp_id: 'wwd402ce40b4720f24'to_party: '2'agent_id: '1000002'api_secret: '9nmYa4p12OkToCbh_oNc'send_resolved: true ## 发送已解决通知


参数说明:


corp_id: #企业微信账号唯一 ID, 可以在我的企业中查看。to_party: #需要发送的组。agent_id: #第三方企业应用的 ID,可以在自己创建的第三方企业应用详情页面查看。api_secret: #第三方企业应用的密钥,可以在自己创建的第三方企业应用详情页面查看。


然后我们创建企业微信的消息模板,template/wechat.tmpl


{{ define "wechat.default.message" }}{{ range alert :=.Alerts }}


【系统报警】告警状态:{{ .Status }}告警级别:{{ alert.Labels.severity }}告警应用:{{ alert.Annotations.summary }}告警详情:{{ alert.Annotations.description }}触发阀值:{{ alert.Annotations.value }}告警主机:{{ alert.Labels.instance }}告警时间:{{ alert.StartsAt.Format "2006-01-02 15:04:05" }}{{ end }}{{ end }}


这个报警的模板其中的值是在 Prometheus 触发的报警信息中提取的,所以你可以根据自己的定义进行修改。


运行 Alertmanager 容器


$ docker run -d -p 9093:9093 --name alertmanager -m 8g --cpus=4 -v /opt/alertmanager.yml:/etc/alertmanager/alertmanager.yml -v /opt/template:/etc/alertmanager/template docker.io/prom/alertmanager:latest


容器运行完成后查看 web 页面 IP:9093


配置报警规则

Prometheus 的报警规则通过 PromQL 语句编写


进入 Prometheus 容器的 rules 目录,上面我们制作镜像的时候已经创建好并挂载到了容器中,现在我们编写其他的规则文件


编写主机监控规则文件,rules/host_sys.yml


cat host_sys.ymlgroups:


  • name: Hostrules:

  • alert: HostMemory Usageexpr: (node_memory_MemTotal_bytes - (node_memory_MemFree_bytes + node_memory_Buffers_bytes + node_memory_Cached_bytes)) / node_memory_MemTotal_bytes * 100 > 90for: 1mlabels:name: Memoryseverity: Warningannotations:summary: " {{ labels.appname }} "description: "宿主机内存使用率超过90%."value: "{{ value }}"

  • alert: HostCPU Usageexpr: sum(avg without (cpu)(irate(node_cpu_seconds_total{mode!='idle'}[5m]))) by (instance,appname) > 0.8for: 1mlabels:name: CPUseverity: Warningannotations:summary: " {{ labels.appname }} "description: "宿主机CPU使用率超过80%."value: "{{ value }}"

  • alert: HostLoadexpr: node_load5 > 20for: 1mlabels:name: Loadseverity: Warningannotations:summary: "{{ labels.appname }} "description: " 主机负载5分钟超过20."value: "{{ value }}"

  • alert: HostFilesystem Usageexpr: (node_filesystem_size_bytes-node_filesystem_free_bytes)/node_filesystem_size_bytes*100>80for: 1mlabels:name: Diskseverity: Warningannotations:summary: " {{ labels.appname }} "description: " 宿主机 [ {{ labels.mountpoint }} ]分区使用超过 80%."value: "{{ $value }}%"

  • alert: HostDiskio writesexpr: irate(node_disk_writes_completed_total{job=~"Host"}[1m]) > 10for: 1mlabels:name: Diskioseverity: Warningannotations:summary: " {{ $labels.app 《一线大厂 Java 面试题解析+后端开发学习笔记+最新架构讲解视频+实战项目源码讲义》开源 name }} "description: " 宿主机 [{{ labels.device }}]磁盘1分钟平均写入IO负载较高."value: "{{ value }}iops"

  • alert: HostDiskio readsexpr: irate(node_disk_reads_completed_total{job=~"Host"}[1m]) > 10for: 1mlabels:name: Diskioseverity: Warningannotations:summary: " {{ labels.appname }} "description: " 宿机 [{{ labels.device }}]磁盘 1 分钟平均读取 IO 负载较高."value: "{{ $value }}iops"

  • alert: HostNetwork_receiveexpr: irate(node_network_receive_bytes_total{device!~"lo|bond[0-9]|cbr[0-9]|veth.|virbr.|ovs-system"}[5m]) / 1048576 > 10for: 1mlabels:name: Network_receiveseverity: Warningannotations:summary: " {{ labels.appname }} "description: " 宿主机 [{{ labels.device }}] 网卡 5 分钟平均接收流量超过 10Mbps."value: "{{ $value }}3Mbps"

  • alert: hostNetwork_transmitexpr: irate(node_network_transmit_bytes_total{device!~"lo|bond[0-9]|cbr[0-9]|veth.|virbr.|ovs-system"}[5m]) / 1048576 > 10for: 1mlabels:name: Network_transmitseverity: Warningannotations:summary: " {{ labels.appname }} "description: " 宿主机 [{{ labels.device }}] 网卡 5 分钟内平均发送流量超过 10Mbps."value: "{{ $value }}3Mbps"


编写容器监控规则文件,rules/container_sys.yml


groups:


  • name: Containerrules:

  • alert: ContainerCPUexpr: (sum by(name,instance) (rate(container_cpu_usage_seconds_total{image!=""}[5m]))*100) > 200for: 1mlabels:name: CPU_Usageseverity: Warningannotations:summary: "{{ labels.name }} "description: " 容器CPU使用超200%."value: "{{ value }}%"

  • alert: Memory Usageexpr: (container_memory_usage_bytes{name=~".+"} - container_memory_cache{name=~".+"}) / container_spec_memory_limit_bytes{name=~".+"} * 100 > 200for: 1mlabels:name: Memoryseverity: Warningannotations:summary: "{{ labels.name }} "description: " 容器内存使用超过200%."value: "{{ value }}%"

  • alert: Network_receiveexpr: irate(container_network_receive_bytes_total{name=~".+",interface=~"eth.+"}[5m]) / 1048576 > 10for: 1mlabels:name: Network_receiveseverity: Warningannotations:summary: "{{ labels.name }} "description: "容器 [{{ labels.device }}] 网卡 5 分钟平均接收流量超过 10Mbps."value: "{{ $value }}Mbps"

  • alert: Network_transmitexpr: irate(container_network_transmit_bytes_total{name=~".+",interface=~"eth.+"}[5m]) / 1048576 > 10for: 1mlabels:name: Network_transmitseverity: Warningannotations:summary: "{{ labels.name }} "description: "容器 [{{ labels.device }}] 网卡 5 分钟平均发送流量超过 10Mbps."value: "{{ $value }}Mbps"


编写报警规则可以参考后面 Grafana 展示看板后的数据展示语句,需要注意的是,我们容器使用的是胖容器的方式,即当作虚拟机来使用,所以需要添加应用和服务停止的 Exporter,如果你的容器守护进程直接就是应用的话,只需要监控容器的启停就可以了。

测试微信报警

Grafana 展示组件

虽然 Prometheus 提供的 Web UI 也可以很好的查看不同指标的视图,但是这个功能非常简单,只适合用来调试。要实现一个强大的监控系统,还需要一个能定制展示不同指标的面板,能支持不同类型的展现方式(曲线图、饼状图、热点图、TopN 等),这就是仪表盘(Dashboard)功能。


Prometheus 开发了一套仪表盘系统 PromDash,不过很快这套系统就被废弃了,官方开始推荐使用 Grafana 来对 Prometheus 的指标数据进行可视化,这不仅是因为 Grafana 的功能非常强大,而且它和 Prometheus 可以完美的无缝融合。


Grafana 是一个用于可视化大型测量数据的开源系统,它的功能非常强大,界面也非常漂亮,使用它可以创建自定义的控制面板,你可以在面板中配置要显示的数据和显示方式,它支持很多不同的数据源,比如:Graphite、InfluxDB、OpenTSDB、Elasticsearch、Prometheus 等,而且它也支持众多的插件 。

部署 Grafana 服务容器

$ docker run -d -h grafana139-211 -m 8g --network trust139 --ip=10.2.139.211 --cpus=4 --name=grafana139-211 -e "GF_SERVER_ROOT_URL=http://10.2.139.211" -e "GF_SECURITY_ADMIN_PASSWORD=passwd" grafana/grafana


运行后访问 IP:3000,user:admin pass:passwd


添加 Prometheus 数据源

导入监控模板

使用编号导入模板,Grafana 服务需要联网,否则需要到 Grafana 模板下载 JSON 文件导入。



下面是我使用的几个模板,导入后可以根据自己的情况定义变量值



主机监控展示看板 Node-exporter 导入 8919 模板容器监控展示看板 cadvisor-exporter 导入 193 模板应用监控展示看板 jmx-exporter 导入 8563 模板 Redis 监控展示看板 Redis-exporter 导入 2751 模板进程监控展示看板 Process-exporter 导入 249 模板

使用 Concul HTTP 注册方式实现服务发现

一般是用服务发现需要应用需要服务注册,我们这边因为微服务改造还没完成,还有一些 tomcat 和 weblogic 中间件,而且选用的注册中心是 Eurka,所以为了在代码不改动的情况下使用服务发现,选择了 concul 作为注册中心,因为是 consul 是可以通过 http 方式注册的。


consul 内部原理



Consul 分为 Client 和 Server 两种节点(所有的节点也被称为 Agent),Server 节点保存数据,Client 负责健康检查及转发数据请求到 Server;Server 节点有一个 Leader 和多个 Follower,Leader 节点会将数据同步到 Follower,Server 的数量推荐是 3 个或者 5 个,在 Leader 挂掉的时候会启动选举机制产生一个新的 Leader。


集群内的 Consul 节点通过 gossip 协议(流言协议)维护成员关系,也就是说某个节点了解集群内现在还有哪些节点,这些节点是 Client 还是 Server。单个数据中心的流言协议同时使用 TCP 和 UDP 通信,并且都使用 8301 端口。跨数据中心的流言协议也同时使用 TCP 和 UDP 通信,端口使用 8302。


集群内数据的读写请求既可以直接发到 Server,也可以通过 Client 使用 RPC 转发到 Server,请求最终会到达 Leader 节点,在允许数据轻微陈旧的情况下,读请求也可以在普通的 Server 节点完成,集群内数据的读写和复制都是通过 TCP 的 8300 端口完成。


具体 consul 的原理及架构请访问:http://blog.didispace.com/consul-service-discovery-exp/

使用 docker 部署 consul 集群

#启动第 1 个 Server 节点,集群要求要有 3 个 Server,将容器 8500 端口映射到主机 8900 端口,同时开启管理界面


docker run -d --name=consul1 -p 8900:8500 -e CONSUL_BIND_INTERFACE=eth0 consul agent --server=true --bootstrap-expect=3 --client=0.0.0.0 -ui


#启动第 2 个 Server 节点,并加入集群 docker run -d --name=consul2 -e CONSUL_BIND_INTERFACE=eth0 consul agent --server=true --client=0.0.0.0 --join 172.17.0.1


#启动第 3 个 Server 节点,并加入集群 docker run -d --name=consul3 -e CONSUL_BIND_INTERFACE=eth0 consul agent --server=true --client=0.0.0.0 --join 172.17.0.2


#启动第 4 个 Client 节点,并加入集群 docker run -d --name=consul4 -e CONSUL_BIND_INTERFACE=eth0 consul agent --server=false --client=0.0.0.0 --join 172.17.0.2


浏览器访问容器映射的 8900 端口:[图片上传失败...(image-3abe6a-1619340200641)]

服务注册到 Consul

最后

面试是跳槽涨薪最直接有效的方式,马上金九银十来了,各位做好面试造飞机,工作拧螺丝的准备了吗?


掌握了这些知识点,面试时在候选人中又可以夺目不少,暴击 9999 点。机会都是留给有准备的人,只有充足的准备,才可能让自己可以在候选人中脱颖而出。




用户头像

还未添加个人签名 2022.04.13 加入

还未添加个人简介

评论

发布
暂无评论
BAT大厂大佬教你:Docker部署Prometheus+Grafana监控系统_Java_爱好编程进阶_InfoQ写作平台