-
Notifications
You must be signed in to change notification settings - Fork 200
Specify network namespace for firecracker process #120
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
Modified the firecracker vm config protobuf message to add the FirecrackerNetworkNamespace field, which lets client specify the network namespace that the firecracker process should be associated with. Signed-off-by: Anirudh Aithal <[email protected]>
runtime/service.go
Outdated
} | ||
// It's unsafe to switch network namespaces without locking down the OS | ||
// thread. Lock it for the start VM operation. | ||
pkgruntime.LockOSThread() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: it looks like the netNS.Do
implementation already takes care of locking the goroutine making the call to its os thread, so we shouldn't need to do the lock/unlock ourselves: https://github.com/containernetworking/plugins/blob/master/pkg/ns/ns_linux.go#L199
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nice catch! i didn't realize it was already doing that! i'll get rid of it.
@@ -52,6 +54,7 @@ import ( | |||
const ( | |||
defaultVsockPort = 10789 | |||
supportedMountFSType = "ext4" | |||
namedNetNSPath = "/var/run/netns/" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just curious, what's the reason we are requiring the ns come from under /var/run/netns
? As far as I knew you can bind a net NS fd anywhere you want on a filesystem, is this just a standard location?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Named network namespaces are typically created under /var/run/netns
. See ip-netns(8)
man page for details. I have not seen too many (any tbh) implementations that use an alternative path. You're right that the netns fd can certainly be bound anywhere on the filesystem. However, because the assumption is the use of named network namespaces, this path was chosen. An alternative could be letting clients specify FirecrackerNetworkNamespacePath
instead of FirecrackerNetworkNamespace
. But, it might be a bit much to specify was my take on it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks, that makes sense. The other middle-ground option I can think of is check if the user specified an absolute or relative path; if they specified an absolute path use that unchanged, if it was relative append it to the end of /var/run/netns/
.
If you agree that makes sense it's probably worth updating, but I don't consider it a blocker given it's just to support an obscure use-case.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since the most widely used library I'm aware of (for dealing with network namespaces in golang) makes this same assumption: https://github.com/vishvananda/netns/blob/13995c7128ccc8e51e9a6bd2b551020a27180abd/netns_linux.go#L81, I'd prefer to keep it the way it is. Let me know if you feel strongly about it and we can make that change.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I see, no that works for me for now, easy to update in the future if ever needed.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If fully specified, we should use the concrete path rather than a relative path. This is useful when the ns is not bind-mounted anywhere but is instead one of the ns files from /proc
, like /proc/<pid>/ns/net
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If fully specified, we should use the concrete path rather than a relative path. This is useful when the ns is not bind-mounted anywhere but is instead one of the ns files from
/proc
, like/proc/<pid>/ns/net
.
Agree. I'll make this change since two of you have asked for it. But, I still don't think that clients would want to do that. It's much easier to manage/deal with named network namespaces and that's what will drive most of the usage of this field imo.
If the client specifies a network namespace name in the firecracker VM config, use that to start the firecracker process. Signed-off-by: Anirudh Aithal <[email protected]>
The '-netns' flag lets callers specify a network namespace for firecracker VM process. Signed-off-by: Anirudh Aithal <[email protected]>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think the right way to do this is with the jailer rather than making the runtime responsible for this.
) | ||
|
||
func main() { | ||
var ip = flag.String("ip", "", "ip address assigned to the container. Example: -ip 172.16.0.1") | ||
var gateway = flag.String("gw", "", "gateway ip address. Example: -gw 172.16.0.1") | ||
var netMask = flag.String("mask", "", "subnet gatway mask. Example: -mask 255.255.255.0") | ||
var netNS = flag.String("netns", "", "firecracker VM network namespace. Example: -netNS testing") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks like the example should read "-netns testing".
) | ||
|
||
func main() { | ||
var ip = flag.String("ip", "", "ip address assigned to the container. Example: -ip 172.16.0.1") | ||
var gateway = flag.String("gw", "", "gateway ip address. Example: -gw 172.16.0.1") | ||
var netMask = flag.String("mask", "", "subnet gatway mask. Example: -mask 255.255.255.0") | ||
var netNS = flag.String("netns", "", "firecracker VM network namespace. Example: -netNS testing") | ||
var hostDevName = flag.String("host_device", defaultHostDevName, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: I'd prefer to use -
inside argument options instead of _
, so this would be host-device
.
"the host device name for the network interface, required when specifying 'netns'. Example: -host_device tap0") | ||
var macAddress = flag.String("mac", defaultMacAddress, | ||
"the mac address for the network interface, required when specifying 'netns'. Example: -mac AA:FC:00:00:00:01") | ||
var kernelNetworkArgs = flag.Bool("kernel_nw_args", false, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same as above.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
+1 for hyphens rather than underscores.
I also would prefer something other than "nw" for network. Maybe kernel-ip-arg
or kernel-net-arg
?
var macAddress = flag.String("mac", defaultMacAddress, | ||
"the mac address for the network interface, required when specifying 'netns'. Example: -mac AA:FC:00:00:00:01") | ||
var kernelNetworkArgs = flag.Bool("kernel_nw_args", false, | ||
"specifies if network params for the VMs should be included with kernel args. Example: -kernel_nw_args true") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this always true when netns
is specified? Does it default to true when netns
is specified? What about when ip
is specified?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this always true when
netns
is specified? Does it default to true whennetns
is specified? What about whenip
is specified?
It's true only when someone sets it. Depending on how your VM is configured you or may not need it. My rootfs has a dhcp client. Hence, I don't need to set this at all. The taskworkflow.md
file demonstrates use-cases with and without it. Please let me know if it's still unclear and I'll try to document more.
@@ -52,6 +54,7 @@ import ( | |||
const ( | |||
defaultVsockPort = 10789 | |||
supportedMountFSType = "ext4" | |||
namedNetNSPath = "/var/run/netns/" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If fully specified, we should use the concrete path rather than a relative path. This is useful when the ns is not bind-mounted anywhere but is instead one of the ns files from /proc
, like /proc/<pid>/ns/net
.
return s.machine.Start(vmmCtx) | ||
} | ||
// Get the network namespace handle. | ||
netNS, err := ns.GetNS(namedNetNSPath + netNSName) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should be able to accept a path like /proc/<pid>/ns/net
here so that a bind-mount is not required.
if err != nil { | ||
return errors.Wrapf(err, "unable to find netns %s", netNSName) | ||
} | ||
return netNS.Do(func(_ ns.NetNS) error { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I agree that the right way to do this would be with jailer. This is something that unblocks folks who want to do this in the meantime. We can easily switch the internal implementation to jailer once #122 is unblocked. |
Closing this for now. The code/architecture has diverged a bit since I wrote this. |
Upgrade go-swagger
…irecracker-microvm#120) add kind to the list of dependencies in the dev's manual Signed-off-by: Shyam Jesal <[email protected]>
Issue #, if available: N/A
Description of changes:
Testing done: Modified the
taskworkflow
example to accept-netns
argument. Tested end-to-end workflow using the same.By submitting this pull request, I confirm that my contribution is made under the terms of the Apache 2.0 license.