KubeOVN is an enterprise-grade Kubernetes networking CNI plugin that leverages OVN (Open Virtual Network) and OVS (Open vSwitch) — the same networking stack used in OpenStack and VMware NSX-T — to provide rich networking capabilities for Kubernetes clusters. Unlike simpler CNIs such as Flannel, KubeOVN delivers subnet management, static IP assignment, VPC tenant isolation, built-in L4 load balancing, per-pod QoS, and NAT policies all in one stack. That richness comes with a more complex failure surface: OVN NB/SB databases, OVS bridges, per-node daemon pods, and the kube-ovn-controller must all be healthy simultaneously for pod networking to work.
This tutorial shows you how to monitor KubeOVN's critical health layers with Vigilmon so you detect networking failures before they become pod connectivity outages.
Why KubeOVN needs external monitoring
KubeOVN's multi-layer architecture means failures can be localized (one node's OVS bridge goes down) or catastrophic (OVN Northbound DB leader election fails and all network provisioning stops). In either case, the failure is often not immediately visible through Kubernetes pod status — pods can show Running while OVN flow programming has stalled and new traffic rules are not being installed.
External monitoring catches what Kubernetes internal probes miss:
- kube-ovn-controller crash — the controller managing logical OVN network objects exits; new pods, services, and subnets get no OVN programming; existing flows continue working temporarily but changes stop being applied
- OVN NB DB leader election failure — the Northbound database stores logical network topology; a leader election failure stops all KubeOVN network provisioning operations
- OVN SB DB failure — the Southbound database stores physical bindings and OpenFlow rules; an SB failure halts flow programming to all nodes
- kube-ovn-daemon missing on a node — without the per-node daemon, that node's OVS bridge cannot be programmed; pods scheduled there get no working network interfaces
- OVS bridge down — if the
br-intorbr-ovnbridge on any node goes down, all pods on that node lose network connectivity - Subnet IP pool exhaustion — a subnet approaching 100% IP utilization starts failing to schedule new pods in its namespace
- OVN flow programming lag — high pod churn or load causes OVN southbound programming to fall behind; new pod flows are not installed within acceptable time
What you'll need
- A Kubernetes cluster with KubeOVN installed (namespace:
kube-systemorkube-ovn) kubectlaccess with permission to read KubeOVN resources- A free Vigilmon account
Step 1: Expose the kube-ovn-monitor health endpoint
KubeOVN ships a built-in monitoring component (kube-ovn-monitor) that exposes metrics and a health endpoint. Use it as your primary health probe:
# Verify kube-ovn-monitor is running
kubectl get pods -n kube-system -l app=kube-ovn-monitor
# Check the monitor service
kubectl get svc kube-ovn-monitor -n kube-system
# Test the metrics endpoint
kubectl port-forward -n kube-system svc/kube-ovn-monitor 10661:10661 &
curl http://localhost:10661/metrics | grep "^kube_ovn" | head -20
Expose the monitor externally:
# kube-ovn-monitor-nodeport.yaml
apiVersion: v1
kind: Service
metadata:
name: kube-ovn-monitor-external
namespace: kube-system
spec:
type: NodePort
selector:
app: kube-ovn-monitor
ports:
- port: 10661
targetPort: 10661
nodePort: 30661
protocol: TCP
Or route via Ingress:
# kube-ovn-monitor-ingress.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: kube-ovn-monitor-health
namespace: kube-system
spec:
rules:
- host: kube-ovn-monitor.internal.example.com
http:
paths:
- path: /metrics
pathType: Prefix
backend:
service:
name: kube-ovn-monitor
port:
number: 10661
Step 2: Monitor the kube-ovn-controller health
The controller is the heart of KubeOVN — it translates Kubernetes network objects into OVN logical topology. Add an HTTP monitor targeting its health endpoint:
# Find the controller health port
kubectl describe deployment kube-ovn-controller -n kube-system | grep -A5 Ports
# Expose it
kubectl expose deployment kube-ovn-controller \
--name=kube-ovn-controller-health \
--type=NodePort \
--port=10660 \
--target-port=10660 \
-n kube-system
In Vigilmon:
- Go to Monitors → New Monitor → HTTP / HTTPS
- URL:
http://kube-ovn.internal.example.com:10660/healthz - Check interval: 1 minute
- Expected response: status code
200 - Name:
kube-ovn-controller health
When the controller crashes, OVN logical network updates stop — no new Subnets, no IP allocations from new Pods, no VPC routing changes. Existing traffic flows continue briefly (OVN southbound flows persist), but the cluster becomes incapable of network provisioning changes.
Step 3: Monitor OVN database health
OVN's NB (Northbound) and SB (Southbound) databases are clustered OVSDB instances. Their health is fundamental — a leader election failure blocks everything.
Check OVN NB database
# Check NB DB pods
kubectl get pods -n kube-system -l app=ovn-central
# Check NB DB cluster status
kubectl exec -n kube-system \
$(kubectl get pod -n kube-system -l app=ovn-central -o name | head -1) \
-- ovn-appctl -t /var/run/ovn/ovnnb_db.ctl cluster/status OVN_Northbound
# Check SB DB cluster status
kubectl exec -n kube-system \
$(kubectl get pod -n kube-system -l app=ovn-central -o name | head -1) \
-- ovn-appctl -t /var/run/ovn/ovnsb_db.ctl cluster/status OVN_Southbound
Set up a Vigilmon heartbeat to monitor OVN DB cluster health:
# ovn-db-health-check.yaml
apiVersion: batch/v1
kind: CronJob
metadata:
name: ovn-db-health-check
namespace: kube-system
spec:
schedule: "*/5 * * * *"
jobTemplate:
spec:
template:
spec:
serviceAccountName: kube-ovn-health-checker
hostNetwork: true
restartPolicy: OnFailure
tolerations:
- operator: Exists
nodeSelector:
ovn-nb-leader: "true"
containers:
- name: checker
image: kubeovn/kube-ovn:latest
env:
- name: VIGILMON_HEARTBEAT_URL
valueFrom:
secretKeyRef:
name: vigilmon-secrets
key: ovn-db-heartbeat
command:
- /bin/sh
- -c
- |
set -e
# Check NB DB leader
NB_STATUS=$(ovn-appctl -t /var/run/ovn/ovnnb_db.ctl \
cluster/status OVN_Northbound 2>&1 | grep "^Status:")
echo "NB DB: $NB_STATUS"
echo "$NB_STATUS" | grep -q "leader" || exit 1
# Check SB DB leader
SB_STATUS=$(ovn-appctl -t /var/run/ovn/ovnsb_db.ctl \
cluster/status OVN_Southbound 2>&1 | grep "^Status:")
echo "SB DB: $SB_STATUS"
echo "$SB_STATUS" | grep -q "leader" || exit 1
curl -fsS "$VIGILMON_HEARTBEAT_URL" > /dev/null
echo "OVN DBs healthy. Heartbeat sent."
In Vigilmon:
- Go to Monitors → New Monitor → Heartbeat
- Name:
ovn-db-cluster-health - Expected interval: 5 minutes
- Grace period: 3 minutes
Step 4: Monitor kube-ovn-daemon DaemonSet coverage
The kube-ovn-daemon runs on every node, managing OVS and local network programming. A missing daemon means pods on that node get no OVN flow installation.
# kube-ovn-daemon-coverage-check.yaml
apiVersion: batch/v1
kind: CronJob
metadata:
name: kube-ovn-daemon-coverage
namespace: kube-system
spec:
schedule: "*/5 * * * *"
jobTemplate:
spec:
template:
spec:
serviceAccountName: kube-ovn-health-checker
restartPolicy: OnFailure
containers:
- name: checker
image: bitnami/kubectl:latest
env:
- name: VIGILMON_HEARTBEAT_URL
valueFrom:
secretKeyRef:
name: vigilmon-secrets
key: kube-ovn-daemon-heartbeat
command:
- /bin/sh
- -c
- |
set -e
DESIRED=$(kubectl get daemonset kube-ovn-daemon -n kube-system \
-o jsonpath='{.status.desiredNumberScheduled}')
READY=$(kubectl get daemonset kube-ovn-daemon -n kube-system \
-o jsonpath='{.status.numberReady}')
if [ "$READY" -lt "$DESIRED" ]; then
echo "ERROR: kube-ovn-daemon coverage $READY/$DESIRED nodes"
exit 1
fi
curl -fsS "$VIGILMON_HEARTBEAT_URL" > /dev/null
echo "kube-ovn-daemon $READY/$DESIRED nodes covered."
Step 5: Monitor subnet IP pool utilization
KubeOVN manages per-subnet IP pools. When a subnet approaches full utilization, new pods in that namespace fail to start with no available IP errors. Set up a proactive alert before you hit the ceiling.
# List subnets and their IP utilization
kubectl get subnet -o json | jq -r \
'.items[] | "\(.metadata.name): \(.status.v4UsingIPs)/\(.status.v4AvailableIPs) used"'
# Find subnets above 80% utilization
kubectl get subnet -o json | jq -r \
'.items[] | select(
(.status.v4UsingIPs + .status.v4AvailableIPs) > 0 and
(.status.v4UsingIPs / (.status.v4UsingIPs + .status.v4AvailableIPs)) > 0.8
) | "\(.metadata.name): ALERT - high IP utilization"'
Add this to a CronJob that pings the heartbeat only when all subnets are below 90% utilization:
# subnet-ip-utilization-check.yaml
apiVersion: batch/v1
kind: CronJob
metadata:
name: subnet-ip-utilization-check
namespace: kube-system
spec:
schedule: "*/10 * * * *"
jobTemplate:
spec:
template:
spec:
serviceAccountName: kube-ovn-health-checker
restartPolicy: OnFailure
containers:
- name: checker
image: bitnami/kubectl:latest
env:
- name: VIGILMON_HEARTBEAT_URL
valueFrom:
secretKeyRef:
name: vigilmon-secrets
key: subnet-utilization-heartbeat
command:
- /bin/sh
- -c
- |
set -e
OVERLOADED=$(kubectl get subnet -o json | jq '
[.items[] |
select(
(.status.v4UsingIPs + .status.v4AvailableIPs) > 0 and
(.status.v4UsingIPs /
(.status.v4UsingIPs + .status.v4AvailableIPs)) > 0.9
)
] | length')
if [ "$OVERLOADED" -gt 0 ]; then
echo "ERROR: $OVERLOADED subnets above 90% IP utilization"
exit 1
fi
curl -fsS "$VIGILMON_HEARTBEAT_URL" > /dev/null
Step 6: Monitor pod network connectivity end-to-end
The ultimate test of KubeOVN health is whether cross-node pod-to-pod connectivity works. A pod networking test that runs periodically and pings the heartbeat on success gives you an authoritative end-to-end check.
# pod-connectivity-probe.yaml
apiVersion: batch/v1
kind: CronJob
metadata:
name: pod-connectivity-probe
namespace: kube-system
spec:
schedule: "*/5 * * * *"
jobTemplate:
spec:
template:
spec:
restartPolicy: Never
containers:
- name: probe
image: curlimages/curl:latest
env:
- name: TARGET_SVC
value: "kube-dns.kube-system.svc.cluster.local"
- name: VIGILMON_HEARTBEAT_URL
valueFrom:
secretKeyRef:
name: vigilmon-secrets
key: pod-connectivity-heartbeat
command:
- /bin/sh
- -c
- |
set -e
# Test DNS resolution (which requires pod network)
nslookup "$TARGET_SVC" > /dev/null
# Test HTTP connectivity within cluster
curl -fsS --max-time 5 \
"http://kube-ovn-monitor.kube-system.svc.cluster.local:10661/metrics" \
> /dev/null
curl -fsS "$VIGILMON_HEARTBEAT_URL" > /dev/null
echo "Pod connectivity healthy. Heartbeat sent."
Step 7: Configure alert channels
KubeOVN failures have direct user impact — they break pod networking. Route alerts to your network/platform on-call immediately.
Critical (page immediately)
Assign to your PagerDuty integration:
kube-ovn-controller health(HTTP)ovn-db-cluster-health(heartbeat)pod-connectivity-probe(heartbeat)
Warning (Slack notification)
Assign to your #platform-networking Slack channel:
kube-ovn-daemon-coverage(heartbeat)subnet-ip-utilization-check(heartbeat)
In Vigilmon, go to Alert Channels → New Channel for each destination and assign to the appropriate monitors.
Step 8: Create a network infrastructure status page
- In Vigilmon, go to Status Pages → New Status Page
- Name: "KubeOVN Network Infrastructure"
- Add monitors grouped by layer:
- Control Plane:
kube-ovn-controller health,ovn-db-cluster-health - Node Layer:
kube-ovn-daemon-coverage - Connectivity:
pod-connectivity-probe - Capacity:
subnet-ip-utilization-check
- Control Plane:
- Share with the network and platform engineering teams
Summary
| Monitor | Type | What it catches |
|---|---|---|
| kube-ovn-controller /healthz | HTTP | Controller crash, no OVN provisioning |
| ovn-db-cluster-health | Heartbeat | NB/SB DB leader election failure |
| kube-ovn-daemon-coverage | Heartbeat | Missing daemon on node(s) |
| pod-connectivity-probe | Heartbeat | Cross-node pod networking broken |
| subnet-ip-utilization-check | Heartbeat | Subnet IP pool >90% full |
| kube-ovn-monitor metrics | HTTP | Monitor component crash |
KubeOVN's rich feature set means a deeper dependency graph than simpler CNIs. Any layer — controller, OVN databases, per-node daemon, or OVS bridges — can fail independently. Multi-layer monitoring with Vigilmon ensures you detect failures at each level and correlate them to their root cause quickly.
Get started free at vigilmon.online — no credit card required, first monitor running in under two minutes.