饮墨

子安饮墨馀三斗,留与卿儿作赋来

Gatus:轻量级健康监控与状态页,5分钟替代臃肿的 Uptime 方案

痛点

运维团队经常面临这样的困境:Prometheus + Alertmanager 体系虽强大,但对于 "服务到底通不通" 这个最基本的问题,配置链路却异常冗长——要写 blackbox_exporter 配置、Prometheus scrape job、告警规则、Alertmanager 路由,最后还得搭个 Grafana dashboard 给业务方看。

而商业方案(Datadog Synthetics、PagerDuty、UptimeRobot Pro)月费动辄几百美元,对中小团队或内部项目来说性价比极低。

核心需求其实很简单: - 定时探测 HTTP/TCP/DNS/gRPC 端点 - 探测失败立即告警(Slack/钉钉/Webhook) - 提供一个简洁状态页,给团队或客户看服务健康状态

Gatus 正是为这个场景而生——单二进制、零依赖、YAML 一把梭配置,自带 UI 状态页,5 分钟内可投产。

方案概述

Gatus 是用 Go 编写的开源健康监控工具,核心特点:

特性 说明
协议支持 HTTP/HTTPS、TCP、DNS、ICMP、gRPC、SSH、WebSocket
条件引擎 支持响应时间、状态码、Body 内容、证书过期时间等条件组合
告警集成 Slack、Teams、Discord、钉钉(Webhook)、PagerDuty、Email、Telegram 等 20+
状态页 内置 Web UI,支持按分组展示、历史可用率、响应时间图表
存储后端 SQLite(默认)/ PostgreSQL,支持持久化历史数据
部署方式 单二进制 / Docker / Kubernetes Helm Chart
资源占用 监控 50 个端点,内存 < 30MB

与 Prometheus blackbox_exporter 对比:

维度 Gatus blackbox_exporter + Prometheus
部署复杂度 1 个容器 + 1 个 YAML 3+ 组件协同
配置学习成本 10 分钟 2+ 小时
内置状态页 ❌ 需额外 Grafana
告警配置 内联在端点定义中 需独立 Alertmanager 配置
适用场景 端点健康 / 状态页 全面监控体系的一部分

结论: Gatus 不是要替代 Prometheus,而是作为轻量级补充——专注于 "服务可达性" 这一垂直场景,以极低运维成本提供即时价值。

实操步骤

Step 1:Docker Compose 快速部署

# docker-compose.yml
version: "3.8"
services:
  gatus:
    image: twinproduction/gatus:latest
    container_name: gatus
    ports:
      - "8080:8080"
    volumes:
      - ./config:/config
      - gatus-data:/data
    environment:
      - GATUS_CONFIG_PATH=/config/config.yaml
    restart: unless-stopped

volumes:
  gatus-data:

Step 2:编写监控配置

# config/config.yaml
storage:
  type: sqlite
  path: /data/gatus.db

ui:
  title: "Ops Status Page"
  header: "服务健康状态"

endpoints:
  # HTTP 健康检查
  - name: "API Gateway"
    group: "Production"
    url: "https://api.example.com/health"
    interval: 30s
    conditions:
      - "[STATUS] == 200"
      - "[RESPONSE_TIME] < 500"
      - "[BODY].status == UP"
    alerts:
      - type: slack
        enabled: true
        failure-threshold: 3
        success-threshold: 2
        description: "API Gateway 健康检查失败"

  # TCP 端口探测
  - name: "MySQL Primary"
    group: "Database"
    url: "tcp://db-primary.internal:3306"
    interval: 15s
    conditions:
      - "[CONNECTED] == true"
      - "[RESPONSE_TIME] < 100"
    alerts:
      - type: slack
        enabled: true
        failure-threshold: 2

  # DNS 解析检查
  - name: "DNS Resolution"
    group: "Infrastructure"
    url: "dns://ns1.example.com"
    dns:
      query-name: "api.example.com"
      query-type: "A"
    conditions:
      - "[DNS_RCODE] == NOERROR"
      - "[RESPONSE_TIME] < 50"

  # SSL 证书过期监控
  - name: "SSL Certificate"
    group: "Security"
    url: "https://www.example.com"
    interval: 1h
    conditions:
      - "[STATUS] == 200"
      - "[CERTIFICATE_EXPIRATION] > 168h"  # 7天前告警
    alerts:
      - type: slack
        enabled: true
        failure-threshold: 1
        description: "SSL证书将在7天内过期!"

alerting:
  slack:
    webhook-url: "${SLACK_WEBHOOK_URL}"
    default-alert:
      enabled: true
      send-on-resolved: true

Step 3:Kubernetes 部署(Helm)

# 添加 Helm repo
helm repo add twin https://twin.github.io/helm-charts
helm repo update

# 安装,使用自定义 values
helm install gatus twin/gatus \
  --namespace monitoring \
  --create-namespace \
  -f gatus-values.yaml

gatus-values.yaml 关键配置:

# gatus-values.yaml
ingress:
  enabled: true
  annotations:
    kubernetes.io/ingress.class: nginx
    cert-manager.io/cluster-issuer: letsencrypt-prod
  hosts:
    - host: status.example.com
      paths:
        - path: /
          pathType: Prefix
  tls:
    - secretName: gatus-tls
      hosts:
        - status.example.com

persistence:
  enabled: true
  size: 1Gi

config:
  storage:
    type: sqlite
    path: /data/gatus.db

Step 4:钉钉告警集成

# 在 config.yaml 的 alerting 段添加
alerting:
  custom:
    url: "https://oapi.dingtalk.com/robot/send?access_token=${DINGTALK_TOKEN}"
    method: "POST"
    headers:
      Content-Type: application/json
    body: |
      {
        "msgtype": "markdown",
        "markdown": {
          "title": "[ALERT_DESCRIPTION]",
          "text": "### [ALERT_DESCRIPTION]\n\n- **端点**: [ENDPOINT_NAME]\n- **分组**: [ENDPOINT_GROUP]\n- **状态**: [ALERT_TRIGGERED_OR_RESOLVED]\n- **条件**: [ENDPOINT_CONDITIONS]"
        }
      }

避坑指南

1. 探测间隔不要设太短

Gatus 每个探测是同步执行的。如果你监控 100 个端点、每个 5 秒间隔,且某些端点响应慢(超时 10s),会导致探测队列积压。建议: - 关键服务:15-30s - 一般服务:60s - 证书/DNS:5m-1h

2. SQLite 在高并发写入下的锁问题

监控端点超过 200 个时,SQLite 的写锁可能导致数据写入延迟。解决方案:

storage:
  type: postgres
  path: "postgres://gatus:password@pg-host:5432/gatus?sslmode=require"

迁移很简单——Gatus 会自动创建表结构,历史数据需手动导入或直接从零开始积累。

3. 容器内 DNS 解析与宿主机不一致

Docker 部署时,容器默认用 Docker 内置 DNS(127.0.0.11),可能解析不到内网域名。解决:

# docker-compose.yml 中添加
services:
  gatus:
    dns:
      - 10.0.0.2      # 内网 DNS
      - 8.8.8.8       # 备用
    # 或者用 host 网络模式
    network_mode: host

进阶用法

条件表达式组合——检测 API 返回内容:

- name: "Payment Service"
  url: "https://pay.example.com/api/v1/health"
  conditions:
    - "[STATUS] == 200"
    - "[RESPONSE_TIME] < 1000"
    - "[BODY].services.database == connected"
    - "[BODY].services.redis == connected"
    - "[BODY].version pat *v2.*"  # 确认版本号模式

外部端点 + 内部端点分组展示:

状态页天然支持分组,可以创建一个对外公开的状态页(只展示外部服务),内部团队看完整视图——通过部署两个 Gatus 实例实现,或用 ui.buttons 做导航。

总结

场景 推荐方案
需要完整可观测性体系 Prometheus + Grafana + Alertmanager
只需服务健康监控 + 状态页 Gatus
需要给客户/业务方看状态 Gatus(内置 UI 开箱即用)
证书过期 + 端口存活告警 Gatus(配置量是 blackbox_exporter 的 1/5)

核心价值: 以最小运维成本(单容器 < 30MB 内存)解决 "服务到底通不通" 的问题,10 分钟内从零到可用告警 + 状态页。

适合谁: - 中小团队需要快速搭建状态页 - 已有 Prometheus 体系但嫌 blackbox_exporter 配置繁琐 - 需要给非技术人员展示服务状态的运维团队

GitHub: https://github.com/TwiN/gatus | Stars: 7k+ | License: Apache 2.0

您还没有登录,请登录后发表评论。