feat(monitoring): 监控编排统一到 FruitServer compose
把原先散落在 D:\fruitshorts\monitoring 的手工栈收编进仓库:prometheus 增加 cAdvisor 与 blackbox 抓取、15 天保留期;grafana 改为 provisioning 自动加载数据源与看板;新增 blackbox/cadvisor 服务;Grafana 管理员密码改走环境变量(必填),不再硬编码 admin/admin。
This commit is contained in:
1 parent
b391ad31af
commit
530da2b1b4
7 files changed
+210
-3
No files matched your search
@@ -30,6 +30,11 @@ MEDIA_ROOT_DIR=/data/uploads
|
|||||||
# false = 两个都关闭(生产若不希望暴露 UI 就设 false,机器可读契约也一并关闭)
|
# false = 两个都关闭(生产若不希望暴露 UI 就设 false,机器可读契约也一并关闭)
|
||||||
SWAGGER_ENABLED=true
|
SWAGGER_ENABLED=true
|
||||||
|
|
||||||
|
# ── 监控 ───────────────────────────────────────────────
|
||||||
|
# Grafana 管理员密码(必填):3000 端口对外开放,不允许用默认 admin/admin
|
||||||
|
GRAFANA_ADMIN_USER=admin
|
||||||
|
GRAFANA_ADMIN_PASSWORD=
|
||||||
|
|
||||||
# ── 可选:Google Play 商店票据校验(不配则保持 disabled)──
|
# ── 可选:Google Play 商店票据校验(不配则保持 disabled)──
|
||||||
STORE_VERIFIER=disabled
|
STORE_VERIFIER=disabled
|
||||||
GOOGLE_PLAY_PACKAGE_NAME=
|
GOOGLE_PLAY_PACKAGE_NAME=
|
||||||
|
|||||||
@@ -0,0 +1,11 @@
|
|||||||
|
# Author: fruit.com.cn
|
||||||
|
# blackbox-exporter 探针模块:只探测 HTTP 2xx,跟随重定向
|
||||||
|
modules:
|
||||||
|
http_2xx:
|
||||||
|
prober: http
|
||||||
|
timeout: 5s
|
||||||
|
http:
|
||||||
|
preferred_ip_protocol: ip4
|
||||||
|
valid_http_versions: ["HTTP/1.1", "HTTP/2.0"]
|
||||||
|
valid_status_codes: [200]
|
||||||
|
follow_redirects: true
|
||||||
+39
-2
@@ -149,6 +149,7 @@ services:
|
|||||||
retries: 3
|
retries: 3
|
||||||
|
|
||||||
# ─────────── 监控 ───────────
|
# ─────────── 监控 ───────────
|
||||||
|
# 编排统一在这里:prometheus(应用指标 + 容器指标 + 黑盒探活)+ grafana(自动加载看板)
|
||||||
prometheus:
|
prometheus:
|
||||||
image: prom/prometheus:latest
|
image: prom/prometheus:latest
|
||||||
container_name: fruitshorts-prometheus
|
container_name: fruitshorts-prometheus
|
||||||
@@ -160,6 +161,15 @@ services:
|
|||||||
- prometheus-data:/prometheus
|
- prometheus-data:/prometheus
|
||||||
command:
|
command:
|
||||||
- "--config.file=/etc/prometheus/prometheus.yml"
|
- "--config.file=/etc/prometheus/prometheus.yml"
|
||||||
|
# 15 天保留期,避免磁盘无限增长
|
||||||
|
- "--storage.tsdb.retention.time=15d"
|
||||||
|
- "--web.enable-lifecycle"
|
||||||
|
healthcheck:
|
||||||
|
test: ["CMD-SHELL", "wget -qO- http://127.0.0.1:9090/-/healthy >/dev/null || exit 1"]
|
||||||
|
interval: 30s
|
||||||
|
timeout: 5s
|
||||||
|
start_period: 20s
|
||||||
|
retries: 3
|
||||||
|
|
||||||
grafana:
|
grafana:
|
||||||
image: grafana/grafana:latest
|
image: grafana/grafana:latest
|
||||||
@@ -169,9 +179,36 @@ services:
|
|||||||
- "3000:3000"
|
- "3000:3000"
|
||||||
volumes:
|
volumes:
|
||||||
- grafana-data:/var/lib/grafana
|
- grafana-data:/var/lib/grafana
|
||||||
|
# 数据源与看板全部来自仓库,换机器不需要手工配
|
||||||
|
- ./grafana/provisioning:/etc/grafana/provisioning:ro
|
||||||
|
- ./grafana/dashboards:/var/lib/grafana/dashboards:ro
|
||||||
environment:
|
environment:
|
||||||
- GF_SECURITY_ADMIN_USER=admin
|
GF_SECURITY_ADMIN_USER: ${GRAFANA_ADMIN_USER:-admin}
|
||||||
- GF_SECURITY_ADMIN_PASSWORD=admin
|
GF_SECURITY_ADMIN_PASSWORD: ${GRAFANA_ADMIN_PASSWORD:?Grafana 管理员密码必填,见 .env.example}
|
||||||
|
GF_USERS_ALLOW_SIGN_UP: "false"
|
||||||
|
TZ: Asia/Shanghai
|
||||||
|
depends_on:
|
||||||
|
- prometheus
|
||||||
|
|
||||||
|
# 黑盒探活:从外部探测接口可用性与耗时
|
||||||
|
blackbox:
|
||||||
|
image: prom/blackbox-exporter:latest
|
||||||
|
container_name: fruitshorts-blackbox
|
||||||
|
restart: unless-stopped
|
||||||
|
volumes:
|
||||||
|
- ./blackbox/blackbox.yml:/etc/blackbox_exporter/config.yml:ro
|
||||||
|
|
||||||
|
# 容器资源指标(CPU / 内存 / 网络 / 重启),供 Prometheus 抓取
|
||||||
|
cadvisor:
|
||||||
|
image: gcr.io/cadvisor/cadvisor:latest
|
||||||
|
container_name: fruitshorts-cadvisor
|
||||||
|
restart: unless-stopped
|
||||||
|
privileged: true
|
||||||
|
volumes:
|
||||||
|
- /:/rootfs:ro
|
||||||
|
- /var/run:/var/run:ro
|
||||||
|
- /sys:/sys:ro
|
||||||
|
- /var/lib/docker/:/var/lib/docker:ro
|
||||||
|
|
||||||
volumes:
|
volumes:
|
||||||
# 命名卷:跟着 compose 项目走,`docker compose down -v` 才会删
|
# 命名卷:跟着 compose 项目走,`docker compose down -v` 才会删
|
||||||
|
|||||||
@@ -0,0 +1,93 @@
|
|||||||
|
{
|
||||||
|
"uid": "fruitshorts-backend",
|
||||||
|
"title": "FruitShorts 后端监控",
|
||||||
|
"tags": ["fruitshorts", "backend"],
|
||||||
|
"timezone": "browser",
|
||||||
|
"editable": true,
|
||||||
|
"schemaVersion": 39,
|
||||||
|
"version": 1,
|
||||||
|
"refresh": "30s",
|
||||||
|
"time": { "from": "now-6h", "to": "now" },
|
||||||
|
"panels": [
|
||||||
|
{
|
||||||
|
"id": 1,
|
||||||
|
"type": "stat",
|
||||||
|
"title": "服务探活(1=正常 0=异常)",
|
||||||
|
"datasource": { "type": "prometheus", "uid": "prometheus" },
|
||||||
|
"gridPos": { "x": 0, "y": 0, "w": 8, "h": 6 },
|
||||||
|
"options": {
|
||||||
|
"colorMode": "background",
|
||||||
|
"graphMode": "none",
|
||||||
|
"reduceOptions": { "calcs": ["lastNotNull"], "fields": "", "values": false }
|
||||||
|
},
|
||||||
|
"fieldConfig": {
|
||||||
|
"defaults": {
|
||||||
|
"mappings": [
|
||||||
|
{ "type": "value", "options": { "0": { "text": "异常", "color": "red", "index": 0 } } },
|
||||||
|
{ "type": "value", "options": { "1": { "text": "正常", "color": "green", "index": 1 } } }
|
||||||
|
],
|
||||||
|
"thresholds": { "mode": "absolute", "steps": [{ "color": "red", "value": null }, { "color": "green", "value": 1 }] }
|
||||||
|
},
|
||||||
|
"overrides": []
|
||||||
|
},
|
||||||
|
"targets": [
|
||||||
|
{ "refId": "A", "expr": "probe_success{job=\"blackbox\"}", "legendFormat": "{{instance}}" }
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 2,
|
||||||
|
"type": "timeseries",
|
||||||
|
"title": "接口探测耗时(秒)",
|
||||||
|
"datasource": { "type": "prometheus", "uid": "prometheus" },
|
||||||
|
"gridPos": { "x": 8, "y": 0, "w": 16, "h": 6 },
|
||||||
|
"fieldConfig": { "defaults": { "unit": "s", "custom": { "lineWidth": 2, "fillOpacity": 10 } }, "overrides": [] },
|
||||||
|
"targets": [
|
||||||
|
{ "refId": "A", "expr": "probe_duration_seconds{job=\"blackbox\"}", "legendFormat": "{{instance}}" }
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 3,
|
||||||
|
"type": "timeseries",
|
||||||
|
"title": "容器 CPU 使用(核)",
|
||||||
|
"datasource": { "type": "prometheus", "uid": "prometheus" },
|
||||||
|
"gridPos": { "x": 0, "y": 6, "w": 12, "h": 8 },
|
||||||
|
"fieldConfig": { "defaults": { "unit": "short", "custom": { "lineWidth": 2, "fillOpacity": 10 } }, "overrides": [] },
|
||||||
|
"targets": [
|
||||||
|
{ "refId": "A", "expr": "sum(rate(container_cpu_usage_seconds_total{name=~\"fruitshorts-(app-api|admin-api|db|redis|transcode-worker)\"}[1m])) by (name)", "legendFormat": "{{name}}" }
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 4,
|
||||||
|
"type": "timeseries",
|
||||||
|
"title": "容器内存(GiB)",
|
||||||
|
"datasource": { "type": "prometheus", "uid": "prometheus" },
|
||||||
|
"gridPos": { "x": 12, "y": 6, "w": 12, "h": 8 },
|
||||||
|
"fieldConfig": { "defaults": { "unit": "bytes", "custom": { "lineWidth": 2, "fillOpacity": 10 } }, "overrides": [] },
|
||||||
|
"targets": [
|
||||||
|
{ "refId": "A", "expr": "sum(container_memory_working_set_bytes{name=~\"fruitshorts-(app-api|admin-api|db|redis|transcode-worker)\"}) by (name)", "legendFormat": "{{name}}" }
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 5,
|
||||||
|
"type": "timeseries",
|
||||||
|
"title": "容器网络接收(B/s)",
|
||||||
|
"datasource": { "type": "prometheus", "uid": "prometheus" },
|
||||||
|
"gridPos": { "x": 0, "y": 14, "w": 12, "h": 8 },
|
||||||
|
"fieldConfig": { "defaults": { "unit": "Bps", "custom": { "lineWidth": 2, "fillOpacity": 10 } }, "overrides": [] },
|
||||||
|
"targets": [
|
||||||
|
{ "refId": "A", "expr": "sum(rate(container_network_receive_bytes_total{name=~\"fruitshorts-(app-api|admin-api|db|redis|transcode-worker)\"}[1m])) by (name)", "legendFormat": "{{name}}" }
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 6,
|
||||||
|
"type": "timeseries",
|
||||||
|
"title": "Prometheus 抓取目标状态(1=UP)",
|
||||||
|
"datasource": { "type": "prometheus", "uid": "prometheus" },
|
||||||
|
"gridPos": { "x": 12, "y": 14, "w": 12, "h": 8 },
|
||||||
|
"fieldConfig": { "defaults": { "unit": "short", "min": 0, "max": 1, "custom": { "lineWidth": 2, "fillOpacity": 10 } }, "overrides": [] },
|
||||||
|
"targets": [
|
||||||
|
{ "refId": "A", "expr": "up", "legendFormat": "{{job}} {{instance}}" }
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
# Author: fruit.com.cn
|
||||||
|
# 看板自动加载:容器内 /var/lib/grafana/dashboards 挂载的是仓库里的 grafana/dashboards
|
||||||
|
apiVersion: 1
|
||||||
|
|
||||||
|
providers:
|
||||||
|
- name: 'FruitShorts'
|
||||||
|
orgId: 1
|
||||||
|
folder: 'FruitShorts'
|
||||||
|
type: file
|
||||||
|
disableDeletion: false
|
||||||
|
updateIntervalSeconds: 30
|
||||||
|
allowUiUpdates: true
|
||||||
|
options:
|
||||||
|
path: /var/lib/grafana/dashboards
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
# Author: fruit.com.cn
|
||||||
|
# Grafana 数据源:compose 内网直连 prometheus 服务
|
||||||
|
apiVersion: 1
|
||||||
|
|
||||||
|
datasources:
|
||||||
|
- name: Prometheus
|
||||||
|
uid: prometheus
|
||||||
|
type: prometheus
|
||||||
|
access: proxy
|
||||||
|
url: http://prometheus:9090
|
||||||
|
isDefault: true
|
||||||
|
editable: false
|
||||||
|
jsonData:
|
||||||
|
timeInterval: 15s
|
||||||
+34
-1
@@ -1,8 +1,13 @@
|
|||||||
# Author: fruit.com.cn
|
# Author: fruit.com.cn
|
||||||
# Prometheus 抓取配置:抓取后端双服务的 actuator 指标(服务名走 compose 网络)
|
# Prometheus 抓取配置:全部走 compose 内网的服务名解析。
|
||||||
|
# - 应用指标:Spring Boot actuator
|
||||||
|
# - 容器指标:cAdvisor
|
||||||
|
# - 探活/耗时:blackbox-exporter(不依赖后端代码,从外部看接口是否可用)
|
||||||
global:
|
global:
|
||||||
scrape_interval: 15s
|
scrape_interval: 15s
|
||||||
evaluation_interval: 15s
|
evaluation_interval: 15s
|
||||||
|
external_labels:
|
||||||
|
project: fruitshorts
|
||||||
|
|
||||||
scrape_configs:
|
scrape_configs:
|
||||||
- job_name: "fruitshorts-app-api"
|
- job_name: "fruitshorts-app-api"
|
||||||
@@ -14,3 +19,31 @@ scrape_configs:
|
|||||||
metrics_path: "/actuator/prometheus"
|
metrics_path: "/actuator/prometheus"
|
||||||
static_configs:
|
static_configs:
|
||||||
- targets: ["admin-api:8080"]
|
- targets: ["admin-api:8080"]
|
||||||
|
|
||||||
|
- job_name: "prometheus"
|
||||||
|
static_configs:
|
||||||
|
- targets: ["localhost:9090"]
|
||||||
|
|
||||||
|
# 容器 CPU / 内存 / 网络 / 重启次数
|
||||||
|
- job_name: "cadvisor"
|
||||||
|
static_configs:
|
||||||
|
- targets: ["cadvisor:8080"]
|
||||||
|
|
||||||
|
# 入口探活:healthz 用于存活判定,两个业务接口用于可用性与耗时
|
||||||
|
- job_name: "blackbox"
|
||||||
|
metrics_path: /probe
|
||||||
|
params:
|
||||||
|
module: [http_2xx]
|
||||||
|
static_configs:
|
||||||
|
- targets:
|
||||||
|
- http://app-api:8081/healthz
|
||||||
|
- http://admin-api:8080/healthz
|
||||||
|
- http://app-api:8081/app/categories
|
||||||
|
- http://app-api:8081/app/home/feed
|
||||||
|
relabel_configs:
|
||||||
|
- source_labels: [__address__]
|
||||||
|
target_label: __param_target
|
||||||
|
- source_labels: [__param_target]
|
||||||
|
target_label: instance
|
||||||
|
- target_label: __address__
|
||||||
|
replacement: blackbox:9115
|
||||||
Reference in new issue
Block a user