PRE-REQUISITES:
1 - SUSE Observability cluster with an exposed OpenTelemetry Collector ingress endpoint.
2 - OpenTelemetry collector installed on SUSE virtualization cluster (>=1.7.x).
3 - Kube-OVN Operator (Experimental) on SUSE virtualization, Refer : https://docs.harvesterhci.io/v1.8/advanced/addons/kubeovn-operator
PROCEDURE:
Kube-OVN exposes metrics through its own services in the kube-system namespace. These need to be scraped and forwarded to SUSE Observability via the OpenTelemetry collector. For example.
http://kube-ovn-controller.kube-system.svc:10660/metrics
http://kube-ovn-monitor.kube-system.svc:10661/metrics
http://kube-ovn-cni.kube-system.svc:10665/metrics
http://kube-ovn-pinger.kube-system.svc:8080/metrics
We need to install OpenTelemetry collector on SUSE Virtualization cluster. Deploy the OpenTelemetry Collector to Scrape Kube-OVN Metrics.
Add the Helm Repository and create Namespace.
helm repo add open-telemetry https://open-telemetry.github.io/opentelemetry-helm-charts
helm repo update
kubectl create namespace open-telemetry
The OTel collector uses bearer token authentication when sending data to SUSE Observability. To create TOKEN refer https://documentation.suse.com/cloudnative/suse-observability/latest/en/setup/otel/getting-started/getting-started-k8s-operator.html#_create_a_service_token.
Store your service token as a Kubernetes secret: Create the API Key Secret.
kubectl create secret generic suse-observability-api-key --from-literal=API_KEY=<YOUR_SERVICE_TOKEN> -n open-telemetry
Create the Helm Values File
cat << EOF > otel-kubeovn-values.yaml
mode: deployment
image:
repository: ghcr.io/open-telemetry/opentelemetry-collector-releases/opentelemetry-collector-k8s
replicaCount: 1
ports:
metrics:
enabled: true
clusterRole:
create: true
rules:
- apiGroups: [""]
resources: ["endpoints", "pods", "services", "nodes"]
verbs: ["get", "list", "watch"]
- apiGroups: [""]
resources: ["secrets"]
verbs: ["get"]
extraEnvs:
- name: API_KEY
valueFrom:
secretKeyRef:
name: suse-observability-api-key
key: API_KEY
config:
extensions:
health_check: {}
bearertokenauth:
scheme: SUSEObservability
token: "${env:API_KEY}"
receivers:
prometheus:
config:
scrape_configs:
- job_name: 'kube-ovn-controller'
scrape_interval: 30s
kubernetes_sd_configs:
- role: endpoints
namespaces:
names:
- kube-system
selectors:
- role: endpoints
field: "metadata.name=kube-ovn-controller"
relabel_configs:
- source_labels: [__meta_kubernetes_endpoint_port_name]
action: keep
regex: metrics
- source_labels: [__meta_kubernetes_pod_name]
target_label: k8s_pod_name
- source_labels: [__meta_kubernetes_namespace]
target_label: k8s_namespace_name
- source_labels: [__meta_kubernetes_endpoint_node_name]
target_label: k8s_node_name
- job_name: 'kube-ovn-monitor'
scrape_interval: 30s
kubernetes_sd_configs:
- role: endpoints
namespaces:
names:
- kube-system
selectors:
- role: endpoints
field: "metadata.name=kube-ovn-monitor"
relabel_configs:
- source_labels: [__meta_kubernetes_endpoint_port_name]
action: keep
regex: metrics
- source_labels: [__meta_kubernetes_pod_name]
target_label: k8s_pod_name
- source_labels: [__meta_kubernetes_namespace]
target_label: k8s_namespace_name
- source_labels: [__meta_kubernetes_endpoint_node_name]
target_label: k8s_node_name
- job_name: 'kube-ovn-cni'
scrape_interval: 30s
kubernetes_sd_configs:
- role: endpoints
namespaces:
names:
- kube-system
selectors:
- role: endpoints
field: "metadata.name=kube-ovn-cni"
relabel_configs:
- source_labels: [__meta_kubernetes_endpoint_port_name]
action: keep
regex: metrics
- source_labels: [__meta_kubernetes_pod_name]
target_label: k8s_pod_name
- source_labels: [__meta_kubernetes_namespace]
target_label: k8s_namespace_name
- source_labels: [__meta_kubernetes_endpoint_node_name]
target_label: k8s_node_name
- job_name: 'kube-ovn-pinger'
scrape_interval: 30s
kubernetes_sd_configs:
- role: endpoints
namespaces:
names:
- kube-system
selectors:
- role: endpoints
field: "metadata.name=kube-ovn-pinger"
relabel_configs:
- source_labels: [__meta_kubernetes_pod_name]
target_label: k8s_pod_name
- source_labels: [__meta_kubernetes_namespace]
target_label: k8s_namespace_name
- source_labels: [__meta_kubernetes_endpoint_node_name]
target_label: k8s_node_name
processors:
memory_limiter:
check_interval: 5s
limit_percentage: 80
spike_limit_percentage: 25
batch:
send_batch_size: 1000
timeout: 10s
resource:
attributes:
- key: k8s_cluster_name
value: "CLUSTER_NAME" # Replcae your clustername
action: upsert
exporters:
debug:
verbosity: basic
otlp/suse-observability:
auth:
authenticator: bearertokenauth
endpoint: "otlp-stackstate.example.com:443"
tls:
insecure_skip_verify: true
service:
extensions:
- health_check
- bearertokenauth
pipelines:
metrics:
receivers:
- prometheus
processors:
- memory_limiter
- batch
- resource
exporters:
- debug
- otlp/suse-observability
EOF
Install the Otel Collector
helm upgrade --install opentelemetry-collector open-telemetry/opentelemetry-collector --values otel-kubeovn-values.yaml
Verify the logs.
kubectl -n open-telemetry logs opentelemetry-collector-58f95f7896-64hh6 -f
2026-06-08T11:52:29.998Z info Metrics {"resource": {"host.name": "harvester-3", "k8s.namespace.name": "open-telemetry", "k8s.node.ip": "192.168.122.155", "k8s.node.name": "harvester-3", "k8s.pod.ip": "10.52.1.36", "k8s.pod.name": "opentelemetry-collector-58f95f7896-64hh6", "service.instance.id": "57b07a46-ec10-4ad1-a840-c719546a0aa7", "service.name": "otelcol-k8s", "service.version": "0.153.0"}, "otelcol.component.id": "debug", "otelcol.component.kind": "exporter", "otelcol.signal": "metrics", "resource metrics": 2, "metrics": 315, "data points": 946}
2026-06-08T11:52:39.995Z info Metrics {"resource": {"host.name": "harvester-2", "k8s.namespace.name": "open-telemetry", "k8s.node.ip": "192.168.122.155", "k8s.node.name": "harvester-2", "k8s.pod.ip": "10.52.1.36", "k8s.pod.name": "opentelemetry-collector-58f95f7896-64hh6", "service.instance.id": "57b07a46-ec10-4ad1-a840-c719546a0aa7", "service.name": "otelcol-k8s", "service.version": "0.153.0"}, "otelcol.component.id": "debug", "otelcol.component.kind": "exporter", "otelcol.signal": "metrics", "resource metrics": 5, "metrics": 901, "data points": 1246}
Verify Metrics in SUSE Observability
Navigate to Metrics in the SUSE Observability UI and search for kube_ovn_

Successful ingestion confirms that Kube-OVN metrics are being collected and forwarded to SUSE Observability.
Visualizing Kube-OVN Metrics in SUSE Observability
After the OpenTelemetry Collector has been configured and Kube-OVN metrics are successfully flowing into SUSE Observability, you can create a custom dashboard to monitor the health and performance of the Kube-OVN networking stack.
Create a New Dashboard
- Log in to SUSE Observability.
- Navigate to Dashboards.
- Select Create Dashboard.
- Once Dashboard created, Add widget into dashboard.
If you want to see total subnet created in kube-OVN use below query.
sum(kube_ovn_logical_switch_ports_num) by (logical_switch_name)
Some of the sample queries listed below.
Virtual Machine RX and TX Traffic per Interface
sum(delta(kube_ovn_interface_rx_bytes[5m])) by (interfaceName)
sum(delta(kube_ovn_interface_tx_bytes[5m])) by (interfaceName)
Logical Switch Port Count
kube_ovn_logical_switch_ports_num
Virtual Machine RX TX Dropped Packets (errors)
sum(delta(kube_ovn_interface_rx_dropped[5m])) by (interfaceName)
sum(delta(kube_ovn_interface_tx_dropped[5m])) by (interfaceName)
Total Active VM Interfaces
count(kube_ovn_interface_rx_packets > 0)
DNS Latency
(sum(delta(pinger_internal_dns_latency_ms_sum[5m])) by (nodeName))
/
(sum(delta(pinger_internal_dns_latency_ms_count[5m])) by (nodeName))
An example Kube-OVN dashboard:

Additional documentation about exposed metrics can be found at https://kubeovn.github.io/docs/stable/en/reference/metrics/