Skip to main content

MinIO

MinIO serves Prometheus-format metrics at /minio/metrics/v3 (the current v3 metrics API) on the S3 API port :9000. The OpenTelemetry Collector's prometheus receiver scrapes that endpoint directly, collecting 100+ metrics across S3 request rate and errors, cluster capacity and drive/erasure-set health, per-drive performance, and host and process resources. This guide configures the receiver, sets up metrics authentication, and ships metrics to base14 Scout.

Prerequisites

RequirementMinimumRecommended
MinIOrelease exposing the metrics endpointcurrent release (v3 metrics API)
OTel Collector Contrib0.90.00.153.0
base14 ScoutAny-

Before starting:

  • The MinIO S3 API port (9000) must be reachable from the host running the Collector.
  • Metrics are token-gated by default - either set MINIO_PROMETHEUS_AUTH_TYPE=public or scrape with a bearer token (see Access Setup).
  • A Scout account and OTLP endpoint.
  • OTel Collector installed - see Docker Compose Setup.

What You'll Monitor

Metrics are grouped into three tiers by how you use them. Scrape Core always, alert on Operational, and reach for Diagnostic during an incident or capacity review. The metric names are MinIO's native v3 exposition (minio_<category>_*), reproduced as the endpoint serves them.

A few surface notes shape how you read this set:

  • up is the liveness signal here. The prometheus receiver emits up = 1 when the /minio/metrics/v3 endpoint responds. That is the monitoring-is-alive signal; minio_cluster_health_drives_online_count (against minio_cluster_health_drives_count) is the erasure-coding durability signal.
  • Use the v3 endpoint. /minio/metrics/v3 is the current metrics API and replaces the deprecated /minio/v2/metrics/{cluster,node,bucket} endpoints (still present in the release, but not for new deployments). The default v3 endpoint returns the minio_api_*, minio_system_*, minio_cluster_*, and minio_scanner_* families. Per-bucket, replication, notification, ILM, and resource detail live at dedicated v3 sub-paths (for example /minio/metrics/v3/bucket/api and /minio/metrics/v3/replication) - add a scrape job per sub-path when you need that detail.
  • Metrics are token-gated by default. Either set MINIO_PROMETHEUS_AUTH_TYPE=public or scrape with a bearer token from mc admin prometheus generate. A 403 with no token is expected otherwise.
  • Erasure-coding health is the storage-specific signal. minio_cluster_erasure_set_read_health / _write_health report whether each set can still serve reads and writes. Below write quorum the set goes read-only; below read quorum it goes offline.
  • Counts scale with topology. Node, drive, and erasure-set counts are 1 on a single-node single-drive deployment. The minio_system_drive_* and minio_cluster_erasure_set_* families expand (one series per drive, one per set) in a distributed deployment.
  • go_* is MinIO's own Go runtime, not a storage signal. Prefer MinIO's own minio_system_process_* and filter go_* with a minio_.*|up keep rule.

Core - is it up and serving

MetricWhat it tells you
upScrape liveness - 1 when the MinIO metrics endpoint responded. The monitoring-is-alive signal on this surface.
minio_api_requests_totalS3 API requests handled, labeled by API name - headline request throughput.
minio_api_requests_errors_totalS3 API requests that returned an error - headline error signal.
minio_cluster_health_capacity_usable_free_bytesUsable free capacity after erasure-coding overhead - running out is a top object-store incident.
minio_cluster_health_drives_online_countDrives currently online (against minio_cluster_health_drives_count) - the erasure-coding durability signal.

Operational - what to alert on

GroupMetricsWhat it tells you
S3 errors and latencyminio_api_requests_4xx_errors_total, minio_api_requests_incoming_total, minio_api_requests_ttfb_seconds_distributionClient-error volume, arriving load, and the time-to-first-byte latency SLO per API.
S3 trafficminio_api_requests_traffic_received_bytes, minio_api_requests_traffic_sent_bytesInbound (uploads) and outbound (downloads) S3 bytes.
Cluster healthminio_cluster_health_drives_count, minio_cluster_health_nodes_online_count, minio_cluster_health_capacity_usable_total_bytes, minio_cluster_health_capacity_raw_free_bytes / _raw_total_bytesTotal drives, online nodes, and usable/raw capacity - the denominators for the durability and capacity ratios.
Erasure-set healthminio_cluster_erasure_set_health, minio_cluster_erasure_set_read_health, minio_cluster_erasure_set_write_health, minio_cluster_erasure_set_online_drives_count, minio_cluster_erasure_set_read_quorum / _write_quorumWhether each set can serve reads/writes and how close it is to losing quorum.
Per-drive healthminio_system_drive_health, minio_system_drive_used_bytes / _free_bytes / _total_bytes, minio_system_drive_free_inodes, minio_system_drive_api_latency_micros, minio_system_drive_perc_util, minio_system_drive_writes_await / _writes_per_sec / _writes_kb_per_secPer-drive health, capacity, inodes, latency, and IO - a slow or full drive localizes a degraded cluster.
Host pressureminio_system_cpu_load_perc, minio_system_cpu_avg_iowait, minio_system_memory_used_perc, minio_system_memory_availableHost CPU load, storage-bound iowait, and memory pressure.
MinIO processminio_system_process_resident_memory_bytes, minio_system_process_cpu_total_seconds, minio_system_process_file_descriptor_open_total, minio_system_process_file_descriptor_limit_totalMinIO's own RSS, CPU time, and open file descriptors against the FD limit.

Diagnostic - for investigation and tuning

Higher cardinality; reach for these during an incident or a capacity review. They are grouped, not enumerated - representative members are named.

GroupRepresentative metricsWhen you reach for it
CPU and memory breakdownminio_system_cpu_load, minio_system_cpu_avg_idle / _system / _user, minio_system_memory_total / _free / _cache / _buffersDecomposing host CPU and memory beyond the headline percentages.
Per-drive counts and inodesminio_system_drive_count, minio_system_drive_online_count, minio_system_drive_total_inodes / _used_inodesPer-node drive visibility and inode accounting.
MinIO process internalsminio_system_process_io_rchar_bytes / _wchar_bytes / _write_bytes, minio_system_process_syscall_read_total / _write_total, minio_system_process_go_routine_total, minio_system_process_virtual_memory_bytes, minio_system_process_uptime_secondsProcess IO, syscalls, goroutines, and virtual memory during a CPU or memory investigation.
Bucket-usage stalenessminio_cluster_usage_objects_buckets_count, minio_cluster_usage_objects_since_last_update_seconds, minio_cluster_usage_buckets_since_last_update_secondsWhether the object/bucket usage figures are fresh.
IAM syncminio_cluster_iam_sync_successes, minio_cluster_iam_last_sync_duration_millis, minio_cluster_iam_since_last_sync_millisIAM replication health on a configured cluster.
Object scannerminio_scanner_bucket_scans_started / _finished, minio_scanner_last_activity_secondsWhether the background object scanner is running.
Runtime and scrape metago_*, scrape_duration_seconds, scrape_samples_scraped, scrape_series_addedMinIO's Go runtime and the receiver-side scrape meta; filter go_* with a minio_.*|up keep rule.

Some families are not on the default v3 endpoint or read 0 until the feature is exercised: per-bucket (minio_bucket_*), replication, notification, ILM, KMS, and audit families live at dedicated v3 sub-paths and require those endpoints to be scraped; multi-node internode-network and healing metrics populate only in a distributed deployment.

Key Alerts to Configure

Threshold guidance for the most useful Core and Operational series. The state and ratio alerts read MinIO's own counts, totals, and limits - they are not invented absolutes. The rate and latency alerts are relative to your own baseline. Tune all of them to your workload.

MetricConditionWhy it matters
up== 0 for > 1mThe metrics endpoint stopped responding - check the MinIO process and the API port.
minio_cluster_health_drives_online_count< minio_cluster_health_drives_countOne or more drives dropped - durability is reduced; replace the drive and let MinIO heal.
minio_cluster_erasure_set_write_health== 0The set can no longer accept writes - restore drives before it goes read-only or offline.
minio_cluster_health_capacity_usable_free_bytes / minio_cluster_health_capacity_usable_total_bytes< 0.1The cluster is running out of usable space - expand or reclaim.
rate(minio_api_requests_errors_total)Rising vs baselineServer-side S3 failures - check drive health, quorum, and recent changes.
minio_api_requests_ttfb_seconds_distributionp99 rising vs baselineRequests are slow - correlate with minio_system_drive_api_latency_micros and iowait.
minio_system_drive_free_inodesApproaching 0A drive is out of inodes - new objects will fail even with free bytes.
minio_system_process_file_descriptor_open_total / minio_system_process_file_descriptor_limit_total> 0.9MinIO is near its FD limit - raise the ulimit.

Access Setup

MinIO exposes Prometheus metrics on the S3 API port, but they are token-gated by default. Pick one of the two options below.

Option 1: Public metrics (no token)

Set the environment variable before starting MinIO so the metrics endpoint serves without auth:

Public metrics
export MINIO_PROMETHEUS_AUTH_TYPE=public

Generate a scrape token with the MinIO client:

Generate bearer token
# Set up the mc alias
mc alias set myminio http://localhost:9000 minioadmin minioadmin

# Generate a Prometheus scrape config with a bearer token
mc admin prometheus generate myminio

This outputs a scrape snippet containing the bearer token; use that token in the Collector config below.

Verify the endpoint responds:

Verify access
# Check MinIO is live
curl -s http://localhost:9000/minio/health/live

# Verify the v3 metrics endpoint (use a token here if not public)
curl -s http://localhost:9000/minio/metrics/v3 | head -20

The default v3 endpoint returns the minio_api_*, minio_system_*, minio_cluster_*, and minio_scanner_* families. Per-bucket, replication, and resource detail live at sub-paths such as /minio/metrics/v3/bucket/api and /minio/metrics/v3/replication.

Configuration

config/otel-collector.yaml
receivers:
prometheus:
config:
scrape_configs:
- job_name: minio
scrape_interval: 10s
metrics_path: /minio/metrics/v3
static_configs:
- targets:
- ${env:MINIO_HOST}:9000 # Change to your MinIO address
metric_relabel_configs:
# Scope to the MinIO namespace; drop go_* and scrape_* noise
- source_labels: [__name__]
regex: 'minio_.*|up'
action: keep

processors:
resource:
attributes:
- key: deployment.environment.name
value: ${env:ENVIRONMENT}
action: upsert
- key: environment
value: ${env:ENVIRONMENT}
action: upsert
- key: service.name
value: ${env:SERVICE_NAME}
action: upsert

batch:
timeout: 10s
send_batch_size: 1024

exporters:
otlphttp/b14:
endpoint: ${env:OTEL_EXPORTER_OTLP_ENDPOINT}
tls:
insecure_skip_verify: true

service:
pipelines:
metrics:
receivers: [prometheus]
processors: [resource, batch]
exporters: [otlphttp/b14]

If metrics are token-gated (Option 2 above), add a bearer token to the scrape job instead of running the endpoint public:

config/otel-collector.yaml (bearer token)
receivers:
prometheus:
config:
scrape_configs:
- job_name: minio
scrape_interval: 10s
metrics_path: /minio/metrics/v3
authorization:
type: Bearer
credentials: ${env:MINIO_METRICS_TOKEN}
static_configs:
- targets:
- ${env:MINIO_HOST}:9000

The metric_relabel_configs keep filter scopes the pipeline to the MinIO namespace - it keeps minio_* and the up liveness series and drops the go_* runtime and scrape_* meta.

Environment Variables

.env
MINIO_HOST=localhost
MINIO_METRICS_TOKEN=your_bearer_token # Only if using Option 2
ENVIRONMENT=your_environment
SERVICE_NAME=your_service_name
OTEL_EXPORTER_OTLP_ENDPOINT=https://<your-tenant>.base14.io

Semconv version note: deployment.environment.name is the current OTel attribute (semantic conventions v1.27+, stable as of v1.41.0). Scout's UI filters on the lowercase environment key, so emit it alongside the OTel-native deployment.environment.name. The legacy deployment.environment is still accepted for backward compatibility.

Verify the Setup

Start the Collector and check for metrics within 60 seconds:

Verify metrics collection
# Check Collector logs for the MinIO scrape
docker logs otel-collector 2>&1 | grep -i "minio"

# Verify MinIO is live
curl -s http://localhost:9000/minio/health/live

# Check the v3 metrics endpoint directly
curl -s http://localhost:9000/minio/metrics/v3 \
| grep minio_cluster_health_capacity_usable_free_bytes

Troubleshooting

403 Forbidden on the metrics endpoint

Cause: Metrics are token-gated and no bearer token was supplied.

Fix:

  1. Generate a token: mc admin prometheus generate <alias>, then add it as authorization: { type: Bearer, credentials: ${env:MINIO_METRICS_TOKEN} } on the scrape job.
  2. Or set MINIO_PROMETHEUS_AUTH_TYPE=public on the MinIO server for tokenless metrics.

Wrong or empty metrics endpoint

Cause: Scraping a deprecated v2 path, or expecting per-bucket / replication detail on the default v3 endpoint.

Fix:

  1. Use /minio/metrics/v3, not the deprecated /minio/v2/metrics/{cluster,node,bucket} paths.
  2. The default v3 endpoint returns the minio_api_*, minio_system_*, minio_cluster_*, and minio_scanner_* families only. Per-bucket, replication, notification, ILM, and resource detail live at dedicated v3 sub-paths - add a scrape job per sub-path (for example /minio/metrics/v3/bucket/api) when you need that detail.

Connection refused on port 9000

Cause: The Collector cannot reach MinIO at the configured address.

Fix:

  1. Verify MinIO is running: docker ps | grep minio or mc admin info <alias>.
  2. Confirm the S3 API port responds: curl http://localhost:9000/minio/health/live.
  3. Check firewall rules if the Collector runs on a separate host.

Slow requests with no obvious cause

Cause: A slow drive or storage-bound saturation is dragging the cluster.

Look at: the Diagnostic and per-drive series - minio_system_drive_api_latency_micros (a slow drive localizes a slow cluster), minio_system_drive_perc_util / minio_system_drive_writes_await, and minio_system_cpu_avg_iowait for storage-bound CPU.

Fix:

  1. Correlate the slow drive's latency with minio_api_requests_ttfb_seconds_distribution.
  2. Replace or rebalance the drive if its utilization stays pinned.

No metrics appearing in Scout

Cause: Metrics are collected but not exported.

Fix:

  1. Check Collector logs for export errors: docker logs otel-collector.
  2. Verify OTEL_EXPORTER_OTLP_ENDPOINT is set correctly.
  3. Confirm the pipeline includes both the receiver and the exporter.

FAQ

Does this work with MinIO running in Kubernetes?

Yes. Set targets to the MinIO service DNS (for example minio.minio.svc.cluster.local:9000). For token-gated metrics, store the bearer token in a Kubernetes secret and reference it as the scrape credentials; or set MINIO_PROMETHEUS_AUTH_TYPE=public on the StatefulSet for tokenless metrics. The Collector can run as a sidecar or a Deployment.

How do I monitor a distributed MinIO cluster?

Scrape each MinIO node - add every node's :9000 to the scrape targets. The capacity, erasure-set, and per-drive series expand in a distributed deployment: minio_system_drive_* produces one series per drive and minio_cluster_erasure_set_* one series per set, so you see per-drive and per-set health rather than a single 1.

Should I use the v2 or v3 metrics endpoint?

Use v3 (/minio/metrics/v3). The /minio/v2/metrics/{cluster,node,bucket} endpoints are deprecated - still present in the release, but not for new deployments.

Do I need a bearer token, or can I scrape without auth?

Metrics are token-gated by default. Set MINIO_PROMETHEUS_AUTH_TYPE=public for tokenless scraping (handy on internal networks), or generate a token with mc admin prometheus generate and supply it as the scrape authorization credentials.

Where are per-bucket and replication metrics?

They are not on the default v3 endpoint. Per-bucket, replication, notification, ILM, and resource detail live at dedicated v3 sub-paths (for example /minio/metrics/v3/bucket/api and /minio/metrics/v3/replication). Add a scrape job per sub-path - and configure the corresponding feature - when you need that detail.

What's Next?

  • Create Dashboards: Explore pre-built dashboards or build your own. See Create Your First Dashboard.
  • Monitor More Components: Add monitoring for PostgreSQL, Redis, and other components.
  • Fine-tune Collection: Scope the scrape with metric_relabel_configs keep filters, and add a scrape job per /minio/metrics/v3 sub-path (bucket, replication, internode) when you need that detail.
Was this page helpful?