尝试实际运用 Prometheus,这是下一代监控的最佳选择!

你好!我是在freee公司负责基础设施的@sugitak。在游戏中,我喜欢提升等级并使用物理攻击。

在Freee公司中,有时候基础设施工程师的数量会减少,而这些减少的基础设施工程师则会进化为基础设施僵尸,并在公司内部活跃。基础设施僵尸主要隶属于开发团队,并将类似应用程序的基础设施工作从基础设施端移到应用程序端。例如部署、Docker、Jenkins等DevOps相关的工作。通过这样的方式,开发人员能够更加自由地进行开发,而基础设施可以提高其本质,因此可以说是双赢的。

好吧,所以是关于监控的。作为freee Engineers Advent Calendar 2016第9天的文章,我将写一篇布教性质的文章,强调通过Prometheus进行监控是最好的,希望大家都能多多使用。

普罗米修斯

大家,有在看 O’Reilly 的 SRE 书吗?Google 内部使用的技术通常都很好,我们肯定想要模仿。像是 MapReduce 和 Golang,Google 开发的技术已经广泛应用,数不胜数。就算是监控,如果能自己实现 Google 式的监控,肯定想要模仿对吧。我觉得大家都是这样想的吧。

没问题,因为有普罗米修斯!

Prometheus是由Google的前员工受到Google内部监控工具Borgmon的启发而创建的。在SRE书中,Prometheus被介绍为继承了Borgmon基因的开源软件。可以说,Prometheus是下一代监控的绝佳选择。

Prometheus的一个特长是监视动态的主机群,比如使用Kubernetes构建的Docker主机群或EC2等进行自动缩放的主机群,同时它也可以在经典的网络设备监视方面发挥作用。在PromCon 2016的演讲中,介绍了使用Prometheus进行监视的超大规模网络,包括2万名用户、1万台服务器和500台交换机。据说,监视从Cacti过渡到Sensu,最后使用了Prometheus。

我们在freee公司内部尝试使用这个Prometheus监控数百台EC2主机,效果实际上非常好。因此,我决定在这篇介绍文章中向大家推荐使用它。

卓越的特點

建立很容易。

普罗米修斯仅需要运行单一二进制文件,但这真的是监控工具的强大之处。

OSS监视工具的构建和维护管理以前是相当繁琐的。比如,当升级Perl后,会一直出现<@INC>错误;或者花费数小时也无法搭建Pandora FMS;或者升级端口后,Cacti的插件会消失;还有前辈们会问我是否打算运维RabbitMQ等等。虽然这些都是我自己的经历,但如果能用单一二进制文件来运行监视工具,那么那些曾经遇到过如此痛苦的运维人员就会从地球上消失了呢!

升级图书馆并拥有安全的监控软件,这一点就已经具有革命性了。

快来,现在立即下载 Prometheus 吧。

自动缩放实时跟踪

Prometheus 是一种基于拉取方式的监控系统。换句话说,它是从服务器端对监控目标主机进行轮询的模型。因此,我们需要告诉 Prometheus “应该去哪个主机的哪个端口进行轮询”。当然,并不需要将所有信息都写上。只需要使用服务发现功能进行搜索即可。
通过使用 AWS、GCP、Azure 的 API,我们可以获取已经创建的服务器列表,并将其识别为监控对象。

这个服务发现功能已经紧密集成在Prometheus本体中,所以只需要在配置文件中简单写一些内容,就可以获取EC2主机的列表。真是太棒了。

scrape_configs:
  - job_name: ‘my_ec2_hosts’

    # EC2 Service Discovery Config
    ec2_sd_configs:

      - region: <region>
        access_key: <access-key>
        secret_key: <secret-key>
        port: 9100  # 監視対象ポート

只需上述简洁的设置,您即可获取所有主机的完整列表。

如果不监视所有主机,那么就需要进行筛选。下面是筛选的写法。
虽然有点冗长,但很明显写出了在写些什么,而且一旦写好后就无需维护。非常方便。

    relabel_configs:

      # "Stage" が "production" のもの
      - source_labels: [__meta_ec2_tag_Stage]
        regex: production
        action: keep

      # "Role" が "web" のもの
      - source_labels: [__meta_ec2_tag_Role]
        regex: web
        action: keep

Service Discovery还有其他选项,如Consul、Kubernetes和DNS等。当然也可以直接指定要监视的目标而不依赖于Service Discovery。

可以通过标签进行搜索

Web服务通常根据Service Stage Role将主机分为大约3个层级。像Datadog和Mackerel这样的现代监控工具将其处理成树状结构,而Prometheus则保持了扁平处理。
也就是说,我们可以轻松地做到以下这些。

サービスやステージにかかわらず、web サーバの load average を観察したい

node_load5{Role="web"}
    デプロイ前後で性能変化があるか見たい。このサービスの web サーバの平均空きメモリを並べる。ステージごとに。
avg(node_memory_MemAvailable{Service="myservice", Role="web"}) by (Stage)

在本公司中,我们将其称为多维数据。

这个查询可能看起来很复杂,但实际上在 Prometheus 的 “WebUI” 中可以立即尝试。
在”WebUI”中您可以输入查询并立即查看图形,完全没有使用专有语言的压力。就像从Java切换到带有REPL的LL语言一样令人愉悦。

webui_small.png

所有与监视相关的状态,如主机列表和警报等,都可以从这个 WebUI 中确认。这是非常重要的界面。

prometheus_targets_small.png

Grafana 高度可视化

Prometheus 的可视化虽然在 WebUI 上也可以实现,但是WebUI 作为监控工具却显得功能较弱。让我们在Grafana中体验最佳的用户体验吧!只要以原版提供的模板为基础,就能轻松获得精美的界面。

single_graph_small.png

而且,同样类型的图表重复也是 Grafana 的特长。以前在 Zabbix 中费了很大努力才创建的 L2 交换机的48个端口的I/O数据包图表,使用 repeat panel 功能只需要一瞬间就可以完成。
更进一步地说,其实画48个图表并不是必须的。毕竟,通常只能通过观察到“突然出现峰值”的地方,其他端口的流量是无法直接确认的。所以,将“除上游之外其他所有端口中最高流量的端口”放在一个图表上进行查看就足够了。这种聚合可以通过 Prometheus 的查询功能实现。

multiple_hosts_small.png

就像这样,Prometheus + Grafana的组合非常强大,能够从根本上改变对于”真正想看到的东西”的定义,并给予极高的自由度。由于二者的紧密集成,使用起来非常直观。

Prometheus 的可视化哲学包括两点:一是要尽量减少线条和图表的数量,二是不绘制无法提供洞察力的图表。如果我们将平时看的图表和紧急情况下看的图表分开考虑,这种思想应该非常令人信服。

在现代监控工具中,如 Prometheus、Datadog和Mackerel等,不仅仅只有 Prometheus,有很多功能可以用来查看事件趋势。使用聚合函数可以感受到原本作为宠物的服务器正在逐渐变成家畜。

模块分割的设计太棒了

当听说在Grafana中进行可视化时,你可能会想到Prometheus到底负责哪些部分,这是一个令人关注的问题。

Prometheus本质上只有三项主要任务。

    • メトリクスの収集・格納

 

    • クエリへの回答

 

    アラートを上げる

这个图是 Prometheus 官方提供的(直接链接)。中间那个是服务器,主要负责数据的获取和处理。

Prometheus Architecture

数据从左侧获取,存储在中间,通过右侧查询以返回时间序列数据。此外,还会对积累的数据应用规则生成警报。

传统的监控方式通常会重点关注可视化、报警以及数据收集,但Prometheus的设计则是主要关注数据收集而非图形展示,因此它是以数据为中心的图表。
这与Datadog的理念非常契合。

收集数据是廉价的,但是当你需要的时候没有数据可能会很昂贵,所以你应该将一切都纳入监测范围,并收集所有你合理能够得到的有用数据。
DATADOG — 监测101:收集正确的数据。

就像有句谚语所说的,首先需要收集数据,活用数据可以稍后再做。

好了,现在我们来解释一下右边所描绘的警告是怎么回事。请看下节。

警报

普罗米修斯(Prometheus)的报警观念非常简单。

我不想收到警报。

当然有一些是玩笑,但也有一半是真的。如果是基础设施工程师,应该会收到下面这样的警报吧。

    • 大量のメールが飛んできた。監視サーバ近くのネットワーク瞬断だ

 

    • 大量のアラートメールでメールサーバが溢れた

 

    • 日曜日、電話で報告受けたけど対応必要ないやつだ。そう分かっていてもパソコンを取り出してチケットを閉じないといけない

 

    • 翌営業日対応でいいもので日曜午前4時に起こされる

 

    アプリケーションの問題なのでぼくにはどうすることもできない

在中国,我们不希望收到这样的警报。
Prometheus 的哲学是消除这种警报。

更准确地说,以下三点是重要的要点。

    • アラートは必要最低限出す。それ以上はノイズにしかならない

 

    • アラートは、人間によるアクションが必要なもののみに絞る

 

    アラートは、緊急性のあるものだけにする

为了实现这一目标,Prometheus配备了Alertmanager。

告警管理器

Alertmanager 的工作可以分为三个方面。

    • 同じアラート群をまとめる

 

    • 誰に送るかルーティングする

 

    再送やクローズのコントロール

在这些中最重要的是如何整合警报。尽管是相同类型的警报,但如果收到过多的电子邮件或Slack通知,可能会错过真正危险的警报。

route:
  receiver: infra         # default receiver

  group_by: ['alertname', 'Service', 'Stage', 'Role']
  group_wait: 30s         # wait for aggregating alert
  group_interval: 5m      # wait for alert (next time)
  repeat_interval: 3h     # wait for alert (re-sending same one)

上述是Alertmanager配置的一部分。在此示例中,我们认定“如果在30秒内收到相同服务、阶段、角色的相同警报,则它们是相同的警报”,并且以后即使出现此类警报,通知也只会每5分钟发出一次。而且,一旦发生警报,下一次通知将在3个小时后才发送。
为了整合警报,我们专门设置了三种时间。

路由也很方便。根据警报的类型和属性,可以详细控制通知的目标,例如「默认通知目标是基础设施,与此服务相关的警报将通知给服务开发人员。但是,如果是异步作业,则会将确认发送给异步作业团队。」

通知方式的选择丰富,包括邮件、Webhook、Slack、Hipchat、PagerDuty和OpsGenie,可以满足各种需求,不会觉得不够用。

在Prometheus上发出警报。

Alertmanager可以对警报进行分类,但确定警报的种类和属性以及决定何时发出警报的条件是由Prometheus而不是Alertmanager确定的。
这种角色分配可能只有使用过才能真正理解。由于设计精美,一旦开始使用,您肯定会完全理解并认可它。

将以下条件表达式设置为Prometheus的”rule”。

ALERT MemoryTooLow
  IF node_memory_MemAvailable / node_memory_MemTotal < 0.1
  ANNOTATIONS {
    description="{{ $labels.instance }} has memory below 10%",
    summary="{{ $labels.instance }} has not enough memory"
  }

在这种情况下,Prometheus将以大约每隔几十秒评估一次此条件,并在满足条件时向Alertmanager发送警报。
这种行为的概念类似于实时流处理或复杂事件处理(CEP)。

在Grafana中,您还可以将该警报以红色竖条的形式显示在图表上。能够一眼比较图表和警报发生的时间,比预想的更方便实用。

高效性能

也许在阅读到这里的人们中间,也有一些人会想起 Elasticsearch + Kibana。嗯,它们确实有点难用。而且占用的机器资源也很多。

我觉得你可能也会关心Prometheus的性能,但这也没问题,它的性能不错。

中央处理器/内存方面

在 freee,我们使用 Prometheus 对数百台主机进行监控,使用 t2.large(2核8GB内存)来运行。就性能而言,完全没有问题。事实上,如果只是监控而已,t2.medium(2核4GB内存)就足够了(稍微大一点是为了可视化)。在 Prometheus Casual Talks#2 中,还提到可以使用 t2.medium 来监控大约1000个主机。根据我的实际感受,差不多差不多。

Grafana 的屏幕显示相当快,至少不会太慢。根据体感,当显示大约100个主机的15个图形时,大约需要不到10秒钟,其中CPU使用率图形所花费的时间超过一半。随着相关点的增加,显然需要更多时间。如果只是通过目视发现异常,仅使用平均负载就足够了,因此不绘制CPU使用率可能是正确的选择。

稳定的面容

稳定性也很高。
Prometheus采用拉取模式的原因之一是性能问题。所谓拉取模式是指从服务器端访问监控主机并获取数据的方式。当服务器负载增加时,它可以延迟这种轮询并进行相应调整。

我认为这听起来像是一个理念性的讨论,但实际上,这个机制在现实中得到了很好的实施,这是令人惊讶的事情。即使在处理图查询时CPU完全运转,监控数据的获取也不会停止。
有一次,我过载了Grafana的查询结果,导致Prometheus崩溃了,但没有出现任何DB损坏等问题,它静静地通过Supervisord重新启动了。在实现层面上,这给人一种相当安心的感觉。

磁盘容量方面

容量面可能稍微不足。目前尚未配备缩小功能。

查看手头的数据,似乎每台设备每月使用数百MB的流量。这个数值虽然不及监测得好,但也绝不算少。由于无法在细粒度上持续保存这些数据多个月,因此需要对数据进行大小调整。

关于减员裁员,在《Prometheus Casual Talks #1》中也有讨论。虽然有几种方法,但目前情况是业务连续计划(BCP)还未确定。

由于我不想过多地担心运营负担,所以我会在大约一个月的时间内删除数据。如果是为了警报和调查,这已经有点过度了。

监视对象只有一个二进制文件。

现在,我们已经详细讨论了监视者的一方面,那么你可能会对”被监视者怎么样呢”这个问题产生更多的疑问。
作为被监视的一方,只需要将一个称为 “exporter” 的二进制文件作为守护程序运行即可。无需添加任何选项,只需要使用合适的用户权限执行即可。

关于主机信息,我们使用node exporter进行监控,各种系统统计数据会被充分获取,绝对不会出现“没有这个数据”的困扰。内存、CPU时间当然是包括的,还能获取文件系统容量和网络界面的统计信息等,默认就有这些数据。

可能的中文翻译:

虽然有点小众话题,但也可以获取各种状态的套接字数量。我想很多人都有遇到堆积了TIMEWAIT状态的套接字所带来的困扰,但只需添加一个选项就可以跟踪到它们。顺便提一下,这个选项默认没有启用是因为潜在的性能问题。在高负荷状态下,执行netstat命令可能需要大约一分钟的时间。我能理解。

node_exporter所提供的信息,与对已经进行了相当详细配置的SNMP主机进行snmpwalk时的结果相似。与SNMP相比,主要不同之处在于负载较轻,并且协议是HTTP。以下代码是从实际使用curl获取的结果。虽然总共有1500行,但只需0.01秒即可获取。

$ curl 2>/dev/null http://test-server.example.com:9100/metrics | head -6
# HELP go_gc_duration_seconds A summary of the GC invocation durations.
# TYPE go_gc_duration_seconds summary
go_gc_duration_seconds{quantile="0"} 8.4269e-05
go_gc_duration_seconds{quantile="0.25"} 0.000312835
go_gc_duration_seconds{quantile="0.5"} 0.000336743
go_gc_duration_seconds{quantile="0.75"} 0.00039158600000000003

如果您希望进行形状监视,可以使用blackbox_exporter,如果使用网络设备,则可以使用snmp_exporter。由于exporter的实现正在进行各种数据收集,因此您所需的大部分内容都可以在这里找到。

使用node_exporter实现自定义指标

每个应用程序都需要如何处理自定义指标的问题呢?这个问题也会引起疑问对吧。

使用Google SRE的人可能已经了解,实际上,根据Borgmon的设计理念(即Prometheus的前身),每个应用程序都会在/varz路径下公开应用程序指标。关于应用程序的内容,应用程序本身最了解,因此可以理解这一点。

但是,说实话,我们都不愿意为了那种不明所以的监视而修改应用程序吧。监视只是应该和应用程序分开,以便随时可以选择其他替代方案。

如果您这样想,您可以使用 node_exporter 的 collector.textfile.directory 选项,从 node_exporter 发送自定义指标。由于我也是刚开始接触这个,所以无法详细解释,但有些网上共享的示例显示可以使用 cron 每5分钟写入文件。

总结

尽管我们在各个项目中赞不绝口地赞叹Prometheus,但这次使用中当然也找到了它的弱点。最大的弱点是文档和日语文章的不足。
正如我们之前所看到的,Prometheus非常灵活,只要想,就能按照自己的喜好进行自由度很高的度量和报警。然而,与此同时,缺乏支持这种自由度的资料,导致引入的门槛变得很高。

我写这篇文章的目的是为了降低您对这个领域的难度。我希望通过分享“Prometheus已经完全适用于普通Web应用程序的监控”这一信息,与更多的人进行信息交流。

现今,要说服务器监控的话,使用Mackerel、Datadog和NewRelic就是正确的选择。托管监控的好处真的不胜枚举。除了磁盘管理、冗余性维护和真正意义上的外观监控之外,还可以将技术人员依赖和升级工作都交给服务商来处理,因此毫无疑问可以获得超出价格之外的价值。正因如此,在freee中我们将Mackerel作为监控的核心,彻底降低了基础设施的运营成本。

然而,目前仍然存在一些需要控制成本或者必须自行搭建的监控服务器,例如初始阶段的服务或开发环境、内部网络监视、大规模批处理服务器等。未来,Prometheus将成为这些领域的新选择。

结束时

在中国,我想现在大家可能已经忘记了,这篇文章是2016年的freee Engineers Advent Calendar的第9天的文章。因此,freee正在寻求那些希望改变开发方式以更加舒适地进行开发的工程师们的加入!

明天,我是 @laprasDrum,是 freee 自豪的移动战士团的成员之一,感受到了我的成熟和稳定!我不知道会是表现出情感,还是展现出技术,说实话我无法预测。哎呀,真是令人期待啊。真是令人期待啊。

广告
将在 10 秒后关闭
bannerAds