vlambda博客
学习文章列表

读书笔记《hands-on-infrastructure-monitoring-with-prometheus》理解和扩展AlertManager

Understanding and Extending Alertmanager

警报是任何监控堆栈中的关键组件。在 Prometheus 生态系统中,警报及其后续通知是解耦的。 Alertmanager 是处理这些警报的组件。在本章中,我们将专注于使用 Alertmanager 将警报转换为有用的通知。从可靠性到定制化,我们将深入研究 Alertmanager 服务的内部运作,提供配置、故障排除和定制所有可用选项所需的知识。我们将确保警报路由、静默和抑制等概念清晰,以便您可以决定如何在自己的堆栈中实现它们。

由于Alertmanager 是一个关键的组件,所以高可用也会有所探讨,我们也会解释一下Prometheus 和Alertmanager 的关系。我们将自定义通知并学习如何构建和使用可重用模板,以便通知在到达目的地时是适当的并携带准确的信息。我们将通过学习如何监控监控系统来结束本章,更重要的是,学习如何在系统部分或完全关闭时发出警报。

我们将在本章中探讨以下主题:

  • Test environment for this chapter.
  • Alertmanager fundamentals.
  • Alertmanager configuration.
  • Common Alertmanager notification integrations.
  • Customizing your alert notifications.
  • Who watches the Watchmen?

Setting up the test environment

为了与 Alertmanager 一起工作,我们将使用三个新实例来模拟高可用性设置。这种方法不仅可以让我们公开所需的配置,还可以验证一切如何协同工作。

我们将使用的设置类似于下图:

读书笔记《hands-on-infrastructure-monitoring-with-prometheus》理解和扩展AlertManager
Figure 11.1: Test environment

Deployment

让我们从部署 Alertmanager 测试环境开始:

  1. To launch a new test environment, move into this chapter's path, relative to the repository root:
cd ./chapter11/
  1. Ensure that no other test environments are running and spin up this chapter's environment:
vagrant global-status
vagrant up
  1. You can validate the successful deployment of the test environment using the following command:
vagrant status

您将收到以下输出:

Current machine states:

prometheus running (virtualbox)
alertmanager01 running (virtualbox)
alertmanager02 running (virtualbox)
alertmanager03 running (virtualbox)

This environment represents multiple VMs. The VMs are all listed
above with their current state. For more information about a specific
VM, run `vagrant status NAME`.

当部署任务结束时,您将能够使用您最喜欢的支持 JavaScript 的 Web 浏览器验证主机上的以下端点:

服务

端点

普罗米修斯

http://192.168.42.10:9090

警报管理器01

http://192.168.42.11:9093

警报管理器02

http://192.168.42.12:9093

警报管理器03

http://192.168.42.13:9093

您应该能够使用以下命令之一访问所需的实例:

实例

命令

普罗米修斯

vagrant ssh prometheus

Alertmanager01

vagrant ssh alertmanager01

Alertmanager02

vagrant ssh alertmanager02

Alertmanager03

vagrant ssh alertmanager03

Cleanup

完成测试后,只需确保您在 ./chapter11/ 内并执行以下命令:

vagrant destroy -f

不用太担心 如果需要,您可以轻松地再次启动环境。

Alertmanager fundamentals

我们在 第 9 章中介绍了 Prometheus 中警报规则的工作原理,< em>定义警报和记录规则,但这些规则本身并没有那么有用。正如我们之前提到的,Prometheus 通过 Webhook 样式的 HTTP 接口将通知处理和路由委托给外部系统。这就是 Alertmanager 的用武之地。

Alertmanager 负责接受 Prometheus 警报规则生成的警报并将其转换为通知。后者可以采用任何形式,例如电子邮件消息、聊天消息、页面,甚至是 Webhook,然后将触发自定义操作,例如将警报记录到数据存储或创建/更新票证。 Alertmanager 也是官方堆栈中唯一一个跨实例分布其状态的组件,以便它可以跟踪诸如哪些警报已经发送以及哪些警报被静音等事情。

The notification pipeline

下图受 Alertmanager 架构图的启发,概述了警报在作为通知成功发送之前所经历的步骤:

读书笔记《hands-on-infrastructure-monitoring-with-prometheus》理解和扩展AlertManager
Figure 11.2: Notification pipeline overview

前面的图表有很多内容需要解压,因此我们将在接下来的几节中逐一介绍这些步骤。了解警报管道的工作原理将帮助您了解各种配置选项、如何排除警报丢失的问题,并充分利用 Alertmanager 提供的所有功能。

Dispatching alert groups to the notification pipeline

每当触发警报规则时,Prometheus 将以 JSON 有效负载的形式向 Alertmanager API 发送警报,并且它将在该规则的每个评估间隔或每分钟(可通过 --rules .alert.resend-delay 标志),以较长者为准。当 Alertmanager 收到警报时,它们会通过调度步骤,在此步骤中,它们将使用一个或多个警报标签进行分组,例如 alertname。我们将在本章稍后的 Alertmanager 配置 部分中讨论更多相关内容。这允许您将警报分类,这可以减少作为同一类别中的多个警报发送并在单个通知中组合在一起的通知数量,这将触发通知管道:

读书笔记《hands-on-infrastructure-monitoring-with-prometheus》理解和扩展AlertManager
Figure 11.3: Alertmanager interface grouping alerts by alertname

当运行具有相同配置的多个 Prometheus 实例时(追求高可用性/冗余时的常见设置),相同条件的警报规则不一定会在完全相同的时间触发。 Alertmanager 通过具有可配置的时间间隔来解决这种情况。它会在执行任何其他操作之前等待,以便可以将类似的警报组合在一起,从而避免针对单一类型的问题发送多个通知。

此分组在所有用户指定的标准中并行完成。然后每个组将触发通知管道,我们将在下面介绍。

Inhibition

一个很好的例子可以帮助我们理解什么警报抑制是想象一个服务器机架以及如果架顶交换机发生故障会发生什么。在这种情况下,该机架中的所有服务器和服务将开始触发警报,因为它们突然变得无法访问。为避免此问题,我们可以使用架顶开关的警报,如果触发该开关,将阻止该机架中所有其他警报的通知发出。这有助于操作员更加专注于真正的问题,并避免大量无法操作的警报。

因此,简而言之,抑制允许您映射警报之间的依赖关系,从而防止相关警报的通知在通知管道中进一步传播。这是在 Alertmanager 配置文件中设置的,这意味着如果更改,禁止需要重新加载服务。

如果在抑制阶段警报不匹配,它将进入消音器步骤。

Silencing

静音是监控/警报系统中的常见概念;这是您可以避免警报通知以有时间限制的方式发出的方法。它通常用于在维护窗口期间禁用通知,或在事件期间暂时抑制重要性较低的警报。 Alertmanager 采用了这一概念,并通过利用以下事实来增强它:传入的警报通常具有一个或多个不同的标签:来自原始警报规则表达式的标签、警报名称、警报的标签字段、来自 alert_relabel_configs< /span>,以及来自 Prometheus external_labels 的那些。这意味着这些标签中的任何一个(或它们的组合)都可用于通过直接匹配或通过正则表达式匹配来临时禁用通知:

读书笔记《hands-on-infrastructure-monitoring-with-prometheus》理解和扩展AlertManager
Figure 11.4: Creating a silence matching alertname=NodeExporterDown
You should be careful with regex matching as you can accidentally silence more than you expect. The Alertmanager web UI can help prevent this as it shows a preview of which firing alerts will be suppressed when creating new silences.

静音是在运行时定义的。它们可以使用 Alertmanager Web 界面、amtool(Alertmanager 命令行界面,稍后将介绍)或直接通过 API 进行设置。它们可以在警报触发时设置,例如在事件期间,或提前设置,以便计划维护不会向值班人员发送垃圾邮件。它不应该是射击警报的永久解决方案,只是一种临时措施;这就是为什么创建静默需要您为其设置到期日期,以及为什么 Web UI 只能识别长达数天的持续时间。

由于静音步骤是在抑制之后进行的,如果您将触发抑制规则的警报静音,它将继续抑制其他警报。

如果警报不匹配任何静默,它将进入通知管道的下一步,即路由阶段。

Routing

当警报批次到达此阶段时,Alertmanager 需要决定将其发送到何处。由于最常见的用例是让不同的人对不同的警报感兴趣,不同警报严重性的不同通知方法,甚至两者的组合,此步骤仅通过路由树实现。它由路由(如果有的话)组成,每个路由指定一个或多个标签的匹配标准和一个接收器,以及一个根节点,它定义一个包罗万象的接收器,以防没有子路由匹配警报组经过。子路由可以有自己的路由,使其成为多级树。匹配按照路由声明的顺序进行,当路由匹配时首先进入定义的子路由,最高深度匹配将定义将使用哪个接收器。当我们使用 Alertmanager 配置将其付诸实践时,这将变得更加清晰。

接收者和通知者在概念上与地址簿联系人类似。接收者是命名的联系人,可以有一个或多个通知者,就像联系信息一样。 Alertmanager 支持许多不同的通知器,它们通常属于以下类别之一:电子邮件、聊天(Slack、WeChat、HipChat)和页面(PagerDuty、Opsgenie、VictorOps、Pushover)。此外,它还支持 Webhook 通知程序,这是一个通用集成点,可用于支持所有其他未内置在 Alertmanager 中的通知系统。

在此路由阶段将警报批次与接收器连接后,Alertmanager 将为该接收器中指定的每个通知器运行通知作业。该作业负责去重、发送和重试通知。对于重复数据删除,它首先检查通知日志(本章稍后将讨论)以确保尚未发送此特定通知;如果已经存在,则不采取进一步行动。接下来,它将尝试发送通知,如果成功,将记录在通知日志中。如果通知失败(例如,API 错误、连接超时等),作业将重试。

现在我们了解了通知管道的基础知识,让我们看看当有多个 Alertmanager 实例时会发生什么以及它们之间如何共享警报状态。

Alertmanager clustering

通知管道的概述不涉及 Alertmanager 的高可用性组件。实现高可用的方式是依靠八卦(基于 HashiCorp 成员列表,https://github.com/hashicorp /memberlist),而不是使用基于共识的协议;这意味着没有真正的理由在集群中选择奇数个实例。使用 gossip,集群在所有 Alertmanager 实例之间共享 通知日志 (nflog),这反过来将知道集群关于通知的集体状态。在网络分区的情况下,分区的每一侧都会发送通知,因为从逻辑上讲,接收更多通知比完全没有通知要好。

正如我们现在所知,抑制是在配置文件级别设置的,因此在所有 Alertmanager 实例中应该是相同的。但是,静音也需要在集群中传播,因为它们是在运行时在单个 Alertmanager 实例上设置的。这是验证集群是否按预期工作的好方法确认配置的静音是否在所有实例中都显示。

Alertmanager /#/status 页面显示 gossip 集群的状态以及已知的对等点。您可以在我们的测试环境中通过打开来查看此端点,例如,http://192.168.42.11:9093/#/status

读书笔记《hands-on-infrastructure-monitoring-with-prometheus》理解和扩展AlertManager
Figure 11.5: Alertmanager cluster status

集群在 Alertmanager 中的工作方式是这样的:每个 Prometheus 实例都向他们知道的所有 Alertmanager 实例发送警报。这些实例,假设它们都在同一个 HA 集群中,对它们自己进行排序,成为第一个的实例将处理警报通知。该实例将通过 gossip 分发通知日志,其中将列出已成功发送的通知。剩余的每个 Alertmanager 实例都会有越来越多的延迟,根据它们各自在排序中的位置,等待通知日志更新。这些实例将不会再次发送通知日志中的警报- 如果通知日志未声明在八卦延迟完成时已处理给定通知,则第二个警报管理器将照顾它,等等:

读书笔记《hands-on-infrastructure-monitoring-with-prometheus》理解和扩展AlertManager
Figure 11.6: Alertmanager clustering overview
Prometheus instances talk directly to all Alertmanager instances, since the cluster members will take care of deduplication between themselves. This means that no load balancers should be placed between Prometheus and Alertmanager.

Alertmanager 集群假设每个实例都使用相同的配置文件运行。但是,如果不这样做只会影响其删除重复通知的能力。

Alertmanager configuration

第 9 章中,定义警报和记录规则< /em>,我们讨论了 Prometheus 如何生成和推送警报。在明确了警报和通知之间的区别之后,现在是时候使用 Alertmanager 来处理 Prometheus 发送的警报并将其转换为通知了。

接下来,我们将完成 Prometheus 所需的配置,以及 Alertmanager 中可用的配置选项,以便我们从监控堆栈中发出通知。

Prometheus configuration

在 Prometheus 中需要进行一些配置,以便我们可以开始使用 Alertmanager。首先要做的是配置外部标签,这些标签是在与外部系统(包括但不限于 Alertmanager)通信时添加到时间序列数据(如果还没有)的标签。这些是唯一标识指标来源的标签,例如 regiondatacenterenvironment。根据经验,如果您想为每个抓取和记录规则添加相同的标签名称/值,那么该标签作为外部标签可能更有意义,因为它不会在 Prometheus 实例中为本地指标引入维度,但很可能在更高级别的系统中有用(例如联合或长期度量存储),我们还将在接下来的几章中看到。正如我们将在以下示例中看到的,外部标签是在 Prometheus 主配置文件的顶级 global 键中配置的。

第二件事是配置 Prometheus 以便它可以向 Alertmanager 发送警报。正如我们之前所讨论的,在 Alertmanager 集群 部分中,Prometheus 实例是必需的,这样您就可以找到并单独向所有 Alertmanager 集群成员发送警报。此配置是在 Prometheus 配置文件中名为 alerting 的顶级部分中设置的。在我们的测试环境中可以找到这个配置的一个例子,如下:

vagrant@prometheus:~$ cat /etc/prometheus/prometheus.yml
global:
  external_labels:
    dc: dc1
alerting:
  alertmanagers:
  - static_configs:
    - targets:
      - alertmanager01:9093
      - alertmanager02:9093
      - alertmanager03:9093
...

在这个alerting部分,我们也可以使用alert_relabel_configs,其配置语法与relabel_configsmetric_relabel_configs相同,如第 5 章中所述,运行 Prometheus 服务器,但在这种情况下,它仅适用于发出的警报。在此处使用重新标记有助于防止某些警报完全到达 Alertmanager,更改或删除标签以简化分组,甚至添加由于某种原因在 external_labels 中没有意义的特定于警报的标签.由于 alert_relabel_configs 在我们发出警报之前运行,因此这些警报中存在外部标签,因此可用于操作。下面是一个防止带有名为 environment 的标签和 development 匹配值的警报被推送到 Alertmanager 的示例:

  alert_relabel_configs:
  - source_labels: [environment]
    regex: development
    action: drop

虽然前面的示例说明了如何删除警报,但不应将其用作永久解决方案,因为更好的解决方案可能是根本不创建这些警报。

接下来,我们将浏览 Alertmanager 配置文件及其主要区域,并指出一些有助于您开始使用它的有用信息。

Configuration file overview

Alertmanager 通过单个配置文件进行配置,并且可以在运行时重新加载它,而无需像 Prometheus 一样重新启动:向进程发送 SIGHUP 或向 发送 HTTP POST 请求/- /reload 端点。例如 Prometheus,将不会应用格式错误的配置将设置为 0

配置文件分为五个顶级部分:globalrouteinhibit_rulesreceivers和< kbd>模板。在接下来的部分中,我们将探索它们中的每一个。

global

全局部分收集在文件的其他部分中有效的所有配置选项,并充当这些选项的默认设置。由于这些参数可能在其他部分被覆盖,因此使用它们是保持配置文件尽可能干净、避免重复的好方法。在本节的所有可用参数中,大部分都与作为通知者的凭证和令牌相关。有一个值得注意的叫做resolve_timeout。 Prometheus 将发送通过在每个评估间隔触发警报规则生成的警报,更新 JSON 有效负载中的 EndTime 字段。当这些问题得到解决时,它会通过更新 EndTime 来通知 Alertmanager 这些解决方案。如果由于某种原因,警报停止定期更新(例如,发送该警报的 Prometheus 实例崩溃并且仍在恢复过程中),Alertmanager 将使用最后一个 received EndTime< /kbd> 来解决警报。 resolve_timeout 配置用于解析由非 Prometheus 系统创建的警报,这些系统不使用 EndTime。需要明确的是,这不是您应该更改的设置,因为它与 Prometheus-Alertmanager 警报协议有关;为了完整起见,这里将对其进行解释。

例如,我们测试环境中 Alertmanager 配置的全局部分如下所示:

global:
  smtp_smarthost: 'mail.example.com:25'
  smtp_from: '[email protected]'
...

此示例配置为使用电子邮件 (SMTP) 通知程序的每个接收者设置默认电子邮件 smarthostfrom 地址。

route

这表面上是 Alertmanager 最重要的配置部分。在本节中,我们将定义如何根据标签(group_by)对警报进行分组,在发送其他通知之前等待新警报多长时间(group_interval),以及如何重复它们很长(repeat_interval),但最重要的是,应该为每个警报批次触发哪些接收器(receiver)。由于每条路由都可以有自己的子路由,这就形成了一个路由树。顶级路由不能有任何匹配的规则,因为它对于不匹配其任何子路由的任何警报都像包罗万象。除了 continue 之外,在路由上进行的每个设置都以级联方式传递到其子路由。虽然默认行为是在找到最具体的匹配项时停止搜索接收者,但可以将 continue 设置为 true,使匹配过程继续进行,从而允许您触发多个接收器。

您可以在我们的测试环境中找到以下示例路由配置:

route:
  receiver: operations
  group_by: ['alertname', 'job']
  group_wait: 30s
  group_interval: 5m
  repeat_interval: 4h

  routes:
  - match_re:
      job: (checkoutService|paymentService)
    receiver: yellow-squad-email
    routes:
    - match:
        severity: pager
      receiver: yellow-squad-pager
...

前面示例中的主路由执行以下操作:

  • Defines the operations receiver as the default route when no other sub-routes match
  • Groups incoming alerts by alertname and job
  • Waits 30 seconds for more alerts to arrive before sending the first notification to reduce the number of notifications for the same problem
  • Waits five minutes before sending additional notifications when new alerts are added to a batch
  • Resends a notification every four hours for each alert batch with the currently firing alerts

此外,它为 job 标签与 checkoutServicepaymentService 与它自己的接收器 yellow-squad 匹配的警报设置子路由-电子邮件。反过来,该子路由定义其自己的子路由,如果严重性标签匹配 pager,则应使用 yellow-squad-pager receiver 代替。

The official Prometheus website offers a routing tree editor and visualizer at https://prometheus.io/webtools/alerting/routing-tree-editor/.

group_by 子句也可以采用 ... 的唯一值,这将指示 Alertmanager 不对传入警报进行任何分组。这很少使用,因为分组的目的是调低通知的数量,从而提高信噪比。此功能的一种可能用法是将每个警报按原样发送到另一个处理警报的系统。

inhibit_rules

在本节中,我们将添加规则来禁止警报。其工作方式是通过在两者上使用匹配器来匹配源警报和静音目标警报。唯一的要求是目标和源上的标签在标签名称和值方面都匹配,例如:

inhibit_rules:
  - source_match:
      job: 'icmp'
    target_match_re:
      alertname: (AlertmanagerDown|NodeExporterDown)
    equal: ['base_instance']

在此示例中,我们可以阅读以下内容:如果有一个带有 job 标签设置为 icmp 的警报,则将所有其他带有 alertname 的警报静音当 base_instance 在所有匹配的警报中相同时,匹配 AlertmanagerDownNodeExporterDown。换句话说,如果运行 Alertmanager 和 Node Exporter 的实例出现故障,请跳过发送有关这些服务的警报,而只发送有关实例本身的警报,从而使操作员能够专注于真正的问题。

If any label in the equal clause does not exist in both source and target alerts, it will be considered matched and thus inhibition will be enabled.
如果警报与禁止规则定义中的源和目标都匹配,则不会禁止该警报 这是为了防止警报自我抑制。

我们可以在以下屏幕截图中看到发生这种情况时的 Alertmanager 界面:

读书笔记《hands-on-infrastructure-monitoring-with-prometheus》理解和扩展AlertManager
Figure 11.7: Alertmanager interface showing only firing notifications

在下面的屏幕截图中,我们可以通过选择右上角的 Inhibited 选项来查看之前屏幕截图中不存在的所有禁止警报:

读书笔记《hands-on-infrastructure-monitoring-with-prometheus》理解和扩展AlertManager
Figure 11.8: Alertmanager interface showing notifications, including the inhibited ones

Alertmanager 界面让您可以鸟瞰所有警报,不仅包括激活的警报,还包括被抑制的警报。默认是不显示禁止警报,以减少视觉混乱;但是,正如我们在前面的屏幕截图中看到的那样,您可以通过选择 Filter/Group 右上角的 Inhibited 复选标记轻松启用显示它们 框。

receiver

当路由匹配时,它将调用接收器。接收器包含通知器,我们将在接下来的部分中更深入地探讨。基本上,接收器是可用集成的命名配置。

在我们的测试环境中,我们可以使用 Webhook 通知器找到一个接收器的示例,如下所示:

route:
  receiver: operations
...
receivers:
- name: 'operations'
  webhook_configs:
  - url: 'http://127.0.0.1:5001'
...

顶级路由,也称为 catch-all 或 fallback 路由,当传入警报在其他子路由中不匹配时,将触发名为 operations 的接收器。 operations 接收器使用单个通知器进行配置,即 Webhook 通知器。这意味着发送到此接收器的警报将发送到 url 配置键中指定的 URL。本章稍后将进一步剖析 Webhook 通知程序。

templates

在本节中,可以定义指向多个可用通知器的自定义通知模板的路径列表。与 Prometheus 中的其他文件路径配置类似,每个路径定义都允许在最后一个组件上进行 globing,并且可以定义如下:

templates:
  - /etc/alertmanager/templates/*.tmpl

我们将使用此部分在自定义您的警报通知部分中定义我们的自定义模板。

The amtool command-line tool

promtool 类似,amtool 是由 Alertmanager HTTP API 支持的易于使用的命令行工具。除了用于验证 Alertmanager 配置文件的正确性之外,它还允许您查询服务器以获取当前触发的警报,并执行诸如静音警报或创建新警报等操作。 amtool 子命令分为四组 alertsilencecheck-config< /kbd> 和 config ,我们将提供每个使用测试环境的概述。

要遵循本节中的示例,请确保连接到 Alertmanager 实例之一。由于它们是集群的,因此它们中的任何一个都可以,例如:

vagrant ssh alertmanager02

登录后,您可以以默认用户身份运行 amtool,因为与 Alertmanager API 交互不需要管理权限。此外,您甚至可以使用 amtool 连接到任何 Alertmanager 实例,而不仅仅是本地实例,因为与 HTTP API 交互的大多数命令都需要您指定实例 URL。

alert

此子命令允许您查询 Alertmanager 集群以获取当前触发的警报,可以通过以下方式实现:

vagrant@alertmanager02:~$ amtool alert --alertmanager.url http://alertmanager02:9093
Alertname Starts At Summary 
deadmanswitch 2019-03-31 14:49:45 UTC 
InstanceDown 2019-03-31 15:48:30 UTC
alert 子命令默认动作是 查询。与上一个示例等效的命令是 amtool 警报查询 --alertmanager.url http://alertmanager02:9093

此子命令的另一个功能是能够按需创建警报。这对于测试目的很有用。例如,让我们使用标签 example="amtool" 创建一个名为 ExampleAlert 的新警报:

vagrant@alertmanager02:~$ amtool alert add alertname="ExampleAlert" example="amtool" --alertmanager.url http://alertmanager02:9093

add 操作要求每个命令参数有一个标签名称/值对,正如我们在前面的代码中看到的那样。此操作还将考虑第一个参数,因为 alertname 没有标签名称。如果我们省略 alertname 标签,则可以创建不带名称的警报,这可能会导致 amtool 和 Alertmanager Web UI 出现一些奇怪的情况,因此建议对此谨慎处理.

我们可以通过稍等片刻(测试环境中定义的 group_wait 为 30 秒)然后再次查询当前警报来检查它是否添加正确:

vagrant@alertmanager02:~$ amtool alert --alertmanager.url http://alertmanager02:9093
Alertname Starts At Summary 
deadmanswitch 2019-03-31 14:49:45 UTC 
InstanceDown 2019-03-31 15:48:30 UTC 
ExampleAlert 2019-03-31 15:55:00 UTC 

此操作还允许您指定其他警报字段,例如结束时间、生成器 URL 和注释。您可以使用 help 标志查询 add 操作命令行界面(参数和选项):

vagrant@alertmanager01:~$ amtool alert add --help

请记住,此新创建的警报将在五分钟不活动后被视为已解决(resolve_timeout 的默认值),因此请务必添加此警报的新实例(通过运行 add 操作)以在您需要更多时间进行测试时继续进行。

我们接下来将使用这个新警报作为静音目标。

silence

使用这个子命令,我们可以管理静音。首先,我们可以尝试使用以下指令查询集群中可用的静音:

vagrant@alertmanager02:~$ amtool silence --alertmanager.url http://alertmanager02:9093
ID Matchers Ends At Created By Comment
silence 子命令默认动作是 查询。与上一个示例等效的命令是 amtool 静音查询 --alertmanager.url http://alertmanager02:9093

正如我们所看到的,目前没有强制执行沉默。让我们通过匹配标签 example="amtool" 为之前生成的警报创建一个新警报,并再次检查静音:

vagrant@alertmanager02:~$ amtool silence add 'example="amtool"' --comment "ups" --alertmanager.url http://alertmanager02:9093
1afa55af-306a-408e-b85c-95b1af0d7169

vagrant@alertmanager02:~$ amtool silence --alertmanager.url http://alertmanager02:9093
ID Matchers Ends At Created By Comment 
1afa55af-306a-408e-b85c-95b1af0d7169 example=amtool 2019-03-31 16:58:08 UTC vagrant ups

我们现在可以看到已经添加了新的静音。要验证它是否已经生效,我们可以使用 alert 子命令并检查 ExampleAlert 是否已从当前警报列表中消失:

vagrant@alertmanager02:~$ amtool alert --alertmanager.url http://alertmanager02:9093
Alertname Starts At Summary 
deadmanswitch 2019-03-31 14:49:45 UTC 
InstanceDown 2019-03-31 15:48:30 UTC

让我们通过使用 expire 操作来删除我们刚刚创建的静默。为此,我们需要静音标识符,当我们列出当前静音时,可以在 ID 列中看到该标识符:

vagrant@alertmanager02:~$ amtool silence expire 1afa55af-306a-408e-b85c-95b1af0d7169 --alertmanager.url http://alertmanager02:9093

vagrant@alertmanager02:~$ amtool silence --alertmanager.url http://alertmanager02:9093
ID Matchers Ends At Created By Comment

如果我们再次查询当前警报列表,我们将再次看到我们的 ExampleAlert

这些是静音功能最常见的用例。还有其他可用的操作,例如批量导入静默(在迁移到新集群时很有用),或者如果您愿意,甚至可以更新现有的静默。像往常一样,--help 标志将为您提供有关如何使用这些操作的指导。

check-config

这可能是 amtool 最有用的特性:能够验证我们的 Alertmanager 配置文件和引用的模板文件的语法和模式。您可以按照以下示例测试 check-config 子命令:

vagrant@alertmanager02:~$ amtool check-config /etc/alertmanager/alertmanager.yml 
Checking '/etc/alertmanager/alertmanager.yml' SUCCESS
Found:
 - global config
 - route
 - 1 inhibit rules
 - 8 receivers
 - 1 templates
  SUCCESS

这种类型的验证很容易自动化,应该在任何配置更改之后,但在重新加载 Alertmanager 实例之前完成,从而防止大多数类型的配置问题。

config

使用 config 子命令,我们可以查看正在运行的 Alertmanager 实例的内部配置,其中包括所有可配置字段,甚至包括未在配置文件中明确列出的字段。您可以通过发出以下命令来检查这一点:

vagrant@alertmanager02:~$ amtool config --alertmanager.url http://alertmanager02:9093
global:
  resolve_timeout: 5m
  http_config: {}
  smtp_from: [email protected]
  smtp_hello: localhost
  smtp_smarthost: example.com:25
  smtp_require_tls: true
  slack_api_url: <secret>
...

未在配置文件中指定的配置字段将显示其默认值,并且处理机密(例如密码和令牌)的字段将被自动编辑。

config 子命令默认操作被显示。与上一个示例等效的命令是 amtool 配置显示 --alertmanager.url http://alertmanager02:9093

下一个子命令操作 routes 生成已配置路由树的文本可视化。此命令可以针对正在运行的 Alertmanager 实例或本地配置文件运行。语法和输出如下:

vagrant@alertmanager02:~$ amtool config routes --alertmanager.url http://alertmanager02:9093
Routing tree:
.
└── default-route receiver: operations
    ├── {job=~"^(?:^(?:(checkoutService|paymentService))$)$"} receiver: yellow-squad-email
    │ └── {severity="pager"} receiver: yellow-squad-pager
    ├── {job="firewall"} receiver: purple-squad-email
    │ ├── {severity="slack"} receiver: purple-squad-slack
    │ └── {severity="pager"} receiver: purple-squad-pager
    └── {alertname=~"^(?:^(?:(AlertmanagerDown|NodeExporterDown))$)$"} receiver: violet-squad-slack
        └── {severity="pager"} receiver: violet-squad-pager

您甚至可以通过为 routes test 操作提供标签并检查将触发哪个路由来验证路由树。我们可以在下面的示例中看到这一点,我们正在验证触发接收器是否实际上是 yellow-squad-email 当警报与 job="checkoutService" 一起出现时 标签:

vagrant@alertmanager02:~$ amtool config routes test 'job="checkoutService"' --config.file /etc/alertmanager/alertmanager.yml 
yellow-squad-email

拥有这个命令行工具可以帮助您简化复杂路由规则的开发并验证生成的配置,甚至不需要在本地运行 Alertmanager 实例。

Kubernetes Prometheus Operator and Alertmanager

第 5 章中,运行 Prometheus 服务器 ,我们有机会尝试使用 Prometheus Operator。由于 Alertmanager 是 Prometheus 堆栈的基本组件,因此 Operator 也能够管理其实例。除了照顾 Alertmanager 集群外,Operator 还负责管理记录和警报规则的配置。

为了深入了解如何使用 Operator 管理 Alertmanager 集群,我们将提供一个完整的设置供您试用。相对于存储库根路径,可以在以下路径中找到用于在我们的 Kubernetes 测试环境中启动和运行 Alertmanager 和 Prometheus 的 Kubernetes 清单:

cd ./chapter11/provision/kubernetes/

以下步骤将确保已配置具有所有必需软件的新 Kubernetes 环境,以便我们可以专注于 Alertmanager 组件:

  1. Validate that no other Kubernetes environment is running:
minikube status
minikube delete
  1. Start an empty Kubernetes environment:
minikube start \
  --cpus=2 \
  --memory=3072 \
  --kubernetes-version="v1.14.0" \
  --vm-driver=virtualbox
  1. Add the Prometheus Operator components and follow its deployment:
kubectl apply -f ./bootstrap/

kubectl rollout status deployment/prometheus-operator -n monitoring
  1. Add the new Prometheus cluster, ensuring that it's successful:
kubectl apply -f ./prometheus/

kubectl rollout status statefulset/prometheus-k8s -n monitoring
  1. Add all the targets to Prometheus and list them:
kubectl apply -f ./services/

kubectl get servicemonitors --all-namespaces

Kubernetes 测试环境运行后,我们可以继续进行特定于 Alertmanager 的配置。与基于虚拟机的测试环境类似,我们不仅需要配置 Alertmanager 本身,还需要配置 Prometheus 的警报规则。

对于 Alertmanager 配置,由于我们可能想要添加敏感信息,例如电子邮件凭据或寻呼机令牌,因此我们将使用 Kubernetes 机密。这也意味着应该有一个 ServiceAccount 来访问该机密。

我们可以通过应用以下清单来创建 ServiceAccount:

kubectl apply -f ./alertmanager/alertmanager-serviceaccount.yaml

由于我们使用的是机密,因此需要将 Alertmanager 配置编码为 base64。提供了一个最小配置,可以通过发出以下命令进行部署:

kubectl apply -f ./alertmanager/alertmanager-configuration.yaml

作为参考,密码中编码的最小配置如下:

global:

route:
  receiver: "null"
  group_by:
    - job
  group_interval: 3m
  repeat_interval: 3h
  routes:
    - match:
        alertname: deadmanswitch
      receiver: "null"

receivers:
  - name: "null"

现在,我们可以继续部署,让 Operator 为我们完成繁重的工作。它将抽象 StatefulSet 的创建并使集群启动并运行。为此,我们需要应用以下清单:

kubectl apply -f ./alertmanager/alertmanager-deploy.yaml

上一个清单的重要部分可以在以下代码段中看到:

...
kind: Alertmanager
...
spec:
  baseImage: quay.io/prometheus/alertmanager
...
  replicas: 3
...

我们可以通过发出以下指令来跟踪部署的状态:

kubectl rollout status statefulset/alertmanager-k8s -n monitoring

为了确保 Prometheus 实例可以从新创建的 Alertmanagers 收集指标,我们将添加一个新的 Service 和 ServiceMonitor。为此,我们需要应用以下清单:

kubectl apply -f ./alertmanager/alertmanager-service.yaml

kubectl apply -f ./alertmanager/alertmanager-servicemonitor.yaml

现在是添加警报规则的时候了。为此,您只需要应用以下清单:

kubectl apply -f ./alertmanager/alerting-rules.yaml

如果你打开之前的清单,你会看到几个规则。以下片段说明了第一个:

...
kind: PrometheusRule
...
spec:
  groups:
  - name: exporter-down
    rules:
    - alert: AlertmanagerDown
      annotations:
        description: Alertmanager is not being scraped.
        troubleshooting: https://github.com/kubernetes-monitoring/kubernetes-mixin/blob/master/runbook.md
      expr: |
        absent(up{job="alertmanager-service",namespace="monitoring"} == 1)
      for: 5m
      labels:
        severity: page
...

这些规则将被添加到 Prometheus 实例中,并且 Operator 将负责重新加载其配置,而不会导致服务停机。

最后,您可以访问 Prometheus 和 Alertmanager 的 Web 界面,并通过发出以下指令来验证您迄今为止所做的所有配置,这将打开几个浏览器选项卡:

minikube service alertmanager-service -n monitoring

minikube service prometheus-service -n monitoring

完成测试后,您可以通过发出以下命令来删除这个基于 Kubernetes 的环境:

minikube delete

此设置让您快速了解如何在 Kubernetes 上将 Alertmanager 与 Prometheus 集成。再一次,Prometheus Operator 抽象了大部分复杂性,让您可以专注于最重要的事情。

Common Alertmanager notification integrations

用户和/或组织对通知方式有不同的要求;有些人可能使用 HipChat 作为通信手段,而另一些人则依赖电子邮件,待命通常需要寻呼系统,例如 PagerDuty 或 VictorOps 等。值得庆幸的是,Alertmanager 提供了几个开箱即用的集成选项,并涵盖了您可能拥有的大部分通知需求。如果没有,总是有 Webhook 通知程序,它允许与自定义通知方法集成。接下来,我们将探索最常见的集成以及如何配置它们,并提供基本示例来帮助您入门。

在考虑与聊天系统集成时要记住的是,它们是为人类设计的,在考虑低优先级警报时建议使用票务系统。当创建警报的过程简单且自助时,管理它们可能会很快失控。工单确保问责制:使用工单比在聊天频道上发出警报的一些主要优势是它们允许跟踪、确定优先级和适当的跟进,以确保警报问题不会再次发生。此方法还隐含地确保了通知的所有权,并阻止了常见的谁是此警报的所有者? 的问题。所有权使服务维护人员能够管理他们收到的警报,并且作为副作用,还有助于减少警报疲劳。

If you happen to be using JIRA for task tracking, there's a custom integration that relies on the Webhook notifier called JIRAlert, available at https://github.com/free/jiralert.

有一个所有通知程序通用的配置键,称为 send_resolved。它接受一个布尔值(真或假)并声明在解决警报时是否应发送通知。 PagerDuty、Opsgenie、VictorOps、Pushover 和 Webhook 集成默认启用此功能,但其余通知程序禁用此功能,这也是您应该防止不必要的垃圾邮件的主要原因。

Email

电子邮件是大多数组织的标准通信方式,因此 Alertmanager 支持它也就不足为奇了。配置方面,设置非常简单;但是,由于 Alertmanager 不直接发送电子邮件,它需要使用实际的电子邮件中继。让我们使用一个有助于快速测试和低预算设置的真实示例,它使用电子邮件提供商的 SMTP(在本例中为 Google 的 Gmail):

global:
  smtp_smarthost: 'smtp.gmail.com:587'
  smtp_from: '[email protected]'
  smtp_auth_username: '[email protected]'
  smtp_auth_identity: '[email protected]'
  smtp_auth_password: '<generated_token>'

route: 
  receiver: 'default'

receivers:
- name: 'default'
  email_configs:
  - to: '[email protected]'

在此特定示例中,由于直接使用您的主 Gmail 密码在在线安全方面是一个坏主意,因此您需要一个启用了双重身份验证的帐户,然后生成一个应用程序密码以在 smtp_auth_password 中使用 字段。

You can find out how to generate app passwords for a Gmail account on the Sign in using App Passwords support page, located at https://support.google.com/accounts/answer/185833.

Chat

在撰写本文时,已经集成了三种聊天服务:Slack、WeChat 和 HipChat。以下示例表示 Slack 集成的配置;在本章后面,我们将为这种集成提供更深入的自定义概述:

global:
  slack_api_url: 'https://hooks.slack.com/services/TOKEN'

route:
  receiver: 'default'

receivers:
- name: 'default'
  slack_configs:
  - channel: '#alerting'

slack_api_url 应该指向一个 Slack Incoming Webhooks URL。您可以通过在 https://api.slack.com/incoming 上访问他们关于此主题的文档了解更多信息-网络钩子。由于 slack_configs 是一个列表,因此您可以在单个接收器上指定多个通道。

Pager

随叫随到通常与携带寻呼机、 物理或其他方式同义。在撰写本文时,Alertmanager 支持四种寻呼机样式的服务集成:PagerDuty、Opsgenie、VictorOps 和 Pushover。这些服务中的每一个的配置上手都相当简单,因为它们主要围绕 API URL 和身份验证令牌。但是,它们还支持更深层次的自定义,例如添加图像和链接,以及配置特定于服务的字段,例如严重性。这些高级配置选项在 Alertmanager 的官方文档中有描述,这里不再赘述。以下示例演示了 PagerDuty 的基本配置:

global:
  pagerduty_url: 'https://events.pagerduty.com/v2/enqueue'

route:
  receiver: 'default'

receivers:
- name: 'default'
  pagerduty_configs:
  - service_key: 'PAGERDUTYSQUADTOKENEXAMPLE'

就像前面的通知器一样,由于 pagerduty_configs 配置是一个列表,因此您可以在单个接收器中触发多个服务路由。您可以在此处找到有关 PagerDuty 与 Alertmanager 集成的更多信息:https://www. pagerduty.com/docs/guides/prometheus-integration-guide/

Webhook

Webhook 集成为自定义集成开辟了无限可能。此功能允许 Alertmanager 使用通知的 JSON 有效负载向您选择的端点发出 HTTP POST 请求。请记住,URL 不可模板化,并且必须将目标端点设计为处理 JSON 有效负载。例如,它可用于将所有通知推送到 Elasticsearch 等日志记录系统中,以便您可以对正在生成的警报执行报告和统计分析。如果您的团队使用 IRC,这也可能是与其集成的解决方案。最后一个例子是我们为本书创建的 alertdump 工具。之前在Chapter 9Defining Alerting和 Recording Rules,用于显示 Prometheus 在触发警报规则时发送的内容,但它也可用于演示 Alertmanager 发送的通知负载。

一个简单的配置可以在下面的代码中看到:

global:

route:
  receiver: 'default'

receivers:
- name: 'default'
  webhook_configs:
  - url: 'http://127.0.0.1:5001'

此配置会将 Alertmanager 收到的每个警报按原样发送到 alertdump,然后将有效负载附加到以运行 alertdump 的主机命名的日志文件中。此日志文件位于每个虚拟机内部均可从我们的测试环境 (/vagrant/cache/alertmanager*.log) 和外部 (./cache/alertmanager) 访问的路径中*.log,相对于存储库根目录)。

null

这本身不是一个通知器,而是一种通常用于删除通知的模式。它的配置方式是指定一个没有通知器的接收器,这会导致通知被丢弃。以下示例确保永远不会发送任何通知:

global:

route:
  receiver: 'null'

receivers:
- name: 'null'

这有时对于演示目的很有用,但没有多大用处;不应触发通知的警报应在其来源而不是在 Alertmanager 中删除,但警报被用作抑制源的除外。

Something to always keep an eye on is the alertmanager_notifications_failed_total Alertmanager metric, as it tracks all the failed attempts to deliver notifications per integration.

现在我们了解了 Alertmanager 通知程序的基础知识,我们可以继续学习如何自定义警报通知,以便正确显示最重要的信息。

Customizing your alert notifications

对于每个可用的集成,Alertmanager 已经包含用于通知的内置模板。然而,这些可以根据用户和/或组织的特定需求进行定制。类似于我们在 第 9 章中探索的警报规则注释,< em>定义警报和记录规则,警报通知使用 Go 模板语言进行模板化。让我们以 Slack 集成为例,了解消息是如何构造的,以便根据您的需求进行定制。

Default message format

为了了解没有任何自定义的通知是什么样的,我们将使用一个非常简单的示例。采用我们在 Prometheus 实例中定义的以下警报规则:

  - alert: deadmanswitch
    expr: vector(42)

一旦此警报开始触发,警报负载将被发送到 Alertmanager。以下代码段演示了正在发送的有效负载。请注意存在的标签,其中包括 Prometheus 实例中的 alertnameexternal_labels

    {
        "labels": {
            "alertname": "deadmanswitch",
            "dc": "dc1"
        },
        "annotations": {},
        "startsAt": "2019-04-02T19:11:30.04754979Z",
        "endsAt": "2019-04-02T19:14:30.04754979Z",
        "generatorURL": "http://prometheus:9090/graph?g0.expr=vector%2842%29&g0.tab=1"
    }

在 Alertmanager 方面,我们将有这个最小配置,以便我们可以发送 Slack 通知(用实际的 Slack 令牌替换 TOKEN):

global:
  slack_api_url: 'https://hooks.slack.com/services/TOKEN'

route:
  receiver: 'default'

receivers:
- name: 'default'
  slack_configs:
  - channel: '#alerting'

最终结果将是如下所示的 Slack 消息:

读书笔记《hands-on-infrastructure-monitoring-with-prometheus》理解和扩展AlertManager
Figure 11.9: Slack default notification format

我们可以看到,默认的通知格式里面有很多信息。但问题仍然存在,这是如何生成的?为了回答这个问题,我们可以查看从我们的基本 Alertmanager 配置生成的 default 接收器的运行时配置,以下代码段说明了这一点:

...
receivers:
- name: default
  slack_configs:
  - send_resolved: false
    http_config: {}
    api_url: <secret>
    channel: '#alerting'
    username: '{{ template "slack.default.username" . }}'
    color: '{{ if eq .Status "firing" }}danger{{ else }}good{{ end }}'
    title: '{{ template "slack.default.title" . }}'
    title_link: '{{ template "slack.default.titlelink" . }}'
    pretext: '{{ template "slack.default.pretext" . }}'
    text: '{{ template "slack.default.text" . }}'
...
The Alertmanager runtime configuration can be inspected by using amtool config or by accessing the /#/status endpoint of an Alertmanager web interface.

正如我们所见,每个可自定义的字段都是使用 Go 模板配置的。我们将使用 username 字段来举例说明 Slack 消息中的用户名是如何生成的,因为它是一个相当简单的模板。使用的所有其他模板都遵循相同的逻辑,但复杂程度各不相同。

Alertmanager 使用的默认模板无法在测试环境实例上本地查阅,因为它们是在 Alertmanager 二进制文件中编译和发布的。但是,我们可以通过查看 Alertmanager 代码库中的 templates/default.tmpl 文件来查阅 Alertmanager 提供的所有通知集成的所有默认模板。在撰写本文时,当前版本为 0.16.2,因此为方便起见,我们在此处链接到引用的文件:https://github.com/prometheus/alertmanager/blob/v0.16.2/template/default.tmpl

如果我们查看 default.tmpl 文件,我们会发现 slack.default.username 模板的定义:

{{ define "slack.default.username" }}{{ template "__alertmanager" . }}{{ end }}

如我们所见,模板使用另一个模板作为其定义。因此,如果我们查找 __alertmanager 模板的定义,我们会发现以下内容:

{{ define "__alertmanager" }}AlertManager{{ end }}

现在,您了解名称 AlertManager 是如何出现在 Slack 通知中的。其他每个模板的跟踪留给您作为练习。在下一节中,我们将学习如何创建自己的模板,然后使用它们来自定义我们的警报通知。

Creating a new template

在我们深入创建模板之前,我们必须首先了解发送到通知模板的数据结构类型。下表描述了可以使用的可用变量:

变量

说明

警报

警报结构列表,每个结构都有自己的状态、标签、注释、StartsAt、EndsAt 和 GeneratorURL

CommonAnnotations

所有警报共有的注释

通用标签

所有警报共有的标签

外部网址

发送警报的警报管理器的 URL

组标签

警报分组中使用的标签

接收器

将处理通知的接收者

状态

只要在该状态下存在警报,就会触发它,否则它将被解决

A comprehensive reference of all available data structures and functions is available at https://prometheus.io/docs/alerting/notifications/.

演示如何构建模板的最佳方式是提供示例。我们构建了以下模板,该模板可在测试环境中使用,完全符合该意图。我们将详细解释每个部分,同时将 Alertmanager 配置分解为仅重要的部分。

我们旨在创建的最终结果可以在以下屏幕截图中看到:

读书笔记《hands-on-infrastructure-monitoring-with-prometheus》理解和扩展AlertManager
Figure 11.10: Example Slack notification template

现在,我们将剖析示例配置,它将生成类似于前面屏幕截图中所示的通知:

route:
  group_by: [alertname, job]
  receiver: null
  routes:
  - match:
      severity: slack
    receiver: purple-squad-slack

在本示例中,我们按 alertnamejob 对警报进行分组。这很重要,因为它会影响 CommonAnnotationsCommonLabels,我们很快就会看到:

receivers:
- name: null
- name: purple-squad-slack
  slack_configs:
  - api_url: 'https://hooks.slack.com/TOKEN'
    channel: '#alerting'
    title: >
      [{{ .Alerts | len }}x ALERT{{ if gt (len .Alerts.Firing) 1 }}S{{end}}] {{ .CommonLabels.alertname }}

正如我们在上表中看到的,.Alerts 是所有警报的列表,因此我们希望该列表的长度 (len) 来为消息创建标题,从触发警报的数量开始。注意 if 子句,它确保在有多个警报时使用复数形式。最后,由于我们按 alertname 对警报进行分组,因此我们在方括号后打印 alertname

    text: >
      :link: <{{ .CommonAnnotations.troubleshooting }}/{{ .CommonLabels.alertname }}|Troubleshooting Guide>

对于消息正文,我们希望为这种特定类型的警报生成故障排除指南的链接。我们的警报正在发送一个名为 troubleshooting 的注释,带有一个基本 URL。如果我们依赖约定以使指南名称与警报名称匹配,我们可以使用这两个字段轻松生成链接。

为了提供有关触发警报的更多上下文,我们将向消息中添加所有可用的警报标签。为了实现这个目标,我们必须遍历列表中的每个警报:

      {{ range .Alerts }}

对于每个警报,我们将打印可用作该警报注释的描述:

       *Description:* {{ .Annotations.description }}
      *Details:*

我们还将打印每个警报标签/值对。为此,我们将遍历 SortedPairs 的结果,它返回标签/值对的排序列表:

        {{- range .Labels.SortedPairs }}
The {{- code trims all trailing whitespace from the preceding text. More information on this is available at https://tip.golang.org/pkg/text/template/#hdr-Text_and_spaces.

我们使用严重性标签作为路由键来选择通知器(寻呼机、电子邮件或 slack),因此我们不想在警报消息中公开它。我们可以通过添加一个 if 子句来做到这一点,这样我们就不会打印那个特定的标签/值:

          {{- if ne .Name "severity"}}
        • *{{ .Name }}:* `{{ .Value }}`
          {{- end}}
      {{- end }}
      {{ end }}

就是这样。您甚至可以通过将此模板从 Alertmanager 配置中取出并放入其自己的模板文件中,从而使其更易于管理。我们在测试环境中完成了这项工作,其中接收器配置如下:

- name: violet-squad-slack
  slack_configs:
  - channel: '#violet-squad-alerts'
    title: '{{ template "slack.example.title" . }}'
    text: '{{ template "slack.example.text" . }}'

所有模板定义都可以在以下路径的 Alertmanager 实例中使用:

/etc/alertmanager/templates/example.tmpl
Notification templating is quite hard to understand and build at first. Luckily, a tool was created by Julius Volz, one of Prometheus' co-founders and core maintainer, that allows you to quickly iterate on Slack notification templates. It's by far the best way to understand how they work and how to generate them. You can find it at https://juliusv.com/promslack/.

Who watches the Watchmen?

监控系统是任何基础设施的关键组成部分。我们依靠它来监视从服务器和网络设备到服务和应用程序的所有内容,并希望在出现问题时得到通知。但是,当问题出在监控堆栈本身,甚至是通知提供程序上,从而生成警报但没有到达我们时,作为操作员,我们将如何知道?

确保监控堆栈已启动并运行,并且通知能够到达接收者,这是一项通常被忽视的任务。在本节中,我们将探讨可以采取哪些措施来减轻风险因素并提高对监控系统的整体信心。

Meta-monitoring and cross-monitoring

从广义上讲,您不能让监控系统自行监控;如果系统发生严重故障,它将无法发送有关它的通知。虽然让 Prometheus 自行抓取是常见的做法(您可能会在大多数教程中看到这一点),但您显然不能依靠它来提醒自己。这就是元监控的用武之地:它是监控监控系统的过程。

您应该考虑缓解此问题的第一个选项是拥有一组 Prometheus 实例来监控其数据中心/区域中的所有其他 Prometheus 实例。由于 Prometheus 自己生成的指标相对较少,因此对于进行元监控的人来说,这将转化为相当轻松的抓取工作;他们甚至不需要完全专注于此:

读书笔记《hands-on-infrastructure-monitoring-with-prometheus》理解和扩展AlertManager
Figure 11.11: Meta-monitoring – Prometheus group monitoring every other group

但是,您可能想知道如何监控这组实例。我们可以不断添加更高级别的实例,以分层方式进行元监控-在数据中心级别,然后在区域级别,然后在全球级别-但我们仍然会留下一组不受监控的服务器。

减轻这一缺点的一种补充技术称为交叉监控。此方法涉及让 Prometheus 实例与它们的对等体处于同一责任级别的监视器上。这样,每个实例将至少有一个其他 Prometheus 监视它并在它失败时生成警报:

读书笔记《hands-on-infrastructure-monitoring-with-prometheus》理解和扩展AlertManager
Figure 11.12: Prometheus groups monitoring themselves

但是如果问题出在 Alertmanager 集群中会发生什么?或者,如果外部连接阻止通知到达通知提供者?或者即使通知提供者本身正在遭受中断?在下一节中,我们将为这些问题提供可能的解决方案。

Dead man's switch alerts

想象一下,您有一组使用 Alertmanager 集群进行警报的 Prometheus 实例。出于某种原因,这两个服务之间发生了网络分区。即使每个 Prometheus 实例检测到它无法再访问任何 Alertmanager 实例,它们也无法发送通知。

在这种情况下,将永远不会发送有关该问题的警报:

读书笔记《hands-on-infrastructure-monitoring-with-prometheus》理解和扩展AlertManager
Figure 11.13: Network partition between Prometheus and Alertmanager

死人开关的原始概念是指一种在停止触发/按下时激活的机制。这个概念已在软件世界中以多种方式采用。出于我们的目的,我们可以通过创建一个应该始终触发 的警报来实现这一点,从而不断发送通知 ,然后检查它是否会停止。这样,我们可以执行从 Prometheus,通过 Alertmanager,到通知提供者,最终到通知的接收者的完整警报路径,这样我们就可以确保端到端的连接性和服务可用性。当然,这与我们所知道的关于警报疲劳的所有知识背道而驰,我们不希望不断地接收有关始终触发警报的页面或电子邮件。您可以实现自己的自定义服务来实现看门狗计时器,但随后您将处于需要对其进行监视的情况。理想情况下,您应该利用第三方来降低此服务遭受同样的中断而导致通知无法发出的风险。

为此,有一个围绕死人的开关类型警报构建的服务,它被奇怪地命名为 Dead Man's Snitch ( deadmanssnitch.com)。这是您的基础架构之外的第三方提供商,负责通过电子邮件或 Webhook 接收始终触发的通知,并且如果该通知停止接收超过可配置的时间量。这种设置缓解了我们之前提出的问题,即使整个数据中心起火,您仍然会被寻呼!

将 Dead Man's Snitch 与 VictorOps 和集成的完整配置指南 PagerDuty 可以在 https://help.victorops.com/knowledge-base/ victorops-dead-mans-snitch-integration/https://www.pagerduty.com/docs/guides/ dead-mans-snitch-integration-guide/,分别。

Summary

在本章中,我们深入研究了 Prometheus 堆栈的警报组件 Alertmanager。该服务的设计考虑了可用性,我们有机会了解它是如何工作的,从生成更好的通知到避免被无用的通知淹没。通知管道是了解 Alertmanager 内部工作原理的一个很好的起点,但我们也完成了它的配置,同时提供示例来更好地巩固这些知识。我们了解了 amtool 及其提供的所有功能,例如直接从命令行添加、删除和更新静音。

Alertmanager 有几个可用的通知集成,我们已经完成了所有这些,因此您可以选择您感兴趣的那些。由于我们都想要更好的通知,我们深入研究了如何自定义默认通知,使用 Slack 作为我们的示例.一个难以解决的问题是如何监控监控系统;在本章中,我们学习了如何确保在没有发出通知时收到警报。

在不断变化的基础架构中,跟踪正在运行的内容和运行的位置并非易事。在下一章中,我们将更深入地了解 Prometheus 如何处理服务发现并为您自动执行这些任务。

Questions

  1. What happens to the notifications if there's a network partition between Alertmanager instances in the same cluster?
  2. Can an alert trigger multiple receivers? What is required for that to happen?
  3. What's the difference between group_interval and repeat_interval?
  4. What happens if an alert does not match any of the configured routes?
  5. If the notification provider you require is not supported natively by Alertmanager, how can you use it?
  6. When writing custom notifications, how are CommonLabels and CommonAnnotations populated?
  7. What can you do to ensure that the full alerting path is working from end to end?

Further reading