Skip to content

Conversation

@sidneychang
Copy link

  • Add discoverContainerIface in pkg/network/network.go to discover the container-side veth endpoint by scanning links in the current netns.
  • Replace places that relied on the hardcoded DefaultInterface with the discovered link.

This implements interface discovery instead of assuming eth0, improving compatibility across different runtimes/CNIs.

Fixes #14

@netlify
Copy link

netlify bot commented Jan 23, 2026

Deploy Preview for urunc canceled.

Name Link
🔨 Latest commit 35f05d3
🔍 Latest deploy log https://app.netlify.com/projects/urunc/deploys/697511b57f8068000849c8c0

@sidneychang sidneychang force-pushed the fix_hardcode_default_interface branch from abb1215 to 5d6bddc Compare January 23, 2026 21:12
@sidneychang sidneychang marked this pull request as draft January 23, 2026 21:15
@sidneychang sidneychang force-pushed the fix_hardcode_default_interface branch 3 times, most recently from 4e84f6d to 418b9c9 Compare January 24, 2026 17:26
@sidneychang sidneychang marked this pull request as ready for review January 24, 2026 17:28
@sidneychang sidneychang force-pushed the fix_hardcode_default_interface branch 2 times, most recently from 1faaa38 to 35f05d3 Compare January 24, 2026 18:38
- Add `discoverContainerIface` in `pkg/network/network.go` to discover the
  container-side veth endpoint by scanning links in the current netns.
- Replace places that relied on the hardcoded `DefaultInterface` with the
  discovered link.

This implements interface discovery instead of assuming `eth0`, improving
compatibility across different runtimes/CNIs.

Fixes urunc-dev#14

Signed-off-by: sidneychang <2190206983@qq.com>
Copy link
Contributor

@cmainas cmainas left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hello @sidneychang ,

thank you for this contribution. May I ask the reasoning of the algorithm to discover the container interface?

I am fine with the changes and they seem to work, but I am not sure if these changes cover all cases of interfaces inside a network namespace.

There is also another corner case that we need to test manually and verify the correctness of this PR. In kubernetes setups when a pod is getting restarted, the network namespace (created by the pause container) remains active and hence the tap0_urunc device still exists. Therefore, when urunc (re)creates the container it identifies the tap0_urunc device and it does not recreates it. So the suggested changes will find out the tap0_urunc interface and as far as I understand it will not be selected, since it will not have a default route. However, it would be nice to verify this assumption with a small test.

@sidneychang
Copy link
Author

Hello @sidneychang ,

thank you for this contribution. May I ask the reasoning of the algorithm to discover the container interface?

I am fine with the changes and they seem to work, but I am not sure if these changes cover all cases of interfaces inside a network namespace.

There is also another corner case that we need to test manually and verify the correctness of this PR. In kubernetes setups when a pod is getting restarted, the network namespace (created by the pause container) remains active and hence the tap0_urunc device still exists. Therefore, when urunc (re)creates the container it identifies the tap0_urunc device and it does not recreates it. So the suggested changes will find out the tap0_urunc interface and as far as I understand it will not be selected, since it will not have a default route. However, it would be nice to verify this assumption with a small test.

Thanks for the review.

In Kubernetes or container network model, the CNI plugin creates the veth interface inside the Pod network namespace (typically eth0), assigns it an IP address, and configures the default gateway and default route. As documented by common CNI implementations (e.g., AWS VPC CNI and Multus), the default route is normally attached to eth0, which makes it a reliable semantic indicator of the primary egress interface. So I tried to find a netlink with default route to replace hardencoded 'eth0'.

I also validated the Kubernetes restart scenario. I created a urnc pod in my kubernetes cluster. After force-killing the QEMU process of a urunc Pod, Kubernetes restarts the Pod while preserving the Pod-level network namespace. In this case, the tap device created by the previous instance still exists. During restart, the network setup fails due to the existing logic:

tapIndex, err := getTapIndex()
if err != nil {
    return nil, fmt.Errorf("getTapIndex failed: %w", err)
}
if tapIndex > 0 {
    return nil, fmt.Errorf(
        "unsupported operation: can't spawn multiple unikernels in the same network namespace",
    )
}

This treats any pre-existing tap as an attempt to spawn multiple unikernels in the same network namespace and aborts network setup, resulting in:

Failed to setup network :unsupported operation: can't spawn multiple unikernels in the same network namespace

This behavior is not introduced by the current changes—the same error can be reproduced with the original implementation as well. The issue is therefore related to tap reuse in preserved network namespaces during Pod restarts, rather than to interface discovery or default-route-based selection of eth0.

I will continue to follow up on this issue, further investigate whether it has any potential side effects or broader impact, and try to address it accordingly.:)

References:

AWS VPC CNI: https://github.com/aws/amazon-vpc-cni-k8s/blob/master/docs/cni-proposal.md

Multus CNI: https://k8snetworkplumbingwg.github.io/multus-cni/docs/how-to-use.html

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Discover the veth endpoint name instead of using default eth0

2 participants