diff --git a/artifacts/docs/README.md b/artifacts/docs/README.md index daad8ffe..640c3053 100644 --- a/artifacts/docs/README.md +++ b/artifacts/docs/README.md @@ -8,7 +8,7 @@ Profiles group services so you can deploy subsets on demand. Activate with `darg ### analytics -Services: cadvisor, grafana, node-exporter, postgres, prometheus, sqitch, traefik +Services: cadvisor, docker-socket-proxy, grafana, node-exporter, postgres, prometheus, sqitch, swarm-scheduler-exporter, traefik ### default @@ -65,6 +65,10 @@ You can see how changes in the database end up in the event stream using `redpan You can check the database connector's setup logs using `portainer`. +### docker-socket-proxy *(production only)* + +The allowlisted proxy in front of the manager's docker socket, for the swarm scheduler exporter. + ### elasticsearch You cannot access the search engine via a web interface. @@ -156,6 +160,10 @@ You can access the event streaming platform's ui at [redpanda.app.localhost](htt You cannot access the database migrations directly. +### swarm-scheduler-exporter *(production only)* + +The exporter that reports the swarm's state, its nodes and each service's tasks to the metrics monitoring. + ### traefik You can access the reverse proxy's dashboard at [traefik.app.localhost](https://traefik.app.localhost/). diff --git a/dargstack.yaml b/dargstack.yaml index 1d1d23b4..c862a40a 100644 --- a/dargstack.yaml +++ b/dargstack.yaml @@ -14,7 +14,7 @@ environment: # tag: latest # optional, defaults to "latest" metadata: - compatibility: ">=4.13.0-0 <5.0.0" + compatibility: ">=4.20.0-0 <5.0.0" name: "vibetype" source: name: "maevsi" diff --git a/src/development/prometheus/configurations/prometheus.yaml b/src/development/prometheus/configurations/prometheus.yaml index 5e60ae2b..996cd1b8 100644 --- a/src/development/prometheus/configurations/prometheus.yaml +++ b/src/development/prometheus/configurations/prometheus.yaml @@ -33,3 +33,7 @@ scrape_configs: - targets: - redpanda:9644 metrics_path: /public_metrics + + - job_name: "swarm-scheduler-exporter" + static_configs: + - targets: ["swarm-scheduler-exporter:8888"] diff --git a/src/production/docker-socket-proxy/compose.yaml b/src/production/docker-socket-proxy/compose.yaml new file mode 100644 index 00000000..15540175 --- /dev/null +++ b/src/production/docker-socket-proxy/compose.yaml @@ -0,0 +1,38 @@ +networks: + docker-socket-proxy: + # Internal: nothing outside the exporter can reach the proxy. + driver: overlay + driver_opts: + com.docker.network.driver.mtu: "1400" + internal: true +services: + docker-socket-proxy: + # The allowlisted proxy in front of the manager's docker socket, for the swarm scheduler exporter. + cap_drop: + - ALL + deploy: + labels: + - dargstack.profiles=analytics + placement: + constraints: + # Only a manager's docker daemon answers the cluster-wide service, node and task calls. + - node.role == manager + resources: + limits: + memory: 64m + reservations: + memory: 32m + update_config: + order: start-first + env_file: + - ./configurations/allowlist.env + image: ghcr.io/tecnativa/docker-socket-proxy:v0.5.0 + logging: + driver: json-file + options: + max-file: "3" + max-size: 20m + networks: + - docker-socket-proxy + volumes: + - /var/run/docker.sock:/var/run/docker.sock:ro diff --git a/src/production/docker-socket-proxy/configurations/allowlist.env b/src/production/docker-socket-proxy/configurations/allowlist.env new file mode 100644 index 00000000..42eaa606 --- /dev/null +++ b/src/production/docker-socket-proxy/configurations/allowlist.env @@ -0,0 +1,39 @@ +# The Docker API sections the proxy forwards to the daemon, for the swarm scheduler exporter. +# Every ACL variable of the image is set explicitly, relying on no default: the image enables EVENTS and VERSION by default. + +# Needed by the exporter. PING is how the client negotiates the API version, so VERSION stays off. +PING=1 +EVENTS=1 +SERVICES=1 +NODES=1 +TASKS=1 +# CONTAINERS: only for the exporter's container metrics, which the stack does not use. +CONTAINERS=0 + +# Not needed: denied. +ALLOW_RESTARTS=0 +ALLOW_START=0 +ALLOW_STOP=0 +AUTH=0 +BUILD=0 +COMMIT=0 +CONFIGS=0 +DISTRIBUTION=0 +EXEC=0 +GRPC=0 +IMAGES=0 +INFO=0 +NETWORKS=0 +PLUGINS=0 +# POST: 0 denies every method but GET (and HEAD), whatever the section. +POST=0 +SECRETS=0 +SESSION=0 +SWARM=0 +SYSTEM=0 +VERSION=0 +VOLUMES=0 + +# Referenced by the image's haproxy.cfg but not given a default in its environment: set to 0 anyway. +ALLOW_PAUSE=0 +ALLOW_UNPAUSE=0 diff --git a/src/production/swarm-scheduler-exporter/compose.yaml b/src/production/swarm-scheduler-exporter/compose.yaml new file mode 100644 index 00000000..cb7c019f --- /dev/null +++ b/src/production/swarm-scheduler-exporter/compose.yaml @@ -0,0 +1,39 @@ +services: + swarm-scheduler-exporter: + # The exporter that reports the swarm's state, its nodes and each service's tasks to the metrics monitoring. + cap_drop: + - ALL + deploy: + labels: + - dargstack.profiles=analytics + placement: + constraints: + # Only a manager's docker daemon serves the cluster-wide data the exporter reads. + - node.role == manager + resources: + limits: + memory: 128m + reservations: + memory: 64m + update_config: + order: start-first + environment: + # The exporter reads the Docker API through the allowlisted socket proxy instead of the socket itself. + - DOCKER_HOST=tcp://docker-socket-proxy:2375 + healthcheck: + # The image is distroless and has no shell, so the binary probes its own readiness endpoint. + test: ["CMD", "/usr/local/bin/swarm-scheduler-exporter", "-healthcheck"] + interval: 30s + timeout: 5s + start_period: 90s + retries: 3 + image: ghcr.io/leinardi/swarm-scheduler-exporter:v1.3.2 + logging: + driver: json-file + options: + max-file: "3" + max-size: 20m + networks: + - default + - docker-socket-proxy + read_only: true