ricardomaraschini/oomhero
GitHub: ricardomaraschini/oomhero
OOMHero 是一个 Kubernetes Sidecar 工具,通过跟踪内存与内核压力指标,在资源耗尽前向应用发送预警信号以避免 OOM 终止。
Stars: 116 | Forks: 11
# OOMHero
一个轻量级的 Kubernetes sidecar,用于监控进程资源使用情况和压力指标,并在资源耗尽前向应用程序发送可配置的信号。
## 概述
OOMHero 在 Kubernetes pod 中与您的应用程序容器一起运行,持续监控内存使用情况、内存压力、I/O 压力和 CPU 压力。当进程超过可配置的阈值(以表达式形式定义)时,OOMHero 会发送 Unix 信号,以便在 OOMKiller 终止您的应用程序之前实现主动的故障修复。
## 功能
- **基于表达式的阈值**:使用内存、OOM score 和压力指标的任意组合来定义复杂的触发器
- **基于信号的通知**:发送可自定义的 Unix 信号(默认:`SIGUSR1` 用于警告,`SIGUSR2` 用于严重警告)
- **HTTP 通知**:通过 HTTP POST 请求发送警报,而不是 Unix 信号
- **冷却时间**:通过可配置的通知间隔防止信号发送过于频繁
- **低开销**:极少的资源占用(通常为 1m CPU,32Mi 内存)
## 工作原理
OOMHero 在设置了 `shareProcessNamespace: true` 的 pod 中运行,这使其能够监控 pod 内的所有进程。它会以可配置的间隔持续扫描进程,根据定义的阈值表达式评估它们的资源使用情况。
当某个进程匹配表达式时:
1. **警告表达式**:向进程发送 SIGUSR1(或自定义信号)
2. **严重表达式**:向进程发送 SIGUSR2(或自定义信号)
应用程序通过实现信号处理程序来采取纠正措施,例如:
- 将缓存刷新到磁盘
- 卸载非关键工作负载
- 触发平滑降级
- 转储诊断信息以供事后分析
- 发起可控的重启
### 阈值表达式
OOMHero 使用 [fasteval](https://github.com/likebike/fasteval) 库来评估阈值表达式。您可以使用标准运算符组合各种指标:
- **逻辑运算**:`&&`(与)、`||`(或)、`!`(非)
- **比较运算**:`>`、`<`、`>=`、`<=`、`==`、`!=`
- **代数运算**:`+`、`-`、`*`、`/`、`%`(取模)、`^`(幂)
#### 可用变量
| 变量 | 类型 | 描述 |
|----------|------|-------------|
| `memory_usage` | `f64` | 当前内存使用量占限制的百分比 (%) |
| `memory_current` | `f64` | 当前内存使用量(字节) |
| `memory_max` | `f64` | 内存限制(字节) |
| `oom_score` | `f64` | 当前 OOM score |
| `oom_score_adj` | `f64` | OOM score 调整值 |
| `{resource}_pressure_{severity}_{window}` | `f64` | 压力指标 |
**压力指标组成部分:**
- **资源**:`memory`、`io`、`cpu`
- **严重程度**:`some`、`full`
- **窗口**:`avg10`、`avg60`、`avg300`、`total`
*示例*:`memory_pressure_full_avg10 > 20`
## 指标
OOMHero 默认在端口 `9000` 上公开 Prometheus 指标。这些指标提供了对所有受监控进程的资源使用情况和压力的实时可见性。
| 指标名称 | 类型 | 标签 | 描述 |
|-------------|------|--------|-------------|
| `memory_usage` | Gauge | `pid`, `cmdline` | 当前内存使用量占限制的百分比 |
| `oom_score` | Gauge | `pid`, `cmdline` | 当前 OOM score(包括调整值) |
| `memory_pressure` | Gauge | `pid`, `cmdline`, `severity_level`, `severity_window` | 内存压力失速信息 |
| `io_pressure` | Gauge | `pid`, `cmdline`, `severity_level`, `severity_window` | I/O 压力失速信息 |
| `cpu_pressure` | Gauge | `pid`, `cmdline`, `severity_level`, `severity_window` | CPU 压力失速信息 |
### 指标标签
- `pid`:进程 ID
- `cmdline`:进程的命令行
- `severity_level`:`some` 或 `full`
- `severity_window`:`avg10`、`avg60`、`avg300` 或 `total` 之一
指标有 1 分钟的空闲超时时间;如果一个进程(由 pid 和 cmdline 标识)在 1 分钟内未被检测到,其指标将被移除。
## 要求
- 带有 Linux 节点的 Kubernetes 集群(内核 4.20+ 以完全支持 PSI)
- Pod 必须设置 `shareProcessNamespace: true`
- 容器需要 `SYS_PTRACE` capability 才能发送信号
- `--warning` 和 `--critical` 表达式都有默认值,但用户应当对其进行自定义。
## 安装
### 使用预构建的容器
```
apiVersion: v1
kind: Pod
metadata:
name: my-application
spec:
shareProcessNamespace: true
containers:
- name: app
image: your-app:latest
resources:
limits:
memory: "512Mi"
cpu: "500m"
- name: oomhero
image: ghcr.io/ricardomaraschini/oomhero:latest
args:
- "--warning=memory_usage > 75"
- "--critical=memory_usage > 90"
- "--loop-interval=100ms"
- "--cooldown-interval=30s"
resources:
limits:
cpu: "1m"
memory: "32Mi"
securityContext:
capabilities:
add:
- SYS_PTRACE
```
### 从源码构建
```
# Clone the repository
git clone https://github.com/yourusername/oomhero
cd oomhero
# Build release binary
make release
# Run locally
./target/release/oomhero --warning "memory_usage > 75" --critical "memory_usage > 90"
```
## 用法
### 基本内存监控
```
oomhero \
--warning "memory_usage > 75" \
--critical "memory_usage > 90" \
--loop-interval 100ms \
--cooldown-interval 30s
```
### 全面资源监控
```
oomhero \
--warning "memory_usage > 70 || memory_pressure_full_avg60 > 50" \
--critical "memory_usage > 85 || memory_pressure_full_avg60 > 80" \
--loop-interval 200ms \
--cooldown-interval 30s
```
### 自定义 OOM Score 逻辑
```
oomhero \
--warning "oom_score > 500" \
--critical "oom_score > 800"
```
### 自定义信号
```
oomhero \
--warning "memory_usage > 75" \
--critical "memory_usage > 90" \
--warning-signal SIGHUP \
--critical-signal SIGTERM
```
### HTTP 通知
```
oomhero \
--warning "memory_usage > 75" \
--critical "memory_usage > 90" \
--http-file-path /etc/oomhero/config.yaml
```
**配置文件格式** (`config.yaml`):
```
url: https://hooks.example.com/alerts
headers:
- name: Authorization
value: Bearer token123
- name: Content-Type
value: application/json
```
**HTTP 请求体**:
```
{
"severity": "Warning",
"process": {
"pid": 1234,
"cmdline": "/usr/bin/myapp"
},
"collected_data": {
"memory_max": 536870912,
"memory_current": 421527552,
"memory_usage": 78.5,
"oom_score": 250,
"oom_score_adj": 0,
"pressure": {
"memory": {
"some": {"avg10": 5.2, "avg60": 3.1, "avg300": 2.8, "total": 1500000},
"full": {"avg10": 0.0, "avg60": 0.0, "avg300": 0.0, "total": 0}
},
"io": {
"some": {"avg10": 0.0, "avg60": 0.0, "avg300": 0.0, "total": 0},
"full": {"avg10": 0.0, "avg60": 0.0, "avg300": 0.0, "total": 0}
},
"cpu": {
"some": {"avg10": 0.0, "avg60": 0.0, "avg300": 0.0, "total": 0},
"full": {"avg10": 0.0, "avg60": 0.0, "avg300": 0.0, "total": 0}
}
}
}
}
```
## 配置选项
| 选项 | 描述 | 默认值 |
|--------|-------------|---------|
| `--warning` | 警告信号表达式 | (空) |
| `--critical` | 严重信号表达式 | (空) |
| `--loop-interval` | 进程扫描频率 | 100ms |
| `--cooldown-interval` | 重复发送信号的最小间隔时间 | 30s |
| `--warning-signal` | 在警告阈值时发送的信号 | SIGUSR1 |
| `--critical-signal` | 在严重阈值时发送的信号 | SIGUSR2 |
| `--http-file-path` | HTTP 通知配置的路径(与信号选项冲突) | (无) |
| `--version` | 显示版本信息 | false |
## 重要注意事项
### 内存限制与请求
OOMHero 基于容器的 **limits** 运行,而不是 requests。如果仅指定了资源 requests 而没有指定 limits,OOMHero 将无法计算出有意义的百分比使用量。
### 性能影响
OOMHero 会按配置的间隔扫描所有进程。请使用 CPU limits 来控制扫描频率和资源消耗。
## 故障排除
### OOMHero 退出并提示 "invalid expression: ..."
确保 `--warning` 和 `--critical` 表达式都是有效的 `fasteval` 表达式,并在启动 OOMHero 时提供。示例:
```
--warning "memory_usage > 75" --critical "memory_usage > 90"
```
### 应用程序未接收到信号
1. 验证 pod 上是否设置了 `shareProcessNamespace: true`
2. 确认 OOMHero 具有 `SYS_PTRACE` capability
3. 检查应用程序是否注册了信号处理程序
4. 查看 OOMHero 日志以了解信号传递错误
### CPU 使用率过高
通过增加 `--loop-interval` 来降低扫描频率,或者设置较低的 CPU limits 以限制 OOMHero 的执行速率。
## 许可证
在 Apache License, Version 2.0 下授权。有关详细信息,请参阅 [LICENSE](LICENSE)。
标签:OOM处理, Sidecar, 可视化界面, 子域名突变, 自定义请求头, 资源监控, 运维工具, 通知系统