使用 `docker events` 过滤出 `oom` 事件并报警
解读
在国内生产环境中,容器因内存超限被 OOM Kill 是高频故障源,轻则服务瞬断,重则触发级联重启。面试官问“用 docker events 过滤 oom 并报警”,表面考一条命令,实则验证候选人是否具备实时告警闭环思维:
- 能否精准过滤 Docker 原生事件流;
- 能否低延迟将事件推送到企业微信/钉钉/飞书;
- 能否去重并分级,避免告警风暴;
- 能否联动自动扩容或触发预案。
答出“一条 grep”只能拿 30 分,给出“事件驱动+去重+分级+回调”的完整脚本才能拿到 90+。
知识点
-
docker events 子命令
- 默认输出 JSON,字段:Type、Action、Actor.ID、Actor.Attributes。
- 时间范围:
--since、--until支持 RFC3339 或相对时间如10m。 - 过滤器:
-f type=container -f event=oom,Docker 20.10+ 才原生支持 oom 事件,老版本需回退到die事件并解析 exitCode=137。
-
OOM 事件特征
- Action=oom,Type=container,Actor.Attributes 含
name、image、oomKilled=true。 - 与
die事件成对出现,需按 container ID 去重,否则双告警。
- Action=oom,Type=container,Actor.Attributes 含
-
告警通道
- 内网:飞书群机器人、钉钉自定义机器人(加签/关键字)。
- 外网:阿里云事件总线+函数计算、腾讯云 CLS+SCF。
- 统一要求:3 秒内到达,支持 Markdown 富文本,可 @责任人。
-
去重与分级
- 内存阀值 30s 内同一容器重复 OOM 只报一次。
- 按服务等级分级:核心服务 P1 电话,非核心 P3 群内通知。
-
脚本健壮性
- 使用
jq解析 JSON,避免grep误匹配。 - 采用
systemd守护,崩溃自动拉起;日志走journald,方便审计。
- 使用
答案
给出一条可直接落地的 Bash 方案,满足CentOS 7/8、Ubuntu 20.04+、统信 UOS等国内主流镜像源,无需 root,普通 docker 用户即可运行。
#!/bin/bash
# file: /usr/local/bin/docker-oom-watchdog.sh
set -euo pipefail
WEBHOOK="https://open.feishu.cn/open-apis/bot/v2/hook/xxxxxxxx"
GRACE=30 # 去重窗口秒
CACHE="/tmp/docker-oom.cache"
touch "$CACHE"
docker events \
--filter 'type=container' \
--filter 'event=oom' \
--format '{{json .}}' | \
while IFS= read -r line; do
id=$(echo "$line" | jq -r .Actor.ID)
name=$(echo "$line" | jq -r .Actor.Attributes.name)
image=$(echo "$line" | jq -r .Actor.Attributes.image)
now=$(date +%s)
# 去重:同一容器 GRACE 秒内只报一次
last=$(grep "^${id}:" "$CACHE" | cut -d: -f2 || echo 0)
if (( now - last < GRACE )); then
continue
fi
# 更新缓存
echo "${id}:${now}" >> "$CACHE"
# 只保留最近 1000 条,防止膨胀
tail -n 1000 "$CACHE" > "${CACHE}.tmp" && mv "${CACHE}.tmp" "$CACHE"
# 组装飞书 Markdown
msg=$(cat <<EOF
**容器 OOM 告警**
- 容器:**${name}**
- 镜像:**${image}**
- ID:\`${id:0:12}\`
- 时间:$(date '+%F %T')
- 主机:$(hostname -f)
EOF
)
curl -sX POST "$WEBHOOK" \
-H 'Content-Type: application/json' \
-d "$(jq -n --arg txt "$msg" '{msg_type:"post",content:{post:{zh_cn:{title:"容器OOM",content:[[{tag:"text",text:$txt}]]}}}}')" \
> /dev/null
done
启动与守护
sudo tee /etc/systemd/system/docker-oom-watchdog.service > /dev/null <<'EOF'
[Unit]
Description=Docker OOM Watchdog
After=docker.service
Requires=docker.service
[Service]
Type=simple
ExecStart=/usr/local/bin/docker-oom-watchdog.sh
Restart=always
RestartSec=5s
StandardOutput=journal
StandardError=journal
[Install]
WantedBy=multi-user.target
EOF
sudo systemctl daemon-reload
sudo systemctl enable --now docker-oom-watchdog
验证
# 制造 OOM
docker run --rm -m 50m alpine sh -c 'dd if=/dev/zero of=/dev/null bs=100M'
# 3 秒内飞书群收到 Markdown 卡片,@全体
拓展思考
-
集群级聚合
在 Swarm 或 K8s 场景,单节点脚本不够,需把事件打到 Kafka,用 Flink 做 1 分钟窗口聚合,输出“服务维度 OOM 率”,再触发 HPA 扩容。 -
根因自动采集
OOM 瞬间自动docker exec抓取/proc/meminfo、top、jmap,压缩后上传到 MinIO,供研发事后复盘,减少 50% 排障时间。 -
与 Prometheus 联动
利用docker_exporter把 OOM 总数转成指标docker_container_oom_total,在 Grafana 配置告警规则,实现图形化趋势+多维度切片(镜像版本、集群、业务线)。 -
安全加固
若容器以 non-root 运行,需确保docker events对普通用户可见:sudo usermod -aG docker watchdog避免脚本因权限失败而静默丢告警。
-
合规审计
国内金融、政务云要求告警留痕 6 个月,可把事件同时写进 Elasticsearch,索引模板开启 ILM,冷热分层节省 70% 存储。