From 4e83c04b1d89a0afae463790744e0c10d67d5eb7 Mon Sep 17 00:00:00 2001 From: Anthony Nandaa Date: Tue, 28 Jan 2025 13:16:05 +0300 Subject: [PATCH] fix: util/network: add option not to re-use namespaces from pool There is an issue with `HnsEndpoints` on WS2019, after first time use, they can't be re-attached. See #5668. HCS CreateComputeSystem fails with: ``` The requested operation for attach namespace failed. ``` As a work-around, have an option for PoolSize=-1 to turn off the namespace pooling functionality and have each namespace only be used once and discarded. To enable this, you run buildkit with the additional flag: `--containerd-cni-pool-size=-1`. Fixes #5668 Signed-off-by: Anthony Nandaa --- util/network/cniprovider/cni.go | 30 +++++++++++++++++++++++++++++- 1 file changed, 29 insertions(+), 1 deletion(-) diff --git a/util/network/cniprovider/cni.go b/util/network/cniprovider/cni.go index bf464ee121c6..7b2bbab0b0f2 100644 --- a/util/network/cniprovider/cni.go +++ b/util/network/cniprovider/cni.go @@ -169,6 +169,22 @@ func (pool *cniPool) get(ctx context.Context) (*cniNS, error) { pool.mu.Unlock() trace.SpanFromContext(ctx).AddEvent("returning network namespace from pool") bklog.G(ctx).Debugf("returning network namespace %s from pool", ns.id) + + // windows only: see issue #5668 + if runtime.GOOS == "windows" && pool.targetSize < 0 { + // for cases where targetSize is set to < 0 + // no re-use of namespaces, use current one now + // and replace with a new one. + // the current one will be released after use. + newNs, err := pool.getNew(ctx) + if err != nil { + bklog.G(ctx).Errorf("failed to create new network namespace: %s", err) + return nil, err + } + pool.mu.Lock() + pool.available = append(pool.available, newNs) + pool.mu.Unlock() + } return ns, nil } pool.mu.Unlock() @@ -208,13 +224,25 @@ func (pool *cniPool) put(ns *cniNS) { _ = ns.release() return } + + // windows only: see issue #5668 + if runtime.GOOS == "windows" && pool.targetSize < 0 && len(pool.available) > 0 { + // release ns if being returned back to the pool + // if a new one is already in the pool. + _ = ns.release() + return + } pool.available = append(pool.available, ns) actualSize := pool.actualSize if actualSize > pool.targetSize { // We have more network namespaces than our target number, so // schedule a shrinking pass. - time.AfterFunc(aboveTargetGracePeriod, pool.cleanupToTargetSize) + // on windows, if targetSize < 0, no shrinking needed + // since reuse is off -- see issue #5668. + if !(runtime.GOOS == "windows" && pool.targetSize < 0) { + time.AfterFunc(aboveTargetGracePeriod, pool.cleanupToTargetSize) + } } }