监控即服务:微服务架构的模块化系统

如今,除了整体代码之外,我们的项目还包括数十个微服务。 他们每个人都需要受到监控。 使用 DevOps 工程师进行如此大规模的工作是有问题的。 我们开发了一个监控系统,为开发人员提供服务。 他们可以独立地将指标写入监控系统,使用它们,基于它们构建仪表板,并向它们附加警报,这些警报将在达到阈值时触发。 对于 DevOps 工程师来说,只有基础设施和文档。

这篇文章是我与我们的演讲的记录 部分 在 RIT++。 许多人要求我们从那里制作报告的文本版本。 如果您参加了会议或观看了视频,您不会发现任何新内容。 还有其他所有人 - 欢迎来到猫。 我将告诉你我们是如何建立这样一个系统的,它是如何工作的,以及我们计划如何更新它。

监控即服务:微服务架构的模块化系统

过去:计划和计划

我们是如何得出现在的监控系统的? 要回答这个问题,需要回到2015年。 这就是当时的样子:

监控即服务:微服务架构的模块化系统

我们有大约 24 个节点负责监控。 有一大堆不同的王冠、脚本、守护进程以某种方式监视某些东西、发送消息和执行功能。 我们认为,我们走得越远,这样的系统就越不可行。 开发它是没有意义的:它太麻烦了。
我们决定选择保留和开发的监控元素以及放弃的监控元素。 一共有 19 个,只剩下石墨、聚合器和作为仪表板的 Grafana。 但新系统会是什么样子呢? 像这样:

监控即服务:微服务架构的模块化系统

我们有一个指标存储:这些是石墨,它将基于快速 SSD 驱动器,这些是某些指标聚合器。 接下来 - Grafana 用于显示仪表板,Moira 用于警报。 我们还想开发一个用于搜索异常的系统。

标准:监控2.0

这就是 2015 年的计划。但是我们不仅要准备基础设施和服务本身,还要准备其文档。 我们为自己制定了企业标准,我们称之为监控2.0。 对系统有什么要求?

  • 持续可用性;
  • 指标存储间隔 = 10 秒;
  • 指标和仪表板的结构化存储;
  • SLA > 99,99%
  • 通过 UDP 收集事件指标(!)。

我们需要 UDP,因为我们有大量的流量和生成指标的事件。 如果一次性将它们全部写入石墨中,存储就会崩溃。 我们还为所有指标选择了一级前缀。

监控即服务:微服务架构的模块化系统

每个前缀都有一些属性。 服务器、网络、容器、资源、应用程序等都有指标。 清晰、严格、类型化的过滤已经实现,我们接受第一级指标并简单地丢弃其余的。 这就是我们在 2015 年规划该系统的方式。 现在有什么?

呈现:监控组件交互图

首先,我们监控应用程序:我们的 PHP 代码、应用程序和微服务 - 简而言之,我们的开发人员编写的所有内容。 所有应用程序都通过 UDP 将指标发送到 Brubeck 聚合器(statsd,用 C 重写)。 事实证明,它是综合测试中最快的。 它通过 TCP 将已经聚合的指标发送到 Graphite。

它有一种称为计时器的指标。 这是一件非常方便的事情。 例如,对于连接到服务的每个用户,您可以向 Brubeck 发送一个包含响应时间的指标。 收到了一百万个回复,但聚合器只返回了 10 个指标。 您有来访人数、最长、最短和平均响应时间、中位数和 4 个百分位数。 然后数据被传输到 Graphite,我们可以实时看到这一切。

我们还对硬件、软件、系统指标和我们旧的 Munin 监控系统(它一直为我们工作到 2015 年)进行了汇总。 我们通过 C 守护进程 CollectD 收集所有这些(它内置了一大堆不同的插件,它可以轮询安装它的主机系统的所有资源,只需在配置中指定将数据写入何处)并且通过它将数据写入Graphite。 它还支持 python 插件和 shell 脚本,因此您可以编写自己的自定义解决方案:CollectD 将从本地或远程主机(假设为 Curl)收集此数据并将其发送到 Graphite。

然后我们将收集到的所有指标发送到 Carbon-c-relay。 这是 Graphite 的 Carbon Relay 解决方案,用 C 语言进行了修改。这是一个路由器,用于收集我们从聚合器发送的所有指标并将它们路由到节点。 同样在路由阶段,它会检查指标的有效性。 首先,它们必须与我之前展示的前缀方案相对应,其次,它们对石墨有效。 否则它们就会掉落。

然后 Carbon-c-relay 将指标发送到 Graphite 集群。 我们使用用 Go 重写的 Carbon-cache 作为指标的主要存储。 由于其多线程,Go-carbon 的性能远远优于 Carbon-cache。 它使用 Whisper 包(标准,用 Python 编写)接收数据并将其写入磁盘。 为了从我们的存储中读取数据,我们使用 Graphite API。 它比标准 Graphite WEB 快得多。 接下来数据会发生什么?

他们去了格拉法纳。 我们使用石墨集群作为主要数据源,此外我们还使用 Grafana 作为显示指标和构建仪表板的 Web 界面。 对于每项服务,开发人员都会创建自己的仪表板。 然后他们基于它们构建图表,显示他们从应用程序编写的指标。 除了Grafana,我们还有SLAM。 这是一个基于 Graphite 数据计算 SLA 的 Python 恶魔。 正如我已经说过的,我们有几十个微服务,每个微服务都有自己的要求。 使用 SLAM,我们查看文档并将其与 Graphite 中的内容进行比较,并比较需求与我们服务的可用性的匹配程度。

让我们更进一步:警报。 它是使用一个强大的系统——莫伊拉(Moira)来组织的。 它是独立的,因为它有自己的 Graphite。 由 SKB“Kontur”的人员开发,用 python 和 Go 编写,完全开源。 莫伊拉接收到的流量与进入石墨的流量相同。 如果由于某种原因您的存储失效了,您的警报仍然有效。

我们在 Kubernetes 中部署了 Moira;它使用 Redis 服务器集群作为主数据库。 结果是一个容错系统。 它将指标流与触发器列表进行比较:如果其中没有提及,则它会删除该指标。 因此它每分钟能够消化千兆字节的指标。

我们还为其附加了一个企业 LDAP,借助该 LDAP,企业系统的每个用户都可以根据现有(或新创建的)触发器为自己创建通知。 由于 Moira 包含 Graphite,因此它支持其所有功能。 因此,您首先将线路复制到 Grafana 中。 查看数据如何在图表上显示。 然后你将同一行复制到 Moira 中。 您将其挂起限制并在输出处收到警报。 要完成这一切,您不需要任何特定知识。 Moira 可以通过短信、电子邮件、Jira、Slack 发出警报......它还支持执行自定义脚本。 当触发器发生在她身上,并且她订阅了自定义脚本或二进制文件时,她会运行它并将该二进制文件的 JSON 发送到 stdin。 因此,您的程序必须解析它。 您将如何处理此 JSON 取决于您。 如果你愿意,可以将其发送到 Telegram,如果你愿意,可以在 Jira 中打开任务,执行任何操作。

我们还使用我们自己开发的警报 - Imagotag。 我们对通常用于商店电子价格标签的面板进行了改造,以满足我们的需求。 我们从莫伊拉那里带来了触发器。 它表明它们处于什么状态以及它们发生的时间。 一些开发人员放弃了 Slack 和电子邮件中的通知,转而使用此面板。

监控即服务:微服务架构的模块化系统

那么,由于我们是一家进步的公司,所以我们也在这个系统中监控了 Kubernetes。 我们使用 Heapster 将其包含在系统中,我们将其安装在集群中,它收集数据并将其发送到 Graphite。 结果,该图如下所示:

监控即服务:微服务架构的模块化系统

监控组件

以下是我们用于此任务的组件的链接列表。 它们都是开源的。

石墨:

碳-c-继电器:

github.com/grobian/carbon-c-relay

布鲁贝克:

github.com/github/brubeck

收集到:

收集网站

莫伊拉:

github.com/moira-alert

格拉法纳:

grafana.com

堆垛机:

github.com/kubernetes/heapster

统计

以下是有关该系统如何为我们运作的一些数据。

聚合器(布鲁贝克)

指标数量:~300/秒
向 Graphite 发送指标的时间间隔:30 秒
服务器资源使用:~ 6% CPU(我们谈论的是成熟的服务器); ~ 1Gb 内存; ~3 Mbps 局域网

石墨(碳)

指标数量:~ 1/分钟
指标更新间隔:30秒
指标存储方案:30秒35天、5分钟90天、10分钟365天(让您了解服务在很长一段时间内发生了什么)
服务器资源占用:~10% CPU; ~ 20Gb 内存; ~30 Mbps 局域网

灵活性

我们 Avito 非常重视监控服务的灵活性。 他到底为什么会变成这样? 首先,它的组件是可以互换的:组件本身及其版本。 其次,支持性。 由于整个项目是开源的,您可以自己编辑代码,进行更改,并实现开箱即用的功能。 使用了相当常见的堆栈,主要是 Go 和 Python,因此完成起来非常简单。

这是一个实际问题的例子。 Graphite 中的度量是一个文件。 它有一个名字。 文件名 = 指标名称。 有一种方法可以到达那里。 Linux 中的文件名限制为 255 个字符。 我们有来自数据库部门的人员(作为“内部客户”)。 他们告诉我们:“我们想要监控我们的 SQL 查询。 它们不是 255 个字符,而是每个 8 MB。 我们希望在 Grafana 中显示它们,查看此请求的参数,更好的是,我们希望看到此类请求的顶部。 如果能实时显示那就太好了。 如果能让他们处于警戒状态,那真是太酷了。”

监控即服务:微服务架构的模块化系统
示例 SQL 查询取自 网站 postgrespro.ru

我们设置了一个 Redis 服务器并使用我们的 Collectd 插件,该插件会转到 Postgres 并从那里获取所有数据,并将指标发送到 Graphite。 但我们用哈希值替换了指标名称。 我们同时将相同的哈希作为键发送到 Redis,并将整个 SQL 查询作为值发送到 Redis。 我们所要做的就是确保 Grafana 可以访问 Redis 并获取这些信息。 我们开放 Graphite API 是因为…… 这是所有监控组件与 Graphite 交互的主界面,我们在其中输入一个名为 aliasByHash() 的新函数 - 从 Grafana 中我们获取指标的名称,并在对 Redis 的请求中使用它作为键,响应我们得到键的值,这是我们的“SQL查询”” 因此,我们在 Grafana 中显示了一个 SQL 查询的显示,理论上不可能在那里显示该查询,以及它的统计信息(调用、行、total_time,...)。

结果

可用性。 我们的监控服务可通过任何应用程序和任何代码 24/7 提供。 如果您有权访问存储设施,则可以将数据写入服务。 语言不重要,决定也不重要。 您只需要知道如何打开套接字、在其中放置度量并关闭套接字。

可靠性。 所有组件都是容错的并且可以很好地处理我们的负载。

入门门槛低。 为了使用这个系统,您不需要学习 Grafana 中的编程语言和查询。 只需打开您的应用程序,在其中输入一个套接字,该套接字将向 Graphite 发送指标,关闭它,打开 Grafana,在其中创建仪表板并查看指标的行为,通过 Moira 接收通知。

独立。 您可以自己完成这一切,无需 DevOps 工程师的帮助。 这是一个优势,因为您现在可以监控您的项目,无需询问任何人 - 无论是开始工作还是进行更改。

我们的目标是什么?

下面列出的一切不仅仅是抽象的想法,而且至少已经迈出了第一步。

  1. 异常检测器。 我们想要创建一个服务,该服务将进入我们的 Graphite 存储并使用各种算法检查每个指标。 已经有我们想要查看的算法,有数据,我们知道如何使用它。
  2. 元数据。 我们有很多服务,它们随着时间的推移而变化,就像与它们一起工作的人一样。 持续手动维护文档不是一种选择。 这就是我们现在将元数据嵌入到微服务中的原因。 它说明了它的开发者、与之交互的语言、SLA 要求、通知应发送到何处以及发送给谁。 部署服务时,所有实体数据都是独立创建的。 结果,您会得到两个链接 - 一个链接到触发器,另一个链接到 Grafana 中的仪表板。
  3. 每个家庭都有监控。 我们相信所有开发人员都应该使用这样的系统。 在这种情况下,您始终了解您的流量在哪里,它发生了什么,它落在哪里,它的弱点在哪里。 例如,如果出现某些情况并使您的服务崩溃,那么您不会在经理的电话中而是通过警报了解到这一情况,并且您可以立即打开最新日志并查看那里发生了什么。
  4. 高性能。 我们的项目不断增长,如今每分钟处理约 2 个指标值。 一年前,这个数字是 000,而且还在继续增长,这意味着一段时间后 Graphite(whisper)将开始给磁盘子系统带来沉重的负载。 正如我已经说过的,由于组件的可互换性,该监控系统非常通用。 有人专门为 Graphite 维护并不断扩展他们的基础设施,但我们决定走不同的路线:使用 点击之家 作为我们指标的存储库。 这个过渡即将完成,很快我将更详细地告诉您这是如何完成的:存在哪些困难以及如何克服这些困难,迁移过程如何进行,我将描述选择作为绑定的组件及其配置。

感谢您的关注! 提出有关该主题的问题,我将尝试在这里或在以下帖子中回答。 也许有人有构建类似监控系统或在类似情况下切换到 Clickhouse 的经验 - 在评论中分享。

来源: habr.com

添加评论