tutorial

How to Monitor OpenYurt Edge Nodes and Cloud-Edge Tunnels with Vigilmon

OpenYurt extends Kubernetes to edge computing scenarios — running workloads on edge nodes that may have intermittent connectivity to the cloud control plane....

OpenYurt extends Kubernetes to edge computing scenarios — running workloads on edge nodes that may have intermittent connectivity to the cloud control plane. This architecture introduces failure modes that standard Kubernetes monitoring simply can't catch: edge nodes going autonomous, cloud-edge tunnels degrading silently, and node pool health diverging from what kubectl reports.

In this tutorial you'll set up comprehensive uptime monitoring for your OpenYurt deployment using Vigilmon — free tier, no credit card required.


Why OpenYurt deployments need external monitoring

OpenYurt's edge autonomy model means your cluster can look healthy to the central control plane while edge nodes are serving stale data, have lost tunnel connectivity, or have fallen back to autonomous operation without anyone noticing.

Key failure modes that internal probes miss:

  • Cloud-edge tunnel degradation — the raven or yurt-tunnel-server component loses connectivity; edge pods stay Running, but traffic from the cloud can no longer reach them
  • Edge node autonomy triggered silentlyYurtHub enables autonomous mode when the API server is unreachable; workloads keep running but management plane visibility is severed
  • NodePool divergence — an entire pool of edge nodes falls behind on scheduling without the central dashboard flagging it
  • YurtAppDaemon/YurtAppSet rollout failures — edge-specific DaemonSet equivalents stall on unreachable nodes, causing partial rollouts that appear complete from the control plane
  • Raven gateway unavailability — east-west traffic between edge node pools fails when the L3 gateway goes down, even though pods on individual nodes report healthy
  • DNS resolution at the edge — edge-local DNS servers diverge from the cloud; services resolve to stale endpoints

External monitoring from multiple geographic regions is the only reliable way to observe what the edge is actually serving to end users.


What you'll need

  • An OpenYurt cluster with at least one edge node pool
  • Edge nodes or services exposed via a public or VPN-accessible endpoint
  • A free Vigilmon account (sign up takes 30 seconds)

Step 1: Add a health endpoint to your edge workloads

OpenYurt workloads are regular Kubernetes pods. Before monitoring, ensure your application exposes a /health endpoint and is deployed as a YurtAppSet or standard Deployment with proper tolerations.

# edge-app-deployment.yaml
apiVersion: apps.openyurt.io/v1alpha1
kind: YurtAppSet
metadata:
  name: edge-api
  namespace: production
spec:
  selector:
    matchLabels:
      app: edge-api
  workloadTemplate:
    deploymentTemplate:
      metadata:
        labels:
          app: edge-api
      spec:
        replicas: 2
        template:
          metadata:
            labels:
              app: edge-api
          spec:
            tolerations:
              - key: node.kubernetes.io/unreachable
                operator: Exists
                effect: NoExecute
                tolerationSeconds: 300
            containers:
              - name: edge-api
                image: your-registry/edge-api:latest
                ports:
                  - containerPort: 8080
                livenessProbe:
                  httpGet:
                    path: /health
                    port: 8080
                  initialDelaySeconds: 10
                  periodSeconds: 30
                readinessProbe:
                  httpGet:
                    path: /health
                    port: 8080
                  initialDelaySeconds: 5
                  periodSeconds: 10
  topology:
    pools:
      - name: edge-pool-us-west
        nodeSelectorTerm:
          matchExpressions:
            - key: apps.openyurt.io/nodepool
              operator: In
              values:
                - edge-pool-us-west
        replicas: 2

A minimal health handler in Node.js:

// health.js
app.get('/health', (req, res) => {
  res.json({
    status: 'ok',
    node: process.env.NODE_NAME || 'unknown',
    pool: process.env.NODE_POOL || 'unknown',
    timestamp: new Date().toISOString(),
  });
});

Step 2: Expose your edge services externally

Edge nodes often sit behind NAT or private networks. Use one of these patterns to expose them for external monitoring:

Option A: LoadBalancer Service (cloud edge)

apiVersion: v1
kind: Service
metadata:
  name: edge-api-svc
  namespace: production
spec:
  type: LoadBalancer
  selector:
    app: edge-api
  ports:
    - protocol: TCP
      port: 80
      targetPort: 8080

Option B: NodePort with firewall rule (bare-metal edge)

apiVersion: v1
kind: Service
metadata:
  name: edge-api-svc
  namespace: production
spec:
  type: NodePort
  selector:
    app: edge-api
  ports:
    - protocol: TCP
      port: 8080
      nodePort: 30080

Then open port 30080 on your edge node's firewall:

# On the edge node
sudo ufw allow 30080/tcp

Step 3: Monitor the cloud-edge tunnel endpoint

The yurt-tunnel-server is the backbone of OpenYurt's cloud-to-edge communication. Monitor it directly.

Find the tunnel server's external address:

kubectl get svc -n kube-system | grep yurt-tunnel-server
# NAME                    TYPE           CLUSTER-IP      EXTERNAL-IP     PORT(S)
# yurt-tunnel-server      LoadBalancer   10.96.100.50    203.0.113.10    10250:31250/TCP,10255:31255/TCP

The tunnel server exposes a metrics endpoint:

curl http://<tunnel-server-ip>:10251/metrics | grep yurt_tunnel

Create a lightweight proxy to expose tunnel health as an HTTP endpoint your monitoring can poll:

// tunnel-health-proxy/main.go
package main

import (
    "encoding/json"
    "fmt"
    "net/http"
    "os/exec"
)

type TunnelStatus struct {
    Status         string `json:"status"`
    ConnectedNodes int    `json:"connected_nodes"`
}

func healthHandler(w http.ResponseWriter, r *http.Request) {
    // Check that yurt-tunnel-agent pods are running
    cmd := exec.Command("kubectl", "get", "pods", "-n", "kube-system",
        "-l", "k8s-app=yurt-tunnel-agent", "--field-selector=status.phase=Running",
        "-o", "jsonpath={.items[*].status.phase}")
    out, err := cmd.Output()
    if err != nil {
        http.Error(w, "tunnel check failed", http.StatusServiceUnavailable)
        return
    }

    status := TunnelStatus{
        Status:         "ok",
        ConnectedNodes: len(string(out)),
    }
    w.Header().Set("Content-Type", "application/json")
    json.NewEncoder(w).Encode(status)
}

func main() {
    http.HandleFunc("/health", healthHandler)
    fmt.Println("Tunnel health proxy listening on :9090")
    http.ListenAndServe(":9090", nil)
}

Step 4: Add a Vigilmon HTTP monitor for the edge service

Log in to Vigilmon and navigate to Monitors → Add Monitor.

| Field | Value | |-------|-------| | Monitor type | HTTP | | Name | OpenYurt edge-api (us-west pool) | | URL | http://<edge-node-ip>:30080/health (or your LoadBalancer IP) | | Check interval | 1 minute | | HTTP method | GET | | Expected status | 200 | | Response must contain | "status":"ok" | | Regions | Select 3+ regions geographically close to your edge site |

Click Save Monitor. Vigilmon will start checking from all selected regions immediately.


Step 5: Add a TCP monitor for the Raven gateway

Raven is OpenYurt's L3 connectivity component for inter-pool communication. Monitor the gateway's exposed port to detect when east-west traffic would fail:

# Find the raven-gateway external IP
kubectl get svc -n kube-system raven-gateway

In Vigilmon, add a second monitor:

| Field | Value | |-------|-------| | Monitor type | TCP | | Name | OpenYurt Raven Gateway (L3) | | Host | <raven-gateway-external-ip> | | Port | 4500 (default IPSec/Raven port) | | Check interval | 1 minute |


Step 6: Monitor node pool health via a status API

Create a simple node pool status exporter to track per-pool readiness:

# nodepool-status-api/app.py
from flask import Flask, jsonify
import subprocess
import json

app = Flask(__name__)

@app.route('/health/nodepool/<pool_name>')
def nodepool_health(pool_name):
    result = subprocess.run(
        ['kubectl', 'get', 'nodepools', pool_name, '-o', 'json'],
        capture_output=True, text=True
    )
    if result.returncode != 0:
        return jsonify({'status': 'error', 'pool': pool_name}), 503

    data = json.loads(result.stdout)
    conditions = data.get('status', {}).get('conditions', [])
    ready = any(c['type'] == 'PoolInitialized' and c['status'] == 'True'
                for c in conditions)

    if not ready:
        return jsonify({'status': 'degraded', 'pool': pool_name}), 503

    ready_nodes = data.get('status', {}).get('readyNodeNum', 0)
    total_nodes = data.get('status', {}).get('nodeNum', 0)

    return jsonify({
        'status': 'ok',
        'pool': pool_name,
        'ready_nodes': ready_nodes,
        'total_nodes': total_nodes,
    })

if __name__ == '__main__':
    app.run(host='0.0.0.0', port=8090)

Add a Vigilmon HTTP monitor for each node pool:

| Field | Value | |-------|-------| | Monitor type | HTTP | | Name | NodePool: edge-pool-us-west | | URL | http://<control-plane-ip>:8090/health/nodepool/edge-pool-us-west | | Expected status | 200 | | Response must contain | "status":"ok" |


Step 7: Configure alerts

In Vigilmon, go to Alerts → Alert Channels and set up your notification channels (email, Slack, PagerDuty, etc.).

Then apply an alert policy to each OpenYurt monitor:

| Setting | Recommended value | |---------|-------------------| | Alert after | 2 consecutive failures (reduces false positives from brief tunnel drops) | | Recovery alert | Enabled (know when edge autonomy resolves) | | Alert channel | Your on-call channel |

For tunnel monitors specifically, a 2-failure threshold before alerting matches OpenYurt's built-in reconnection retry window.


Step 8: Set up a status page

If you serve external customers from edge nodes, create a public status page in Vigilmon:

  1. Navigate to Status Pages → Create Status Page
  2. Add your edge-api monitors grouped by pool name
  3. Add the Raven gateway monitor as "Internal Infrastructure"
  4. Share the status page URL with your operations team

What you're monitoring now

| Monitor | What it detects | |---------|-----------------| | Edge HTTP (per pool) | Application-level failures at the edge, pod crashes, 5xx errors | | Raven Gateway TCP | L3 inter-pool connectivity loss | | Node pool status API | Pool-wide readiness degradation, partial node failures | | Tunnel health proxy | Cloud-edge tunnel breaks, autonomous mode triggers |


Conclusion

OpenYurt's edge autonomy model is powerful, but it also makes failures harder to see. Kubernetes control-plane liveness is not the same as edge user experience. Vigilmon gives you an external vantage point that catches tunnel outages, node pool degradation, and routing failures that internal probes miss — no agents to install on edge nodes, just lightweight HTTP and TCP checks from multiple regions.

Sign up for a free Vigilmon account and add your first OpenYurt monitor today.

Monitor your app with Vigilmon

Free plan — 5 monitors, no credit card required. Up and running in 60 seconds.

Start free →