tutorial

How to Monitor macvlan CNI with Vigilmon (HTTP + TCP + Alerts)

macvlan CNI is a Kubernetes CNI plugin that creates macvlan interfaces inside pods, giving each pod its own MAC address and direct Layer 2 presence on the ph...

macvlan CNI is a Kubernetes CNI plugin that creates macvlan interfaces inside pods, giving each pod its own MAC address and direct Layer 2 presence on the physical network without any overlay encapsulation. Unlike VXLAN-based CNI plugins, macvlan bypasses the virtual switch entirely — pod traffic enters the physical network directly on the parent interface, producing near-native throughput with minimal CPU overhead. It is the preferred CNI for performance-sensitive workloads such as network functions, high-frequency trading pods, and bare-metal telco applications where every microsecond of forwarding latency matters. When macvlan CNI is working correctly, pods receive unique MAC addresses, appear as first-class endpoints on the physical switch, and communicate at line rate. When it fails — because the parent interface is misconfigured, an IP conflicts with another host on the subnet, or the parent interface link goes down — pods lose external connectivity while appearing healthy to Kubernetes. Vigilmon provides the external uptime monitoring that macvlan CNI cannot self-report: continuous HTTP and TCP checks from outside your network that detect reachability failures the moment they occur. You can add your first monitor for free, no credit card required.


Why macvlan CNI needs external monitoring

  • Parent interface promiscuous mode disabled on the switch silently drops all macvlan pod traffic. macvlan creates virtual interfaces that share the parent NIC but present distinct MAC addresses. Many managed switches implement port security policies that drop frames from unknown MAC addresses, treating macvlan pod traffic as a MAC spoofing attack. When port security is enforced — after a switch configuration audit, a firmware update, or a new VLAN policy — all macvlan pod frames are silently discarded at the switch port. The pod interface remains UP, the CNI reports no error, and Kubernetes readiness probes that run on the same node pass because they do not traverse the switch. An external HTTP monitor probing the pod's macvlan IP detects this complete loss of external reachability immediately.

  • IP address conflict with a physical host causes intermittent ARP resolution failures. macvlan assigns pod IP addresses from the subnet of the parent interface, meaning pod IPs live in the same broadcast domain as physical hosts. If a newly provisioned bare-metal server, a network appliance, or a management interface is assigned an IP that overlaps with a macvlan pod IP, ARP responses become non-deterministic — sometimes the pod answers, sometimes the physical host answers. The result is intermittent connectivity: some clients reach the pod, others are silently routed to the wrong host. Kubernetes health probes are not affected because they address the pod directly via the overlay network. An external HTTP monitor with a strict expected-response body check reliably detects this class of intermittent failure.

  • macvlan cannot communicate with the parent host after interface creation. A fundamental constraint of macvlan is that pods with macvlan interfaces cannot communicate with the node that hosts them via the macvlan interface — traffic between the pod and its parent host is blocked by the kernel macvlan driver. This means that a Kubernetes node running macvlan pods cannot directly health-probe those pods on their macvlan IP. Any readiness or liveness probe that runs from the node to the macvlan pod IP is silently blocked and cannot be used to verify macvlan reachability. An external HTTP monitor is not subject to this restriction and is the correct mechanism to verify macvlan pod reachability from outside.

  • Parent interface MTU mismatch causes silent packet fragmentation and large-payload failures. macvlan inherits the MTU of the parent interface. If the parent interface has a non-standard MTU — for example, a jumbo-frame NIC configured at 9000 bytes — but the physical network path has a lower MTU ceiling, large macvlan packets are silently fragmented or dropped by intermediate switches that do not support the larger frame size. Small HTTP health check requests (under 1500 bytes) succeed normally, masking the issue. Bulk data transfers, TLS handshakes with large certificates, or gRPC responses with large payloads fail silently. An external HTTP monitor that retrieves a response body of known size detects this class of MTU-related failure.

  • macvlan pod IP reuse after rapid pod restart creates stale ARP cache entries on physical switches. When a pod using macvlan CNI is deleted and a new pod is immediately scheduled with the same IP but a different MAC address — a common occurrence in deployments with pod disruption budgets set to zero — physical switches and routers retain the stale ARP cache entry mapping the old MAC to the IP for the duration of the ARP cache TTL (often several minutes). During this window, traffic destined for the new pod is forwarded to the old, now-deleted pod's MAC address, where it is dropped. Kubernetes reports the new pod as running and ready, but external clients cannot reach it. An external HTTP monitor detects this stale-ARP blackhole because it probes from outside the cluster, traversing the same switch that has the stale entry.


What you'll need

  • A running Kubernetes cluster with macvlan CNI configured (typically via Multus CNI with a macvlan NetworkAttachmentDefinition)
  • The physical IP address or hostname of a macvlan-attached pod endpoint, for example http://192.168.1.101
  • A free Vigilmon account — monitors start running in under a minute with no credit card required

Step 1: Expose macvlan CNI workload health endpoints

Verify macvlan CNI is assigning interfaces correctly and that a pod endpoint is reachable before configuring Vigilmon monitors.

# Check the macvlan NetworkAttachmentDefinition
kubectl get network-attachment-definitions -A
kubectl describe network-attachment-definition macvlan-conf -n <namespace>

# Sample NetworkAttachmentDefinition:
# {
#   "cniVersion": "0.3.1",
#   "type": "macvlan",
#   "master": "eth0",
#   "mode": "bridge",
#   "ipam": {
#     "type": "host-local",
#     "subnet": "192.168.1.0/24",
#     "rangeStart": "192.168.1.100",
#     "rangeEnd": "192.168.1.200"
#   }
# }

# Check that a pod has a macvlan interface attached
kubectl exec -n <namespace> <macvlan-pod> -- ip addr show
# Expected: an interface (e.g. net1) with a 192.168.1.x IP address and a unique MAC

# Verify the macvlan interface is UP
kubectl exec -n <namespace> <macvlan-pod> -- ip link show net1
# Expected:
# 3: net1@eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP
#     link/ether aa:bb:cc:dd:ee:ff brd ff:ff:ff:ff:ff:ff

# Test reachability to the macvlan IP from a host on the same subnet
MACVLAN_IP=$(kubectl exec -n <namespace> <macvlan-pod> -- ip -4 addr show net1 | grep -oP '(?<=inet )[^/]+')
echo "macvlan pod IP: $MACVLAN_IP"
ping -c 3 $MACVLAN_IP

# Test HTTP from the same subnet host
curl -I http://$MACVLAN_IP/health
# Expected:
# HTTP/1.1 200 OK

# Check for IP conflicts using arping
arping -c 3 -I eth0 $MACVLAN_IP
# Expected: only one MAC address in the replies

Step 2: Set up HTTP monitoring in Vigilmon

Add an HTTP monitor for the macvlan pod endpoint:

  1. Log in to vigilmon.online and click Add Monitor.
  2. Set Monitor type to HTTP.
  3. Enter the URL: http://192.168.1.101/health (the macvlan pod's physical IP address).
  4. Set Check interval to 60 seconds and Expected status code to 200.
  5. Click Save Monitor — Vigilmon will run the first check within a minute.

Add a monitor with a response body check to detect ARP conflicts

macvlan IP conflicts produce intermittent responses from different hosts. A keyword check catches cases where the wrong host responds:

  1. Click Add Monitor again.
  2. Set Monitor type to HTTP.
  3. Enter the URL: http://192.168.1.101/health
  4. Set Expected status code to 200.
  5. Under Advanced settings, add a Keyword check: enter a unique string that only your pod's health endpoint returns (for example "service":"macvlan-workload").
  6. Click Save Monitor.

Why external monitoring catches what internal checks miss

macvlan CNI has a structural limitation: pods with macvlan interfaces cannot be probed from their own host node via the macvlan IP. Every Kubernetes liveness and readiness probe that runs on the hosting node is architecturally incapable of verifying macvlan reachability. Vigilmon is not subject to this restriction. It probes from entirely outside your infrastructure, traversing the physical switch that enforces port security and holds the ARP cache — the exact path where macvlan failures manifest. Switch-level packet drops, stale ARP entries, and IP conflicts are invisible to every in-cluster health mechanism and are only reliably caught by an external probe.


Step 3: Monitor macvlan CNI's TCP port

A TCP monitor verifies transport-layer connectivity to the macvlan pod IP independently of any application health check.

  1. In Vigilmon, click Add Monitor.
  2. Set Monitor type to TCP.
  3. Enter Host: 192.168.1.101 and Port: 80 (or the application port).
  4. Set Check interval to 60 seconds.
  5. Click Save Monitor.

Find macvlan pod IPs and their listening ports:

# List all pods with macvlan annotations and their IPs
kubectl get pods -A -o json | python3 -c "
import json, sys
data = json.load(sys.stdin)
for pod in data['items']:
    ann = pod['metadata'].get('annotations', {})
    nets = ann.get('k8s.v1.cni.cncf.io/network-status', '')
    if 'macvlan' in nets:
        print(pod['metadata']['name'], nets[:200])
"

# Check what ports the macvlan pod is listening on
kubectl exec -n <namespace> <macvlan-pod> -- ss -tlnp
# Sample output:
# State  Recv-Q  Send-Q  Local Address:Port
# LISTEN 0       128     0.0.0.0:80         0.0.0.0:*   users:(("nginx",pid=1))
# LISTEN 0       128     0.0.0.0:9090       0.0.0.0:*   users:(("metrics",pid=12))

# Test TCP connectivity directly to macvlan IP
nc -zv 192.168.1.101 80 && echo "Port open" || echo "Port CLOSED"

Step 4: Configure alert channels

Email alerts

  1. In Vigilmon, go to Alert Channels and click Add Channel.
  2. Choose Email and enter the address that should receive notifications (for example, netops@example.com or an on-call distribution list for network-sensitive workloads).
  3. Assign this channel to all macvlan CNI monitors created in Steps 2 and 3.
  4. Click Save — Vigilmon will send a test email to confirm delivery.

Webhook alerts

For Slack, PagerDuty, or a network management platform, add a webhook channel:

  1. In Alert Channels, click Add Channel and choose Webhook.
  2. Paste your endpoint URL.
  3. Vigilmon will POST the following JSON payload when a monitor transitions to down:
{
  "monitor_id": "mon_macvlan_health",
  "monitor_name": "macvlan pod /health",
  "status": "down",
  "previous_status": "up",
  "checked_at": "2026-07-12T09:14:22Z",
  "response_time_ms": null,
  "status_code": null,
  "error": "Connection refused",
  "url": "http://192.168.1.101/health"
}
  1. Assign all macvlan CNI monitors to this channel and click Save.

Runbook: diagnostics to run when an alert fires

#!/bin/bash
# macvlan CNI alert runbook — run these in order when Vigilmon fires

echo "=== Pod status ==="
kubectl get pods -A | grep <macvlan-workload>

echo "=== macvlan interface status in pod ==="
kubectl exec -n <namespace> <macvlan-pod> -- ip addr show net1 2>/dev/null || echo "Interface query failed"

echo "=== macvlan interface link state ==="
kubectl exec -n <namespace> <macvlan-pod> -- ip link show net1 2>/dev/null

echo "=== ARP check for macvlan IP ==="
arping -c 5 -I eth0 192.168.1.101 2>/dev/null || echo "arping failed or IP unreachable"

echo "=== HTTP endpoint response ==="
curl -sv http://192.168.1.101/health 2>&1 | tail -20

echo "=== Parent interface status ==="
ip link show eth0
ip addr show eth0

echo "=== ARP table on host ==="
arp -n | grep 192.168.1

echo "=== Recent pod events ==="
kubectl get events -n <namespace> --sort-by='.lastTimestamp' | grep <macvlan-pod> | tail -20

echo "=== Network attachment status ==="
kubectl get pods -n <namespace> <macvlan-pod> -o jsonpath='{.metadata.annotations.k8s\.v1\.cni\.cncf\.io/network-status}' | python3 -m json.tool

echo "=== Port connectivity ==="
nc -zv 192.168.1.101 80

echo "=== Multus logs for macvlan errors ==="
kubectl logs -n kube-system -l app=multus --tail=50 | grep -i "macvlan\|error\|fail" | tail -20

Step 5: Create a public status page

A Vigilmon status page gives your network operations team and application owners a single URL to check macvlan CNI workload health during incidents — no cluster access or subnet-local network required.

  1. In Vigilmon, navigate to Status Pages and click New Status Page.
  2. Give it a name such as macvlan Workload Network and choose a subdomain like macvlan-status.vigilmon.page.
  3. Add all monitors created in this tutorial: the /health HTTP monitor, the keyword-check HTTP monitor, and the TCP port monitor.
  4. Optionally add a description noting that this workload uses macvlan CNI for direct Layer 2 network presence and that a monitor alert may indicate a switch-level ARP or port security issue.
  5. Click Publish — the page is immediately accessible and updates in real time.

Share this URL in your network operations runbooks and link it from any documentation describing the macvlan-based workloads. When connectivity issues are reported, the status page confirms whether the macvlan pod is reachable from outside the cluster before engineers begin switch-level or CNI-level investigation.


Putting it all together

| Monitor | Type | What it catches | |---|---|---| | http://192.168.1.101/health | HTTP | Pod unreachable, switch port security drop, macvlan attach failure | | http://192.168.1.101/health (keyword) | HTTP | ARP conflict sending traffic to wrong host, unexpected response body | | 192.168.1.101:80 | TCP | Transport-level failure, port not listening on macvlan interface |

# Quick-reference diagnostic one-liners when a Vigilmon alert fires

# 1. Is the macvlan pod running?
kubectl get pods -A | grep <macvlan-workload>

# 2. Does the pod have a net1 interface with the expected IP?
kubectl exec -n <namespace> <macvlan-pod> -- ip addr show net1

# 3. Is there an ARP conflict for the macvlan IP?
arping -c 3 -I eth0 192.168.1.101

# 4. Is the health endpoint responding?
curl -sf http://192.168.1.101/health || echo "Health check FAILED"

# 5. Is port 80 open on the macvlan IP?
nc -zv 192.168.1.101 80 && echo "Port open" || echo "Port CLOSED"

# 6. Is the parent interface up?
ip link show eth0 | grep "state UP"

# 7. Are there macvlan attach errors in Multus logs?
kubectl logs -n kube-system -l app=multus --tail=20 | grep -i "macvlan\|error"

# 8. What MAC address is associated with the macvlan IP in the ARP table?
arp -n 192.168.1.101

What's next

  • Heartbeat monitoring for macvlan interface health — Configure a Kubernetes CronJob that runs inside the macvlan pod, verifies that the net1 interface is UP and that the expected IP is assigned, and POSTs a heartbeat to a Vigilmon dead-man's-switch endpoint. If the macvlan interface is detached or its IP changes, the heartbeat stops and Vigilmon fires an alert independently of HTTP endpoint availability checks.
  • SSL certificate monitoring — If your macvlan-attached workload exposes HTTPS directly on its physical IP, add a Vigilmon SSL monitor to alert before TLS certificate expiry causes connection failures that appear as network errors but are actually certificate rejections.
  • Latency baseline for switch degradation detection — Use Vigilmon's response time history to establish a latency baseline for your macvlan pod endpoints. Because macvlan traffic traverses the physical switch without overlay encapsulation, any increase in switch forwarding latency — due to spanning tree recalculation, port congestion, or a storm control event — appears directly in the Vigilmon response time chart as a sudden increase, providing an early warning before switch-level problems cause connection timeouts.

Get started free at vigilmon.online — no credit card, monitors start running in under a minute.

Monitor your app with Vigilmon

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

Start free →