githubEdit

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 Configurationarrow-up-right.

discovery.instrument block

  • interfaces attribute

    List 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_interfaces attribute

    Enable 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: true

    Example: Disable automatic discovery for static interface monitoring

    discovery "instrument" {
      interfaces = ["tunl*", "flannel*"]
      auto_discover_interfaces = false
    }
  • tc_priority attribute

    TC 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: 1

    Valid Values: 1–32767

    Example: Run Mermin after other TC programs

    discovery "instrument" {
      interfaces = ["veth*", "tunl*"]
      tc_priority = 100
    }
  • tcx_order attribute

    Order 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 eth0 and ens32

  • No wildcards or patterns

  • Most explicit, least flexible

Glob Patterns

Shell-style wildcard matching:

Wildcard Characters:

  • *: Matches zero or more characters

    • eth* matches eth0, eth1, eth10, etc.

  • ?: Matches exactly one character

    • ens?3 matches ens03, ens13, but not ens3 or ens123

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:

circle-exclamation

Pattern Resolution

Mermin resolves patterns at startup and configuration reload:

  1. List available interfaces: Queries the host's network interfaces

  2. Apply patterns: Matches each pattern against available interfaces

  3. Deduplicate: Removes duplicate interfaces if matched by multiple patterns

  4. 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 IPv6

  • CNI-specific interfaces (cali*, cilium_*, lxc*, gke*, eni*, azure*, ovn-k8s*) for various network plugins

  • No 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

circle-info

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):

  1. Pod created → veth pair created → Controller detects RTM_NEWLINK → Attaches eBPF programs

  2. 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, eno1

  • Tunnel interfaces: tunl0, flannel.1

  • Bridge 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.

circle-exclamation

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:

  1. List available interfaces:

  2. Test pattern matching:

  3. 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:

  1. Verify interface exists: ip link show

  2. Use glob patterns instead of exact names

  3. Check if interface is created after Mermin starts

Capturing Too Much Traffic

Symptom: High CPU/memory usage, too many flows

Solutions:

  1. Reduce monitored interfaces:

  2. Remove CNI interfaces:

  3. 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:

  1. Monitor only physical interfaces:

  2. 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

  1. Start with defaults: Use default patterns for initial deployment

  2. Monitor metrics: Watch packet/flow counts per interface

  3. Test patterns: Validate interface resolution in non-production first

  4. Use the narrowest patterns that meet your needs: Prefer specific patterns when limiting scope (e.g., a single physical interface)

  5. Document choices: Comment why specific interfaces are monitored

  6. 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

  1. Configure Tunnel Protocol Detection: Handle VXLAN, Geneve, and WireGuard

  2. Filter Flows by Interface: Reduce noise from specific interfaces

Need Help?

Last updated