In our previous blog post, we explored how NetApp Harvest provides a single collection layer across your entire storage estate, whether you are using ONTAP on-prem or in the cloud across Google Cloud, Azure, AWS etc. We also walked through the set up for Google Cloud NetApp Volumes (GCNV) Flex Unified pools with ONTAP-mode enabled.
While unified collection is a massive operational win, realtime metrics availability is the key to improve incident response times and protect your mission critical application workloads.
Current monitoring tools often rely on five-minute polling intervals, which can obscure transient performance issues. Even GCNV metrics in Cloud Monitoring are sampled every five minutes. Imagine a sudden I/O microburst hits a core transactional database, a five-minute average will effectively mask the critical latency spike that caused the application timeout, leaving you without actionable data. By the time you see the stale data, you are already fielding customer complaints instead of preventing them.
This is where NetApp Harvest on GCNV provides real-time monitoring to catch and diagnose these transient bottlenecks exactly when they happen for your enterprise-critical workloads. NetApp Harvest provides you with real-time insights into performance, health, and status of your enterprise critical workloads, playing a vital role in digital security and risk management.
Let’s take a look at how you can plug this into your familiar Google Cloud Monitoring dashboards, or utilize monitoring tools like prometheus & grafana for even shorter collection intervals.
NetApp Harvest: Native integration with Google Cloud Monitoring
NetApp Harvest acts as a bridge to the tools you already trust. By utilizing an OpenTelemetry (OTel) exporter, Harvest takes the rich, granular performance data pulled from your GCNV instances and streams it directly into Google Cloud Monitoring.
This is a double win for your operations:
- First, you do not need to re-architect your applications or deploy any complex third-party tools.
- And second, your teams work in a familiar environment without having to get used to new systems and dashboards.
While Harvest is capable of supporting even sub-second collection intervals, our export cadence and metrics selection should respect Google’s ingestion rules. With Google Cloud Monitoring, the 5-minute sampling rate can be reduced down to as low as 5 seconds with this pipeline.
Best Practice: How often should harvest poll?
Our general recommendation is to set 1 minute as the default polling interval. Collecting more frequently puts additional load on ONTAP, and depending on the number of instances and counters being collected, ONTAP's APIs may not be able to respond quickly enough to meet a sub-minute schedule.
You can safely use sub-minute intervals for your critical workloads, by scoping your configuration deliberately. Limit sub-minute schedules to high-priority collectors and use object filtering to keep the instance set small. This gives you second-by-second insight exactly where it matters, without putting unnecessary pressure on ONTAP's management APIs across the rest of your estate.
This is exactly what we will do today. We will set configuration for KeyPerf - which is a small set of important metrics (including IOPS, latency, and throughput) at an interval of 10 seconds. While we will monitor Rest and EMS at the default interval of 3 minutes.
Although google managed prometheus allows 5-second granularity, the UI displays the data points at the granularity of 1 minute even when zoomed in. For sub-minute monitoring, we need to manually set the granularity on the metrics explorer by changing the min-interval (Or steps with PromQL) on the UI. This can bring it down to a granularity of 10s at the most. Instead, we can run a grafana instance that pulls data from the same prometheus endpoint, with no additional setup.
Understanding the architecture
By querying the GCNV ONTAP-mode API, NetApp Harvest surfaces granular performance metrics on a local Prometheus-compatible endpoint. A downstream OpenTelemetry Collector then scrapes this data to handle necessary filtering and processing. These metrics are subsequently streamed into Google Managed Prometheus (GMP), integrating directly into your Google Cloud Monitoring environment.
This architecture empowers your teams to utilize Metrics Explorer, PromQL, and alerting directly on Google Cloud UI.
Setting up Harvest on GCNV with Google MonitoringLet’s take a look at how you can set this up in minutes!
Prerequisites:
- Create Flex Unified storage pool with Ontap-mode
- Install Docker Engine & latest Go on a Linux host.
- Install Harvest (Also covered in the previous blog post)
Step 1: Configure Harvest
Please follow all the steps, from the previous blog post to get Harvest up and running, along with Prometheus.
For real time monitoring, Harvest lets you override the default polling schedule per collector using a custom config directory. Let’s set the KeyPerf data interval to 10 seconds (which we would later see in Grafana), that drives capacity and performance decisions. Ensure “harvest.yml” points to the new configuration.
harvest.yml:
Exporters:
prometheus1:
exporter: Prometheus
addr: 0.0.0.0
port_range: 2000-2030
Defaults:
use_insecure_tls: true
exporters:
- prometheus1
Pollers:
gcnv-pool-1:
datacenter: <location>
addr: netapp.googleapis.com/v1/projects/<project_name>/locations/<location>/storagePools/<storage_pool_name>/ontap
gcnv_ontap_mode: true
credentials_script:
path: /home/rishikec_netapp_com/harvest/gcnv-token.sh
schedule: 5m
timeout: 10s
collectors:
- Rest
- KeyPerf
- Ems
exporters:
- prometheus1
conf_path: customconf:conf
Step 2: Modify configuration file as per your enterprise needs
Let’s copy the default configuration file in a custom directory and then edit it.
mkdir -p customconf/keyperf
cp ~/harvest/conf/keyperf/default.yaml ~/harvest/customconf/keyperf/default.yaml
customconf/keyperf/default.yaml:
collector: KeyPerf
# Order here matters!
schedule:
- counter: 24h
- data: 10s
objects:
Aggregate: aggr.yaml
CIFSvserver: cifs_vserver.yaml
Cluster: cluster.yaml
EthernetSwitchPort: ethernet_switch_port.yaml
FlexCache: flexcache.yaml
LIF: lif.yaml
Lun: lun.yaml
Namespace: namespace.yaml
NFSv3: nfsv3.yaml
NFSv41: nfsv4_1.yaml
NFSv4: nfsv4.yaml
SystemNode: system_node.yaml
Volume: volume.yaml
Restart harvest with the new configuration set & verify.
Step 3: Configuring the OpenTelemetry Collector
Before tuning the OTel configuration, it helps to understand platform rules documented in Google Cloud Monitoring quotas:
https://cloud.google.com/monitoring/quotas
- Minimum write interval per time series — ≥ 5 seconds
- Labels per custom / external / workload metric — 30
- Labels per Prometheus (GMP) metric — 200
- Active time series from Prometheus per monitored resource — 1,000,000
- Active time series from custom / external / workload metrics — 200,000 each
- Max time series per write request — 200
What this means for our integration:
- OTel scrape interval to GMP must be ≥ 5s, regardless of Harvest poll rate.
- Use the managed prometheus exporter, not the legacy googlecloud exporter to allow up to 200 Labels. Harvest metrics carry many labels (volume name, node, SVM, aggregate) and will exceed 30.
- Using managed prometheus also sets our active time series cap at 1M.
- GMP bills per sample ingested, so filtering noisy or redundant metrics before export directly reduces cost.
Now, Create an otel-collector-config.yaml configuration file.
The OpenTelemetry Collector is the bridge between Harvest's Prometheus endpoint and Google Managed Prometheus. OTel docs can be found here:
https://opentelemetry.io/docs/
OTel scrapes :2000/metrics, applies a lightweight processing pipeline to clean up labels and filter noise, then pushes to GMP. Three things matter in this config: the receiver (what to scrape), the processors (what to fix), and the exporter (where to send).
receivers:
prometheus:
config:
scrape_configs:
- job_name: harvest
scrape_interval: 10s
scrape_timeout: 10s
honor_timestamps: false
static_configs:
- targets: ['localhost:2000']
exporters:
googlemanagedprometheus:
project: <project_name>
metric:
add_metric_suffixes: false
processors:
memory_limiter:
check_interval: 10s
limit_percentage: 80
spike_limit_percentage: 15
resourcedetection:
detectors: [gcp]
filter/drop_noisy:
metrics:
exclude:
match_type: regexp
metric_names:
- ".*_labels$"
- "^metadata_.*"
transform/collision:
metric_statements:
- context: resource
statements:
- set(attributes["service.instance.id"], "<host_name>:2000")
- context: datapoint
statements:
- set(attributes["exported_cluster"], attributes["cluster"])
- delete_key(attributes, "cluster")
batch:
send_batch_size: 500
timeout: 10s
service:
telemetry:
logs:
level: info
pipelines:
metrics:
receivers: [prometheus]
processors: [memory_limiter, filter/drop_noisy, transform/collision, resourcedetection, batch]
exporters: [googlemanagedprometheus]
Key elements in the pipeline:
- memory_limiter: Every 10 seconds OTel checks its own memory usage and available RAM. This to prevent OOM crashes. It slows down on its own based on the set configuration.
- filter/drop_noisy: We exclude *_labels metrics — these carry ONTAP object metadata as label key-value pairs. This can exceed the 200 label limit.
- transform/collision: GMP reserves certain label names — cluster, job, instance, location, namespace — because it uses them internally on the monitored resource descriptor. If your metrics arrive with a label named cluster, GMP would drop it or create a descriptor collision, and you lose the label entirely. The fix is to rename it.
- resource_detection: This queries the GCE metadata server and attaches the VM's identity — project_id, instance_id, zone — to every metric as the monitored_resource.
- honor_timestamps: false: OTel scrapes every 10s but based on your config, Harvest collectors (Ex. rest, ems) may refresh every few minutes. In this case OTel would send the same timestamp to GMP multiple times, which would be rejected. Setting this to false tells OTel to stamp each scrape with the current time, ensuring monotonically increasing timestamps.
Note: The order of the processors can help you optimize your collection. Keeping memory_limiter first prevents OOM crashes from propagating into the pipeline. Further, ensuring you filter before transforming avoids unnecessary CPU usage for metrics you are going to drop.
Step 4: Run OTel & Check if everything is up and running
docker run -d \
--name otelcol \
--restart=always \
--network host \
-v /home/rishikec_netapp_com/harvest/otel/otel.yaml:/otel.yaml \
otel/opentelemetry-collector-contrib:0.105.0 \
--config=/otel.yaml
Let’s make sure everything is up and running.
$ docker ps
$ docker logs otelcol # Ensure Otel logs are clean.
Step 5: Monitor!
Go ahead and check the UI on https://console.cloud.google.com/monitoring/metrics-explorer
Select Prometheus Target as the resource type. You will see metrics grouped by their natural categories — Volume, Node, Cluster, SVM — reflecting the ONTAP object hierarchy Harvest uses.
Let’s take a look at volume_nfs_write_ops.
You can also utilize PromQL to search for specific time series!
We can set the interval/steps to 10s manually and see that granularity on the UI.
While this gives us great visibility, we can see organized dashboards, and even granular intervals using Grafana. Grafana is already up at http://localhost:3000 (or your bastion's external IP on port 3000). No extra setup is required!
A note on metric descriptor naming:
Metrics appear in the picker as Prometheus/metric_name/unknown. The /unknown suffix is the unit field in GMP's metric descriptor. Harvest's Prometheus endpoint does not emit OpenMetrics # UNIT hints, so GMP cannot infer the unit and displays unknown.
This is cosmetic only — metric names, labels, values, and PromQL queries are fully correct and unaffected.
What you achieved today!
Congratulations, you have a fully operational, real-time observability pipeline running natively on Google Cloud! Now your team sees every performance and capacity metric time, queryable in PromQL, through the same Cloud Monitoring workflows your teams already use.
This is just the foundation, build on it!
- Alerts: Setup alerts on latency & space metrics to catch performance degradation and capacity exhaustion!
- Scale: Scale across pools, just add a new poller in Harvest and each GCNV storage pool is monitored in real time; OTel scrapes all of them, and GMP aggregates across your entire storage estate!
- Dashboards: Create permanent charts and add it to custom dashboards to capture relevant Harvest metrics for your application and workflow needs directly on Google Cloud Monitoring!
- MCP Server: Leverage Harvest MCP to empower your monitoring with AI!
Get started with real-time monitoring with Harvest on GCNV today!
If you haven’t already, start with the first part: NetApp Harvest on Google Cloud NetApp Volumes: Get started today!
Get involved and stay connected!