From f17189a154a0cad69048917fe3efc7011e87259c Mon Sep 17 00:00:00 2001 From: Samuel Ortiz Date: Mon, 14 Feb 2022 09:27:18 +0100 Subject: [PATCH 1/2] ocihook: Add a networking namespace annotation key With VM based runtimes (e.g. Kata), the spec.State.Pid value does not necessarily runs in the container/pod networking namespace, but can also be in the host one. With those runtime, using the passed Pid to resolve the networking namespace for OCI plugins to be used result in setting the container network entirely in the host namespace. We add a "nerdct/network-namespace" for runtimes to explictly tell nerdctl which netns path to use instead of deriving it from the runtime PID. Signed-off-by: Samuel Ortiz --- pkg/ocihook/ocihook.go | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/pkg/ocihook/ocihook.go b/pkg/ocihook/ocihook.go index eca53c2d561..b16075e3ce1 100644 --- a/pkg/ocihook/ocihook.go +++ b/pkg/ocihook/ocihook.go @@ -44,6 +44,16 @@ import ( "github.com/sirupsen/logrus" ) +const ( + // NetworkNamespace is the network namespace path to be passed to the CNI plugins. + // When this annotation is set from the runtime spec.State payload, it takes + // precedence over the PID based resolution (/proc//ns/net) where pid is + // spec.State.Pid. + // This is mostly used for VM based runtime, where the spec.State PID does not + // necessarily lives in the created container networking namespace. + NetworkNamespace = labels.Prefix + "network-namespace" +) + func Run(stdin io.Reader, stderr io.Writer, event, dataStore, cniPath, cniNetconfPath string) error { if stdin == nil || event == "" || dataStore == "" || cniPath == "" || cniNetconfPath == "" { return errors.New("got insufficient args") From 17d8c005e6f8759a0f234fe273272ba16ce136d5 Mon Sep 17 00:00:00 2001 From: Samuel Ortiz Date: Mon, 14 Feb 2022 09:31:48 +0100 Subject: [PATCH 2/2] ocihook: Use the passed netns annotation when set When a runtime specify the labels.NetworkNamespace annotation, we use it over the passed Pid. That allows VM based runtimes to explictly use a networking namespace path they create. Fixes #787 Signed-off-by: Samuel Ortiz --- pkg/ocihook/ocihook.go | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/pkg/ocihook/ocihook.go b/pkg/ocihook/ocihook.go index b16075e3ce1..8b1fc1e109c 100644 --- a/pkg/ocihook/ocihook.go +++ b/pkg/ocihook/ocihook.go @@ -262,9 +262,21 @@ func loadSpec(bundle string) (*hookSpec, error) { } func getNetNSPath(state *specs.State) (string, error) { - if state.Pid == 0 { - return "", errors.New("state.Pid is unset") + // If we have a network-namespace annotation we use it over the passed Pid. + netNsPath, netNsFound := state.Annotations[NetworkNamespace] + if netNsFound { + if _, err := os.Stat(netNsPath); err != nil { + return "", err + } + + return netNsPath, nil } + + if state.Pid == 0 && !netNsFound { + return "", errors.New("Both state.Pid and the netNs annotation are unset") + } + + // We dont't have a networking namespace annotation, but we have a PID. s := fmt.Sprintf("/proc/%d/ns/net", state.Pid) if _, err := os.Stat(s); err != nil { return "", err