Traefik, Meshkit-collector, PNG-Renderer

This commit is contained in:
Michael Wyraz 2021-11-17 00:49:39 +01:00
parent 5cb0b1444d
commit 4d922104cd
14 changed files with 517 additions and 228 deletions

View File

@ -0,0 +1,4 @@
# Beispiel-Konfiguration. Als .env kopieren und anpassen
# Domainname für das Traefik-Dashboard (und ggf. anderen Infrastruktur-Krempel)
INFRASTRUCTURE_DOMAIN=infra.freifunk-leipzig.de

2
infrastructure/.gitignore vendored Normal file
View File

@ -0,0 +1,2 @@
/.env
/data

6
infrastructure/README.md Normal file
View File

@ -0,0 +1,6 @@
# Infrastruktur-Container
## Traefik
* TLS-Terminierung
* Routen anhand von Annotations

View File

@ -0,0 +1,44 @@
---
version: "3.5"
networks:
services:
name: services
services:
traefik:
image: library/traefik:v2.4.5
hostname: traefik
networks:
- services
restart: unless-stopped
command: |
--log.level=INFO
--api.dashboard=true
--providers.docker=true
--providers.docker.exposedbydefault=false
--entrypoints.http.address=:80
--entrypoints.https.address=:443
--certificatesresolvers.default.acme.httpchallenge=true
--certificatesresolvers.default.acme.httpchallenge.entrypoint=http
--certificatesresolvers.default.acme.email=
--certificatesresolvers.default.acme.storage=/data/acme.json
ports:
- "80:80"
- "443:443"
volumes:
- "/var/run/docker.sock:/var/run/docker.sock:ro"
- "./data/traefik:/data"
labels:
traefik.enable: "true"
traefik.http.routers.dashboard.rule: Host(`${INFRASTRUCTURE_DOMAIN:?INFRASTRUCTURE_DOMAIN is required}`) && (PathPrefix(`/dashboard`) || PathPrefix(`/api`))
traefik.http.routers.dashboard.service: api@internal
traefik.http.routers.dashboard.tls.certresolver: default
# http -> https
traefik.http.routers.http2https.entrypoints: http
traefik.http.routers.http2https.rule: PathPrefix(`/`)
traefik.http.routers.http2https.priority: "900"
traefik.http.routers.http2https.middlewares: http2https
traefik.http.middlewares.http2https.redirectscheme.scheme: https

View File

@ -1,4 +1,7 @@
# Example configuration. Copy to "envfile" and modify to your needs
# Example configuration. Copy to ".env" and modify to your needs
# Domain (required)
MAPSERVER_DOMAIN=map.freifunk-leipzig.de
# Fastd settings
FASTD_MTU=1426

View File

@ -1,2 +1,2 @@
/envfile
/.env
/data

View File

@ -27,6 +27,15 @@ Umgebungsvariablen:
* keine
### meshviewer-collector
Ein kleines Programm (https://github.com/genofire/meshviewer-collector), welches weitere Karten einsammelt und an Yanic weiterleitet. Wird verwendet, um Libremesh-Nodes in die Karte einzubinden.
Umgebungsvariablen:
* keine
* TODO: externe Karten konfigurierbar machen
### meshviewer
Der Meshviewer-Container stellt die Meshviewer-Anwendung aus https://git.dezentrale.cloud/Freifunk-Leipzig/meshviewer/src/branch/ffle sowie die zugehörigen Meshviewer-Daten bereit.
@ -43,3 +52,8 @@ Umgebungsvariablen:
* GF_SECURITY_ADMIN_USER: initialier Admin-Benutzer für Grafana
* GF_SECURITY_ADMIN_PASSWORD: initiales Admin-Passwort (sollte beim ersten Login unbedingt geändert werden!)
### renderer / renderer-proxy
Da Grafana Bilder sehr langsam rendert, wird prometheus-png als Renderer eingesetzt. Die Charts werden direkt aus den Victoriametrics-Daten erzeugt. Vor dem Renderer ist NGinx als Proxy, um die URLs mit den PromQL-Queries korrekt zusammenzubauen.

View File

@ -1,29 +1,25 @@
---
version: '3.4'
version: '3.5'
networks:
services:
external:
name: services
services:
fastd:
build: ./fastd
env_file: envfile
env_file: .env
privileged: true # required to create the tap device
sysctls:
net.ipv6.conf.all.disable_ipv6: 0 # enable ipv6 withn container
net.ipv6.conf.all.forwarding: 1
stop_grace_period: 0s
yanic:
build: ./yanic
network_mode: "service:fastd"
stop_grace_period: 10s
volumes:
- ./data/yanic:/data
meshviewer:
build: ./meshviewer
ports:
- 80:80
volumes:
- ./data/yanic/meshviewer:/usr/share/nginx/html/data
restart: unless-stopped
networks:
- services
victoriametrics:
image: victoriametrics/victoria-metrics:v1.69.0
command: |
@ -31,6 +27,42 @@ services:
-selfScrapeInterval=30s
volumes:
- ./data/victoriametrics:/victoria-metrics-data
networks:
- services
restart: unless-stopped
yanic:
build: ./yanic
network_mode: "service:fastd"
stop_grace_period: 10s
volumes:
- ./data/yanic:/data
depends_on:
- fastd
- victoriametrics
restart: unless-stopped
meshviewer-collector:
build: ./meshviewer-collector
network_mode: "service:fastd"
stop_grace_period: 10s
volumes:
- ./data/meshviewer-collector:/data
depends_on:
- fastd
restart: unless-stopped
meshviewer:
build: ./meshviewer
volumes:
- ./data/yanic/meshviewer:/usr/share/nginx/html/data
labels:
traefik.enable: "true"
traefik.http.routers.meshviewer.rule: Host(`${MAPSERVER_DOMAIN:?MAPSERVER_DOMAIN is required}`)
traefik.http.routers.meshviewer.tls.certresolver: default
networks:
- services
restart: unless-stopped
grafana:
image: grafana/grafana:8.2.3
@ -39,12 +71,12 @@ services:
# https://blog.56k.cloud/provisioning-grafana-datasources-and-dashboards-automagically/
- ./grafana/provisioning/datasources:/etc/grafana/provisioning/datasources
- ./grafana/provisioning/dashboards:/etc/grafana/provisioning/dashboards
env_file: envfile
env_file: .env
environment:
GF_LOG_MODE: console
GF_AUTH_ANONYMOUS_ENABLED: "true"
ports:
- 81:3000
GF_SERVER_ROOT_URL: "%(protocol)s://%(domain)s:%(http_port)s/grafana/"
GF_SERVER_SERVE_FROM_SUB_PATH: "true"
user: root
entrypoint:
- /bin/sh
@ -52,3 +84,34 @@ services:
- |
chown grafana /var/lib/grafana
exec su grafana -s /bin/sh -c /run.sh
labels:
traefik.enable: "true"
traefik.http.routers.grafana.rule: Host(`${MAPSERVER_DOMAIN:?MAPSERVER_DOMAIN is required}`) && PathPrefix(`/grafana`)
traefik.http.routers.grafana.tls.certresolver: default
networks:
- services
restart: unless-stopped
renderer-proxy:
image: nginx:1.21-alpine
volumes:
- ./renderer-proxy:/etc/nginx/conf.d/:ro
labels:
traefik.enable: "true"
traefik.http.routers.renderer.rule: Host(`${MAPSERVER_DOMAIN:?MAPSERVER_DOMAIN is required}`) && PathPrefix(`/render`)
traefik.http.routers.renderer.tls.certresolver: default
networks:
- services
restart: unless-stopped
renderer:
image: lomik/prometheus-png:v0.5.0
network_mode: "service:renderer-proxy"
command:
- -prometheus
- http://victoriametrics:8428
depends_on:
- renderer-proxy
restart: unless-stopped
# 650x350

View File

@ -1,215 +1,302 @@
{
"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"
},
"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"
}
]
},
"editable": true,
"fiscalYearStartMonth": 0,
"gnetId": null,
"graphTooltip": 0,
"id": 1,
"iteration": 1636893346139,
"links": [],
"liveNow": false,
"panels": [
{
"datasource": null,
"fieldConfig": {
"defaults": {
"color": {
"mode": "thresholds"
},
"mappings": [],
"thresholds": {
"mode": "absolute",
"steps": [
{
"color": "green",
"value": null
},
{
"color": "red",
"value": 80
}
]
}
},
"overrides": []
},
"gridPos": {
"h": 3,
"w": 12,
"x": 0,
"y": 0
},
"id": 4,
"interval": null,
"maxDataPoints": 1,
"options": {
"colorMode": "value",
"graphMode": "area",
"justifyMode": "auto",
"orientation": "auto",
"reduceOptions": {
"calcs": [
"lastNotNull"
],
"fields": "",
"values": false
},
"text": {},
"textMode": "name"
},
"pluginVersion": "8.2.3",
"targets": [
{
"exemplar": false,
"expr": "node_clients.total{nodeid=\"$node_id\"}",
"format": "time_series",
"instant": true,
"interval": "",
"legendFormat": "{{hostname}}",
"refId": "A"
}
],
"timeFrom": "1y",
"timeShift": null,
"title": "hostname",
"type": "stat"
},
{
"datasource": null,
"fieldConfig": {
"defaults": {
"color": {
"mode": "palette-classic"
},
"custom": {
"axisLabel": "",
"axisPlacement": "auto",
"barAlignment": 0,
"drawStyle": "line",
"fillOpacity": 0,
"gradientMode": "none",
"hideFrom": {
"legend": false,
"tooltip": false,
"viz": false
},
"lineInterpolation": "linear",
"lineWidth": 1,
"pointSize": 5,
"scaleDistribution": {
"type": "linear"
},
"showPoints": "auto",
"spanNulls": false,
"stacking": {
"group": "A",
"mode": "none"
},
"thresholdsStyle": {
"mode": "off"
}
},
"mappings": [],
"thresholds": {
"mode": "absolute",
"steps": [
{
"color": "green",
"value": null
},
{
"color": "red",
"value": 80
}
]
}
},
"overrides": []
},
"gridPos": {
"h": 9,
"w": 12,
"x": 0,
"y": 3
},
"id": 2,
"options": {
"legend": {
"calcs": [],
"displayMode": "list",
"placement": "bottom"
},
"tooltip": {
"mode": "single"
}
},
"targets": [
{
"exemplar": true,
"expr": "node_clients.total{nodeid=\"$node_id\"}",
"interval": "",
"legendFormat": "",
"refId": "A"
}
],
"title": "Connected clients",
"type": "timeseries"
"type": "dashboard"
}
],
"schemaVersion": 31,
"style": "dark",
"tags": [],
"templating": {
"list": [
{
"allValue": null,
"datasource": null,
"definition": "label_values(nodeid)",
"description": null,
"error": null,
"hide": 0,
"includeAll": false,
"label": null,
"multi": false,
"name": "node_id",
"options": [],
"query": {
"query": "label_values(nodeid)",
"refId": "StandardVariableQuery"
]
},
"editable": true,
"fiscalYearStartMonth": 0,
"gnetId": null,
"graphTooltip": 0,
"iteration": 1637104630864,
"links": [],
"liveNow": false,
"panels": [
{
"datasource": null,
"fieldConfig": {
"defaults": {
"color": {
"mode": "thresholds"
},
"refresh": 1,
"regex": "",
"skipUrlSync": false,
"sort": 0,
"type": "query"
"mappings": [],
"thresholds": {
"mode": "absolute",
"steps": [
{
"color": "green",
"value": null
},
{
"color": "red",
"value": 80
}
]
}
},
"overrides": []
},
"gridPos": {
"h": 3,
"w": 12,
"x": 0,
"y": 0
},
"id": 4,
"interval": null,
"maxDataPoints": 1,
"options": {
"colorMode": "value",
"graphMode": "none",
"justifyMode": "auto",
"orientation": "auto",
"reduceOptions": {
"calcs": [
"lastNotNull"
],
"fields": "",
"values": false
},
"text": {},
"textMode": "name"
},
"pluginVersion": "8.2.3",
"targets": [
{
"exemplar": false,
"expr": "node_clients.total{nodeid=\"$node_id\"}[1y]",
"format": "time_series",
"instant": true,
"interval": "",
"legendFormat": "{{hostname}}",
"refId": "A"
}
]
],
"title": "hostname",
"type": "stat"
},
"time": {
"from": "now-6h",
"to": "now"
{
"datasource": null,
"fieldConfig": {
"defaults": {
"color": {
"mode": "palette-classic"
},
"custom": {
"axisLabel": "",
"axisPlacement": "auto",
"barAlignment": 0,
"drawStyle": "line",
"fillOpacity": 0,
"gradientMode": "none",
"hideFrom": {
"legend": false,
"tooltip": false,
"viz": false
},
"lineInterpolation": "linear",
"lineWidth": 1,
"pointSize": 5,
"scaleDistribution": {
"type": "linear"
},
"showPoints": "never",
"spanNulls": false,
"stacking": {
"group": "A",
"mode": "none"
},
"thresholdsStyle": {
"mode": "off"
}
},
"decimals": 0,
"mappings": [],
"thresholds": {
"mode": "absolute",
"steps": [
{
"color": "green",
"value": null
}
]
}
},
"overrides": []
},
"gridPos": {
"h": 9,
"w": 12,
"x": 0,
"y": 3
},
"id": 2,
"options": {
"legend": {
"calcs": [],
"displayMode": "hidden",
"placement": "bottom"
},
"tooltip": {
"mode": "single"
}
},
"targets": [
{
"exemplar": true,
"expr": "max_over_time(node_clients.total{nodeid=\"$node_id\"}[10m])",
"interval": "",
"legendFormat": "",
"refId": "A"
}
],
"title": "Connected clients",
"type": "timeseries"
},
"timepicker": {},
"timezone": "",
"title": "Node (public)",
"uid": "KoKOqJc7k",
"version": 3
}
{
"datasource": null,
"fieldConfig": {
"defaults": {
"color": {
"mode": "palette-classic"
},
"custom": {
"axisLabel": "",
"axisPlacement": "auto",
"barAlignment": 0,
"drawStyle": "line",
"fillOpacity": 0,
"gradientMode": "none",
"hideFrom": {
"legend": false,
"tooltip": false,
"viz": false
},
"lineInterpolation": "linear",
"lineWidth": 1,
"pointSize": 5,
"scaleDistribution": {
"type": "linear"
},
"showPoints": "never",
"spanNulls": false,
"stacking": {
"group": "A",
"mode": "none"
},
"thresholdsStyle": {
"mode": "off"
}
},
"decimals": 0,
"mappings": [],
"thresholds": {
"mode": "absolute",
"steps": [
{
"color": "green",
"value": null
}
]
},
"unit": "binBps"
},
"overrides": []
},
"gridPos": {
"h": 9,
"w": 12,
"x": 0,
"y": 12
},
"id": 5,
"options": {
"legend": {
"calcs": [],
"displayMode": "list",
"placement": "bottom"
},
"tooltip": {
"mode": "single"
}
},
"targets": [
{
"exemplar": true,
"expr": "irate(node_traffic.rx.bytes{nodeid=\"$node_id\"})",
"interval": "",
"legendFormat": "Traffic (in)",
"refId": "A"
},
{
"exemplar": true,
"expr": "irate(node_traffic.tx.bytes{nodeid=\"$node_id\"})",
"hide": false,
"interval": "",
"legendFormat": "Traffic (out)",
"refId": "B"
}
],
"title": "Traffic",
"type": "timeseries"
}
],
"refresh": "30s",
"schemaVersion": 31,
"style": "dark",
"tags": [],
"templating": {
"list": [
{
"allValue": null,
"current": {
"selected": false,
"text": "14cc202b86c0",
"value": "14cc202b86c0"
},
"datasource": null,
"definition": "label_values(nodeid)",
"description": null,
"error": null,
"hide": 0,
"includeAll": false,
"label": null,
"multi": false,
"name": "node_id",
"options": [],
"query": {
"query": "label_values(nodeid)",
"refId": "StandardVariableQuery"
},
"refresh": 1,
"regex": "",
"skipUrlSync": false,
"sort": 0,
"type": "query"
}
]
},
"time": {
"from": "now-24h",
"to": "now"
},
"timepicker": {},
"timezone": "",
"title": "Node (public)",
"uid": "KoKOqJc7k",
"version": 9
}

View File

@ -0,0 +1,15 @@
FROM golang:1.16-alpine as builder
RUN go get -v -u github.com/genofire/meshviewer-collector@45acc9a25f6d7a57c89309d657a346d7167c2df7
FROM alpine:3.14
COPY --from=builder /go/bin/meshviewer-collector /bin/meshviewer-collector
RUN apk add --update --no-cache bash
ADD entrypoint.sh /entrypoint.sh
VOLUME /data
CMD /entrypoint.sh

View File

@ -0,0 +1,23 @@
#!/bin/bash
set -e
mkdir -p /config /data
cat << EOF > "/config/config.toml"
run_every = "1m"
ignore_meshviewer = "6d"
ignore_node = "6h"
status_json = "/data/status.json"
[dataPaths]
"http://db.leipzig.freifunk.net/uptime/meshviewer.json" = "meshkit"
[yanic_connection]
type = "udp6"
address = "localhost:10011"
EOF
exec /bin/meshviewer-collector collect --config /config/config.toml

View File

@ -0,0 +1,9 @@
FROM golang:1.16-alpine as builder
RUN go get -v -u github.com/itskoko/prometheus-renderer@v0.0.5
FROM alpine:3.14
COPY --from=builder /go/bin/renderd /bin/renderd
ENTRYPOINT ["/bin/renderd"]

View File

@ -0,0 +1,13 @@
server {
listen 80;
server_name localhost;
location ~ /render/clients/(.*) {
proxy_pass "http://127.0.0.1:8080/?g0.expr=max_over_time(node_clients.total%7Bnodeid=%22$1%22%7D[30m])&width=650&height=350&g0.legend=Clients%20(total)";
}
location ~ /render/traffic/(.*) {
proxy_pass "http://127.0.0.1:8080/?g0.expr=irate(node_traffic.tx.bytes%7Bnodeid=%22$1%22%7D)&g1.expr=irate(node_traffic.rx.bytes%7Bnodeid=%22$1%22%7D)&width=650&height=350&g0.legend=Traffic%20(out)&g1.legend=Traffic%20(in)";
}
}

View File

@ -27,6 +27,12 @@ multicast_address = "ff02::2:1001"
ifname = "bat0"
multicast_address = "ff05::2:1001"
[[respondd.interfaces]]
ifname = "lo"
ip_address = "::1"
send_no_request = true
port = 10011
[webserver]
enable = false