Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 10 additions & 4 deletions internal/config/nsmgr/types_linux.go
Original file line number Diff line number Diff line change
Expand Up @@ -83,11 +83,17 @@ func (n *namespace) Remove() error {
return nil
}

// try to unmount, ignoring "not mounted" (EINVAL) error.
if err := unix.Unmount(fp, unix.MNT_DETACH); err != nil && err != unix.EINVAL {
return fmt.Errorf("unable to unmount %s: %w", fp, err)
// Don't run into unmount issues if the network namespace does not exist any more.
if _, err := os.Stat(fp); err == nil {
// try to unmount, ignoring "not mounted" (EINVAL) error.
if err := unix.Unmount(fp, unix.MNT_DETACH); err != nil && err != unix.EINVAL {
return fmt.Errorf("unable to unmount %s: %w", fp, err)
}

return os.RemoveAll(fp)
}
return os.Remove(fp)

return nil
}

// GetNamespace takes a path and type, checks if it is a namespace, and if so
Expand Down
15 changes: 14 additions & 1 deletion server/sandbox_network.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"context"
"fmt"
"math"
"os"
"time"

cnitypes "github.com/containernetworking/cni/pkg/types"
Expand Down Expand Up @@ -187,7 +188,19 @@ func (s *Server) networkStop(ctx context.Context, sb *sandbox.Sandbox) error {
return err
}
if err := s.config.CNIPlugin().TearDownPodWithContext(stopCtx, podNetwork); err != nil {
return fmt.Errorf("failed to destroy network for pod sandbox %s(%s): %w", sb.Name(), sb.ID(), err)
retErr := fmt.Errorf("failed to destroy network for pod sandbox %s(%s): %w", sb.Name(), sb.ID(), err)

if _, statErr := os.Stat(podNetwork.NetNS); statErr != nil {
return fmt.Errorf("%w: stat netns path %q: %w", retErr, podNetwork.NetNS, statErr)
}

// The netns file may still exists, which means that it's likely
// corrupted. Remove it to allow cleanup of the network namespace:
if rmErr := os.RemoveAll(podNetwork.NetNS); rmErr != nil {
return fmt.Errorf("%w: failed to remove netns path: %w", retErr, rmErr)
}

log.Warnf(ctx, "Removed invalid netns path %s from pod sandbox %s(%s)", podNetwork.NetNS, sb.Name(), sb.ID())
}

return sb.SetNetworkStopped(ctx, true)
Expand Down
21 changes: 21 additions & 0 deletions test/network.bats
Original file line number Diff line number Diff line change
Expand Up @@ -166,3 +166,24 @@ function check_networking() {
# shellcheck disable=SC2010
[[ $(ls $CNI_RESULTS_DIR | grep "$POD") == "" ]]
}

@test "Clean up network if pod netns gets destroyed" {
start_crio

POD=$(crictl runp "$TESTDATA/sandbox_config.json")

# remove the network namespace
NETNS_PATH=/var/run/netns/
NS=$(crictl inspectp "$POD" |
jq -er '.info.runtimeSpec.linux.namespaces[] | select(.type == "network").path | sub("'$NETNS_PATH'"; "")')

# remove network namespace
ip netns del "$NS"

# fake invalid netns path
touch "$NETNS_PATH$NS"

# be able to remove the sandbox
crictl rmp -f "$POD"
grep -q "Removed invalid netns path $NETNS_PATH$NS from pod sandbox" "$CRIO_LOG"
}
Loading