Configure Discovery of Network Interfaces
Block: discovery.instrument
Mermin attaches eBPF programs to network interfaces to capture packets as they traverse the network stack. Interface selection is critical because different interfaces see different traffic — choosing the right interfaces ensures you capture pod-to-pod, inter-node, and external traffic without gaps or duplication. You specify interfaces using flexible patterns (literals, globs, or regex) that are resolved against available host interfaces at startup and during runtime.
Configuration
A full configuration example can be found in the Default Configuration.
discovery.instrument block
discovery.instrument blockinterfacesattributeList of interface name patterns to monitor for network traffic capture. Patterns can be literals, globs, or regex expressions. Mermin attaches eBPF programs to all interfaces matching these patterns.
Type: List of Strings
Default:
["veth*", "tunl*", "ip6tnl*", "vxlan*", "flannel*", "cali*", "cilium_*", "lxc*", "gke*", "eni*", "azure*", "ovn-k8s*"]Example: Monitor only physical interfaces
discovery "instrument" { interfaces = ["eth*", "ens*", "en*"] }auto_discover_interfacesattributeEnable the Interface Controller for automatic network interface discovery and management. When enabled, Mermin continuously watches for interface changes via netlink events and automatically attaches/detaches eBPF programs as interfaces are created or destroyed. This is particularly useful for ephemeral interfaces like veth pairs.
Type: Boolean
Default:
trueExample: Disable automatic discovery for static interface monitoring
discovery "instrument" { interfaces = ["tunl*", "flannel*"] auto_discover_interfaces = false }tc_priorityattributeTC priority for eBPF program attachment (netlink only, kernel < 6.6). Controls where Mermin's programs run in the TC chain relative to other programs. Higher values = lower priority = runs later in the chain. Values below 30 may run before some CNI programs.
Type: Integer
Default:
1Valid Values: 1–32767
Example: Run Mermin after other TC programs
discovery "instrument" { interfaces = ["veth*", "tunl*"] tc_priority = 100 }tcx_orderattributeOrder in the TCX program chain (TCX only, kernel ≥ 6.6). Controls whether Mermin's eBPF programs run before or after other programs in the chain. Using
"last"(default) is recommended for observability to see traffic after CNI and security programs have processed it.Type: String
Default:
"last"Valid Values:
"last": Runs after other programs (recommended for observability)"first": Runs before other programs
Example: Run Mermin before other TCX programs
discovery "instrument" { interfaces = ["veth*", "tunl*"] tcx_order = "first" }
Interface Patterns
Mermin supports three pattern types for interface matching:
Literal Names
Exact interface name matching:
Matches exactly
eth0andens32No wildcards or patterns
Most explicit, least flexible
Glob Patterns
Shell-style wildcard matching:
Wildcard Characters:
*: Matches zero or more characterseth*matcheseth0,eth1,eth10, etc.
?: Matches exactly one characterens?3matchesens03,ens13, but notens3orens123
Examples:
Regex Patterns
Full regular expression matching (enclosed in /):
Regex syntax:
Pattern must be enclosed in forward slashes:
/pattern/Supports full regex syntax
Maximum pattern length: 256 characters (security limit)
Examples:
Regex patterns must escape special characters. Use \\d for digits, \\w for word characters, etc.
Pattern Resolution
Mermin resolves patterns at startup and configuration reload:
List available interfaces: Queries the host's network interfaces
Apply patterns: Matches each pattern against available interfaces
Deduplicate: Removes duplicate interfaces if matched by multiple patterns
Attach eBPF programs: Attaches to all resolved interfaces
Resolution Example
Host interfaces:
Configuration:
Resolved interfaces:
Not included: lo (loopback), docker0 (not matched). Loopback is typically excluded because it carries only localhost traffic and is rarely needed for flow observability.
Default Configuration
If interfaces is empty or not specified, Mermin uses these defaults. Both an empty list (interfaces = []) and omitting the option yield the same default set.
Strategy: Complete visibility without flow duplication
veth*captures all same-node pod-to-pod traffic (works with all bridge-based CNIs)Tunnel/overlay interfaces (
tunl*,ip6tnl*,vxlan*,flannel*) capture inter-node traffic for both IPv4 and IPv6CNI-specific interfaces (
cali*,cilium_*,lxc*,gke*,eni*,azure*,ovn-k8s*) for various network pluginsNo physical interfaces (
eth*,ens*) or bridge interfaces (cni0,docker0) to avoid duplication or missing same-node traffic
This works for most CNI configurations including Flannel, Calico, Cilium, kindnetd, and cloud providers. Supports dual-stack (IPv4+IPv6) clusters.
Traffic Visibility Strategies
The interfaces you monitor determine what traffic Mermin captures:
Complete Visibility (Default)
Monitor veth pairs and tunnel/overlay interfaces:
Captures:
✅ Same-node pod-to-pod traffic (via veth)
✅ Inter-node traffic (via tunnel/overlay interfaces)
✅ No flow duplication (separate packet paths)
Trade-offs:
⚠️ Higher overhead (monitors many veth interfaces in large clusters)
⚠️ Veth interfaces churn (created/destroyed with pods)
Use cases:
Complete network observability
Debugging same-node communication
Most production deployments
Inter-Node Only (Lower Overhead)
Monitor only physical interfaces:
Captures:
✅ Traffic between nodes
✅ Traffic to/from external networks
❌ Misses same-node pod-to-pod traffic
Trade-offs:
✅ Low overhead (few interfaces)
✅ No flow duplication (only physical interfaces monitored)
❌ Incomplete visibility (misses same-node pod traffic)
Use cases:
Clusters with minimal same-node communication
Cost-sensitive deployments
External traffic focus
Physical + CNI (Full Visibility with Duplication Risk)
Monitor both physical and CNI interfaces:
Captures:
✅ All inter-node traffic
✅ All intra-node pod-to-pod traffic
⚠️ May see duplicate flows (same traffic captured on multiple interfaces)
Use cases:
Complete visibility requirements
Debugging pod-to-pod communication
Compliance or security auditing
For most use cases, the default configuration (complete visibility with veth + tunnel interfaces) provides comprehensive observability without duplication.
Dynamic Interface Discovery
Mermin includes an Interface Controller that automatically discovers and manages network interfaces. The controller continuously watches for interface changes and synchronizes the configured patterns with active interfaces, attaching/detaching eBPF programs as interfaces are created and destroyed. This is particularly useful for ephemeral interfaces like veth pairs that come and go with pods.
Discovery Configuration
How It Works
Continuous Synchronization:
Maintains desired state (configured interface patterns)
Tracks actual state (active interfaces, attached eBPF programs)
Synchronizes state by attaching/detaching programs when changes are detected
Real-Time Netlink Events:
Watches for Linux netlink RTM_NEWLINK/RTM_DELLINK events
Detects interface state changes (UP/DOWN)
Automatically syncs when interfaces are created or destroyed
Interface Lifecycle (with Controller):
Pod created → veth pair created → Controller detects RTM_NEWLINK → Attaches eBPF programs
Pod deleted → veth pair removed → Controller detects RTM_DELLINK → Detaches eBPF programs
State Management:
Controller owns all interface-related state
TC link IDs tracked for clean detachment
Pattern matching happens once during discovery, not per-packet
Static vs. Dynamic Interfaces
Static interfaces (attached at startup only):
Physical interfaces:
eth0,ens32,eno1Tunnel interfaces:
tunl0,flannel.1Bridge interfaces:
cni0,docker0
Dynamic interfaces (continuously monitored):
Veth pairs:
vethXXXXXXXX(created/destroyed with pods)Temporary interfaces created by CNI plugins
Performance Considerations
Overhead:
Controller has zero CPU overhead when no changes occur
Sync operations (attach/detach) are fast (<10ms per interface)
No impact on packet processing performance
State management happens off the data path
Memory:
Each monitored interface adds ~1KB to memory usage
Controller state: patterns, active interfaces, TC links (~100KB baseline)
In clusters with 1000 pods (2000 veth interfaces), total is ~2.1MB
Netlink socket overhead is negligible (<100KB)
Scaling:
Tested with 10,000+ veth interfaces without performance degradation
Controller syncing happens asynchronously, doesn't block packets
Event-driven architecture scales efficiently with high pod churn
O(1) lookups for interface state and TC link management
Disabling the Interface Controller
For specialized scenarios where you only want static interface monitoring:
This disables the controller's synchronization and watches only interfaces present at startup. Note: With the interface controller enabled, there's no performance reason to disable this feature - the overhead is negligible.
When auto_discover_interfaces is disabled, the Interface Controller does not run. Mermin only attaches to interfaces present at startup. New interfaces created after startup will not be monitored until Mermin is restarted.
TC Attachment Order
When attaching eBPF programs to interfaces, Mermin supports two options that affect where its programs run in the TC chain relative to other programs (e.g., CNI or Cilium):
tc_priority(netlink only, kernel < 6.6): TC priority for program attachment. Higher values = lower priority = runs later. Default:1. Range: 1–32767. Values below 30 may run before some CNI programs.tcx_order(TCX only, kernel ≥ 6.6): Order in the TCX program chain. Options:"last"(default; runs after other programs, recommended for observability) or"first"(runs before).
Most deployments can leave these at their defaults. Tune them only if you need Mermin to see traffic before or after specific CNI or security programs.
CNI-Specific Patterns
Different Container Network Interfaces create different interface patterns:
Flannel
Flannel typically creates cni0 bridge interface.
Calico
Calico creates caliXXXXXXXX interfaces for each pod.
Cilium
Cilium uses cilium_host and cilium_net interfaces.
GKE
GKE creates gkeXXXXXXXX interfaces for pods.
Weave Net
Weave Net uses a weave interface.
Cloud Provider Patterns
AWS (EKS)
GCP (GKE)
Azure (AKS)
Bare Metal / On-Premises
Advanced Patterns
Exclude Specific Interfaces
While Mermin doesn't support exclusion patterns directly, use specific patterns to include only desired interfaces:
Broad Patterns for Varying Hosts
Use broad patterns that adapt to host configuration:
Troubleshooting
No Interfaces Matched
Symptom: Log message "no interfaces matched the configured patterns"
Solutions:
List available interfaces:
Test pattern matching:
Update configuration:
Interface Not Found
Symptom: Warning log that an interface was not found (e.g. "interface '…' not found in datalink::interfaces()")
Causes:
Interface doesn't exist
Interface name changed
Node has different interface naming
Solutions:
Verify interface exists:
ip link showUse glob patterns instead of exact names
Check if interface is created after Mermin starts
Capturing Too Much Traffic
Symptom: High CPU/memory usage, too many flows
Solutions:
Reduce monitored interfaces:
Remove CNI interfaces:
Add flow filters (see Filtering)
Flow Duplication
Symptom: Same flow appears multiple times
Causes:
Monitoring both physical and virtual interfaces
Same packet traverses multiple monitored interfaces
Solutions:
Monitor only physical interfaces:
Deduplicate in backend:
Use flow fingerprinting (Community ID)
Deduplicate based on 5-tuple + timestamps
Monitoring Interface Resolution
Check logs to see which interfaces Mermin resolved:
Example log output:
Best Practices
Start with defaults: Use default patterns for initial deployment
Monitor metrics: Watch packet/flow counts per interface
Test patterns: Validate interface resolution in non-production first
Use the narrowest patterns that meet your needs: Prefer specific patterns when limiting scope (e.g., a single physical interface)
Document choices: Comment why specific interfaces are monitored
Review periodically: Interface naming may change with OS upgrades
Complete Configuration Examples
Minimal (Physical Interfaces Only)
Physical Interfaces Only (Alternative)
Complete Visibility (With CNI)
Regex-Based Selection
Next Steps
Configure Tunnel Protocol Detection: Handle VXLAN, Geneve, and WireGuard
Filter Flows by Interface: Reduce noise from specific interfaces
Configure for Your CNI: CNI-specific interface patterns
Troubleshoot Missing Traffic: Understand what each interface type captures
Need Help?
Troubleshoot Interface Issues: Resolve missing flows
GitHub Discussions: Ask about your specific CNI setup
Last updated