Alertmanager-silencer告警静默

基于v0.28

总体流程

sequenceDiagram
    participant Alert as 告警(Labels)
    participant Silencer as Silencer
    participant Silences as Silences
    participant Store as state(存储)
    participant Marker as AlertMarker

    Alert->>Silencer: 新告警流入,调用 Mutes(lset)
    Silencer->>Marker: 查询该告警指纹的静默状态
    alt Marker 版本与 Silences 一致
        Silencer->>Silences: 仅查询已知静默ID是否仍然有效
    else Marker 版本不一致
        Silencer->>Silences: 全量查询所有匹配该告警的静默
    end
    Silences->>Store: 检索活跃/待生效静默
    Store-->>Silences: 返回静默列表
    Silences-->>Silencer: 返回匹配静默
    Silencer->>Marker: 更新告警的静默状态
    alt 存在活跃静默
        Silencer-->>Alert: 返回 true(被静默)
    else 无活跃静默
        Silencer-->>Alert: 返回 false(未被静默)
    end

    Note over Silencer,Silences: <b>核心流程说明:</b><br/>1. 新告警到达,Silencer 查询静默状态<br/>2. 若有活跃静默,告警被静默,不再通知<br/>3. 若无活跃静默,告警正常进入后续流程

运行原理

初始化

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
silencer := silence.NewSilencer(silences, marker, logger)

// Silences 结构体负责静默的存储、查询、GC、快照、分布式同步等。
type Silences struct {
clock quartz.Clock // 时钟接口,便于测试

logger *slog.Logger // 日志
metrics *metrics // 监控指标
retention time.Duration // 过期静默的保留时长
limits Limits // 静默数量和大小限制

mtx sync.RWMutex // 并发控制
st state // 静默状态存储(map)
version int // 状态版本号,每次变更递增
broadcast func([]byte) // 分布式同步广播函数
mc matcherCache // 匹配器缓存
}

// NewSilencer 创建一个新的 Silencer 实例。
// s: 静默存储对象
// m: 告警标记器
// l: 日志对象
// 返回值: 新的 Silencer 实例
func NewSilencer(s *Silences, m types.AlertMarker, l *slog.Logger) *Silencer {
return &Silencer{
silences: s,
marker: m,
logger: l,
}
}

更新API配置

1
2
3
4
5
// 更新API配置
api.Update(conf, func(labels model.LabelSet) {
inhibitor.Mutes(labels)
silencer.Mutes(labels)
})

告警静默

核心静默

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
// Silencer 结构体将 Silences 与 AlertMarker 绑定,实现 Muter 接口,
// 用于判断某个告警是否被静默。
type Silencer struct {
silences *Silences // 静默存储对象
marker types.AlertMarker // 告警标记器
logger *slog.Logger // 日志
}

// Mutes 判断给定标签集合(lset)是否被当前静默规则静默。
// lset: 需要判断的标签集合(告警)
// 返回值: true 表示被静默,false 表示未被静默
func (s *Silencer) Mutes(lset model.LabelSet) bool {
fp := lset.Fingerprint()
activeIDs, pendingIDs, markerVersion, _ := s.marker.Silenced(fp)

var (
err error
allSils []*pb.Silence
newVersion = markerVersion
)
if markerVersion == s.silences.Version() {
totalSilences := len(activeIDs) + len(pendingIDs)
// 无静默直接返回
if totalSilences == 0 {
return false
}
// 仅需检查已有静默是否仍然有效
allIDs := append(append(make([]string, 0, totalSilences), activeIDs...), pendingIDs...)
allSils, _, err = s.silences.Query(
QIDs(allIDs...),
QState(types.SilenceStateActive, types.SilenceStatePending),
)
} else {
// 有新静默,需全量查询
allSils, newVersion, err = s.silences.Query(
QState(types.SilenceStateActive, types.SilenceStatePending),
QMatches(lset),
)
}
if err != nil {
s.logger.Error("Querying silences failed, alerts might not get silenced correctly", "err", err)
}
if len(allSils) == 0 {
// 没有任何静默,重置标记
s.marker.SetActiveOrSilenced(fp, newVersion, nil, nil)
return false
}
// 重新计算当前活跃和待生效的静默 ID
activeIDs, pendingIDs = nil, nil
now := s.silences.nowUTC()
for _, sil := range allSils {
switch getState(sil, now) {
case types.SilenceStatePending:
pendingIDs = append(pendingIDs, sil.Id)
case types.SilenceStateActive:
activeIDs = append(activeIDs, sil.Id)
default:
// 已过期静默无需处理
}
}
s.logger.Debug(
"determined current silences state",
"now", now,
"total", len(allSils),
"active", len(activeIDs),
"pending", len(pendingIDs),
)
sort.Strings(activeIDs)
sort.Strings(pendingIDs)

s.marker.SetActiveOrSilenced(fp, newVersion, activeIDs, pendingIDs)

return len(activeIDs) > 0
}


// MemMarker 是 AlertMarker 的内存实现。
type MemMarker struct {
alerts map[model.Fingerprint]*AlertStatus // 告警状态存储
groups map[string]*groupStatus // 分组状态存储

mtx sync.RWMutex // 并发控制
}

// Silenced 返回告警是否被静默、相关静默 ID、版本号等。
func (m *MemMarker) Silenced(alert model.Fingerprint) (activeIDs, pendingIDs []string, version int, silenced bool) {
s := m.Status(alert)
return s.SilencedBy, s.pendingSilences, s.silencesVersion,
s.State == AlertStateSuppressed && len(s.SilencedBy) > 0
}

内存告警管理实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
// AlertMarker 用于标记告警的静默/抑制状态,所有方法均为并发安全。
type AlertMarker interface {
// SetActiveOrSilenced 设置告警的静默状态,activeSilenceIDs/pendingSilenceIDs 为影响该告警的静默 ID。
// version: 静默状态版本号
SetActiveOrSilenced(alert model.Fingerprint, version int, activeSilenceIDs, pendingSilenceIDs []string)
// SetInhibited 设置告警的抑制状态,alertIDs 为抑制该告警的其他告警 ID。
SetInhibited(alert model.Fingerprint, alertIDs ...string)

// Count 统计指定状态的告警数量。
Count(...AlertState) int

// Status 获取指定告警的状态。
Status(model.Fingerprint) AlertStatus
// Delete 删除指定告警的状态。
Delete(model.Fingerprint)

// Unprocessed/Active/Silenced/Inhibited 判断告警是否处于对应状态。
// Silenced 返回影响该告警的静默 ID、版本号等。
Unprocessed(model.Fingerprint) bool
Active(model.Fingerprint) bool
Silenced(model.Fingerprint) (activeIDs, pendingIDs []string, version int, silenced bool)
Inhibited(model.Fingerprint) ([]string, bool)
}

// GroupMarker 用于标记分组的静默状态,所有方法均为并发安全。
// routeID: 路由唯一标识,groupKey: 分组唯一标识
type GroupMarker interface {
// Muted 判断分组是否被静默,返回静默时间区间名列表和是否被静默。
Muted(routeID, groupKey string) ([]string, bool)
// SetMuted 标记分组被哪些时间区间静默。
SetMuted(routeID, groupKey string, timeIntervalNames []string)
// DeleteByGroupKey 删除指定分组的所有标记。
DeleteByGroupKey(routeID, groupKey string)
}

// NewMarker 创建一个 AlertMarker 实现。
func NewMarker(r prometheus.Registerer) *MemMarker {
m := &MemMarker{
alerts: map[model.Fingerprint]*AlertStatus{},
groups: map[string]*groupStatus{},
}
m.registerMetrics(r)
return m
}

// MemMarker 是 AlertMarker 的内存实现。
type MemMarker struct {
alerts map[model.Fingerprint]*AlertStatus // 告警状态存储
groups map[string]*groupStatus // 分组状态存储

mtx sync.RWMutex // 并发控制
}

// Muted 实现 GroupMarker,判断分组是否被静默。
func (m *MemMarker) Muted(routeID, groupKey string) ([]string, bool) {
m.mtx.Lock()
defer m.mtx.Unlock()
status, ok := m.groups[routeID+groupKey]
if !ok {
return nil, false
}
return status.mutedBy, len(status.mutedBy) > 0
}

// SetMuted 实现 GroupMarker,设置分组被哪些时间区间静默。
func (m *MemMarker) SetMuted(routeID, groupKey string, timeIntervalNames []string) {
m.mtx.Lock()
defer m.mtx.Unlock()
status, ok := m.groups[routeID+groupKey]
if !ok {
status = &groupStatus{}
m.groups[routeID+groupKey] = status
}
status.mutedBy = timeIntervalNames
}

// DeleteByGroupKey 删除指定分组的所有标记。
func (m *MemMarker) DeleteByGroupKey(routeID, groupKey string) {
m.mtx.Lock()
defer m.mtx.Unlock()
delete(m.groups, routeID+groupKey)
}

// registerMetrics 注册告警状态相关的监控指标。
func (m *MemMarker) registerMetrics(r prometheus.Registerer) {
newMarkedAlertMetricByState := func(st AlertState) prometheus.GaugeFunc {
return prometheus.NewGaugeFunc(
prometheus.GaugeOpts{
Name: "alertmanager_marked_alerts",
Help: "How many alerts by state are currently marked in the Alertmanager regardless of their expiry.",
ConstLabels: prometheus.Labels{"state": string(st)},
},
func() float64 {
return float64(m.Count(st))
},
)
}

alertsActive := newMarkedAlertMetricByState(AlertStateActive)
alertsSuppressed := newMarkedAlertMetricByState(AlertStateSuppressed)
alertStateUnprocessed := newMarkedAlertMetricByState(AlertStateUnprocessed)

r.MustRegister(alertsActive)
r.MustRegister(alertsSuppressed)
r.MustRegister(alertStateUnprocessed)
}

// Count 实现 AlertMarker,统计指定状态的告警数量。
func (m *MemMarker) Count(states ...AlertState) int {
m.mtx.RLock()
defer m.mtx.RUnlock()

if len(states) == 0 {
return len(m.alerts)
}

var count int
for _, status := range m.alerts {
for _, state := range states {
if status.State == state {
count++
}
}
}
return count
}

// SetActiveOrSilenced 实现 AlertMarker,设置告警的静默状态。
func (m *MemMarker) SetActiveOrSilenced(alert model.Fingerprint, version int, activeIDs, pendingIDs []string) {
m.mtx.Lock()
defer m.mtx.Unlock()

s, found := m.alerts[alert]
if !found {
s = &AlertStatus{}
m.alerts[alert] = s
}
s.SilencedBy = activeIDs
s.pendingSilences = pendingIDs
s.silencesVersion = version

// 若无静默/抑制,则为 active,否则为 suppressed
if len(activeIDs) == 0 && len(s.InhibitedBy) == 0 {
s.State = AlertStateActive
return
}

s.State = AlertStateSuppressed
}

// SetInhibited 实现 AlertMarker,设置告警的抑制状态。
func (m *MemMarker) SetInhibited(alert model.Fingerprint, ids ...string) {
m.mtx.Lock()
defer m.mtx.Unlock()

s, found := m.alerts[alert]
if !found {
s = &AlertStatus{}
m.alerts[alert] = s
}
s.InhibitedBy = ids

// 若无静默/抑制,则为 active,否则为 suppressed
if len(ids) == 0 && len(s.SilencedBy) == 0 {
s.State = AlertStateActive
return
}

s.State = AlertStateSuppressed
}

// Status 实现 AlertMarker,获取指定告警的状态。
func (m *MemMarker) Status(alert model.Fingerprint) AlertStatus {
m.mtx.RLock()
defer m.mtx.RUnlock()

if s, found := m.alerts[alert]; found {
return *s
}
return AlertStatus{
State: AlertStateUnprocessed,
SilencedBy: []string{},
InhibitedBy: []string{},
}
}

// Delete 实现 AlertMarker,删除指定告警的状态。
func (m *MemMarker) Delete(alert model.Fingerprint) {
m.mtx.Lock()
defer m.mtx.Unlock()

delete(m.alerts, alert)
}

// Unprocessed 实现 AlertMarker,判断告警是否为未处理状态。
func (m *MemMarker) Unprocessed(alert model.Fingerprint) bool {
return m.Status(alert).State == AlertStateUnprocessed
}

// Active 实现 AlertMarker,判断告警是否为活跃状态。
func (m *MemMarker) Active(alert model.Fingerprint) bool {
return m.Status(alert).State == AlertStateActive
}

// Inhibited 实现 AlertMarker,判断告警是否被抑制。
func (m *MemMarker) Inhibited(alert model.Fingerprint) ([]string, bool) {
s := m.Status(alert)
return s.InhibitedBy,
s.State == AlertStateSuppressed && len(s.InhibitedBy) > 0
}

// Silenced 返回告警是否被静默、相关静默 ID、版本号等。
func (m *MemMarker) Silenced(alert model.Fingerprint) (activeIDs, pendingIDs []string, version int, silenced bool) {
s := m.Status(alert)
return s.SilencedBy, s.pendingSilences, s.silencesVersion,
s.State == AlertStateSuppressed && len(s.SilencedBy) > 0
}