Grafana Agent (Kubernetes) and Prometheus (VM / Bare-Metal)
This topic explains how to configure the metrics collection layer to scrape Fabric metrics from the bundled JMX Exporter. The collection layer differs between Kubernetes and VM / bare-metal deployments:
Both paths result in Fabric and JVM metrics being available in Prometheus for dashboards, alerting, and Thanos federation.
This how-to covers:
It does not cover dashboard creation, alert rules, Thanos configuration, or Loki log collection. Those are covered in related topics.
[ K8s + VM ] Applies to both deployment models.
Before configuring the collection layer, confirm that Fabric is already exposing metrics through the JMX Exporter. You should be able to run the following from inside the Fabric runtime context and receive Prometheus-format output:
curl http://localhost:7170/metrics
If this does not return metrics, resolve that first. See How to Enable the JMX Exporter for Fabric and How to Verify That Fabric Is Exposing Metrics.
You should also know:
[ K8s ] In Kubernetes, Grafana Agent is the metrics collector. Prometheus is not configured directly to scrape Fabric. Grafana Agent scrapes Fabric pods and remote-writes to a per-cluster Prometheus instance.
Grafana Agent uses Kubernetes service discovery to find pods and services in the cluster. It does not use static target lists. There are two ways to configure it to scrape Fabric metrics:
The K2view Grafana Agent Helm chart (k8s-monitoring) supports both patterns. Annotation-based autodiscovery is disabled by default in the chart and must be explicitly enabled.
When annotation-based autodiscovery is enabled in the Grafana Agent chart, any pod annotated with the scrape annotation will be automatically discovered and scraped. To enable:
In your Grafana Agent values override file, set:
metrics:
autoDiscover:
enabled: true
Then annotate the Fabric pod or deployment with the following annotations:
k8s.grafana.com/scrape: "true"
k8s.grafana.com/metrics.portNumber: "7170"
For iid_finder, add a separate annotation entry pointing to port 7270, or configure it as a second scrape target.
Note: Annotation-based autodiscovery discovers pods and services cluster-wide. Apply the scrape annotation only to pods you intend to monitor, and use metric filtering (see Section 4) to control what is retained.
For more control over discovery, scraping, and relabeling, add an explicit River pipeline to the Grafana Agent configuration. This is the recommended approach when you need to apply specific filtering or label transformations to Fabric metrics.
A minimal River pipeline that discovers Fabric pods by label and scrapes port 7170:
discovery.relabel "fabric_pods" {
targets = discovery.kubernetes.pods.targets
rule {
source_labels = ["__meta_kubernetes_pod_label_app"]
regex = "fabric"
action = "keep"
}
rule {
source_labels = ["__meta_kubernetes_pod_container_port_number"]
regex = "7170"
action = "keep"
}
}
prometheus.scrape "fabric_jmx" {
targets = discovery.relabel.fabric_pods.output
job_name = "fabric-jmx"
forward_to = [prometheus.relabel.metrics_service.receiver]
}
Adjust the label selector (app=fabric) to match the actual labels on your Fabric pods. The forward_to destination (prometheus.relabel.metrics_service) is the standard metrics forwarding component created by the k8s-monitoring chart.
To also scrape iid_finder, add a second discovery.relabel and prometheus.scrape block targeting port 7270.
Pass the River configuration to the Grafana Agent chart:
helm upgrade grafana-agent . \\
--namespace grafana-agent \\
--values grafana-agent-values.yaml \\
--set-file extraConfig=fabric-scrape.river
After applying the configuration, confirm that Grafana Agent is discovering and scraping Fabric endpoints:
kubectl logs -n grafana-agent -l app.kubernetes.io/name=grafana-agent | grep fabric
curl -s http://<PROMETHEUS_HOST>:9090/api/v1/query?query=jvm_memory_bytes_used | jq .
Note: Grafana Agent remote-writes to Prometheus. It may take up to one scrape interval (default 60s) for metrics to appear in Prometheus after configuration is applied.
[ VM / Bare-Metal ] In VM deployments, Prometheus scrapes Fabric hosts directly. There is no Grafana Agent and no service discovery. Each Fabric host must be listed explicitly as a static scrape target.
Add scrape jobs to your Prometheus configuration file (prometheus.yml) on the monitoring machine. You need one job for Fabric metrics and one for Node Exporter metrics on each host:
scrape_configs:
# Fabric JMX Exporter — one entry per Fabric host
- job_name: fabric-jmx
metrics_path: /metrics
static_configs:
- targets:
- <FABRIC_HOST_1>:7170
- <FABRIC_HOST_2>:7170
labels:
env: production
# iid_finder JMX Exporter — add if iid_finder is running
- job_name: iidfinder-jmx
metrics_path: /metrics
static_configs:
- targets:
- <FABRIC_HOST_1>:7270
- <FABRIC_HOST_2>:7270
# Node Exporter — one entry per Fabric host
- job_name: node-exporter
metrics_path: /metrics
static_configs:
- targets:
- <FABRIC_HOST_1>:9100
- <FABRIC_HOST_2>:9100
Note: Replace
After adding or updating scrape targets, reload Prometheus to apply the configuration without restarting:
curl -X POST http://localhost:9090/-/reload
If hot-reload is not enabled, restart Prometheus:
systemctl restart prometheus
http://<PROMETHEUS_HOST>:9090/targets
Confirm the fabric-jmx job is present and all targets show State: UP
Run a test query for a known Fabric or JVM metric:
http://<PROMETHEUS_HOST>:9090/graph?g0.expr=jvm_memory_bytes_used
A target showing State: DOWN means Prometheus can see the target in its configuration but cannot reach it. Check network reachability between the Prometheus machine and the Fabric host, and confirm the JMX Exporter is running on the expected port.
[ K8s + VM ] Applies to both deployment models. The principle is the same; the syntax differs between Grafana Agent River config and Prometheus YAML.
The Fabric JMX Exporter exposes all available metrics by default. Without filtering, Prometheus can ingest far more data than is operationally useful. Filtering and relabeling should be applied at the collection layer to:
Start from a known useful set and drop everything else. For Fabric, the typically useful families are:
The families most commonly worth dropping are high-volume exporters that produce many series with little operational value. Node Exporter in particular exposes a very large number of metric families — review which ones are actually used in your dashboards and drop the rest.
Note: The real scaling pressure in Prometheus comes from active series, not from the number of metric names. A single metric with many label values can generate hundreds of distinct series. Always review active series counts after changing filtering rules.
In a River pipeline, use a prometheus.relabel component to filter metrics before forwarding:
prometheus.relabel "fabric_jmx" {
rule {
source_labels = ["__name__"]
regex = "fabric_.*|jvm_.*|tomcat_.*|process_.*"
action = "keep"
}
forward_to = [prometheus.relabel.metrics_service.receiver]
}
Update the prometheus.scrape component to forward to this relabel component instead of directly to metrics_service:
prometheus.scrape "fabric_jmx" {
targets = discovery.relabel.fabric_pods.output
job_name = "fabric-jmx"
forward_to = [prometheus.relabel.fabric_jmx.receiver]
}
In Prometheus YAML, use metric_relabel_configs within the scrape job:
- job_name: fabric-jmx
metrics_path: /metrics
static_configs:
- targets:
- <FABRIC_HOST_1>:7170
metric_relabel_configs:
- source_labels: [__name__]
regex: \'fabric_.*|jvm_.*|tomcat_.*|process_.*\'
action: keep
Note: metric_relabel_configs runs after the scrape. It filters what gets stored in Prometheus. relabel_configs runs before the scrape and controls target selection. Use metric_relabel_configs for metric family filtering.
If a metric is useful but has too many labels creating excessive series, drop unwanted labels using a labeldrop action:
Grafana Agent (River):
rule {
action = "labeldrop"
regex = "some_high_cardinality_label"
}
Prometheus YAML:
metric_relabel_configs:
- action: labeldrop
regex: \'some_high_cardinality_label\'
For detailed guidance on filtering strategy, cardinality management, and retention impact, see How to Control Metric Volume with Filtering and Relabeling.
[ K8s + VM ] Run these checks after configuring the collection layer.
Kubernetes: Check Grafana Agent logs for scrape activity and confirm metrics are flowing to Prometheus.
kubectl logs -n grafana-agent -l app.kubernetes.io/name=grafana-agent | grep -i "fabric\\|scrape"
VM: Open the Prometheus Targets UI and confirm the fabric-jmx job shows State: UP for all configured targets.
http://<PROMETHEUS_HOST>:9090/targets
Once the collection layer is scraping, run a simple query for known Fabric or JVM metrics. You do not need a full dashboard yet — the important validation is that time series are present:
# JVM heap memory
jvm_memory_bytes_used{area="heap"}
# Fabric reads
fabric_read_total
# Active series in Prometheus (health check)
prometheus_tsdb_head_series
Kubernetes: The Grafana Agent cannot reach the Fabric pod on port 7170. Check that the JMX Exporter is running inside the pod (curl from inside the pod), and check network policy rules between the Grafana Agent namespace and the Fabric namespace.
VM: Prometheus cannot reach the Fabric host on port 7170. Check firewall rules between the monitoring machine and the Fabric host. Confirm Node Exporter and the JMX Exporter are both running on the Fabric host.
Kubernetes: Autodiscovery is not finding the Fabric pods. Check that the scrape annotation is present on the pod (Option A) or that the River pipeline label selector matches the actual pod labels (Option B).
VM: The static target is missing from prometheus.yml, or Prometheus was not reloaded after the configuration change.
Kubernetes:
VM / Bare-Metal:
Grafana Agent (Kubernetes) and Prometheus (VM / Bare-Metal)
This topic explains how to configure the metrics collection layer to scrape Fabric metrics from the bundled JMX Exporter. The collection layer differs between Kubernetes and VM / bare-metal deployments:
Both paths result in Fabric and JVM metrics being available in Prometheus for dashboards, alerting, and Thanos federation.
This how-to covers:
It does not cover dashboard creation, alert rules, Thanos configuration, or Loki log collection. Those are covered in related topics.
[ K8s + VM ] Applies to both deployment models.
Before configuring the collection layer, confirm that Fabric is already exposing metrics through the JMX Exporter. You should be able to run the following from inside the Fabric runtime context and receive Prometheus-format output:
curl http://localhost:7170/metrics
If this does not return metrics, resolve that first. See How to Enable the JMX Exporter for Fabric and How to Verify That Fabric Is Exposing Metrics.
You should also know:
[ K8s ] In Kubernetes, Grafana Agent is the metrics collector. Prometheus is not configured directly to scrape Fabric. Grafana Agent scrapes Fabric pods and remote-writes to a per-cluster Prometheus instance.
Grafana Agent uses Kubernetes service discovery to find pods and services in the cluster. It does not use static target lists. There are two ways to configure it to scrape Fabric metrics:
The K2view Grafana Agent Helm chart (k8s-monitoring) supports both patterns. Annotation-based autodiscovery is disabled by default in the chart and must be explicitly enabled.
When annotation-based autodiscovery is enabled in the Grafana Agent chart, any pod annotated with the scrape annotation will be automatically discovered and scraped. To enable:
In your Grafana Agent values override file, set:
metrics:
autoDiscover:
enabled: true
Then annotate the Fabric pod or deployment with the following annotations:
k8s.grafana.com/scrape: "true"
k8s.grafana.com/metrics.portNumber: "7170"
For iid_finder, add a separate annotation entry pointing to port 7270, or configure it as a second scrape target.
Note: Annotation-based autodiscovery discovers pods and services cluster-wide. Apply the scrape annotation only to pods you intend to monitor, and use metric filtering (see Section 4) to control what is retained.
For more control over discovery, scraping, and relabeling, add an explicit River pipeline to the Grafana Agent configuration. This is the recommended approach when you need to apply specific filtering or label transformations to Fabric metrics.
A minimal River pipeline that discovers Fabric pods by label and scrapes port 7170:
discovery.relabel "fabric_pods" {
targets = discovery.kubernetes.pods.targets
rule {
source_labels = ["__meta_kubernetes_pod_label_app"]
regex = "fabric"
action = "keep"
}
rule {
source_labels = ["__meta_kubernetes_pod_container_port_number"]
regex = "7170"
action = "keep"
}
}
prometheus.scrape "fabric_jmx" {
targets = discovery.relabel.fabric_pods.output
job_name = "fabric-jmx"
forward_to = [prometheus.relabel.metrics_service.receiver]
}
Adjust the label selector (app=fabric) to match the actual labels on your Fabric pods. The forward_to destination (prometheus.relabel.metrics_service) is the standard metrics forwarding component created by the k8s-monitoring chart.
To also scrape iid_finder, add a second discovery.relabel and prometheus.scrape block targeting port 7270.
Pass the River configuration to the Grafana Agent chart:
helm upgrade grafana-agent . \\
--namespace grafana-agent \\
--values grafana-agent-values.yaml \\
--set-file extraConfig=fabric-scrape.river
After applying the configuration, confirm that Grafana Agent is discovering and scraping Fabric endpoints:
kubectl logs -n grafana-agent -l app.kubernetes.io/name=grafana-agent | grep fabric
curl -s http://<PROMETHEUS_HOST>:9090/api/v1/query?query=jvm_memory_bytes_used | jq .
Note: Grafana Agent remote-writes to Prometheus. It may take up to one scrape interval (default 60s) for metrics to appear in Prometheus after configuration is applied.
[ VM / Bare-Metal ] In VM deployments, Prometheus scrapes Fabric hosts directly. There is no Grafana Agent and no service discovery. Each Fabric host must be listed explicitly as a static scrape target.
Add scrape jobs to your Prometheus configuration file (prometheus.yml) on the monitoring machine. You need one job for Fabric metrics and one for Node Exporter metrics on each host:
scrape_configs:
# Fabric JMX Exporter — one entry per Fabric host
- job_name: fabric-jmx
metrics_path: /metrics
static_configs:
- targets:
- <FABRIC_HOST_1>:7170
- <FABRIC_HOST_2>:7170
labels:
env: production
# iid_finder JMX Exporter — add if iid_finder is running
- job_name: iidfinder-jmx
metrics_path: /metrics
static_configs:
- targets:
- <FABRIC_HOST_1>:7270
- <FABRIC_HOST_2>:7270
# Node Exporter — one entry per Fabric host
- job_name: node-exporter
metrics_path: /metrics
static_configs:
- targets:
- <FABRIC_HOST_1>:9100
- <FABRIC_HOST_2>:9100
Note: Replace
After adding or updating scrape targets, reload Prometheus to apply the configuration without restarting:
curl -X POST http://localhost:9090/-/reload
If hot-reload is not enabled, restart Prometheus:
systemctl restart prometheus
http://<PROMETHEUS_HOST>:9090/targets
Confirm the fabric-jmx job is present and all targets show State: UP
Run a test query for a known Fabric or JVM metric:
http://<PROMETHEUS_HOST>:9090/graph?g0.expr=jvm_memory_bytes_used
A target showing State: DOWN means Prometheus can see the target in its configuration but cannot reach it. Check network reachability between the Prometheus machine and the Fabric host, and confirm the JMX Exporter is running on the expected port.
[ K8s + VM ] Applies to both deployment models. The principle is the same; the syntax differs between Grafana Agent River config and Prometheus YAML.
The Fabric JMX Exporter exposes all available metrics by default. Without filtering, Prometheus can ingest far more data than is operationally useful. Filtering and relabeling should be applied at the collection layer to:
Start from a known useful set and drop everything else. For Fabric, the typically useful families are:
The families most commonly worth dropping are high-volume exporters that produce many series with little operational value. Node Exporter in particular exposes a very large number of metric families — review which ones are actually used in your dashboards and drop the rest.
Note: The real scaling pressure in Prometheus comes from active series, not from the number of metric names. A single metric with many label values can generate hundreds of distinct series. Always review active series counts after changing filtering rules.
In a River pipeline, use a prometheus.relabel component to filter metrics before forwarding:
prometheus.relabel "fabric_jmx" {
rule {
source_labels = ["__name__"]
regex = "fabric_.*|jvm_.*|tomcat_.*|process_.*"
action = "keep"
}
forward_to = [prometheus.relabel.metrics_service.receiver]
}
Update the prometheus.scrape component to forward to this relabel component instead of directly to metrics_service:
prometheus.scrape "fabric_jmx" {
targets = discovery.relabel.fabric_pods.output
job_name = "fabric-jmx"
forward_to = [prometheus.relabel.fabric_jmx.receiver]
}
In Prometheus YAML, use metric_relabel_configs within the scrape job:
- job_name: fabric-jmx
metrics_path: /metrics
static_configs:
- targets:
- <FABRIC_HOST_1>:7170
metric_relabel_configs:
- source_labels: [__name__]
regex: \'fabric_.*|jvm_.*|tomcat_.*|process_.*\'
action: keep
Note: metric_relabel_configs runs after the scrape. It filters what gets stored in Prometheus. relabel_configs runs before the scrape and controls target selection. Use metric_relabel_configs for metric family filtering.
If a metric is useful but has too many labels creating excessive series, drop unwanted labels using a labeldrop action:
Grafana Agent (River):
rule {
action = "labeldrop"
regex = "some_high_cardinality_label"
}
Prometheus YAML:
metric_relabel_configs:
- action: labeldrop
regex: \'some_high_cardinality_label\'
For detailed guidance on filtering strategy, cardinality management, and retention impact, see How to Control Metric Volume with Filtering and Relabeling.
[ K8s + VM ] Run these checks after configuring the collection layer.
Kubernetes: Check Grafana Agent logs for scrape activity and confirm metrics are flowing to Prometheus.
kubectl logs -n grafana-agent -l app.kubernetes.io/name=grafana-agent | grep -i "fabric\\|scrape"
VM: Open the Prometheus Targets UI and confirm the fabric-jmx job shows State: UP for all configured targets.
http://<PROMETHEUS_HOST>:9090/targets
Once the collection layer is scraping, run a simple query for known Fabric or JVM metrics. You do not need a full dashboard yet — the important validation is that time series are present:
# JVM heap memory
jvm_memory_bytes_used{area="heap"}
# Fabric reads
fabric_read_total
# Active series in Prometheus (health check)
prometheus_tsdb_head_series
Kubernetes: The Grafana Agent cannot reach the Fabric pod on port 7170. Check that the JMX Exporter is running inside the pod (curl from inside the pod), and check network policy rules between the Grafana Agent namespace and the Fabric namespace.
VM: Prometheus cannot reach the Fabric host on port 7170. Check firewall rules between the monitoring machine and the Fabric host. Confirm Node Exporter and the JMX Exporter are both running on the Fabric host.
Kubernetes: Autodiscovery is not finding the Fabric pods. Check that the scrape annotation is present on the pod (Option A) or that the River pipeline label selector matches the actual pod labels (Option B).
VM: The static target is missing from prometheus.yml, or Prometheus was not reloaded after the configuration change.
Kubernetes:
VM / Bare-Metal: