Skip to content

Commit 23c638b

Browse files
saschagrunertopenshift-cherrypick-robot
authored andcommitted
Allow to remove pod sandbox on netns removal
We should not error on sandbox removal if the netns path gets either removed or invalidated. This path allows removing the sandbox and cleans up the stale netns path. Signed-off-by: Sascha Grunert <[email protected]>
1 parent 16d9bd6 commit 23c638b

File tree

3 files changed

+45
-5
lines changed

3 files changed

+45
-5
lines changed

internal/config/nsmgr/types_linux.go

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -83,11 +83,17 @@ func (n *namespace) Remove() error {
8383
return nil
8484
}
8585

86-
// try to unmount, ignoring "not mounted" (EINVAL) error.
87-
if err := unix.Unmount(fp, unix.MNT_DETACH); err != nil && err != unix.EINVAL {
88-
return fmt.Errorf("unable to unmount %s: %w", fp, err)
86+
// Don't run into unmount issues if the network namespace does not exist any more.
87+
if _, err := os.Stat(fp); err == nil {
88+
// try to unmount, ignoring "not mounted" (EINVAL) error.
89+
if err := unix.Unmount(fp, unix.MNT_DETACH); err != nil && err != unix.EINVAL {
90+
return fmt.Errorf("unable to unmount %s: %w", fp, err)
91+
}
92+
93+
return os.RemoveAll(fp)
8994
}
90-
return os.Remove(fp)
95+
96+
return nil
9197
}
9298

9399
// GetNamespace takes a path and type, checks if it is a namespace, and if so

server/sandbox_network.go

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import (
44
"context"
55
"fmt"
66
"math"
7+
"os"
78
"time"
89

910
cnitypes "github.com/containernetworking/cni/pkg/types"
@@ -187,7 +188,19 @@ func (s *Server) networkStop(ctx context.Context, sb *sandbox.Sandbox) error {
187188
return err
188189
}
189190
if err := s.config.CNIPlugin().TearDownPodWithContext(stopCtx, podNetwork); err != nil {
190-
return fmt.Errorf("failed to destroy network for pod sandbox %s(%s): %w", sb.Name(), sb.ID(), err)
191+
retErr := fmt.Errorf("failed to destroy network for pod sandbox %s(%s): %w", sb.Name(), sb.ID(), err)
192+
193+
if _, statErr := os.Stat(podNetwork.NetNS); statErr != nil {
194+
return fmt.Errorf("%w: stat netns path %q: %w", retErr, podNetwork.NetNS, statErr)
195+
}
196+
197+
// The netns file may still exists, which means that it's likely
198+
// corrupted. Remove it to allow cleanup of the network namespace:
199+
if rmErr := os.RemoveAll(podNetwork.NetNS); rmErr != nil {
200+
return fmt.Errorf("%w: failed to remove netns path: %w", retErr, rmErr)
201+
}
202+
203+
log.Warnf(ctx, "Removed invalid netns path %s from pod sandbox %s(%s)", podNetwork.NetNS, sb.Name(), sb.ID())
191204
}
192205

193206
return sb.SetNetworkStopped(ctx, true)

test/network.bats

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -166,3 +166,24 @@ function check_networking() {
166166
# shellcheck disable=SC2010
167167
[[ $(ls $CNI_RESULTS_DIR | grep "$POD") == "" ]]
168168
}
169+
170+
@test "Clean up network if pod netns gets destroyed" {
171+
start_crio
172+
173+
POD=$(crictl runp "$TESTDATA/sandbox_config.json")
174+
175+
# remove the network namespace
176+
NETNS_PATH=/var/run/netns/
177+
NS=$(crictl inspectp "$POD" |
178+
jq -er '.info.runtimeSpec.linux.namespaces[] | select(.type == "network").path | sub("'$NETNS_PATH'"; "")')
179+
180+
# remove network namespace
181+
ip netns del "$NS"
182+
183+
# fake invalid netns path
184+
touch "$NETNS_PATH$NS"
185+
186+
# be able to remove the sandbox
187+
crictl rmp -f "$POD"
188+
grep -q "Removed invalid netns path $NETNS_PATH$NS from pod sandbox" "$CRIO_LOG"
189+
}

0 commit comments

Comments
 (0)