diff --git a/README.md b/README.md index 769e875..57768c8 100644 --- a/README.md +++ b/README.md @@ -41,6 +41,114 @@ Services: * caddy (reverse proxy and basic auth provider for prometheus, alertmanager and unsee) +## Alternative install with Traefik and HTTPS + +If you have a Docker Swarm cluster with a global Traefik [set up as described in this article](https://medium.com/@tiangolo/docker-swarm-mode-and-traefik-for-a-https-cluster-20328dba6232), you can deploy Swarmprom integrated with that global Traefik proxy. + +This way, each Swarmprom service will have its own domain, and each of them will be served using HTTPS, with certificates generated (and renewed) automatically. + +### Requisites + +These instructions assume you already have Traefik set up following that guide above, in short: + +* With automatic HTTPS certificate generation. +* A Docker Swarm network `traefik-public`. +* Filtering to only serve containers with a tag `traefik-public`. + +### Instructions + +* Clone this repository and enter into the directory: + +```bash +$ git clone https://github.com/stefanprodan/swarmprom.git +$ cd swarmprom +``` + +* Set and export an `ADMIN_USER` environment variable: + +```bash +export ADMIN_USER=admin +``` + +* Set and export an `ADMIN_PASSWORD` environment variable: + + +```bash +export ADMIN_PASSWORD=changethis +``` + +* Set and export a hashed version of the `ADMIN_PASSWORD` using `openssl`, it will be used by Traefik's HTTP Basic Auth for most of the services: + +```bash +export HASHED_PASSWORD=$(openssl passwd -apr1 $ADMIN_PASSWORD) +``` + +* Set and export a single variable with the username and password in "`htpasswd`" format: + +```bash +export USERNAME_PASSWORD=$ADMIN_USER:$HASHED_PASSWORD +``` + +* You can check the contents with: + +```bash +echo $USERNAME_PASSWORD +``` + +it will look like: + +``` +admin:$apr1$89eqM5Ro$CxaFELthUKV21DpI3UTQO. +``` + +* Create and export an environment variable `DOMAIN`, e.g.: + +```bash +export DOMAIN=example.com +``` + +and make sure that the following sub-domains point to your Docker Swarm cluster IPs: + +* `grafana.example.com` +* `alertmanager.example.com` +* `unsee.example.com` +* `prometheus.example.com` + +(and replace `example.com` with your actual domain). + +**Note**: You can also use a subdomain, like `swarmprom.example.com`. Just make sure that the subdomains point to (at least one of) your cluster IPs. Or set up a wildcard subdomain (`*`). + +* Set and export an environment variable with the tag used by Traefik public to filter services (by default, it's `traefik-public`): + +```bash +export TRAEFIK_PUBLIC_TAG=traefik-public +``` + +* If you are using Slack and want to integrate it, set the following environment variables: + +```bash +export SLACK_URL=https://hooks.slack.com/services/TOKEN +export SLACK_CHANNEL=devops-alerts +export SLACK_USER=alertmanager +``` + +**Note**: by using `export` when declaring all the environment variables above, the next command will be able to use them. + +* Deploy the Traefik version of the stack: + + +```bash +docker stack deploy -c docker-compose.traefik.yml swarmprom +``` + +To test it, go to each URL: + +* `https://grafana.example.com` +* `https://alertmanager.example.com` +* `https://unsee.example.com` +* `https://prometheus.example.com` + + ## Setup Grafana Navigate to `http://:3000` and login with user ***admin*** password ***admin***. diff --git a/docker-compose.traefik.yml b/docker-compose.traefik.yml new file mode 100644 index 0000000..773615e --- /dev/null +++ b/docker-compose.traefik.yml @@ -0,0 +1,237 @@ +version: "3.3" + +networks: + net: + driver: overlay + attachable: true + traefik-public: + external: true + +volumes: + prometheus: {} + grafana: {} + alertmanager: {} + +configs: + dockerd_config: + file: ./dockerd-exporter/Caddyfile + node_rules: + file: ./prometheus/rules/swarm_node.rules.yml + task_rules: + file: ./prometheus/rules/swarm_task.rules.yml + +services: + dockerd-exporter: + image: stefanprodan/caddy + networks: + - net + environment: + - DOCKER_GWBRIDGE_IP=172.18.0.1 + configs: + - source: dockerd_config + target: /etc/caddy/Caddyfile + deploy: + mode: global + resources: + limits: + memory: 128M + reservations: + memory: 64M + + cadvisor: + image: google/cadvisor + networks: + - net + command: -logtostderr -docker_only + volumes: + - /var/run/docker.sock:/var/run/docker.sock:ro + - /:/rootfs:ro + - /var/run:/var/run + - /sys:/sys:ro + - /var/lib/docker/:/var/lib/docker:ro + deploy: + mode: global + resources: + limits: + memory: 128M + reservations: + memory: 64M + + grafana: + image: stefanprodan/swarmprom-grafana:5.3.4 + networks: + - net + environment: + - GF_SECURITY_ADMIN_USER=${ADMIN_USER:-admin} + - GF_SECURITY_ADMIN_PASSWORD=${ADMIN_PASSWORD:-admin} + - GF_USERS_ALLOW_SIGN_UP=false + #- GF_SERVER_ROOT_URL=${GF_SERVER_ROOT_URL:-localhost} + #- GF_SMTP_ENABLED=${GF_SMTP_ENABLED:-false} + #- GF_SMTP_FROM_ADDRESS=${GF_SMTP_FROM_ADDRESS:-grafana@test.com} + #- GF_SMTP_FROM_NAME=${GF_SMTP_FROM_NAME:-Grafana} + #- GF_SMTP_HOST=${GF_SMTP_HOST:-smtp:25} + #- GF_SMTP_USER=${GF_SMTP_USER} + #- GF_SMTP_PASSWORD=${GF_SMTP_PASSWORD} + volumes: + - grafana:/var/lib/grafana + deploy: + mode: replicated + replicas: 1 + placement: + constraints: + - node.role == manager + resources: + limits: + memory: 128M + reservations: + memory: 64M + labels: + - traefik.frontend.rule=Host:grafana.${DOMAIN} + - traefik.enable=true + - traefik.port=3000 + - traefik.tags=${TRAEFIK_PUBLIC_TAG:-traefik-public} + - traefik.docker.network=traefik-public + # Traefik service that listens to HTTP + - traefik.redirectorservice.frontend.entryPoints=http + - traefik.redirectorservice.frontend.redirect.entryPoint=https + # Traefik service that listens to HTTPS + - traefik.webservice.frontend.entryPoints=https + networks: + - default + - net + - traefik-public + + alertmanager: + image: stefanprodan/swarmprom-alertmanager:v0.14.0 + networks: + - net + environment: + - SLACK_URL=${SLACK_URL:-https://hooks.slack.com/services/TOKEN} + - SLACK_CHANNEL=${SLACK_CHANNEL:-general} + - SLACK_USER=${SLACK_USER:-alertmanager} + command: + - '--config.file=/etc/alertmanager/alertmanager.yml' + - '--storage.path=/alertmanager' + volumes: + - alertmanager:/alertmanager + deploy: + mode: replicated + replicas: 1 + placement: + constraints: + - node.role == manager + resources: + limits: + memory: 128M + reservations: + memory: 64M + labels: + - traefik.frontend.rule=Host:alertmanager.${DOMAIN} + - traefik.enable=true + - traefik.port=9093 + - traefik.tags=${TRAEFIK_PUBLIC_TAG:-traefik-public} + - traefik.docker.network=traefik-public + # Traefik service that listens to HTTP + - traefik.redirectorservice.frontend.entryPoints=http + - traefik.redirectorservice.frontend.redirect.entryPoint=https + # Traefik service that listens to HTTPS + - traefik.webservice.frontend.entryPoints=https + - traefik.frontend.auth.basic=${USERNAME_PASSWORD} + networks: + - default + - net + - traefik-public + + unsee: + image: cloudflare/unsee:v0.8.0 + networks: + - net + environment: + - "ALERTMANAGER_URIS=default:http://alertmanager:9093" + deploy: + mode: replicated + replicas: 1 + labels: + - traefik.frontend.rule=Host:unsee.${DOMAIN} + - traefik.enable=true + - traefik.port=8080 + - traefik.tags=${TRAEFIK_PUBLIC_TAG:-traefik-public} + - traefik.docker.network=traefik-public + # Traefik service that listens to HTTP + - traefik.redirectorservice.frontend.entryPoints=http + - traefik.redirectorservice.frontend.redirect.entryPoint=https + # Traefik service that listens to HTTPS + - traefik.webservice.frontend.entryPoints=https + - traefik.frontend.auth.basic=${USERNAME_PASSWORD} + networks: + - default + - net + - traefik-public + + node-exporter: + image: stefanprodan/swarmprom-node-exporter:v0.16.0 + networks: + - net + environment: + - NODE_ID={{.Node.ID}} + volumes: + - /proc:/host/proc:ro + - /sys:/host/sys:ro + - /:/rootfs:ro + - /etc/hostname:/etc/nodename + command: + - '--path.sysfs=/host/sys' + - '--path.procfs=/host/proc' + - '--collector.textfile.directory=/etc/node-exporter/' + - '--collector.filesystem.ignored-mount-points=^/(sys|proc|dev|host|etc)($$|/)' + - '--no-collector.ipvs' + deploy: + mode: global + resources: + limits: + memory: 128M + reservations: + memory: 64M + + prometheus: + image: stefanprodan/swarmprom-prometheus:v2.5.0 + networks: + - net + command: + - '--config.file=/etc/prometheus/prometheus.yml' + - '--storage.tsdb.path=/prometheus' + - '--storage.tsdb.retention=24h' + volumes: + - prometheus:/prometheus + configs: + - source: node_rules + target: /etc/prometheus/swarm_node.rules.yml + - source: task_rules + target: /etc/prometheus/swarm_task.rules.yml + deploy: + mode: replicated + replicas: 1 + placement: + constraints: + - node.role == manager + resources: + limits: + memory: 2048M + reservations: + memory: 128M + labels: + - traefik.frontend.rule=Host:prometheus.${DOMAIN} + - traefik.enable=true + - traefik.port=9090 + - traefik.tags=${TRAEFIK_PUBLIC_TAG:-traefik-public} + - traefik.docker.network=traefik-public + # Traefik service that listens to HTTP + - traefik.redirectorservice.frontend.entryPoints=http + - traefik.redirectorservice.frontend.redirect.entryPoint=https + # Traefik service that listens to HTTPS + - traefik.webservice.frontend.entryPoints=https + - traefik.frontend.auth.basic=${USERNAME_PASSWORD} + networks: + - default + - net + - traefik-public