微服务监控探索

达芬奇密码2018-08-17 14:07

微服务监控简介

作为一种灵活性极强的构架风格,微服务在各种开发项目中日益普及。当开发者从微服务架构获得敏捷时,观测整个系统的运行情况成为最大的痛点。
从网络流量分析的角度出发,通过生成各个微服务之间访问关系的拓扑结构来直观地观察整个系统的运作状况。

监控整体架构


部署

目前各组件部署在测试集群的容器环境中

  • elasticsearch
  • kibana
  • topology


packetbeat

packetbeat是一个实时网络包分析工具,可以用于应用的监控和性能分析。它对7层协议进行解析,根据requests和responses划分transactions,对每一个transaction产生一个json文档写入elasticsearch(通常情况下)。

目前packetbeat兼容的协议包括:

  • HTTP
  • MySQL
  • PostgreSQL
  • Redis
  • Thrift-RPC
  • MongoDB
  • DNS
  • Memcache

    安装

    官方提供的安装方式

    sudo apt-get install libpcap0.8
    curl -L -O https://download.elastic.co/beats/packetbeat/packetbeat_1.1.1_amd64.deb 
    sudo dpkg -i packetbeat_1.1.1_amd64.deb

配置

基本的配置包括网络设备,输出(本例是es),各协议端口。 配置文件默认为/etc/packetbeat/packetbeat.yml,最基本的配置示例如下:

interfaces: {device: docker0}
output:
  elasticsearch:
    hosts: ['223.252.222.168:42400']
protocols:
  dns:
    ports: [53]
  http:
    ports: [8000, 8080]
  memcache:
    ports: [11211]
  mongodb:
    ports: [27017]
  mysql:
    ports: [3306]
  pgsql:
    ports: [5432]
  redis:
    ports: [6379]
  thrift:
    ports: [9090] 

抓包方式

packetbeat支持三种抓包方式:

  • pcap 依赖于libpcap,兼容各种平台,但性能并非最高(默认方式)
  • af_packet 内存映射方式,该方式性能优于pcap并且不依赖内核模块,但是仅限于linux
  • pf_ring 依赖ntop.org的项目,该方式性能最佳,但是依赖于内核模块且限于linux

运行

/etc/init.d/packetbeat start

packetbeat配置动态修改(ctl_pb)

packetbeat的部署以node为单位,因此需要为其配置该node上所有service的服务端口,然而单个node上运行着多个service的示例,并且由于k8s的调度会动态的创建和销毁,因此需要动态的修改packetbeat的配置。

ctl_pb.py负责在每个node上动态修改packetbeat的配置,其工作流程大致如下:

  1. 初始化k8s_api地址以及docker daemon的api地址
  2. 以stream的方式请求docker daemon的watch api,当有容器创建或销毁时返回该event,并触发更新配置的操作
  3. 根据宿主机的ip用k8s_api获得该node上所有podip
  4. 根据podip获得该node上所有endpoint的端口
  5. 更新packetbeat的配置文件并重启packetbeat

topology

整体预览效果如下:

图中边的粗细对应请求数的大小,边的颜色对应延迟的大小

生成topology的流程大致如下:

  1. 初始化完成读取配置文件等信息,包括es地址、k8s_api地址等等
  2. 根据宿主机的ip从k8s_api的/pods查询该node上所有podIP,返回ip-->podname的字典
  3. 接受请求or定时刷新触发,使用es的search api拉取符合过滤条件(时间周期、协议类型等)的数据,生成拓扑图必须的节点---nodes[]和边---links[]的数组,并计算对应的请求数、平均responsetime等统计信息
  4. 对节点和边信息中的ip,若存在ip-->podname的对应关系则转换为podname
  5. 若某ip没有对应podname,则转换为查询DNS返回的hostname
  6. 利用得到的nodes[]和links[]渲染模板,生成html
  7. 拓扑图的渲染使用开源JS作图库Echarts中的力导向图

Kibana Plugin

为了和更好的结合elk,将topology作为plugin集成到kibana的visualization里是一个不错的选择。然而kibana官方文档只介绍了plugin的安装,并没有相关的develop文档...从收集到的民间文档来看,开发plugin存在以下坑:

  1. 由于不是官方api,用到的api很可能在下个版本被和谐,意味着对每一个版本的kibana都要调整
  2. plugin安装的来源限于官方或者github,需要发布后才能安装
  3. 最关键的是,在kibana的官方repo中赫然写着:

鉴于以上,还是部署了一个kibana的dev模式进行尝试开发一个Visualization用于展示拓扑结构。 一个Visualization plugin的核心主要由template和controller控制,在模板中的div中指定controller用以操作内部变量和逻辑。拓扑图的实现基于开源js作图库Echarts,其原理是为每一个图指定一个固定大小的空白div,然后在js中取得该div对象并进行初始化和渲染。因此想法是讲初始化和渲染的逻辑放在controller中,如下图:

然而实际情况存在以下问题:

  1. controller需要继承kibana中的ui/modules,从代码上看该module属于angularJS风格,然而在该module中大部分angularJS的内置方法都无法使用,例如service $document;
  2. 该module中无法使用除了kibana/src以外的模块,包括echarts和nodejs内置模块;
  3. 该module似乎不是很兼容异步数据加载和渲染(未验证)。

由于以上问题,渲染的逻辑只能以/标签写在template中,然而template中的标签是无法动态修改的(需要通过controller),因此需要另外的部分去修改template从而在每次Visualization读取template时加载数据的变化,目前的实现是通过一个web server定期将模板渲染出的拓扑图导出成html,用该html作为Visualization的template:

目前的效果可以在kibana dashboard中添加拓扑结构图,然而该图的统计时间范围控制、前端参数等等都在web server中控制,并且由于异步渲染的问题,在dashboard中需要先切换到别的标签再切换回来才能看到该图...

参考资料


网易云新用户大礼包:https://www.163yun.com/gift

本文来自网易实践者社区,经作者何丹授权发布。