01 . Openfalcon小米监控简介及部署

Open-Falcon简介

介绍

  • 监控系统是整个运维环节,乃至整个产品生命周期中最重要的一环,事前及时预警发现故障,事后提供翔实的数据用于追查定位问题。
  • 监控系统作为一个成熟的运维产品,业界有很多开源的实现可供选择。当公司刚刚起步,业务规模较小,运维团队也刚刚建立的初期,选择一款开源的监控系统,是一个省时省力,效率最高的方案。
  • 之后,随着业务规模的持续快速增长,监控的对象也越来越多,越来越复杂,监控系统的使用对象也从最初少数的几个SRE,扩大为更多的DEVS,SRE。
    这时候,监控系统的容量和用户的“使用效率”成了最为突出的问题。
  • 监控系统业界有很多杰出的开源监控系统。我们在早期,一直在用zabbix,不过随着业务的快速发展,以及互联网公司特有的一些需求,现有的开源的监控系统在性能、扩展性、和用户的使用效率方面,已经无法支撑了。
  • 因此,我们在过去的一年里,从互联网公司的一些需求出发,从各位SRE、SA、DEVS的使用经验和反馈出发,结合业界的一些大的互联网公司做监控,用监控的一些思考出发,设计开发了小米的监控系统:open-falcon。

Open-Falcon特点

  1. 强大灵活的数据采集: 自动发现,支持falcon-agent、snmp、支持用户主动push、用户自定义插件支持,opentsdb data model like (timestamp、endpoint、metric、key-value tags)
  2. 水平扩展能力: 支持每个周期上亿次的数据采集、告警判定、历史数据存储和查询.
  3. 高效率的告警策略管理: 高效的portal、支持策略模板、模板集成和覆盖、多种告警方式、支持callback调用.
  4. 人性化的告警设置: 最大告警次数、告警级别、告警恢复通知、告警暂停、不同时段不同阈值、支持维护周期.
  5. 高效的graph组件: 单机支撑200万metric的上报、归档、存储(周期为1分钟)
  6. 高效的历史数据query组件: 采用rrdtool的数据归档策略,秒级返回上百个metric一年的历史数据.
  7. dashboard: 多维度的数据展示、用户自定义Screen。
  8. 高可用: 整个系统无核心单点,易运维,易部署,可水平扩展.
  9. 开发语言: 整个系统的后端全部采用golang编写,portal和dashboard使用Python编写.

缺点:

  1. 每个Graph(数据存储)实例均是单点. (这点很大程度上解决了,Transfer中可以配置Graph双写,手工维护双写列表麻烦,但这个列表基本不怎么变)
  2. Graph扩容有损,
  3. 报警没有入库,当前未恢复的报警是存在Alarm内存中的,重启就丢了,历史报警也没入库,无法追溯.
  4. 报警现场没有保存: 因为使用rrd存储历史数据,一天后数据就被做了归档处理,查看历史报警时刻趋势图,无法查看当前准确值.
  5. 前端展示功能很鸡肋,哪怕有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的数据来源,一般有三种

  1. falcon-agent采集的基础监控数据
  2. falcon-agent执行用户自定义的插件返回的数据
  3. 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'
posted @ 2020-05-31 22:48  常见-youmen  阅读(1936)  评论(0编辑  收藏  举报