Kube-OVN News and Blog

From Metrics to Dashboards:Monitoring Kube-OVN with SUSE Observability

Written by Amol Kharche | Jun 15, 2026 5:35:01 AM

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

  1. Log in to SUSE Observability.
  2. Navigate to Dashboards.
  3. Select Create Dashboard.
  4. 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/