Skip to content

[FEATURE REQUEST] Use File based service discovery instead of DNS based for flexibility #10

@bvis

Description

@bvis

Current Situation

Currently DFSL + DFM use the DNS based service discovery. AFAIK DFSL just checks changes in services in the docker API and sends each change to DFM.

This approach is simple and effective but comes with some limitations:

  • We don't have any way to add the node information where each task is running, as Docker is not providing this info ATM.
  • We cannot add arbitrary labels to each service/task for more granular info
  • Each time an exporter is restarted the id, that is based in the task IP changes, then we lose continuity in the metrics.

As you may see relabelling does not offer any value useful for identifying where the request is coming from:

image

Proposal

Prometheus allows to use other discovery systems, while Swarm is not integrated (I've not seen any improvement in this area in a year) we could make usage of Docker API calls + File based discovery service for getting more info for improving the collected metrics.

Example

~ $ curl -s -g -H "Content-Type: application/json" --unix-socket /var/run/docker.sock "http:/v1.24/tasks?filters={\"desired-state\":[\"running\"],\"service\":[\"monitoring_cadvisor\"]}" | jq '[.[] | {NodeID: .NodeID, Labels: .Spec.Conta
inerSpec.Labels, Addresses: .NetworksAttachments[0].Addresses[0] }]'
[
  {
    "NodeID": "zixucyzgugv4fmcf0funaqele",
    "Labels": {
      "com.docker.stack.namespace": "monitoring",
      "com.df.environment": "prod",
      "com.df.xxxx.scrapeTasks": "true"
    },
    "Addresses": "10.0.3.13/24"
  },
  {
    "NodeID": "qz9u95jos3fibvewxxbj9y5i8",
    "Labels": {
      "com.docker.stack.namespace": "monitoring",
      "com.df.environment": "prod",
      "com.df.xxxx.scrapeTasks": "true"
    },
    "Addresses": "10.0.3.12/24"
  },
  {
    "NodeID": "l0n731v8859ejdnnubqvjyuwd",
    "Labels": {
      "com.docker.stack.namespace": "monitoring",
      "com.df.environment": "prod",
      "com.df.xxxx.scrapeTasks": "true"
    },
    "Addresses": "10.0.3.11/24"
  }
]
$ curl -s --unix-socket /var/run/docker.sock http:/v1.31/nodes/zixucyzgugv4fmcf0funaqele | jq '.Description.Hostname'
"node-1"

These queries finally allow to generate an structure like this for Prometheus:

[
  {
    "targets": [ "10.0.3.13:8080" ],
    "labels": {
      "env": "prod",
      "job": "cadvisor",
      "node": "node-1"
    }
  },
  {
    "targets": [ "10.0.3.12:8080" ],
    "labels": {
      "env": "prod",
      "job": "cadvisor",
      "node": "node-2"
    }
  },
  {
    "targets": [ "10.0.3.11:8080" ],
    "labels": {
      "env": "prod",
      "job": "cadvisor",
      "node": "node-3"
    }
  },
  {
    "targets": [ "10.0.0.8:9100" ],
    "labels": {
      "env": "prod",
      "job": "node-exporter",
      "node": "node-1"
    }
  },
  {
    "targets": [ "10.0.0.9:9100" ],
    "labels": {
      "env": "prod",
      "job": "node-exporter",
      "node": "node-2"
    }
  }
]

Which could be stored in a dynamic file that should change every time something in the exporters change. This file can be used with a reference in the prometheus.yml file:

- job_name: 'dummy'  # This is a default value, it is mandatory.
  file_sd_configs:
    - files:
      - /etc/prometheus/prometheus.sd.json

And doing some relabelling to use the node entry as target in Prometheus.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions