一、Kubernetes 容器监控的标配—Prometheus
1、简介
Prometheus 是由 SoundCloud 开发的开源监控告警系统并且带时序数据库,基于 Go 语言,是 Google BorgMon 监控系统的开源版本。2016 年,由 Google 发起的 Linux 基金会旗下的原生云基金会(Cloud Native Computing Foundation,CNCF)将 Prometheus 纳入其第二大开源项目。Prometheus 在开源社区也十分活跃,在 GitHub 上拥有两万多 Star,并且系统每隔一两周就会有一个小版本的更新。
随着 Kubernetes 在容器调度和管理上确定领头羊的地位,Prometheus 也成为 Kubernetes 容器监控的标配。
2、优点
Prometheus 的优点有很多,如下所述。
(1)提供多维度数据模型和灵活的查询方式,通过将监控指标关联多个 tag,来将监控数据进行任意维度的组合,并且提供简单的 PromQL 查询方式,还提供 HTTP 查询接口,可以很方便地结合 Grafana 等 GUI 组件展示数据。
(2)在不依赖外部存储的情况下,支持服务器节点的本地存储,通过 Prometheus 自带的时序数据库,可以完成每秒千万级的数据存储;不仅如此,在保存大量历史数据的场景中,Prometheus 可以对接第三方时序数据库如 OpenTSDB 等。
(3)定义了开放指标数据标准,以基于 HTTP 的 Pull 方式采集时序数据,只有实现了 Prometheus 监控数据格式的监控数据才可以被 Prometheus 采集、汇总,并支持以 Push 方式向中间网关推送时序列数据,能更加灵活地应对多种监控场景。
(4)支持通过静态文件配置和动态发现机制发现监控对象,自动完成数据采集。Prometheus 目前已经支持 Kubernetes、etcd、Consul 等多种服务发现机制,可以减少运维人员的手动配置环节,在容器运行环境中尤为重要。
(5)易于维护,可以通过二进制文件直接启动,并且提供了容器化部署镜像。
(6)支持数据的分区采样和联邦部署,支持大规模集群监控。
3、架构
下面简单介绍 Prometheus 的架构。
Prometheus 的基本原理是通过 HTTP 周期性抓取被监控组件的状态,任意组件只要提供对应的 HTTP 接口并且符合 Prometheus 定义的数据格式,就可以接入 Prometheus 监控。
如图1-9 所示为 Prometheus 的整体架构图(来自 Prometheus 官网),展现了 Prometheus 内部模块及相关的外围组件之间的关系。
图1-9
PrometheusServer 负责定时在目标上抓取 metrics(指标)数据,每个抓取目标都需要暴露一个 HTTP 服务接口用于 Prometheus 定时抓取。这种调用被监控对象获取监控数据的方式被称为 Pull(拉)。Pull 方式体现了 Prometheus 独特的设计哲学与大多数采用了 Push(推)方式的监控系统不同。
Pull 方式的优势是能够自动进行上游监控和水平监控,配置更少,更容易扩展,更灵活,更容易实现高可用。展开来说就是 Pull 方式可以降低耦合。由于在推送系统中很容易出现因为向监控系统推送数据失败而导致被监控系统瘫痪的问题,所以通过 Pull 方式,被采集端无须感知监控系统的存在,完全独立于监控系统之外,这样数据的采集完全由监控系统控制,增强了整个系统的可控性。
Prometheus 通过 Pull 方式采集数据,那么它如何获取监控对象呢?Prometheus 支持两种方式:第 1 种是通过配置文件、文本文件等进行静态配置;第 2 种是支持 ZooKeeper、Consul、Kubernetes 等方式进行动态发现,例如对于 Kubernetes 的动态发现,Prometheus 使用 Kubernetes 的 API 查询和监控容器信息的变化,动态更新监控对象,这样容器的创建和删除就都可以被 Prometheus 感知。
Storage 通过一定的规则清理和整理数据,并把得到的结果存储到新的时间序列中,这里有两种存储方式。
一种是本地存储。通过 Prometheus 自带的时序数据库将数据保存到本地磁盘,为了性能考虑,建议使用 SSD。但本地存储的容量毕竟有限,建议不要保存超过一个月的数据。
另一种是远端存储,适用于存储大量监控数据。通过中间层的适配器的转化,目前 Prometheus 支持 OpenTSDB、InfluxDB、Elasticsearch 等后端存储,通过适配器实现 Prometheus 存储的 remote write 和 remote read 接口,便可以接入 Prometheus 作为远端存储使用。如图1-10 所示展现了 Prometheus 当前支持的远端数据库。
图1-10
Prometheus 通过 PromQL 和其他 API 可视化地展示收集的数据。Prometheus 支持多种方式的图表可视化,例如 Grafana、自带的 PromDash 及自身提供的模版引擎等。Prometheus 还提供 HTTP API 查询方式,自定义所需要的输出。
Prometheus 通过 Pull 方式拉取数据,但某些现有系统是通过 Push 方式实现的,为了接入这些系统,Prometheus 提供了对 PushGateway 的支持,这些系统主动推送 metrics 到 PushGateway,而 Prometheus 只是定时去 Gateway 上抓取数据。
AlertManager 是独立于 Prometheus 的一个组件,在触发了预先设置在 Prometheus 中的高级规则后,Prometheus 便会推送告警信息到 AlertManager。AlertManager 提供了十分灵活的告警方式,可以通过邮件、slack 或者钉钉等途径推送。并且 AlertManager 支持高可用部署,为了解决多个 AlertManager 重复告警的问题,引入了 Gossip,在多个 AlertManager 之间通过 Gossip 同步告警信息。
AlertManager 的整体工作流程如图1-11 所示。
二、其他开源监控工具
除了市场上提供的很多 SaaS 商业工具如监控宝、监控易、听云等,还有一些开源监控工具如 Zabbix、Open-Falcon 等。
1、Zabbix
Zabbix 是由 AlexeiVladishev 开源的分布式监控系统,支持多种采集方式和采集客户端,同时支持 SNMP、IPMI、JMX、Telnet、SSH 等多种协议,它将采集到的数据存放到数据库中,然后对其进行分析整理,如果符合告警规则,则触发相应的告警。
Zabbix 主要有以下几个核心概念。
主机(Host):是 Zabbix 监控的对象抽象,每个监控对象都有一个 IP 地址,这里的主机不仅限于物理服务器,可能是虚拟机容器或者某个网络设备。
主机组(Host Group):是一组主机的集合,主要用于多用户之间的资源隔离,将主机组和用户关联,这样 Zabbix 的不同用户便只对自己管理的资源可见。
条目(Item):是一个指标的相关监控数据,每个条目都有一个 key 去标识,以区分不同的指标。
应用(Application):是一组条目的集合,一个条目可以属于一个或多个应用。
模板(Template):是 Zabbix 里快速配置的利器,用于快速定义被监控主机的预设条目集合,通常包含条目、触发器、视图、应用及服务发现规则,通过将主机关联模板来避免重复配置主机。
触发器(Trigger):是 Zabbix 的告警规则,用于评估某监控对象在某特定条目内接收到的数据是否匹配阈值,如果匹配,则触发器状态将从 OK 转变为 Problem,当数据量再次回到合理范围时,触发器状态又将从 Problem 转变为 OK。
动作(Action):是 Zabbix 在某个事件发生后执行的动作。事件主要指告警事件、网络发现新主机加入事件、自动注册(代理)事件和内部事件(监控项不支持);行为主要包括发送邮件通知、执行远程命令或者执行 Zabbix 的附加动作。
Zabbix 的组件图如图1-12 所示。
图1-12
如图1-12 所示,Zabbix 由以下几个组件构成。
1)ZabbixServer
Zabbix 的核心组件,由C语言编写而成,主要负责接收 Agent 发送的监控信息,并进行汇总存储。Zabbix Server 需要完成以下三个主要工作。
设备注册。有两种方式可以将监控对象注册到设备中:一种是手动配置 Agent 地址,但如果需要将机房中的几百台机器一次性加入,则将是很大的工作量;另一种是采用自动发现机制,可以配置整个网段,Server 会检测整个网段的主机,并且可以自动配置模板、触发器等一系列相关配置。
数据收集。这里既包括主动采集,也包括被动接收,采集到的数据首先会被放置在内存中,然后被批量保存在数据库中。
定期的数据清理及告警触发。通过配置的触发器匹配采集数据,如果满足条件,则发出告警。
2)Zabbix Database
用于存储所有配置信息,以及由 Zabbix 收集的监控数据。后端数据库支持 MySQL、PostgreSQL、Oracle 等,通常用到的是 MySQL,并提供 ZabbixWeb 页面的数据查询方式。由于采用了关系型数据库存储时序数据,所以 Zabbix 在监控大规模集群时常常在数据存储方面捉襟见肘。
3)Zabbix Web
Zabbix 的 GUI 组件,由 PHP 编写而成,通常与 Server 运行在同一台主机上,提供监控数据的展现和系统配置,主要配置包括监控模板、告警等。
4)Proxy
可选组件,常用于分布式监控环境中,代理 Server 收集部分被监控端的监控数据并按照一定的频率统一发往 Server 端。
Proxy 有自己的数据库,引入 Proxy 主要是为了解决以下两个问题。
Server 和 Agent 之间网络不连通,这种情况在跨网络、跨机房的场景中经常出现。
在大规模部署时减轻 Server 的压力,毕竟在同时连接这么多 Agent 时,Server 需要维护更多的连接。以 Proxy 模式进行部署时,Agent 配置的上游地址是 Proxy,而 Proxy 配置的是 Server。
5)Agent
部署在被监控主机上,负责收集本地数据并发往 Server 端或 Proxy 端,Agent 会启动一个名为 Agentd 的守护进程。
Agent 分为两种模式:主动和被动。主动是指 Agent 主动采集数据并将数据发送到 Server/Proxy;被动是指 Server 每次都主动调用 Agent 获取数据。Agent 还能执行用户的自定义脚本,从而完成一些原生 Agent 不具备的功能。
这里补充讲解 Zabbix 的一个工具,即 Zabbix_sender。Zabbix_sender 是一个命令行工具,可用于主动向 Zabbix 服务端发送监控数据,这样可避免 Agent 一直等待监控任务完成。有意思的是,Zabbix 本身由一个商业团队维护,该团队免费提供 Zabbix 软件,但收取支持和维护费用。这和 Red Hat 的思路如出一辙,在系统软件日趋成熟的未来,软件的商业模式将逐步从出售许可证转变为收取服务费用,这也是大势所趋。
2、Nagios
Nagios 原名为 NetSaint,由 Ethan Galstad 开发并维护。Nagios 是一个老牌监控工具,由C语言编写而成,主要针对主机监控(CPU、内存、磁盘等)和网络监控(SMTP、POP3、HTTP 和 NNTP 等),当然也支持用户自定义的监控脚本,如图1-13 所示。
图1-13
Nagios 的整体架构非常清晰,它通过 Plugin 采集各种监控数据,例如针对 SNMP 监控时,通过 SNMP plugin 和在监控对象上运行的 snmpd 通信获取网络信息;它还支持一种更加通用和安全的采集方式 NRPE(Nagios RemotePluginExecutor),它首先在远端启动一个 NRPE 守护进程,用于在远端主机上面运行检测命令,在 Nagios 服务端用 check nrep 的 plugin 插件通过 SSL 对接到 NRPE 守护进程,执行相应的监控行为。相比 SSH 远程执行命令的方式,这种方式更加安全。当然,Nagios 也支持 SSH 的 Plugin。
Nagios 数据被保存在 RDD(Round Robin Database,环形数据库)中,RDD 适用于存储时序数据,支持以下 4 种监控数据。
gauge:仪表盘数据。
counter:计数器。
absolute:不同时间段的变化率,为正数。
driver:变化率,指当前值和前一个监控数值的比值,有正有负。
RDD 的存储原理比较简单,它把整个数据存储空间构建成圆环,指针指向最新的数据位置并且会随着数据读写移动,如果此时没有获取监控数据,RDD 就会使用默认的 unknown 填充,保证数据对齐。每个数据库文件都以 .rdd 结尾,大小是固定的,如图1-14 所示。
图1-14
3、Open-Falcon
Open-Falcon 是小米开源的企业级监控工具,由 Go 语言开发而成,包括小米、滴滴、美团等在内的互联网公司都在使用它,是一款灵活、可扩展并且高性能的监控方案,整体架构如图1-15 所示。
图1-15
下面对如图1-15 所示的组件进行简单介绍。
Falcon-agent:用 Go 语言开发的 Daemon 程序,运行在每台 Linux 服务器上,用于采集主机上的各种指标数据,主要包括 CPU、内存、磁盘、文件系统、内核参数、Socket 连接等,目前已经支持 200 多项监控指标。并且,Agent 支持用户自定义的监控脚本,脚本必须返回 Agent 指定的数组格式。Agent 采集的数据会通过 RPC 方式上报到 Transfer。为了避免单个 Transfer 发生故障,Agent 支持配置多个 Transfer 地址,还可以忽略多余的监控指标。Agent 本身也可以成为一个 Proxy-gateway 代理网关,接收第三方 HTTP 请求并将其转发到 Transfer 中。
Hearthbeat server:简称 HBS(心跳服务),每个 Agent 都会周期性地通过 RPC 方式将自己的状态上报给 HBS,主要包括主机名、主机 IP、Agent 版本和插件版本,Agent 还会从 HBS 获取自己需要执行的采集任务和自定义插件。
Transfer:负责接收 Agent 发送的监控数据,并对数据进行整理,在过滤后通过一致性 Hash 算法将数据发送到 Judge 或者 Graph。为了支持存储大量的历史数据,Transfer 还支持 OpenTSDB。Transfer 本身没有状态,可以随意扩展。
Judge:告警模块,Transfer 转发到 Judge 的数据会触发用户设定的告警规则,如果满足,则会触发邮件、微信或者回调接口。这里为了避免重复告警,引入了 Redis 暂存告警,从而完成告警合并和抑制。
Graph:RRD 数据上报、归档、存储的组件。Graph 在收到数据以后,会以 RRDtool 的数据归档方式存储数据,同时提供 RPC 方式的监控查询接口。
API:主要提供查询接口,不但可以从 Graph 里读取监控数据,还可以对接 MySQL,用于保存告警、用户等信息。
Dashboard:由 Python 开发而成,提供 Open-Falcon 的数据和告警展现,监控数据来自 Graph,Dashboard 允许用户自定义监控面板。
Aggregator:聚合组件,聚合某集群下所有机器的某个指标的值,提供一种集群视角的监控体验。通过定时从 Graph 获取数据,按照集群聚合产生新的监控数据并将监控数据发送到 Transfer。
监控系统的对比
下面针对 Prometheus、Zabbix、Nagios 和 Open-Falcon 这几种监控系统进行横向对比,如表1-1 所示。
表1-1
监控系统 |
开发语言 |
成熟度 |
扩展性1 |
高性能 |
社区活跃度 |
对容器的支持 |
企业使用情况 |
Zabbix |
C +PHP |
高 |
高 |
低 |
中 |
低 |
高 |
Nagios |
C |
高 |
中 |
中 |
低 |
低 |
低 |
Open-Falcon |
Go |
中 |
高 |
高 |
中 |
中 |
中 |
Prometheus |
Go |
中 |
高 |
高 |
高 |
高 |
高 |
从开发语言上看,为了应对高并发和快速迭代的需求,监控系统的开发语言已经慢慢从C转移到 Go。
不得不说,Go 凭借简洁的语法和优雅的并发,在 Java 占据业务开发领域、C占领底层开发领域的情况下,准确定位中间件开发需求,在当前的开源中间件产品中被广泛应用。
从系统成熟度方面来看,Zabbix 和 Nagios 都是老牌的监控系统:Zabbix 是在 1998 年出现的,Nagios 是在 1999 年出现的,系统功能比较稳定,成熟度较高。而 Prometheus 和 Open-Falcon 都是最近几年才诞生的,虽然功能还在不断迭代、更新,但它们站在巨人的肩膀之上,在架构设计上借鉴了很多老牌监控系统的经验。
从系统扩展性方面来看,Zabbix 和 Open-Falcon 都可以自定义各种监控脚本。Zabbix 不仅可以做到主动推送,还可以做到被动拉取;Prometheus 则定义了一套监控数据规范,并通过各种 exporter 扩展系统采集能力。
从数据存储方面来看,Zabbix 采用关系数据库存储数据,这极大限制了 Zabbix 的数据采集性能。Nagios 和 Open-Falcon 都采用了 RDD 数据存储方式。Open-Falcon 还加入了一致性 Hash 算法进行数据分片,并且可以对接到 OpenTSDB,而且 Prometheus 自研的一套高性能时序数据库,在 V3 版本时可以达到每秒千万级别的数据存储,可通过对接第三方时序数据库扩展对历史数据的存储性能。
从社区活跃度方面来看,目前 Zabbix 和 Nagios 的社区活跃度比较低,尤其是 Nagios,Open-Falcon 的社区虽然也比较活跃,但基本都是国内的公司在参与。Prometheus 的社区活跃度很高,并且得到 CNCF 的支持,后期的发展值得期待。
从容器支持方面来看,由于 Zabbix 和 Nagios 出现得比较早,当时容器还没有诞生,所以它们对容器的支持自然也比较差。Open-Falcon 虽然提供了容器监控功能,但支持力度有限。Prometheus 的动态发现机制,不仅支持 Swarm 原生集群,还支持 Kubernetes 容器集群监控,是目前容器监控的最佳解决方案。Zabbix 在传统监控系统中,尤其是在服务器相关监控方面,占据绝对优势。Nagios 则在网络监控方面有广泛应用。伴随着容器的发展,Prometheus 开始成为容器监控方面的标配,并将被广泛应用。总体来说,Prometheus 可以说是目前监控领域最锋利的“瑞士军刀”了。
本文节选自《深入浅出 Prometheus:原理、应用、源码与拓展详解》一书。陈晓宇,杨川胡,陈啸编著,由电子工业出版社博文视点出版。