Skip to main content

记录与告警

本指南将向你展示如何基于 Prometheus Operator 一键部署 Alertmanager 集群并集成 Prometheus,并使用 PrometheusRules 记录指标数据和推送告警。

介绍

Prometheus 是一个开源系统监控和警报工具包。它将其指标收集并存储为时间序列数据,即指标信息与记录它的时间戳一起存储,以及称为标签的可选键值对。

下图说明了 Prometheus 的架构及其一些生态系统组件:

Prometheus 从检测作业中直接或通过中间推送网关从短期作业中抓取指标。它在本地存储所有抓取的样本,并对这些数据运行规则,以从现有数据聚合和记录新的时间序列或生成警报。Grafana 或其他 API 使用者可用于可视化收集的数据。

准备开始

在开始之前,我们需要做以下准备工作:

1、安装 Kusion 工具链

我们推荐使用 kusion 的官方安装工具 kusionup,可实现 kusion 多版本管理等关键能力。详情信息请参阅下载和安装

2、下载开源 Konfig 大库

在本篇指南中,需要用到部分已经抽象实现的 KCL 模型,有关 KCL 语言的介绍,可以参考 Tour of KCL

仓库地址: https://github.com/KusionStack/konfig.git

3、可用的 Kubernetes 集群

必须要有一个 Kubernetes 集群,同时 Kubernetes 集群最好带有 kubectl 命令行工具。 如果你还没有集群,你可以通过 Minikube 构建一个你自己的集群。

4、安装 Prometheus Operator

Prometheus Operator 安装很简单,只需:

kubectl create -f bundle.yaml

详见 Prometheus Operator 快速开始

组件部署

在 konfig 大库的 prometheus-install 项目中,保存了设置 Prometheus 和 Alertmanager 的完整的配置:

  • Alertmanager 集群
  • AlertmanagerConfig
  • Alertmanager 服务
  • Prometheus 集群
  • Prometheus 依赖的 RBAC
  • Prometheus 服务
info

想要体验快速部署结果,可直接跳到一键部署小节。

配置 Alertmanager

Alertmanager 默认启动是按照最低配置,这并没什么用处,因为它在接收报警时不会发送任何通知。

你有 3 种方式来提供 Alertmanager 配置

  1. 使用存储在 Kubernetes 密钥中的本机 Alertmanager 配置文件。
  2. 使用 spec.alertmanagerConfiguration 在定义主 Alertmanager 配置的同一命名空间中引用 AlertmanagerConfig 对象。
  3. 定义 spec.alertmanagerConfigSelectorspec.alertmanagerConfigNamespaceSelector 告诉 Operator 应该选择哪些 AlertmanagerConfigs 对象并将其与主 Alertmanager 配置合并。
tip

prometheus-install 项目中使用的第二种方式。

  1. 以下是 AlertmanagerConfig 配置,Alertmanager 将通知发送到虚构的 webhook 服务:
_alertmanager_config: monitoringv1alpha1.AlertmanagerConfig{
metadata = {
name = "main"
namespace = _common_namespace
labels = {
"alertmanagerConfig" = "main"
}
}
spec = {
route = {
groupBy = ["job"]
groupWait = "30s"
groupInterval = "5m"
repeatInterval = "12h"
receiver = "webhook"
}
receivers = [
{
name = "webhook"
webhookConfigs = [
{
url = "http://example.com/"
}
]
}
]
}
}
  1. 设置 3 个副本的 Alertmanager 集群,并引用 AlertmanagerConfig 对象:
_alertmanager: monitoringv1.Alertmanager{
metadata = {
name = "main"
namespace = "default"
}
spec = {
replicas = 3
# 使用 AlertmanagerConfig 作为全局配置
alertmanagerConfiguration = {
name = _alertmanager_config.metadata.name
}
}
}
  1. 公开 Alertmanager 服务,用于被后续的 Prometheus 实例集成。 创建 Kubernetes Service,监听目标端口 9093
_alertmanager_svc: corev1.Service{
metadata = {
name = "alertmanager"
namespace = "default"
}
spec = {
selector = {
"alertmanager" = _alertmanager.metadata.name
}
ports = [
{
name = "web"
port = 9093
targetPort = "web"
}
{
name = "reloader-web"
port = 8080
targetPort = "reloader-web"
}
]
sessionAffinity = "ClientIP"
}
}
tip

详细配置,请查看源码文件: prometheus-install/prod/main.k

此 Alertmanager 集群现在功能齐全且高可用,但不会针对它触发任何报警。这是因为你还没有设置 Prometheus 应用。

配置 Prometheus

在创建 Prometheus 之前,必须先为 Prometheus 服务帐户创建 RBAC 规则。

  1. Prometheus ClusterRole 配置:
_prometheus_clusterrole: rbac.ClusterRole {
metadata = {
name = "prometheus"
namespace = "default"
}
rules = [
{
apiGroups = [""]
resources = ["nodes", "nodes/metrics", "services", "endpoints", "pods"]
verbs = ["get", "list", "watch"]
}
{
apiGroups = [""]
resources = ["configmaps"]
verbs = ["get"]
}
{
apiGroups = ["networking.k8s.io"]
resources = ["ingresses"]
verbs = ["get", "list", "watch"]
}
{
nonResourceURLs = ["/metrics"]
verbs = ["get"]
}
]
}
tip

RBAC 的完整配置,请查看源码文件:prometheus-install/base/base.k

  1. 创建 Prometheus,它将向 Alertmanger 集群发送报警:
_prometheus: monitoringv1.Prometheus{
metadata = {
name = "main"
namespace = "default"
}
spec = {
# 指定 ServiceAccount
serviceAccountName = "prometheus"
replicas = 2
# ruleSelector 为空,表示不选择任何 PrometheusRule。
ruleSelector = {
matchLabels = {
"role" = "alert-rules"
"prometheus" = "main"
}
}
serviceMonitorSelector = {
matchLabels = {
"prometheus" = "main"
}
}
# 通过 Alertmanager 的公开的 Service,配置 Alertmanager
alerting = {
alertmanagers = [
{
name = _alertmanager_svc.metadata.name
namespace = _alertmanager_svc.metadata.namespace
port = _alertmanager_svc.spec.ports[0].name
}
]
}
}
}
  1. 最后,为了方便验证,顺便公开 Prometheus Admin API。 创建 Kubernetes Service,监听目标端口 9090
_prometheus_svc: corev1.Service{
metadata = {
name = "prometheus"
namespace = "default"
}
spec = {
selector = {
"prometheus" = _prometheus.metadata.name
}
ports = [
{
name = "web"
port = 9090
targetPort = "web"
}
{
name = "reloader-web"
port = 8080
targetPort = "reloader-web"
}
]
sessionAffinity = "ClientIP"
}
}

Prometheus admin API 允许访问删除某个时间范围内的系列、清理墓碑、捕获快照等。 有关 admin API 的更多信息可以在 Prometheus 官方文档中找到。

tip

详细配置,请查看源码文件: prometheus-install/prod/main.k

一键部署

目前已经完成所有监控报警相关配置,现在开始一键部署。首先进入 prometheus-install stack 目录:

cd konfig/base/examples/monitoring/prometheus-install/prod

再执行 kusion apply:

kusion apply

输出类似于:

✔︎  Compiling in stack prod...                                                                                                                            

Stack: prod ID Action
* ├─ rbac.authorization.k8s.io/v1:ClusterRole:default:prometheus Create
* ├─ monitoring.coreos.com/v1:Alertmanager:default:main Create
* ├─ monitoring.coreos.com/v1alpha1:AlertmanagerConfig:default:main Create
* ├─ monitoring.coreos.com/v1:Prometheus:default:main Create
* ├─ rbac.authorization.k8s.io/v1:ClusterRoleBinding:default:prometheus Create
* ├─ v1:ServiceAccount:default:prometheus Create
* ├─ v1:Service:default:alertmanager Create
* └─ v1:Service:default:prometheus Create

? Do you want to apply these diffs? [Use arrows to move, type to filter]
yes
> details
no

选择 yes,开始部署。部署完成后,执行下面的命令,将本地端口 30900 转发到 k8s Service 端口 9090

kubectl port-forward svc/prometheus-example 30900:9090

现在,你可以打开 http://127.0.0.1:30900,访问 Prometheus 界面,进入 “Status > Runtime & Build Information” 页面,检查 Prometheus 是否发现了 3 个 Alertmanager 示例:

PrometheusRule

自定义资源定义 (CRD) PrometheusRule 声明式定义 Prometheus 实例使用的所需 Prometheus 规则,包括记录规则和报警规则。这些规则由 Operator 协调并动态加载,无需重新启动 Prometheus。

记录规则

记录规则可以预先计算经常需要或计算量大的表达式,并将其结果保存为一组新的时间序列。查询预先计算的结果通常比每次需要时执行原始表达式要快得多。这对于仪表板特别有用,仪表板每次刷新时都需要重复查询相同的表达式。

下面的代码片段,是以节点信息为例的记录规则:

_sum_of_node_memory = """\
sum(
node_memory_MemAvailable_bytes{job="node-exporter"} or
(
node_memory_Buffers_bytes{job="node-exporter"} +
node_memory_Cached_bytes{job="node-exporter"} +
node_memory_MemFree_bytes{job="node-exporter"} +
node_memory_Slab_bytes{job="node-exporter"}
)
) by (cluster)
"""

_node_cpu = """\
sum(rate(node_cpu_seconds_total{job="node-exporter",mode!="idle",mode!="iowait",mode!="steal"}[5m])) /
count(sum(node_cpu_seconds_total{job="node-exporter"}) by (cluster, instance, cpu))
"""

_sum_of_node_memory 记录节点可用内存总量,以 byte 为单位。

_node_cpu 计算每 5 分钟节点 CPU 的平均增长率。

tip

详细配置, 请查看源码文件: prometheus-rules/record/main.k.

现在,你可以创建上面的记录规则。

1、进入 prometheus-rules 项目的 record 目录:

cd konfig/base/examples/monitoring/prometheus-rules/record

2、创建规则:

kusion apply --yes

3、检查 Prometheus 已加载规则:

kubectl port-forward svc/prometheus-example 30900:9090

现在,你可以打开 http://127.0.0.1:30900,访问 Prometheus 界面,进入 “Status > Rules” 页面,检查 Prometheus 是否已加载 node.rules

拓展阅读

如果你想看到记录规则小节所生成的折线图,你需要在 default 命名空间部署 node-exporter 服务。

info

如何安装 node-exporter? 请查看这里: node-exporter.yaml

那么,你将会看到,节点可用内存的折线图:

和节点 CPU 每 5 分钟平均增长率的折线图:

报警规则

报警规则可以根据 Prometheus 表达式语言表达式定义报警条件,并将有关触发报警的通知发送到外部服务。每当报警表达式在给定时间点产生一个或多个矢量元素时,对于这些元素的标签集,报警就会被视为已激活。

下面的代码片段是报警规则的示例:

_alerts: monitoringv1.PrometheusRule {
metadata = {
name = "example-alert"
namespace = "default"
labels: {
"prometheus": "example",
"role": "alert-rules",
}
}
spec = {
groups = [
{
name = "alert.rules"
rules = [
{
alert: "ExampleAlert"
# vector() 函数将标量作为没有标签的向量返回。
expr: "vector(1)"
}
]
}
]
}
}

示例报警的表达式使用内部函数 vertor(),它将总是返回向量 1,即总是会触发报警。

tip

详细配置, 请查看源码文件: prometheus-rules/alert/main.k.

现在,你可以创建报警规则:

1、进入 prometheus-rules 项目的 alert 目录:

cd konfig/base/examples/monitoring/prometheus-rules/alert

2、创建规则:

kusion apply --yes

3、检查 Prometheus 已加载规则:

由于你已经完成了端口转发的步骤,因此只需要刷新 “Status > Rules” 页面,检查 Prometheus 是否已加载 alert.rules

4、检查 Alertmanager 成功接收报警:

kubectl port-forward svc/alertmanager-example 30903:9093

现在,你可以打开 http://127.0.0.1:30903,访问 Alertmanager 界面,发现示例报警: