Appearance
Prometheus StatsD Exporter 部署
接收應用程式以 StatsD 協定推送的指標,並將其轉換為 Prometheus 格式的橋接元件;支援獨立部署與 Sidecar 兩種模式。
概述
StatsD Exporter 是 Prometheus 生態中一個特殊的 Exporter:它不是主動連線到目標系統抓取指標,而是扮演一個 StatsD Server,等待應用程式主動將 metrics 以 UDP/TCP 推送過來。這種推送(push)模式適合無法暴露 HTTP /metrics 端點的應用程式,例如傳統的 Gunicorn Web Server 透過 statsd 函式庫自動送出請求統計。
有兩種部署方式:
- 獨立部署(Helm Chart):一個共用的 StatsD Exporter 服務,多個應用程式的指標都推送到同一個端點
- Sidecar 部署(推薦):每個應用 Pod 帶一個自己的 StatsD Exporter,隨主服務一同重啟,指標隔離性更好
核心內容
Metric Mapping 機制
StatsD 原始 metric 名稱通常是點號分隔的路徑(如 myapp.gunicorn.request.status.200),Prometheus 期望的格式是帶 Label 的結構化名稱(如 gunicorn_response_code{app="myapp", status="200"})。
Mapping 設定透過 glob 模式(* 萬用字元)捕捉路徑中的動態部分,再以 $1、$2 引用轉換為 Label:
yaml
mappings:
- match: "*.gunicorn.request.status.*"
name: "gunicorn_response_code"
labels:
app: "$1" # 捕捉第一個 *
status: "$2" # 捕捉最後一個 *獨立 vs. Sidecar 選擇
| 面向 | 獨立部署 | Sidecar 部署 |
|---|---|---|
| 管理複雜度 | 低(一個服務) | 高(每個 Pod 一份) |
| 指標隔離性 | 低(共用 Port) | 高(應用私有) |
| 服務生命週期 | 獨立 | 隨主服務重啟 |
| Prometheus 抓取 | ClusterIP Service | Pod 同一個 Service |
| 推薦場景 | 舊系統整合 | 新服務開發 |
Sidecar 模式的網路特性
Sidecar Container 與主容器共用 Pod 網路命名空間,因此應用程式的 StatsD 連線目標是 127.0.0.1:9125(localhost),不需要服務發現或跨 Pod 通訊。
Lifecycle API(資料殘留問題)
StatsD Exporter 在資料停止推送後仍會保留先前的 metric 值(不像 Prometheus 的 target 可以標記為 down)。啟用 --web.enable-lifecycle 後,可呼叫以下端點來重設 Exporter 狀態:
| 端點 | 功能 |
|---|---|
/-/reload | 重新載入 Mapping 設定 |
/-/quit | 停止 Exporter(觸發 Pod 重啟) |
關鍵要點
- StatsD Exporter 是被動接收推送的 Server,而非主動抓取的 Client
- Mapping 設定決定 Prometheus 指標的命名與 Label 結構,需與應用程式的 metric 格式對應
- Sidecar 模式下,應用程式連線
127.0.0.1:9125;Service 額外開放9102供 Prometheus 抓取 - Helm Chart 的 NodePort 無法透過 Chart 指定埠號,需要另外建立 Service YAML
- 資料殘留問題:資料停止後 Exporter 仍保留舊值,可用 Lifecycle API 清除
實際應用
Gunicorn Web Server 啟動時配置 statsd_host="127.0.0.1:9125",透過 gunicorn_statsd 等函式庫自動將請求統計(狀態碼、回應時間、Worker 數量)推送到 StatsD Exporter Sidecar,再由 Prometheus 定期從 Pod 的 9102 端口抓取轉換後的指標,最終在 Grafana 上呈現 API 效能儀表板。
部署設定參考
以下為實際部署時使用的完整設定,供日後查詢與複製使用。
環境參數
| 項目 | 獨立部署 | Sidecar 部署 |
|---|---|---|
| 接收埠(UDP/TCP) | 9125 | 9125 |
| Prometheus 抓取埠 | 9102 | 9102 |
| NodePort(接收) | 31728 | — |
| Namespace | monitoring | 與主服務相同 |
獨立部署(Helm Chart)
statsd-values.yaml
yaml
extraArgs:
- --web.enable-lifecycle
statsd:
udpPort: 9125
tcpPort: 9125
mappingConfig: |-
mappings:
- match: "*.gunicorn.request.status.*"
help: "gunicorn response code"
name: "gunicorn_response_code"
labels:
app: "$1"
status: "$2"
- match: "*.gunicorn.workers"
name: "gunicorn_workers"
labels:
app: "$1"
- match: "*.gunicorn.requests"
name: "gunicorn_requests"
labels:
app: "$1"
- match: "*.gunicorn.request.duration"
name: "gunicorn_request_duration"
labels:
app: "$1"
- match: "*.gunicorn.request.duration_count"
name: "gunicorn_request_duration_count"
labels:
app: "$1"
- match: "*.gunicorn.request.duration_sum"
name: "gunicorn_request_duration_sum"
labels:
app: "$1"
service:
type: NodePort
port: 9102安裝指令
bash
helm install statsd-exporter \
-f statsd-values.yaml \
--namespace monitoring \
--insecure-skip-tls-verify \
prometheus-community/prometheus-statsd-exporter自訂 NodePort Service(固定埠號)
yaml
apiVersion: v1
kind: Service
metadata:
name: statsd-nodeport-service
namespace: monitoring
spec:
type: NodePort
ports:
- name: statsd-tcp
nodePort: 31728
port: 9125
protocol: TCP
targetPort: statsd-tcp
- name: statsd-udp
nodePort: 31728
port: 9125
protocol: UDP
targetPort: statsd-udp
selector:
app.kubernetes.io/instance: statsd-exporter
app.kubernetes.io/name: prometheus-statsd-exporterSidecar 部署
建立 Mapping ConfigMap
statsd_mapping.yml:
yaml
mappings:
- match: "*.gunicorn.request.status.*"
help: "gunicorn response code"
name: "gunicorn_response_code"
labels:
app: "$1"
status: "$2"
- match: "*.gunicorn.workers"
name: "gunicorn_workers"
labels:
app: "$1"
- match: "*.gunicorn.requests"
name: "gunicorn_requests"
labels:
app: "$1"
- match: "*.gunicorn.request.duration"
name: "gunicorn_request_duration"
labels:
app: "$1"
- match: "*.gunicorn.request.duration_count"
name: "gunicorn_request_duration_count"
labels:
app: "$1"
- match: "*.gunicorn.request.duration_sum"
name: "gunicorn_request_duration_sum"
labels:
app: "$1"bash
kubectl create configmap buyer-helper-server-dev-statsd-mapping \
--from-file=buyer_server/statsd_mapping.yml \
-n default \
-o yaml --dry-run=client | kubectl apply -f -Deployment 中加入 Sidecar Container
yaml
containers:
# ... 主服務容器 ...
- name: statsd-exporter
image: prom/statsd-exporter
ports:
- containerPort: 9102
args:
- "--statsd.mapping-config=/tmp/statsd_mapping.yml"
volumeMounts:
- name: statsd-mapping-config-volume
mountPath: /tmp
volumes:
- name: statsd-mapping-config-volume
configMap:
name: buyer-helper-server-dev-statsd-mappingService 設定(加入 Exporter 埠)
yaml
ports:
- name: http
port: 9194
nodePort: 30002
targetPort: 9194
- name: exporter
port: 9102
targetPort: 9102Gunicorn 連線設定(Python)
python
statsd_host = "127.0.0.1:9125"相關概念
- Prometheus Exporter 部署模式 — Exporter 的通用 K8s 部署模式
- Prometheus on Kubernetes 部署 — 收集 StatsD Exporter 指標的 Prometheus 伺服器設定(含 statsd-exporter scrape job)
- Gunicorn 原生 ASGI Worker — Gunicorn 25.1.0 原生 ASGI Worker 的功能說明與部署指南