apiVersion: v1 kind: ConfigMap metadata: name: traefik-grafana-dashboard namespace: kube-mon labels: grafana_dashboard: "1" release: "kube-prometheus-stack-1761819498" data: traefik-overview.json: |- { "annotations": { "list": [ { "builtIn": 1, "datasource": "-- Grafana --", "enable": true, "hide": true, "iconColor": "rgba(0, 211, 255, 1)", "name": "Annotations & Alerts", "target": { "limit": 100, "matchAny": false, "tags": [], "type": "dashboard" }, "type": "dashboard" } ] }, "editable": true, "fiscalYearStartMonth": 0, "graphTooltip": 0, "id": null, "links": [], "panels": [ { "collapsed": false, "gridPos": { "h": 1, "w": 24, "x": 0, "y": 0 }, "id": 30, "panels": [], "title": "Overview", "type": "row" }, { "datasource": "$prometheus_ds", "fieldConfig": { "defaults": { "mappings": [], "thresholds": { "mode": "absolute", "steps": [ { "color": "green", "value": null }, { "color": "orange", "value": 5 }, { "color": "red", "value": 20 } ] }, "unit": "reqps" }, "overrides": [] }, "gridPos": { "h": 4, "w": 6, "x": 0, "y": 1 }, "id": 1, "options": { "colorMode": "background", "graphMode": "area", "justifyMode": "auto", "orientation": "auto", "reduceOptions": { "calcs": [ "lastNotNull" ], "fields": "", "values": false }, "textMode": "auto" }, "targets": [ { "expr": "sum(rate(traefik_entrypoint_requests_total{entrypoint=~\"$entrypoint\"}[5m]))", "legendFormat": "", "refId": "A" } ], "title": "Requests/s", "type": "stat" }, { "datasource": "$prometheus_ds", "fieldConfig": { "defaults": { "mappings": [], "thresholds": { "mode": "absolute", "steps": [ { "color": "green", "value": null }, { "color": "orange", "value": 1 }, { "color": "red", "value": 5 } ] }, "unit": "reqps" }, "overrides": [] }, "gridPos": { "h": 4, "w": 6, "x": 6, "y": 1 }, "id": 2, "options": { "colorMode": "background", "graphMode": "area", "justifyMode": "auto", "orientation": "auto", "reduceOptions": { "calcs": [ "lastNotNull" ], "fields": "", "values": false }, "textMode": "auto" }, "targets": [ { "expr": "sum(rate(traefik_entrypoint_requests_total{entrypoint=~\"$entrypoint\",code=~\"4..\"}[5m]))", "legendFormat": "", "refId": "A" } ], "title": "4xx/s", "type": "stat" }, { "datasource": "$prometheus_ds", "fieldConfig": { "defaults": { "mappings": [], "thresholds": { "mode": "absolute", "steps": [ { "color": "green", "value": null }, { "color": "orange", "value": 0.5 }, { "color": "red", "value": 2 } ] }, "unit": "reqps" }, "overrides": [] }, "gridPos": { "h": 4, "w": 6, "x": 12, "y": 1 }, "id": 3, "options": { "colorMode": "background", "graphMode": "area", "justifyMode": "auto", "orientation": "auto", "reduceOptions": { "calcs": [ "lastNotNull" ], "fields": "", "values": false }, "textMode": "auto" }, "targets": [ { "expr": "sum(rate(traefik_entrypoint_requests_total{entrypoint=~\"$entrypoint\",code=~\"5..\"}[5m]))", "legendFormat": "", "refId": "A" } ], "title": "5xx/s", "type": "stat" }, { "datasource": "$prometheus_ds", "fieldConfig": { "defaults": { "mappings": [], "thresholds": { "mode": "absolute", "steps": [ { "color": "green", "value": null }, { "color": "orange", "value": 250 }, { "color": "red", "value": 1000 } ] }, "unit": "ms" }, "overrides": [] }, "gridPos": { "h": 4, "w": 6, "x": 18, "y": 1 }, "id": 4, "options": { "colorMode": "background", "graphMode": "area", "justifyMode": "auto", "orientation": "auto", "reduceOptions": { "calcs": [ "lastNotNull" ], "fields": "", "values": false }, "textMode": "auto" }, "targets": [ { "expr": "1000 * histogram_quantile(0.95, sum by (le) (rate(traefik_entrypoint_request_duration_seconds_bucket{entrypoint=~\"$entrypoint\"}[$__rate_interval])))", "legendFormat": "", "refId": "A" } ], "title": "P95 Latency", "type": "stat" }, { "collapsed": false, "gridPos": { "h": 1, "w": 24, "x": 0, "y": 5 }, "id": 31, "panels": [], "title": "Traffic, Latency & Routing", "type": "row" }, { "datasource": "$prometheus_ds", "fieldConfig": { "defaults": { "unit": "reqps" }, "overrides": [] }, "gridPos": { "h": 8, "w": 12, "x": 0, "y": 6 }, "id": 5, "options": { "legend": { "displayMode": "list", "placement": "bottom", "showLegend": true }, "tooltip": { "mode": "multi", "sort": "desc" } }, "targets": [ { "expr": "sum by (entrypoint) (rate(traefik_entrypoint_requests_total{entrypoint=~\"$entrypoint\"}[$__rate_interval]))", "legendFormat": "{{entrypoint}}", "refId": "A" } ], "title": "Requests by Entrypoint", "type": "timeseries" }, { "datasource": "$prometheus_ds", "fieldConfig": { "defaults": { "unit": "reqps" }, "overrides": [] }, "gridPos": { "h": 8, "w": 12, "x": 12, "y": 6 }, "id": 6, "options": { "legend": { "displayMode": "list", "placement": "bottom", "showLegend": true }, "tooltip": { "mode": "multi", "sort": "desc" } }, "targets": [ { "expr": "sum by (code) (rate(traefik_entrypoint_requests_total{entrypoint=~\"$entrypoint\",code=~\"[2345]..\"}[$__rate_interval]))", "legendFormat": "{{code}}", "refId": "A" } ], "title": "Status Codes", "type": "timeseries" }, { "datasource": "$prometheus_ds", "fieldConfig": { "defaults": { "unit": "ms" }, "overrides": [] }, "gridPos": { "h": 8, "w": 12, "x": 0, "y": 14 }, "id": 7, "options": { "legend": { "displayMode": "list", "placement": "bottom", "showLegend": true }, "tooltip": { "mode": "multi", "sort": "desc" } }, "targets": [ { "expr": "1000 * histogram_quantile(0.50, sum by (le) (rate(traefik_entrypoint_request_duration_seconds_bucket{entrypoint=~\"$entrypoint\"}[$__rate_interval])))", "legendFormat": "p50", "refId": "A" }, { "expr": "1000 * histogram_quantile(0.95, sum by (le) (rate(traefik_entrypoint_request_duration_seconds_bucket{entrypoint=~\"$entrypoint\"}[$__rate_interval])))", "legendFormat": "p95", "refId": "B" }, { "expr": "1000 * histogram_quantile(0.99, sum by (le) (rate(traefik_entrypoint_request_duration_seconds_bucket{entrypoint=~\"$entrypoint\"}[$__rate_interval])))", "legendFormat": "p99", "refId": "C" } ], "title": "Latency Percentiles", "type": "timeseries" }, { "datasource": "$prometheus_ds", "fieldConfig": { "defaults": { "unit": "reqps" }, "overrides": [] }, "gridPos": { "h": 8, "w": 12, "x": 12, "y": 14 }, "id": 8, "options": { "displayMode": "gradient", "legend": { "displayMode": "hidden", "showLegend": false }, "orientation": "horizontal", "reduceOptions": { "calcs": [ "lastNotNull" ], "fields": "", "values": false }, "showUnfilled": true }, "targets": [ { "expr": "topk(10, sum by (router) (rate(traefik_router_requests_total{router=~\"$router\"}[$__rate_interval])))", "legendFormat": "{{router}}", "refId": "A" } ], "title": "Top Routers by RPS", "type": "bargauge" }, { "datasource": "$prometheus_ds", "fieldConfig": { "defaults": { "unit": "short" }, "overrides": [] }, "gridPos": { "h": 8, "w": 8, "x": 0, "y": 22 }, "id": 9, "options": { "legend": { "displayMode": "list", "placement": "bottom", "showLegend": true }, "tooltip": { "mode": "multi", "sort": "desc" } }, "targets": [ { "expr": "sum by (entrypoint) (traefik_open_connections{entrypoint=~\"$entrypoint\"})", "legendFormat": "{{entrypoint}}", "refId": "A" } ], "title": "Open Connections", "type": "timeseries" }, { "datasource": "$prometheus_ds", "fieldConfig": { "defaults": { "mappings": [], "thresholds": { "mode": "absolute", "steps": [ { "color": "green", "value": null }, { "color": "orange", "value": 1 }, { "color": "red", "value": 5 } ] }, "unit": "short" }, "overrides": [] }, "gridPos": { "h": 8, "w": 4, "x": 8, "y": 22 }, "id": 10, "options": { "colorMode": "background", "graphMode": "none", "justifyMode": "auto", "orientation": "auto", "reduceOptions": { "calcs": [ "lastNotNull" ], "fields": "", "values": false }, "textMode": "auto" }, "targets": [ { "expr": "count(traefik_tls_certs_not_after < (time() + 14 * 24 * 3600))", "legendFormat": "", "refId": "A" } ], "title": "Certs expiring in 14d", "type": "stat" }, { "datasource": "$prometheus_ds", "fieldConfig": { "defaults": { "unit": "reqps" }, "overrides": [] }, "gridPos": { "h": 8, "w": 12, "x": 12, "y": 22 }, "id": 11, "options": { "displayMode": "gradient", "legend": { "displayMode": "hidden", "showLegend": false }, "orientation": "horizontal", "reduceOptions": { "calcs": [ "lastNotNull" ], "fields": "", "values": false }, "showUnfilled": true }, "targets": [ { "expr": "topk(10, sum by (router) (rate(traefik_router_requests_total{router=~\"$router\",code=~\"5..\"}[$__rate_interval])))", "legendFormat": "{{router}}", "refId": "A" } ], "title": "Top Routers by 5xx/s", "type": "bargauge" }, { "collapsed": false, "gridPos": { "h": 1, "w": 24, "x": 0, "y": 30 }, "id": 34, "panels": [], "title": "Prometheus Deep Dive", "type": "row" }, { "datasource": "$prometheus_ds", "fieldConfig": { "defaults": { "mappings": [], "thresholds": { "mode": "absolute", "steps": [ { "color": "green", "value": null }, { "color": "orange", "value": 50 }, { "color": "red", "value": 90 } ] }, "unit": "percent" }, "overrides": [] }, "gridPos": { "h": 4, "w": 4, "x": 0, "y": 31 }, "id": 35, "options": { "colorMode": "background", "graphMode": "area", "justifyMode": "auto", "orientation": "auto", "reduceOptions": { "calcs": [ "lastNotNull" ], "fields": "", "values": false }, "textMode": "auto" }, "targets": [ { "expr": "100 * sum(rate(traefik_entrypoint_requests_tls_total{entrypoint=~\"$entrypoint\"}[5m])) / clamp_min(sum(rate(traefik_entrypoint_requests_total{entrypoint=~\"$entrypoint\"}[5m])), 0.001)", "legendFormat": "", "refId": "A" } ], "title": "TLS Share", "type": "stat", "description": "Share of Traefik requests arriving over TLS for the selected entrypoints." }, { "datasource": "$prometheus_ds", "fieldConfig": { "defaults": { "mappings": [], "thresholds": { "mode": "absolute", "steps": [ { "color": "green", "value": null }, { "color": "orange", "value": 1 }, { "color": "red", "value": 10 } ] }, "unit": "reqps" }, "overrides": [] }, "gridPos": { "h": 4, "w": 4, "x": 4, "y": 31 }, "id": 36, "options": { "colorMode": "background", "graphMode": "area", "justifyMode": "auto", "orientation": "auto", "reduceOptions": { "calcs": [ "lastNotNull" ], "fields": "", "values": false }, "textMode": "auto" }, "targets": [ { "expr": "sum(rate(traefik_entrypoint_requests_tls_total{entrypoint=~\"$entrypoint\"}[5m]))", "legendFormat": "", "refId": "A" } ], "title": "TLS Requests/s", "type": "stat", "description": "TLS request rate across the selected entrypoints." }, { "datasource": "$prometheus_ds", "fieldConfig": { "defaults": { "mappings": [], "thresholds": { "mode": "absolute", "steps": [ { "color": "green", "value": null }, { "color": "orange", "value": 1048576 }, { "color": "red", "value": 10485760 } ] }, "unit": "binBps" }, "overrides": [] }, "gridPos": { "h": 4, "w": 4, "x": 8, "y": 31 }, "id": 37, "options": { "colorMode": "background", "graphMode": "area", "justifyMode": "auto", "orientation": "auto", "reduceOptions": { "calcs": [ "lastNotNull" ], "fields": "", "values": false }, "textMode": "auto" }, "targets": [ { "expr": "sum(rate(traefik_entrypoint_requests_bytes_total{entrypoint=~\"$entrypoint\"}[5m]))", "legendFormat": "", "refId": "A" } ], "title": "Ingress Traffic", "type": "stat", "description": "Request bandwidth entering Traefik." }, { "datasource": "$prometheus_ds", "fieldConfig": { "defaults": { "mappings": [], "thresholds": { "mode": "absolute", "steps": [ { "color": "green", "value": null }, { "color": "orange", "value": 1048576 }, { "color": "red", "value": 10485760 } ] }, "unit": "binBps" }, "overrides": [] }, "gridPos": { "h": 4, "w": 4, "x": 12, "y": 31 }, "id": 38, "options": { "colorMode": "background", "graphMode": "area", "justifyMode": "auto", "orientation": "auto", "reduceOptions": { "calcs": [ "lastNotNull" ], "fields": "", "values": false }, "textMode": "auto" }, "targets": [ { "expr": "sum(rate(traefik_entrypoint_responses_bytes_total{entrypoint=~\"$entrypoint\"}[5m]))", "legendFormat": "", "refId": "A" } ], "title": "Egress Traffic", "type": "stat", "description": "Response bandwidth leaving Traefik." }, { "datasource": "$prometheus_ds", "fieldConfig": { "defaults": { "mappings": [], "thresholds": { "mode": "absolute", "steps": [ { "color": "green", "value": null }, { "color": "orange", "value": 1 }, { "color": "red", "value": 10 } ] }, "unit": "short" }, "overrides": [] }, "gridPos": { "h": 4, "w": 4, "x": 16, "y": 31 }, "id": 39, "options": { "colorMode": "background", "graphMode": "area", "justifyMode": "auto", "orientation": "auto", "reduceOptions": { "calcs": [ "lastNotNull" ], "fields": "", "values": false }, "textMode": "auto" }, "targets": [ { "expr": "sum(increase(traefik_config_reloads_total[24h]))", "legendFormat": "", "refId": "A" } ], "title": "Config Reloads 24h", "type": "stat", "description": "How often Traefik reloaded its dynamic configuration in the last 24 hours." }, { "datasource": "$prometheus_ds", "fieldConfig": { "defaults": { "mappings": [], "thresholds": { "mode": "absolute", "steps": [ { "color": "green", "value": null }, { "color": "orange", "value": 24 }, { "color": "red", "value": 168 } ] }, "unit": "short" }, "overrides": [] }, "gridPos": { "h": 4, "w": 4, "x": 20, "y": 31 }, "id": 40, "options": { "colorMode": "background", "graphMode": "area", "justifyMode": "auto", "orientation": "auto", "reduceOptions": { "calcs": [ "lastNotNull" ], "fields": "", "values": false }, "textMode": "auto" }, "targets": [ { "expr": "(time() - max(traefik_config_last_reload_success)) / 3600", "legendFormat": "", "refId": "A" } ], "title": "Last Successful Reload Age (h)", "type": "stat", "description": "Hours since the last successful configuration reload reported by Traefik." }, { "datasource": "$prometheus_ds", "fieldConfig": { "defaults": { "unit": "reqps" }, "overrides": [] }, "gridPos": { "h": 8, "w": 8, "x": 0, "y": 35 }, "id": 41, "options": { "displayMode": "gradient", "legend": { "displayMode": "hidden", "showLegend": false }, "orientation": "horizontal", "reduceOptions": { "calcs": [ "lastNotNull" ], "fields": "", "values": false }, "showUnfilled": true }, "targets": [ { "expr": "topk(12, sum by (exported_service) (rate(traefik_service_requests_total{exported_service=~\"$backend_regex\"}[$__rate_interval])))", "legendFormat": "{{exported_service}}", "refId": "A" } ], "title": "Top Backends by RPS", "type": "bargauge", "description": "Backend services with the highest request rate according to Traefik service metrics." }, { "datasource": "$prometheus_ds", "fieldConfig": { "defaults": { "unit": "binBps" }, "overrides": [] }, "gridPos": { "h": 8, "w": 8, "x": 8, "y": 35 }, "id": 42, "options": { "displayMode": "gradient", "legend": { "displayMode": "hidden", "showLegend": false }, "orientation": "horizontal", "reduceOptions": { "calcs": [ "lastNotNull" ], "fields": "", "values": false }, "showUnfilled": true }, "targets": [ { "expr": "topk(12, sum by (exported_service) (rate(traefik_service_responses_bytes_total{exported_service=~\"$backend_regex\"}[$__rate_interval])))", "legendFormat": "{{exported_service}}", "refId": "A" } ], "title": "Top Backends by Response Throughput", "type": "bargauge", "description": "Backend services returning the most response traffic." }, { "datasource": "$prometheus_ds", "fieldConfig": { "defaults": { "unit": "ms" }, "overrides": [] }, "gridPos": { "h": 8, "w": 8, "x": 16, "y": 35 }, "id": 43, "options": { "displayMode": "gradient", "legend": { "displayMode": "hidden", "showLegend": false }, "orientation": "horizontal", "reduceOptions": { "calcs": [ "lastNotNull" ], "fields": "", "values": false }, "showUnfilled": true }, "targets": [ { "expr": "topk(12, 1000 * histogram_quantile(0.95, sum by (exported_service, le) (rate(traefik_service_request_duration_seconds_bucket{exported_service=~\"$backend_regex\"}[$__rate_interval]))))", "legendFormat": "{{exported_service}}", "refId": "A" } ], "title": "Slowest Backends by P95", "type": "bargauge", "description": "Backends with the highest p95 request latency from Traefik's point of view." }, { "datasource": "$prometheus_ds", "fieldConfig": { "defaults": { "unit": "ms" }, "overrides": [] }, "gridPos": { "h": 8, "w": 8, "x": 0, "y": 43 }, "id": 44, "options": { "displayMode": "gradient", "legend": { "displayMode": "hidden", "showLegend": false }, "orientation": "horizontal", "reduceOptions": { "calcs": [ "lastNotNull" ], "fields": "", "values": false }, "showUnfilled": true }, "targets": [ { "expr": "topk(12, 1000 * histogram_quantile(0.95, sum by (router, le) (rate(traefik_router_request_duration_seconds_bucket{router=~\"$router\"}[$__rate_interval]))))", "legendFormat": "{{router}}", "refId": "A" } ], "title": "Slowest Routers by P95", "type": "bargauge", "description": "Routers with the highest p95 latency." }, { "datasource": "$prometheus_ds", "fieldConfig": { "defaults": { "unit": "reqps" }, "overrides": [] }, "gridPos": { "h": 8, "w": 8, "x": 8, "y": 43 }, "id": 45, "options": { "displayMode": "gradient", "legend": { "displayMode": "hidden", "showLegend": false }, "orientation": "horizontal", "reduceOptions": { "calcs": [ "lastNotNull" ], "fields": "", "values": false }, "showUnfilled": true }, "targets": [ { "expr": "sum by (tls_version) (rate(traefik_service_requests_tls_total{exported_service=~\"$backend_regex\"}[$__rate_interval]))", "legendFormat": "TLS {{tls_version}}", "refId": "A" } ], "title": "TLS Requests by Version", "type": "bargauge", "description": "Current TLS request split by negotiated TLS version." }, { "datasource": "$prometheus_ds", "fieldConfig": { "defaults": { "unit": "short" }, "overrides": [] }, "gridPos": { "h": 8, "w": 8, "x": 16, "y": 43 }, "id": 46, "options": { "displayMode": "gradient", "legend": { "displayMode": "hidden", "showLegend": false }, "orientation": "horizontal", "reduceOptions": { "calcs": [ "lastNotNull" ], "fields": "", "values": false }, "showUnfilled": true }, "targets": [ { "expr": "bottomk(12, (max by (cn) (traefik_tls_certs_not_after) - time()) / 86400)", "legendFormat": "{{cn}}", "refId": "A" } ], "title": "Soonest Certificate Expiry (days)", "type": "bargauge", "description": "Certificates with the fewest days remaining before expiry, deduplicated by CN." }, { "collapsed": false, "gridPos": { "h": 1, "w": 24, "x": 0, "y": 51 }, "id": 32, "panels": [], "title": "Fail2Ban & Ban History", "type": "row" }, { "datasource": "$loki_ds", "fieldConfig": { "defaults": { "mappings": [], "thresholds": { "mode": "absolute", "steps": [ { "color": "green", "value": null }, { "color": "orange", "value": 1 }, { "color": "red", "value": 5 } ] }, "unit": "short" }, "overrides": [] }, "gridPos": { "h": 4, "w": 6, "x": 0, "y": 52 }, "id": 14, "options": { "colorMode": "background", "graphMode": "area", "justifyMode": "auto", "orientation": "auto", "reduceOptions": { "calcs": [ "lastNotNull" ], "fields": "", "values": false }, "textMode": "auto" }, "targets": [ { "editorMode": "code", "expr": "sum(count_over_time({namespace=\"traefik\", pod=~\"$pod_regex\", container=\"traefik\"} | json | __error__=\"\" | prefix=\"Fail-2-Ban\" | msg =~ \"(Extend Ban for .*|Ban for .*)\" [$__range]))", "instant": true, "queryType": "instant", "refId": "A" } ], "title": "Ban / Extend Events", "type": "stat", "description": "Log-based count of Fail2Ban ban or ban-extension events in the selected time range." }, { "datasource": "$loki_ds", "fieldConfig": { "defaults": { "mappings": [], "thresholds": { "mode": "absolute", "steps": [ { "color": "green", "value": null }, { "color": "orange", "value": 1 }, { "color": "red", "value": 5 } ] }, "unit": "short" }, "overrides": [] }, "gridPos": { "h": 4, "w": 6, "x": 6, "y": 52 }, "id": 15, "options": { "colorMode": "background", "graphMode": "area", "justifyMode": "auto", "orientation": "auto", "reduceOptions": { "calcs": [ "lastNotNull" ], "fields": "", "values": false }, "textMode": "auto" }, "targets": [ { "editorMode": "code", "expr": "count(sum by (ip) (count_over_time({namespace=\"traefik\", pod=~\"$pod_regex\", container=\"traefik\"} | json | __error__=\"\" | prefix=\"Fail-2-Ban\" | msg =~ \"(Extend Ban for .*|Ban for .*)\" | regexp \"(?:Extend Ban|Ban) for (?P[0-9A-Fa-f:.]+)\" | ip =~ \"$ip_regex\" [$__range])))", "instant": true, "queryType": "instant", "refId": "A" } ], "title": "IPs Seen in Ban Events", "type": "stat", "description": "Unique IPs with at least one Fail2Ban ban event in the selected time range. This is log-derived, not a kernel live-ban list." }, { "datasource": "$loki_ds", "fieldConfig": { "defaults": { "unit": "short" }, "overrides": [] }, "gridPos": { "h": 4, "w": 12, "x": 12, "y": 52 }, "id": 16, "options": { "displayMode": "gradient", "legend": { "displayMode": "hidden", "showLegend": false }, "orientation": "horizontal", "reduceOptions": { "calcs": [ "lastNotNull" ], "fields": "", "values": false }, "showUnfilled": true }, "targets": [ { "editorMode": "code", "expr": "topk(25, sum by (ip) (count_over_time({namespace=\"traefik\", pod=~\"$pod_regex\", container=\"traefik\"} | json | __error__=\"\" | prefix=\"Fail-2-Ban\" | msg =~ \"(Extend Ban for .*|Ban for .*)\" | regexp \"(?:Extend Ban|Ban) for (?P[0-9A-Fa-f:.]+)\" | ip =~ \"$ip_regex\" [$__range])))", "instant": true, "legendFormat": "{{ip}}", "queryType": "instant", "refId": "A" } ], "title": "Blocked IPs by Ban Events", "type": "bargauge", "description": "Top IPs ranked by Fail2Ban ban events seen in logs during the selected time range." }, { "datasource": "$loki_ds", "fieldConfig": { "defaults": { "unit": "short" }, "overrides": [] }, "gridPos": { "h": 8, "w": 12, "x": 0, "y": 56 }, "id": 17, "options": { "legend": { "displayMode": "list", "placement": "bottom", "showLegend": true }, "tooltip": { "mode": "multi", "sort": "desc" } }, "targets": [ { "editorMode": "code", "expr": "sum(count_over_time({namespace=\"traefik\", pod=~\"$pod_regex\", container=\"traefik\"} | json | __error__=\"\" | prefix=\"Fail-2-Ban\" | msg =~ \"(Extend Ban for .*|Ban for .*)\" [$__interval]))", "legendFormat": "block events", "queryType": "range", "refId": "A" } ], "title": "Ban Events Over Time", "type": "timeseries", "description": "Time series of Fail2Ban ban events. Useful for spotting brute-force or scan spikes." }, { "datasource": "$loki_ds", "gridPos": { "h": 8, "w": 12, "x": 12, "y": 56 }, "id": 18, "options": { "dedupStrategy": "none", "enableLogDetails": true, "prettifyLogMessage": false, "showCommonLabels": false, "showLabels": true, "showTime": true, "sortOrder": "Descending", "wrapLogMessage": true }, "targets": [ { "direction": "backward", "editorMode": "code", "expr": "{namespace=\"traefik\", pod=~\"$pod_regex\", container=\"traefik\"} | json | __error__=\"\" | prefix=\"Fail-2-Ban\" | msg =~ \"(Extend Ban for .*|Ban for .*|Un-Banned .*|Clearing out state for .*|Failed to get Client Identifier.*)\" | msg =~ \".*$ip_regex.*\"", "queryType": "range", "refId": "A" } ], "title": "Fail2Ban Event Logs", "type": "logs", "description": "Raw Fail2Ban event lines, filterable via the shared IP regex variable." }, { "collapsed": false, "gridPos": { "h": 1, "w": 24, "x": 0, "y": 64 }, "id": 19, "panels": [], "title": "Client IP & Host Analysis", "type": "row" }, { "datasource": "$loki_ds", "fieldConfig": { "defaults": { "mappings": [], "thresholds": { "mode": "absolute", "steps": [ { "color": "green", "value": null }, { "color": "orange", "value": 100 }, { "color": "red", "value": 250 } ] }, "unit": "short" }, "overrides": [] }, "gridPos": { "h": 4, "w": 8, "x": 0, "y": 65 }, "id": 20, "options": { "colorMode": "background", "graphMode": "area", "justifyMode": "auto", "orientation": "auto", "reduceOptions": { "calcs": [ "lastNotNull" ], "fields": "", "values": false }, "textMode": "auto" }, "targets": [ { "editorMode": "code", "expr": "count(sum by (ClientHost) (count_over_time({namespace=\"traefik\", pod=~\"$pod_regex\", container=\"traefik\"} | json | __error__=\"\" | RequestHost =~ \"$request_host\" | ClientHost =~ \"$ip_regex\" [$__range])))", "instant": true, "queryType": "instant", "refId": "A" } ], "title": "Unique Client IPs", "type": "stat", "description": "Distinct client source IPs seen in Traefik access logs for the selected host/IP filters." }, { "datasource": "$loki_ds", "fieldConfig": { "defaults": { "mappings": [], "thresholds": { "mode": "absolute", "steps": [ { "color": "green", "value": null }, { "color": "orange", "value": 25 }, { "color": "red", "value": 100 } ] }, "unit": "short" }, "overrides": [] }, "gridPos": { "h": 4, "w": 8, "x": 8, "y": 65 }, "id": 21, "options": { "colorMode": "background", "graphMode": "area", "justifyMode": "auto", "orientation": "auto", "reduceOptions": { "calcs": [ "lastNotNull" ], "fields": "", "values": false }, "textMode": "auto" }, "targets": [ { "editorMode": "code", "expr": "count(sum by (ClientHost) (count_over_time({namespace=\"traefik\", pod=~\"$pod_regex\", container=\"traefik\"} | json | __error__=\"\" | RequestHost =~ \"$request_host\" | ClientHost =~ \"$ip_regex\" | DownstreamStatus >= 400 | DownstreamStatus < 500 [$__range])))", "instant": true, "queryType": "instant", "refId": "A" } ], "title": "Unique 4xx Client IPs", "type": "stat", "description": "Distinct source IPs that triggered 4xx responses in the selected time range." }, { "datasource": "$loki_ds", "fieldConfig": { "defaults": { "mappings": [], "thresholds": { "mode": "absolute", "steps": [ { "color": "green", "value": null }, { "color": "orange", "value": 5 }, { "color": "red", "value": 20 } ] }, "unit": "short" }, "overrides": [] }, "gridPos": { "h": 4, "w": 8, "x": 16, "y": 65 }, "id": 22, "options": { "colorMode": "background", "graphMode": "area", "justifyMode": "auto", "orientation": "auto", "reduceOptions": { "calcs": [ "lastNotNull" ], "fields": "", "values": false }, "textMode": "auto" }, "targets": [ { "editorMode": "code", "expr": "count(sum by (ClientHost) (count_over_time({namespace=\"traefik\", pod=~\"$pod_regex\", container=\"traefik\"} | json | __error__=\"\" | RequestHost =~ \"$request_host\" | ClientHost =~ \"$ip_regex\" | DownstreamStatus >= 500 [$__range])))", "instant": true, "queryType": "instant", "refId": "A" } ], "title": "Unique 5xx Client IPs", "type": "stat", "description": "Distinct source IPs that hit upstream/server-side failures in the selected time range." }, { "datasource": "$loki_ds", "fieldConfig": { "defaults": { "unit": "short" }, "overrides": [] }, "gridPos": { "h": 8, "w": 8, "x": 0, "y": 69 }, "id": 23, "options": { "displayMode": "gradient", "legend": { "displayMode": "hidden", "showLegend": false }, "orientation": "horizontal", "reduceOptions": { "calcs": [ "lastNotNull" ], "fields": "", "values": false }, "showUnfilled": true }, "targets": [ { "editorMode": "code", "expr": "topk(15, sum by (ClientHost) (count_over_time({namespace=\"traefik\", pod=~\"$pod_regex\", container=\"traefik\"} | json | __error__=\"\" | RequestHost =~ \"$request_host\" | ClientHost =~ \"$ip_regex\" [$__range])))", "instant": true, "legendFormat": "{{ClientHost}}", "queryType": "instant", "refId": "A" } ], "title": "Top Client IPs by Requests", "type": "bargauge", "description": "Request-heavy client IPs from Traefik access logs for the selected range." }, { "datasource": "$loki_ds", "fieldConfig": { "defaults": { "unit": "short" }, "overrides": [] }, "gridPos": { "h": 8, "w": 8, "x": 8, "y": 69 }, "id": 24, "options": { "displayMode": "gradient", "legend": { "displayMode": "hidden", "showLegend": false }, "orientation": "horizontal", "reduceOptions": { "calcs": [ "lastNotNull" ], "fields": "", "values": false }, "showUnfilled": true }, "targets": [ { "editorMode": "code", "expr": "topk(15, sum by (ClientHost) (count_over_time({namespace=\"traefik\", pod=~\"$pod_regex\", container=\"traefik\"} | json | __error__=\"\" | RequestHost =~ \"$request_host\" | ClientHost =~ \"$ip_regex\" | DownstreamStatus >= 400 | DownstreamStatus < 500 [$__range])))", "instant": true, "legendFormat": "{{ClientHost}}", "queryType": "instant", "refId": "A" } ], "title": "Top Client IPs by 4xx", "type": "bargauge", "description": "Client IPs producing the most 4xx responses in the selected range." }, { "datasource": "$loki_ds", "fieldConfig": { "defaults": { "unit": "short" }, "overrides": [] }, "gridPos": { "h": 8, "w": 8, "x": 16, "y": 69 }, "id": 25, "options": { "displayMode": "gradient", "legend": { "displayMode": "hidden", "showLegend": false }, "orientation": "horizontal", "reduceOptions": { "calcs": [ "lastNotNull" ], "fields": "", "values": false }, "showUnfilled": true }, "targets": [ { "editorMode": "code", "expr": "topk(15, sum by (ClientHost) (count_over_time({namespace=\"traefik\", pod=~\"$pod_regex\", container=\"traefik\"} | json | __error__=\"\" | RequestHost =~ \"$request_host\" | ClientHost =~ \"$ip_regex\" | DownstreamStatus >= 500 [$__range])))", "instant": true, "legendFormat": "{{ClientHost}}", "queryType": "instant", "refId": "A" } ], "title": "Top Client IPs by 5xx", "type": "bargauge", "description": "Client IPs associated with the most 5xx responses in the selected range." }, { "datasource": "$loki_ds", "fieldConfig": { "defaults": { "unit": "short" }, "overrides": [] }, "gridPos": { "h": 8, "w": 12, "x": 0, "y": 77 }, "id": 26, "options": { "displayMode": "gradient", "legend": { "displayMode": "hidden", "showLegend": false }, "orientation": "horizontal", "reduceOptions": { "calcs": [ "lastNotNull" ], "fields": "", "values": false }, "showUnfilled": true }, "targets": [ { "editorMode": "code", "expr": "topk(12, sum by (RequestHost) (count_over_time({namespace=\"traefik\", pod=~\"$pod_regex\", container=\"traefik\"} | json | __error__=\"\" | RequestHost =~ \"$request_host\" | ClientHost =~ \"$ip_regex\" | DownstreamStatus >= 400 | DownstreamStatus < 500 [$__range])))", "instant": true, "legendFormat": "{{RequestHost}}", "queryType": "instant", "refId": "A" } ], "title": "Top Request Hosts by 4xx", "type": "bargauge", "description": "Hosts currently attracting the most client-side errors or probes." }, { "datasource": "$loki_ds", "fieldConfig": { "defaults": { "unit": "short" }, "overrides": [] }, "gridPos": { "h": 8, "w": 12, "x": 12, "y": 77 }, "id": 27, "options": { "displayMode": "gradient", "legend": { "displayMode": "hidden", "showLegend": false }, "orientation": "horizontal", "reduceOptions": { "calcs": [ "lastNotNull" ], "fields": "", "values": false }, "showUnfilled": true }, "targets": [ { "editorMode": "code", "expr": "topk(12, sum by (RequestHost) (count_over_time({namespace=\"traefik\", pod=~\"$pod_regex\", container=\"traefik\"} | json | __error__=\"\" | RequestHost =~ \"$request_host\" | ClientHost =~ \"$ip_regex\" | DownstreamStatus >= 500 [$__range])))", "instant": true, "legendFormat": "{{RequestHost}}", "queryType": "instant", "refId": "A" } ], "title": "Top Request Hosts by 5xx", "type": "bargauge", "description": "Hosts whose backends currently generate the most 5xx responses." }, { "datasource": "$loki_ds", "fieldConfig": { "defaults": { "unit": "short" }, "overrides": [] }, "gridPos": { "h": 8, "w": 12, "x": 0, "y": 85 }, "id": 28, "options": { "cellHeight": "sm", "showHeader": true, "footer": { "show": false, "reducer": [ "sum" ], "fields": "" } }, "targets": [ { "editorMode": "code", "expr": "topk(50, sum by (ip) (count_over_time({namespace=\"traefik\", pod=~\"$pod_regex\", container=\"traefik\"} | json | __error__=\"\" | prefix=\"Fail-2-Ban\" | msg =~ \"(Extend Ban for .*|Ban for .*)\" | regexp \"(?:Extend Ban|Ban) for (?P[0-9A-Fa-f:.]+)\" | ip =~ \"$ip_regex\" [$__range])))", "instant": true, "legendFormat": "{{ip}}", "queryType": "instant", "refId": "A" } ], "title": "Blocked IPs in Selected Range", "type": "table", "description": "IP addresses that were blocked by Fail2Ban during the selected time range. This is log-derived history, not a live nftables/iptables inventory." }, { "datasource": "$loki_ds", "gridPos": { "h": 8, "w": 12, "x": 12, "y": 85 }, "id": 29, "options": { "dedupStrategy": "none", "enableLogDetails": true, "prettifyLogMessage": false, "showCommonLabels": false, "showLabels": true, "showTime": true, "sortOrder": "Descending", "wrapLogMessage": true }, "targets": [ { "direction": "backward", "editorMode": "code", "expr": "{namespace=\"traefik\", pod=~\"$pod_regex\", container=\"traefik\"} | json | __error__=\"\" | prefix=\"Fail-2-Ban\" | msg =~ \"(Extend Ban for .*|Ban for .*|Un-Banned .*|Clearing out state for .*|Failed to get Client Identifier.*)\" | msg =~ \".*$ip_regex.*\"", "queryType": "range", "refId": "A" } ], "title": "Recent Fail2Ban Ban / Unban Events", "type": "logs", "description": "Recent Fail2Ban state changes and related events, filtered by the shared IP regex when needed." }, { "collapsed": false, "gridPos": { "h": 1, "w": 24, "x": 0, "y": 93 }, "id": 33, "panels": [], "title": "Raw Traefik Logs", "type": "row" }, { "datasource": "$loki_ds", "gridPos": { "h": 10, "w": 12, "x": 0, "y": 94 }, "id": 12, "options": { "dedupStrategy": "none", "enableLogDetails": true, "prettifyLogMessage": false, "showCommonLabels": false, "showLabels": true, "showTime": true, "sortOrder": "Descending", "wrapLogMessage": true }, "targets": [ { "direction": "backward", "editorMode": "code", "expr": "{namespace=\"traefik\", pod=~\"$pod_regex\", container=\"traefik\"} | json | __error__=\"\" | RequestHost =~ \"$request_host\" | ClientHost =~ \"$ip_regex\"", "queryType": "range", "refId": "A" } ], "title": "Access Logs (Filtered)", "type": "logs" }, { "datasource": "$loki_ds", "gridPos": { "h": 10, "w": 12, "x": 12, "y": 94 }, "id": 13, "options": { "dedupStrategy": "none", "enableLogDetails": true, "prettifyLogMessage": false, "showCommonLabels": false, "showLabels": true, "showTime": true, "sortOrder": "Descending", "wrapLogMessage": true }, "targets": [ { "direction": "backward", "editorMode": "code", "expr": "{namespace=\"traefik\", pod=~\"$pod_regex\", container=\"traefik\"} | json | __error__=\"\" | RequestHost =~ \"$request_host\" | ClientHost =~ \"$ip_regex\" | DownstreamStatus >= 400", "queryType": "range", "refId": "A" } ], "title": "Error Logs (4xx/5xx)", "type": "logs" } ], "refresh": "30s", "schemaVersion": 41, "tags": [ "traefik", "prometheus", "loki", "security", "fail2ban" ], "templating": { "list": [ { "current": { "selected": true, "text": "Prometheus", "value": "Prometheus" }, "hide": 0, "includeAll": false, "label": "Prometheus", "multi": false, "name": "prometheus_ds", "options": [], "query": "prometheus", "refresh": 1, "regex": "", "skipUrlSync": false, "type": "datasource" }, { "current": { "selected": true, "text": "Loki Traefik", "value": "Loki Traefik" }, "hide": 0, "includeAll": false, "label": "Loki", "multi": false, "name": "loki_ds", "options": [], "query": "loki", "refresh": 1, "regex": "", "skipUrlSync": false, "type": "datasource" }, { "allValue": ".*", "current": { "selected": true, "text": "All", "value": "$__all" }, "datasource": "$prometheus_ds", "definition": "label_values(traefik_entrypoint_requests_total, entrypoint)", "hide": 0, "includeAll": true, "label": "Entrypoint", "multi": true, "name": "entrypoint", "options": [], "query": { "query": "label_values(traefik_entrypoint_requests_total, entrypoint)", "refId": "EntrypointVar" }, "refresh": 1, "regex": "", "skipUrlSync": false, "sort": 1, "type": "query" }, { "allValue": ".*", "current": { "selected": true, "text": "All", "value": "$__all" }, "datasource": "$prometheus_ds", "definition": "label_values(traefik_router_requests_total, router)", "hide": 0, "includeAll": true, "label": "Router", "multi": true, "name": "router", "options": [], "query": { "query": "label_values(traefik_router_requests_total, router)", "refId": "RouterVar" }, "refresh": 1, "regex": "", "skipUrlSync": false, "sort": 1, "type": "query" }, { "current": { "selected": true, "text": "traefik-.*", "value": "traefik-.*" }, "hide": 0, "label": "Pod Regex", "name": "pod_regex", "options": [ { "selected": true, "text": "traefik-.*", "value": "traefik-.*" } ], "query": "traefik-.*", "skipUrlSync": false, "type": "textbox" }, { "current": { "selected": true, "text": ".*", "value": ".*" }, "hide": 0, "label": "Host Regex", "name": "request_host", "options": [ { "selected": true, "text": ".*", "value": ".*" } ], "query": ".*", "skipUrlSync": false, "type": "textbox" }, { "current": { "selected": true, "text": ".*", "value": ".*" }, "hide": 0, "label": "IP Regex", "name": "ip_regex", "options": [ { "selected": true, "text": ".*", "value": ".*" } ], "query": ".*", "skipUrlSync": false, "type": "textbox" }, { "current": { "selected": true, "text": ".*", "value": ".*" }, "hide": 0, "label": "Backend Regex", "name": "backend_regex", "options": [ { "selected": true, "text": ".*", "value": ".*" } ], "query": ".*", "skipUrlSync": false, "type": "textbox" } ] }, "time": { "from": "now-6h", "to": "now" }, "timepicker": { "refresh_intervals": [ "10s", "30s", "1m", "5m", "15m", "30m", "1h", "2h", "1d" ] }, "timezone": "browser", "title": "Traefik Overview", "uid": "traefik-overview", "version": 10, "weekStart": "" }