Open-Falcon简介
介绍
- 监控系统是整个运维环节,乃至整个产品生命周期中最重要的一环,事前及时预警发现故障,事后提供翔实的数据用于追查定位问题。
- 监控系统作为一个成熟的运维产品,业界有很多开源的实现可供选择。当公司刚刚起步,业务规模较小,运维团队也刚刚建立的初期,选择一款开源的监控系统,是一个省时省力,效率最高的方案。
- 之后,随着业务规模的持续快速增长,监控的对象也越来越多,越来越复杂,监控系统的使用对象也从最初少数的几个SRE,扩大为更多的DEVS,SRE。 这时候,监控系统的容量和用户的“使用效率”成了最为突出的问题。
- 监控系统业界有很多杰出的开源监控系统。我们在早期,一直在用zabbix,不过随着业务的快速发展,以及互联网公司特有的一些需求,现有的开源的监控系统在性能、扩展性、和用户的使用效率方面,已经无法支撑了。
- 因此,我们在过去的一年里,从互联网公司的一些需求出发,从各位SRE、SA、DEVS的使用经验和反馈出发,结合业界的一些大的互联网公司做监控,用监控的一些思考出发,设计开发了小米的监控系统:open-falcon。
Open-Falcon特点
- 强大灵活的数据采集: 自动发现,支持falcon-agent、snmp、支持用户主动push、用户自定义插件支持,opentsdb data model like (timestamp、endpoint、metric、key-value tags)
- 水平扩展能力: 支持每个周期上亿次的数据采集、告警判定、历史数据存储和查询.
- 高效率的告警策略管理: 高效的portal、支持策略模板、模板集成和覆盖、多种告警方式、支持callback调用.
- 人性化的告警设置: 最大告警次数、告警级别、告警恢复通知、告警暂停、不同时段不同阈值、支持维护周期.
- 高效的graph组件: 单机支撑200万metric的上报、归档、存储(周期为1分钟)
- 高效的历史数据query组件: 采用rrdtool的数据归档策略,秒级返回上百个metric一年的历史数据.
- dashboard: 多维度的数据展示、用户自定义Screen。
- 高可用: 整个系统无核心单点,易运维,易部署,可水平扩展.
- 开发语言: 整个系统的后端全部采用golang编写,portal和dashboard使用Python编写.
缺点:
- 每个Graph(数据存储)实例均是单点. (这点很大程度上解决了,Transfer中可以配置Graph双写,手工维护双写列表麻烦,但这个列表基本不怎么变)
- Graph扩容有损,
- 报警没有入库,当前未恢复的报警是存在Alarm内存中的,重启就丢了,历史报警也没入库,无法追溯.
- 报警现场没有保存: 因为使用rrd存储历史数据,一天后数据就被做了归档处理,查看历史报警时刻趋势图,无法查看当前准确值.
- 前端展示功能很鸡肋,哪怕有grafana,没有现成的grafana页面,需要自己编辑.
架构
相关服务组件详解
绘图组件
1.Falcon-Agent http:1998
数据采集组件: 部署到目标机器采集机器监控项: agent内置了一个http接口,会自动采集预先定义的各种采集项,每隔60秒,push到transfer。
2.Transfer http:6060 rpc:8433 socket:4444
agent与transfer建立长连接,将数据汇报给tarnsfer transfer默认监听在:8433端口上,agent会通过jsonrpc的方式来push数据上来 transfer将数据发送给judge和graph
3.Graph http:6070 rpc:6071
graph组件是存储绘图数据、历史数据的组件。transfer会把接收到的数据,转发给graph。 监听端口为6071,校验方法如下,返回ok表示服务正常。 curl -s "http://127.0.0.1:6071/health"
4.Query http:9966
绘图数据的查询接口,因为graph是分片存储的,如果要传输给dashboard,就需要query组件收集用户的数据进行聚合再返回给用户。
5.Dashboard http:8081
Dashboard是面向用户的查询界面,在这里,用户可以看到push到graph中的所有数据,并查看其趋势图。
6.Task http:8002
负责一些定时任务,索引全量更新,垃圾索引清理,自身组件监控等
报警组件
1.Sender
调用各个公司提供的mail-privider和sms-privider,按照某个并发度,从redis读取邮件,短信并发送, alarm生成的报警短信和报警邮件是直接写入redis即可,由sender来发送。
2.UIC http:80
用户组管理,单点登录
3.Portal http:5050
配置报警策略,管理机器分组的web端
4.HBS http:6031 rpc:6030
Heartbeat Server心跳服务,只依赖Protal的DB
5.Judge http:6081 rpm:6080
告警判断模块
6.Links http:6090
报警合并依赖的web端,存放报警详情
7.Alarm http:9912
报警时间处理器: 处理报警事件,judge的报警事件写入到redis,alarm从redis读取数据
8.Mail-privider&&sms-provider http:4000
发送邮件http api
9.Nodata http:6090
检测监控数据的上报异常
Aggregator http:6055
集群聚合模块: 聚合某集群下所有机器某个指标的值,提供一种集群视觉的监控体验
Falcon-Agent监控项
代码语言:javascript复制每台服务器,都有安装falcon-agent,falcon-agent是一个golang开发的daemon程序,用于自发现的采集单机的各种数据和指标,这些指标包括不限于以下几个方面,共计200多项指标:
* CPU相关
* 磁盘相关
* IO
* Load
* 内存相关
* 网络相关
* 端口存活、进程存活
* ntp offset(插件)
* 某个进程资源消耗(插件)
* netstat.ss等相关统计项采集
* 机器内核配置参数
只要安装了falcon-agent的机器,就会自动开始采集各项指标,主动上报,不需要用户在server做任何配置(这和zabbix有很大的不同),这样做的好处,就是用户维护方便,覆盖率高. 当然这样做也会给server造成较大的压力,不过open-falcon的服务端单机性能足够高,同时可以水平扩展,所以自动采集足够多的数据,反而是一件好的事情,对于SRE和DEV来讲,事后追查问题,不再是难题. 另外,falcon-agent提供了一个proxy-gateway,用户可以方便的通过http接口,push数据到本机的gateway,gateway会帮忙高效率的转发给server端.
数据模型
Data Mode是否强大,是否灵活,对于监控系统用户的“使用效率”至关重要,比如以zabbix为例,上报的数据为hostname(或者ip)、metric,那么用户添加告警策略,管理告警策略的时候,就只能以这两个维度进行。举一个常见的场景: hostA的磁盘空间,小于5%,就告警,一般的服务器上,都会有两个主要的分区,根分区和home分区,在zabbix里面,就得加两条规则: 如果是hadoop的机器,一般都还会有十几块的数据盘,还得多加10多条规则,这样就很痛苦,不幸福,不利于自动化(当然zabbix可以通过配置一些自动发现策略来搞定这个,不过比较麻烦)
数据收集
transfer: 接收客户端发送的数据,做一些数据规整,检查之后,转发到多个后端系统去处理,在转发到每个后端业务系统的时候,transfer会根据一致性hash算法,进行数据分片,来达到后端业务系统的水平扩展. transfer提供jsonRpc接口和telnet接口两种方式,judge,graph,opentsdb,judge是我们开发的高性能告警判定组件,graph使我们开发的高性能数据存储、归档查询组件,opentsdb是开源的时间序列数据存储服务,可以通过transfer的配置文件来开启.
transfer的数据来源,一般有三种
- falcon-agent采集的基础监控数据
- falcon-agent执行用户自定义的插件返回的数据
- client library: 线上的业务系统,都嵌入使用了统一的perfcounter.jar,对于业务系统中每个RPC接口的qps、latency都会主动采集并上报.
说明: 上面这三种数据,都会先发送给本机的proxy-gateway,再由gateway转发给transfer. 基础监控是指只要是个机器(或容器)就能监控,比如cpu,mem,net,io,disk等,这些监控项采集的方式固定,不需要配置,也不需要用户提供额外的参数指定,只要agent跑起来就可以直接采集数据上报上去,非基础监控则相反.比如端口监控,你不给我端口就不行,不然我上报所有65535个端口的监听服务你也用不了,这类监控需要用户配置后才会开始采集上报的监控(包括类似于端口监控的配置触发类监控,以及类似于mysql的插件脚本类监控),一般就不算基础监控的范畴了.
报警
报警判定,是由judge组件来完成。用户在web portal来配置相关的报警策略,存储在Mysql中,hearbeat server会定期加载Mysql中的内容,judge也会定期和hearbeat server保持沟通,来获取相关的报警策略. heartbeat server不仅仅单纯的加载Mysql中的内容,根据模板继承、模板项覆盖、报警动作覆盖、模板和hostGroup绑定,计算出最终关联到endpoint的告警策略,提供给judge组件来使用. transfer转发给judge的每条数据,都会触发相关策略的判定,来决定是否满足报警条件,如果满足条件,则会发送给alarm,alarm再以邮件、短信、米聊等形式通知相关用户,也可以执行用户预先配置好的callback地址. 用户可以很灵活的来配置告警判定策略,比如连续n次满足条件,连续n次的最大值满足条件、不同时间段不同的阈值,如果出于维护周期内则忽略等等. 另外也支持突升突降类的判定和告警.
API
到这里,数据已经成功的存储在了graph里,如何快速的读出来,读过去1小时的,过去一个月的,过去一年的都需要1秒之内返回. 这些都是靠graph和API组件来实现的,transfer会将数据往graph组件转发一份,graph收到数据以后,会以rdtool的数据归档方式来存储,同时提供查询的RPC接口. API面向终端用户,收到查询请求后,会去多个graph里面,查询不同metric的数据,汇总后统一返回给用户.
存储
对于监控系统来讲,历史数据的存储和高效率查询,永远是一个很难的问题! 数据量大,目前我们的监控系统,每个周期,大概有2000万次数据上报(上报周期为1分钟和5分钟两种,各占50%),一天24小时内,从来不会有业务低峰,不管是白天还是夜晚,每个周期,总会有那么多数据要更新. 写操作多,一般的业务系统,通常是读多写少,可以方便的使用各种缓存技术,再者各类数据库,对于查询操作的处理效率远远高于写操作,而监控系统恰恰相反,写操作远远高于读,每个周期几千万次的更新操作,对于常用数据库(Mysql,Postgresql,MongoDB)都是无法完成的. 高效率的查,我们说的监控系统操作少,是相对于写入来讲,监控系统本身对于读的要求很高,用户经常会有查询上百个meitric,在过去一天、一周、一月、一年的数据,如何在一秒内返回给用户并绘图,这是个不小的挑战. open-falcon在这块,投入了较大的精力,我们把数据按照用途分成两类,一类是用来绘图的,一类是用户做数据挖掘的. 对于绘图的数据来讲,查询要快是关键,同时不能丢失信息量,对于用户要查询100个metric,在过去一年里的数据里,数据量本身就在那里了,很那1秒之类返回,另外就算返回了,前端也无法渲染这么多的数据,还得采样,造成很多无畏的消耗和浪费。我们参考rrdtool的理念。数据每次存入的时候,会自动进行采样,存档. 我们归档策略如下: 历史数据保存5年 。同时为了不丢失信息量,数据归档的时候,会按照平均值采样、最大值采样、最小值采样.
滴滴云基于OpenFalcon的二次开发
Open-Falcon 二进制部署
代码语言:javascript复制# Open-Falcon,为前后端分离的架构,包含 backend 和 frontend 两部分.
# 部署有三种方式:
# 1. 源码安装(当中有一步需要编译)
# 2. 二进制包安装:(官方已经编译好的,其余跟源码安装一样)
# 3. docker 安装
List:
代码语言:javascript复制Package:
mysql5.7
redis3.2
go1.13.4.linux-amd64.tar.gz
open-falcon-v0.2.1.tar.gz
python-virtualenv
python-devel
openldap-devel
mysql-devel
节点名 | IP | 软件版本 | 硬件 | 网络 | 说明 |
---|---|---|---|---|---|
falcon-binary | 172.19.0.6 | list 里面都有 | 2C4G | Nat,内网 | 测试环境 |
注意事项
跟传统服务修改配置文件数据库密码不一样,因为 open-falcon 是前后端分离,需要给前端也授权数据库权限,否则部分前端功能报错 500
准备系统环境
代码语言:javascript复制# 1.初始化
init_security() {
systemctl stop firewalld
systemctl disable firewalld &>/dev/null
setenforce 0
sed -i '/^SELINUX=/ s/enforcing/disabled/' /etc/selinux/config
sed -i '/^GSSAPIAu/ s/yes/no/' /etc/ssh/sshd_config
sed -i '/^#UseDNS/ {s/^#//;s/yes/no/}' /etc/ssh/sshd_config
systemctl enable sshd crond &> /dev/null
rpm -e postfix --nodeps
echo -e "