01 . Openfalcon小米监控简介及部署
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监控项
每台服务器,都有安装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 二进制部署
# Open-Falcon,为前后端分离的架构,包含 backend 和 frontend 两部分.
# 部署有三种方式:
# 1. 源码安装(当中有一步需要编译)
# 2. 二进制包安装:(官方已经编译好的,其余跟源码安装一样)
# 3. docker 安装
List:
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
准备系统环境
# 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 "\033[32m [安全配置] ==> OK \033[0m"
}
init_security
init_yumsource() {
if [ ! -d /etc/yum.repos.d/backup ];then
mkdir /etc/yum.repos.d/backup
fi
mv /etc/yum.repos.d/* /etc/yum.repos.d/backup 2>/dev/null
if ! ping -c2 www.baidu.com &>/dev/null
then
echo "您无法上外网,不能配置yum源"
exit
fi
curl -o /etc/yum.repos.d/163.repo http://mirrors.163.com/.help/CentOS7-Base-163.repo &>/dev/null
curl -o /etc/yum.repos.d/epel.repo http://mirrors.aliyun.com/repo/epel-7.repo &>/dev/null
yum clean all
timedatectl set-timezone Asia/Shanghai
echo "nameserver 114.114.114.114" > /etc/resolv.conf
echo "nameserver 8.8.8.8" >> /etc/resolv.conf
chattr +i /etc/resolv.conf
yum -y install ntpdate
ntpdate -b ntp1.aliyun.com
echo -e "\033[32m [YUM Source] ==> OK \033[0m"
}
init_yumsource
安装 Open-Falcon 的 Database 组件服务
init_redis() {
yum -y install redis git
sed -i 's/bind 127.0.0.1/bind 172.19.0.6/' /etc/redis.conf # 此处IP为你自己的主机IP
systemctl start redis && systemctl enable redis
if [ $? -eq 0 ] ;then
echo -e "\033[32m [ Redis server ] ==> OK \033[0m";
fi
}
init_redis
init_mysql() {
rpm -e mariadb-libs --nodeps
rm -rf /var/lib/mysql
rm -rf /etc/my.cnf
tar xvf /root/mysql-5.7.23-1.el7.x86_64.rpm-bundle.tar -C /usr/local/
cd /usr/local
rpm -ivh mysql-community-server-5.7.23-1.el7.x86_64.rpm \
mysql-community-client-5.7.23-1.el7.x86_64.rpm mysql-community-common-5.7.23-1.el7.x86_64.rpm \
mysql-community-libs-5.7.23-1.el7.x86_64.rpm mysql-community-devel-5.7.23-1.el7.x86_64.rpm
rm -rf mysql-community-*
}
changepass() {
sed -i '/\[mysqld]/ a skip-grant-tables' /etc/my.cnf
systemctl restart mysqld
mysql <<EOF
update mysql.user set authentication_string='' where user='root' and Host='localhost';
flush privileges;
EOF
sed -i '/skip-grant/d' /etc/my.cnf
systemctl restart mysqld
yum -y install expect
systemctl start ntpd && systemctl enable ntpd
expect <<-EOF
spawn mysqladmin -uroot -p password "ZHOUjian.20"
expect {
"password" { send "\r" }
}
expect eof
EOF
systemctl restart mysqld
}
main() {
init_redis
init_mysql
changepass
}
main
准备 Open-Falcon 数据目录,并下载 Open-Falcon 的 Git 仓库
init_falcon_data_directory() {
mkdir -pv /home/open-falcon && cd /home/open-falcon
git clone https://github.com/open-falcon/falcon-plus.git
cd /home/open-falcon/falcon-plus/scripts/mysql/db_schema/ #初始化mysql的表结构,必须取保mysql服务是正常启动的。
mysql -uroot -pZHOUjian.20 < 1_uic-db-schema.sql
mysql -uroot -pZHOUjian.20 < 2_portal-db-schema.sql
mysql -uroot -pZHOUjian.20 < 3_dashboard-db-schema.sql
mysql -uroot -pZHOUjian.20 < 4_graph-db-schema.sql
mysql -uroot -pZHOUjian.20 < 5_alarms-db-schema.sql
}
init_falcon_data_directory
安装后端并启动
export FALCON_HOME=/home/work
export WORKSPACE=$FALCON_HOME/open-falcon
mkdir -p $WORKSPACE
tar xvf open-falcon-v0.2.1.tar.gz -C $WORKSPACE
cd $WORKSPACE`
grep -Ilr 3306 ./ | xargs -n1 -- sed -i 's/root:/root:ZHOUjian.20/g'
cd $WORKSPACE
# 启动
./open-falcon start
# 检查所有模块的启动状况
./open-falcon check
部署前端
# 创建工作目录
export HOME=/home/work
export WORKSPACE=$HOME/open-falcon
mkdir -p $WORKSPACE
cd $WORKSPACE
# 克隆前端代码
cd $WORKSPACE
git clone https://github.com/open-falcon/dashboard.git
# 安装依赖包
yum install -y python-virtualenv python-devel openldap-devel
yum groupinstall "Development tools"
cd $WORKSPACE/dashboard/
virtualenv ./env
./env/bin/pip install -r pip_requirements.txt -i https://pypi.douban.com/simple
# 修改配置
dashboard的配置文件为: 'rrd/config.py',请根据实际情况修改
# API_ADDR 表示后端api组件的地址
API_ADDR = "http://127.0.0.1:8080/api/v1"
# 根据实际情况,修改PORTAL_DB_*, 默认用户名为root,默认密码为""
# 根据实际情况,修改ALARM_DB_*, 默认用户名为root,默认密码为""
# 以开发者模式启动
./env/bin/python wsgi.py
# 使用浏览器访问IP:8081即可
# 以生产模式启动
bash control start
# 停止dashboard运行
bash control stop
# 查看日志
bash control tail
# 可以修改一下wsgi.py配置文件,指定IP和端口,默认是0.0.0.0
Dashbord 用户管理
dashbord 没有默认创建任何账号包括管理账号,需要你通过页面进行注册账号。
想拥有管理全局的超级管理员账号,需要手动注册用户名为 root 的账号(第一个帐号名称为 root 的用户会被自动设置为超级管理员)。
超级管理员可以给普通用户分配权限管理。
小提示:注册账号能够被任何打开 dashboard 页面的人注册,所以当给相关的人注册完账号后,需要去关闭注册账号功能。只需要去修改 API 组件的配置文件 cfg.json,将 signup_disable 配置项修改为 true,重启 API 即可。当需要给人开账号的时候,再将配置选项改回去,用完再关掉即可。
Open-Falcon 容器部署
# 注意事项:
# 1:初始化环境跟上面一样,此处就不重复了,请执行上面两个初始化环境函数,再执行下面命令;
# 2:如果docker启动容器不小心弄错了,记得删除容器再run;
准备 docker 依赖包和 docker 的 yum 源并安装
# 安装需要的软件包,yum-util 提供yum-config-manager功能,另外两个是devicemapper驱动依赖的
yum install -y yum-utils device-mapper-persistent-data lvm2
# 准备yum源
# docker 官方源
sudo yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo
# 阿里云源
sudo yum-config-manager --add-repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
# 由于repo中默认只开启stable仓库,所以这里安装的是最新稳定版
yum install docker-ce
# Docker镜像加速
# 没有启动/etc/docker 目录不存在,需要自己建立,启动会自己创建;
mkdir /etc/docker
# 为了期望我们镜像下载快一点,应该定义一个镜像加速器,加速器在国内
vim /etc/docker/daemon.json
{
"registry-mirrors": ["https://registry.docker-cn.com"]
}
# 启动docker
systemctl start docker && systemctl enable docker && systemctl daemon-reload
注意
启动docker前清理一下环境,防止目录冲突
# 防止环境有之前装过的mysql,做一下清理
# yum方式安装的mysql
yum -y remove mysql mysql-server mysql-libs compat-mysql51
rm -rf /var/lib/mysql
rm -rf /etc/my.cnf # 有可能my.cnf改名为my.cnf.rpmsave
# 查看是否还有mysql软件
rpm -qa|grep mysql
rpm方式安装的mysql
# 查看系统中是否以rpm包安装的mysql:
rpm -qa | grep -i mysql
MySQL-server-5.6.17-1.el6.i686
MySQL-client-5.6.17-1.el6.i686
# 卸载mysql:
rpm -e MySQL-server-5.6.17-1.el6.i686
rpm -e MySQL-client-5.6.17-1.el6.i686
# 删除mysql服务
chkconfig --list | grep -i mysql
chkconfig --del mysql
# 删除分散mysql文件夹
whereis mysql 或者 find / -name mysql
mysql: /usr/lib/mysql /usr/share/mysql
mysql的所有目录以及文件:
rm -rf /usr/lib/mysql
rm -rf /usr/share/mysql
安装mysql容器
docker run -itd \
--name falcon-mysql \
-v /home/work/mysql-data:/var/lib/mysql \
-e MYSQL_ROOT_PASSWORD=test123456 \
-p 3306:3306 \
mysql:5.7
# 安装的版本为mysql:5.7 默认用户名root 密码 test123456
初始化mysql表结构
# cd /tmp && \
git clone --depth=1 https://github.com/open-falcon/falcon-plus && \
cd /tmp/falcon-plus/ && \
for x in `ls ./scripts/mysql/db_schema/*.sql`; do
echo init mysql table $x ...;
docker exec -i falcon-mysql mysql -uroot -ptest123456 < $x;
done
# rm -rf /tmp/falcon-plus/
安装后端
docker pull openfalcon/falcon-plus:v0.3
docker run -itd --name falcon-plus \
--link=falcon-mysql:db.falcon \
--link=falcon-redis:redis.falcon \
-p 8433:8433 \
-p 8080:8080 \
-e MYSQL_PORT=root:test123456@tcp\(db.falcon:3306\) \
-e REDIS_PORT=redis.falcon:6379 \
-v /home/work/open-falcon/data:/open-falcon/data \
-v /home/work/open-falcon/logs:/open-falcon/logs \
openfalcon/falcon-plus:v0.3
启动open-falcon后端模块
docker exec falcon-plus sh ctrl.sh start \ graph hbs judge transfer nodata aggregator agent gateway api alarm
# 或者您可以按照以下方式启动/停止/重启特定模块:
docker exec falcon-plus sh ctrl.sh start/stop/restart xxx
# 检查后端模块的状态
docker exec falcon-plus ./open-falcon check
# 或者您可以在主机中的/ home / work / open-falcon / logs /中查看日志
ls -l /home/work/open-falcon/logs/
安装前端
# 在容器中启动Open-Falcon仪表盘
docker run -itd --name falcon-dashboard \
-p 8081:8081 \
--link=falcon-mysql:db.falcon \
--link=falcon-plus:api.falcon \
-e API_ADDR=http://api.falcon:8080/api/v1 \
-e PORTAL_DB_HOST=db.falcon \
-e PORTAL_DB_PORT=3306 \
-e PORTAL_DB_USER=root \
-e PORTAL_DB_PASS=test123456 \
-e PORTAL_DB_NAME=falcon_portal \
-e ALARM_DB_HOST=db.falcon \
-e ALARM_DB_PORT=3306 \
-e ALARM_DB_USER=root \
-e ALARM_DB_PASS=test123456 \
-e ALARM_DB_NAME=alarms \
-w /open-falcon/dashboard openfalcon/falcon-dashboard:v0.2.1 \
'./control startfg'