下面主要以四个方面展开讨论:
- agent部署,监控 agent 在多云环境多种不同中间件维护方式下,如何部署?
- 统一采集,不同类型中间件的监控数据如何统一采集?
- 标签统一,不同类型的metrics如何统一处理,确保监控视图/告警能够路由至正确的业务团队?
- 安全采集,对于需要auth的中间件,agent需要有独立的账号密码才能够采集到监控指标,账号密码如何加密保障安全?
2. 优化之前采用 exporter
2.1 agent部署
基于混合云架构下,对于相同的中间件,不同业务组之间使用的方式是迥异的。例如mysql,A业务选择了云厂提供的托管RDS,而B业务会选择服务器上自建MySQL 使用mysql_exporter进行指标采集时,原生组件并不能提供一对多的方式,即单个exporter只能够采集单个数据库资源的指标。对于自建MySQL,我们将exporter部署在了中间件所在的服务器上;而对于云厂托管RDS,我们在每个VPC下选择了一台服务器,在这台机器上启动不同的exporter进程以监控多实例 因agent部署方式不统一,增大了当资源变更时的运维成本,对于监控的发现/下线等配置文件都需要人工维护。尽管使用了ansible编排监控配置文件,但是对于不同部署方式的资源,需要编写多套playbook提供支撑
2.2 统一采集
各类不同中间件采用不同的监控agent,不同的agent使用逻辑也是迥异的,例如node_exporter是将实例信息通过file_sd方式写入target到prometheus中读取,而pika_exporter却是将实例信息维护在一个单独的配置文件中,由agent直接读取配置抓取数据,prometheus只需要配置job
- node_exporter
[root@* ~]# cat /etc/prometheus/file_sd/node.yml |head -n 10
- labels:
public_cloud: "huawei" region: "***" team_id: "***" team_name: "***" host_name: "***" host_ip: "1.1.1.1"targets:
- 1.1.1.1:9100
[root@ ~]# cat /var/lib/pika_exporter/pika.host
- job_name: "node_exporter" file_sd_configs:
- files:
- "/etc/prometheus/file_sd/node*.yml"
- pika_exporter
[root@ ~]# cat /var/lib/pika_exporter/pika.host
1.1.1.1:6300,passwd,cluster_name
[root@ ~]# cat/etc/prometheus/prometheus.yml
- job_name: 'pika_exporter' scrape_interval: 30s
static_configs:
- targets: ['127.0.0.1:9099']
当agent类型有数十种时,运维成本急剧升高,工作变为由经验和人力堆积的苦力活被监控资源类型:
- 采集器
- 服务器 node_exporter
- redis redis_exporter
- mysql mysql_exporter
- mongodb
- mongo_exporter
- ... ...
2.3 标签统一
对于每个metrics,我们期望能够进行溯源,定位到具体的业务下,这样在监控视图/告警时,才能够精确定位到团队,让团队聚焦于自己的监控告警。底层标签的统一也方便了后续的上层运维应用能够更好的抽象各类不同业务特性。使用prometheus,针对job或者job下的target附加业务相关lable,例如 team_id=***,team_name=***
标签如何配置
回到上面说的问题,以MySQL为例,单个云厂的RDS实例需要启用单独的expoter进程采集数据,那么在prometheus配置时,lable只能附加在job层级。对于云厂提供的托管RDS/Redis/Mongo 等实例,部分宿主机相关指标,我们无法通过exporter进行采集。exporter采集的是中间件接口接口返回的数据,不具备采集中间件所在的宿主机指标的能力。例如无法获取到CPU使用率/磁盘使用率/磁盘IOPS等指标 同时,对于一些资源指标,我们也无法使用社区的exporter进行收集,例如 LB/VPC 等相关云原生组件 当然,成熟的云厂会提供API或者它们定制的exporter用以获取监控数据,但是metric/lable 与社区exporter完全不一致。即使我们能够通过云厂exporter获取到数据,但是并不能够将lable使用prometheus精确的附加在每一个资源上。例如AWS提供的cloud watch,对接在prometheus时不需要配置target,那么lable只能够写在job层对所有资源附加相同的lable,不能满足我们的需求
如果不能打平配置上的差异与使用不同方式获取到的metric/lable的差异,不仅提高了运维复杂性,对于相同中间件的监控/告警 体验是割裂开的,不够完美。
2.4 安全采集
对于需要auth才能够使用的中间件,我们需要维护一份密码配置文件供exporter使用,而在服务器上明文保存密码是不安全的
3. 优化之后采用 telegraf 采集
使用telegraf解决痛点 参考链接:https://github.com/influxdata/telegraf
3.1 agent部署 & 统一采集
对于常见的中间件资源,telegraf社区均已适配,可实现由统一的telegraf二进制包,同时启动不同的systemd管理不同类型的中间件监控agent 并且telegraf input原生支持一对多,单机部署即可满足对所有中间件资源的监控指标抓取
[root@ ~]# systemctl status telegraf-telegraf-mongo.service telegraf-mysql.service telegraf-pika.service telegraf-redis.service
[root@ ~]# cat /etc/prometheus/prometheus.yml
- job_name: "telegraf-mysql" scrape_interval: 15s
metrics_path: "/metrics" static_configs:
- targets:
- 127.0.0.1:9274
- job_name: "telegraf-pika" scrape_interval: 15s
metrics_path: "/metrics" static_configs:
- targets:
- 127.0.0.1:9275
- job_name: "telegraf-mongo" scrape_interval: 15s
metrics_path: "/metrics" static_configs:
- targets:
- 127.0.0.1:9280
[root@ ~]# cat /etc/systemd/system/telegraf-mysql.service
[Unit]
Description=Telegraf Exporter
After=network.target
[Service]
WorkingDirectory=/opt/apps/telegraf-mysql
ExecStart=/usr/local/bin/telegraf --config /opt/apps/telegraf-mysql/telegraf.conf --config-directory /opt/apps/telegraf-mysql/telegraf.d
Restart=on-failure
[Install]
WantedBy=multi-user.target
3.2 标签统一
telegraf的processors支持value mapping,可以依据已经存在的key-value映射新的lables到metrics中 参考链接:https://docs.influxdata.com/telegraf/v1.23/configuration/#metric-filtering
此处我们使用mapping构造了 team_id,team_name,instance_name三个lable,它会查询所有抓取到的 mysql metrics中的lable,若存在server=1.1.1.1,则映射上述三个指定的key-values到metrics中 配置文件
[root@ ~]# cat /opt/apps/telegraf-mysql/telegraf.conf
[global_tags] region = "***"
[agent]
interval = "10s" round_interval = true metric_batch_size = 1000 metric_buffer_limit = 10000 collection_jitter = "0s" flush_interval = "10s" flush_jitter = "0s" precision = "0s" hostname = "" omit_hostname = false [[outputs.prometheus_client]]
listen = ":9274"
[[inputs.mysql]]
gather_global_variables = true gather_slave_status = true interval_slow="10s" servers = ["username:password@tcp(1.1.1.1:3306)/"]
[[processors.enum]]
[[processors.enum.mapping]]
tag = "server" dest = "team_id" default = "null" [processors.enum.mapping.value_mappings]
"1.1.1.1:3306" = "123"
[[processors.enum]]
[[processors.enum.mapping]]
tag = "server" dest = "team_name" default = "null" [processors.enum.mapping.value_mappings]
"1.1.1.1:3306" = "test-team"
[[processors.enum]]
[[processors.enum.mapping]]
tag = "server" dest = "instance_name" default = "null" [processors.enum.mapping.value_mappings]
"1.1.1.1:3306" = "test-instance"
测试
[root@ ~]# curl 127.0.0.1:9274/metrics|grep mysql_up{
mysql_up{instance_name="test-instance",region="***",server="1.1.1.1:3306",team_id="123",team_name="test-team"} 1
而配置文件的生成,需要编写脚本去资源中心获取到具体的实例信息,进行自动渲染。从而实现监控的自动发现。这依赖于运维需要有一个统一的资源平台能够对内服务,不多赘述。当使用同一个监控agent时,脚本的维护才会简单,否则不同类型的中间件监控都需要编写不同脚本来实现自动发现。
同时,telegraf支持多种不同的input数据输入 对于aws cloud watch或者华为云的cloudeye,我们可以将他们先以job方式在prometheus抓取数据,此时不进行lable增添 而后通过telegraf的mapping和input prometheus data,利用从资源中心获取到的key-valus,进行数据的二次格式化增加需要的lable,实现标签的统一 参考链接:https://docs.influxdata.com/telegraf/v1.23/data_formats/input/
3.3 安全采集
可惜的是,telegraf原生也不支持对密码的加密 好处是,telegraf各个组件代码风格是统一的,不像各类exporter。对于telegraf的二次开发,只要实现对某个INPUT模块的密码编码解码,可以很快复用到其他INPUT模块,高效实现各个不同中间件在使用监控时的密码安全
4. 总结
本文是近期将监控采集器从 exporter 迁移到 telegraf 的一次总结,主要从 agent 部署、统一采集、标签统一、安全采集四个方面,比较了优化前后的差异。
但 telegraf 也存在一些问题,telegraf 原生支持二百余个模块,同时提供各类高级功能,实际使用中,发现某些模块抓取的指标并不令人满意。例如mysql_exporter中的up指标(探活),telegraf未进行采集 使用时可按需裁剪,保留需要的模块,否则使用起来较重(二进制几百M)。对于更多高级用法,需要进行一定的二次开发才能更好适配业务需求。同时 telegraf 的 Grafana 面板较少,因此我们需要花费点时间手工绘制。