通过 /_node/_local/_system 获取 BEAM 内存占用并设置 Prometheus 告警规则?

解读

在国内生产环境中,CouchDB 通常以 三节点以上集群 形态部署在 CentOS 7/8 或国产麒麟、统信 OS 上,并接入公司统一的 Prometheus + Alertmanager + 企业微信/钉钉 监控体系。
面试官问这道题,核心想验证三件事:

  1. 你是否知道 CouchDB 暴露 BEAM 虚拟机指标的 唯一官方入口 就是 /_node/_local/_system
  2. 能否把 Erlang 内存数据 准确映射成 Prometheus 可识别的指标;
  3. 能否结合国内 SRE 告警规范(分级、收敛、值班)写出一条 可落地的 PromQL 告警规则
    如果仅回答“用 curl 拿一下 JSON”而忽略指标转换、标签设计、阈值合理性,会被直接判定为 “只玩过单机”

知识点

  1. /_node/_local/_system 返回的是 Erlang 运行时快照,关键字段:
    • memory.total:BEAM 占用的 全部内存(含进程堆、ETS、代码区、二进制区);
    • memory.processes_used:实际 业务进程 占用;
    • memory.system:虚拟机自身开销;
    • memory.binary:大二进制对象(附件、视图索引)占用,最容易 OOM
  2. CouchDB 原生不带 Prometheus 格式,需要 sidecar exporter自定义脚本 将 JSON 转成 /metrics。国内大厂普遍用 Python + prometheus_client 写 50 行脚本,挂到 systemd service,监听 9984 端口。
  3. Prometheus 标签设计必须带 clusternodeinstance 三个维度,方便 多集群、多节点 场景做 聚合与屏蔽
  4. 告警阈值需参考 物理机内存 而非固定绝对值;国内习惯用 80%、90%、95% 三级阈值,并配合 for: 5m 抑制毛刺。
  5. Alertmanager 路由要匹配 CouchDB 值班组,并附加 runbook 链接(内部 Confluence),否则告警会被 “狼来了” 直接忽略。

答案

  1. 采集端
    编写 couchdb_beam_exporter.py,每分钟拉取 http://127.0.0.1:5984/_node/_local/_system,提取:

    couchdb_beam_memory_bytes{cluster="prod",node="couchdb@10.0.0.11",type="total"}  6.8e+09
    couchdb_beam_memory_bytes{cluster="prod",node="couchdb@10.0.0.11",type="binary"} 2.1e+09
    couchdb_beam_memory_bytes{cluster="prod",node="couchdb@10.0.0.11",type="processes_used"} 3.4e+09
    

    脚本内部把 memory.total/proc/meminfoMemTotal 相除,额外暴露:

    couchdb_beam_memory_ratio{cluster="prod",node="couchdb@10.0.0.11"} 0.83
    
  2. Prometheus 告警规则(YAML 片段,可直接放入 kube-prometheus-stackadditionalPrometheusRulesMap

    groups:
    - name: couchdb_beam_memory
      interval: 30s
      rules:
      - alert: CouchDBBeamMemoryHigh
        expr: couchdb_beam_memory_ratio > 0.80
        for: 5m
        labels:
          severity: warning
          team: dba
          cluster: "{{ $labels.cluster }}"
          node: "{{ $labels.node }}"
        annotations:
          summary: "CouchDB BEAM 内存占用超过 80%"
          description: "节点 {{ $labels.node }} BEAM 内存占比 {{ $value | humanizePercentage }},请关注 binary 与视图索引增长。"
          runbook: "https://wiki.company.com/couchdb-oom-runbook"
    
      - alert: CouchDBBeamMemoryCritical
        expr: couchdb_beam_memory_ratio > 0.95
        for: 2m
        labels:
          severity: critical
          team: dba
        annotations:
          summary: "CouchDB BEAM 内存即将 OOM"
          description: "节点 {{ $labels.node }} BEAM 内存占比 {{ $value | humanizePercentage }},请立即扩容或重启视图压缩。"
    
  3. 验证
    使用 stress2 工具往 CouchDB 灌 100 k 附件,观察 Prometheus Graph 中 couchdb_beam_memory_ratio 曲线在 2 分钟内从 0.4 涨到 0.85,告警如期触发,企业微信机器人 @DBA 值班群,符合国内 “5 分钟内响应” 的 SLA 要求。

拓展思考

  1. 如果集群部署在 ARM 国产芯片 上,Erlang 的内存分配策略 +MMmcs 默认值可能导致 内存碎片 更高,建议把阈值下调到 75% 并开启 +MBlmbcs 512 参数,重新压测后再调告警。
  2. 当 binary 区单项超过 总内存 40% 时,可直接触发 视图压缩作业;可把规则再拆一条:
    expr: couchdb_beam_memory_bytes{type="binary"} / couchdb_beam_memory_bytes{type="total"} > 0.4
    
    并通过 Webhook 调用 内部 Jenkins Job 自动执行 /_view_compaction,实现 告警-自愈闭环
  3. 为了应对 双 11 级别突发流量,可把 for 缩短到 30s,但需先在 预发环境chaosblade 注入内存负载,验证 误报率 < 2% 才能上线,否则会被 SRE 红牌 打回。