Summary
#6480 fixed the unbounded connection pool in networking.HttpClientBuilder.Build by setting IdleConnTimeout, MaxIdleConns and MaxIdleConnsPerHost. Several &http.Transport{} literals elsewhere in the tree construct their own transport with only the two timeouts set and keep-alives left on, so IdleConnTimeout is still zero — meaning an idle pooled connection never expires and a dropped client pins a socket plus its goroutine pair for the process lifetime.
Known sites:
pkg/auth/discovery/discovery.go (two)
pkg/oauthproto/discovery.go
pkg/oauthproto/dcr.go
pkg/auth/oauth/oidc.go
Already correct, for reference: pkg/webhook/client.go (bounded) and pkg/oauthproto/cimd/fetch.go (keep-alives disabled).
Related: wrappers that swallow CloseIdleConnections
http.Client.CloseIdleConnections type-asserts the outermost transport, so any wrapping RoundTripper that does not implement and forward the method silently makes the call a no-op. #6480 fixed networking.ValidatingTransport, the oauth2.Transport wrapper, and limitedBodyTransport, and added networking.IdleConnectionCloser as the named capability to assert against. These wrappers still re-hide the pool of a builder-built client:
bearerTokenTransport — pkg/auth/dcr/resolver.go
oauthproto.UserAgentTransport — pkg/auth/oauth/flow.go
auth.WrapTransport — pkg/registry/api/shared.go
pkg/authz/authorizers/http/http_client.go
There are also three pre-existing anonymous interface{ CloseIdleConnections() } assertions in pkg/vmcp (client/client.go, headerforward/transport.go) that should assert against networking.IdleConnectionCloser instead.
Why this is separate
#6479 scoped itself to the shared builder, and these are now bounded in practice by that fix only where the client comes from Build. The hand-rolled transports are not. Fixing them is mechanical; the better long-term answer is probably routing them through the builder, which is a larger refactor.
A shared networking.ForwardCloseIdle helper would make the wrapper half hard to get wrong.
Context
Summary
#6480 fixed the unbounded connection pool in
networking.HttpClientBuilder.Buildby settingIdleConnTimeout,MaxIdleConnsandMaxIdleConnsPerHost. Several&http.Transport{}literals elsewhere in the tree construct their own transport with only the two timeouts set and keep-alives left on, soIdleConnTimeoutis still zero — meaning an idle pooled connection never expires and a dropped client pins a socket plus its goroutine pair for the process lifetime.Known sites:
pkg/auth/discovery/discovery.go(two)pkg/oauthproto/discovery.gopkg/oauthproto/dcr.gopkg/auth/oauth/oidc.goAlready correct, for reference:
pkg/webhook/client.go(bounded) andpkg/oauthproto/cimd/fetch.go(keep-alives disabled).Related: wrappers that swallow
CloseIdleConnectionshttp.Client.CloseIdleConnectionstype-asserts the outermost transport, so any wrappingRoundTripperthat does not implement and forward the method silently makes the call a no-op. #6480 fixednetworking.ValidatingTransport, theoauth2.Transportwrapper, andlimitedBodyTransport, and addednetworking.IdleConnectionCloseras the named capability to assert against. These wrappers still re-hide the pool of a builder-built client:bearerTokenTransport—pkg/auth/dcr/resolver.gooauthproto.UserAgentTransport—pkg/auth/oauth/flow.goauth.WrapTransport—pkg/registry/api/shared.gopkg/authz/authorizers/http/http_client.goThere are also three pre-existing anonymous
interface{ CloseIdleConnections() }assertions inpkg/vmcp(client/client.go,headerforward/transport.go) that should assert againstnetworking.IdleConnectionCloserinstead.Why this is separate
#6479 scoped itself to the shared builder, and these are now bounded in practice by that fix only where the client comes from
Build. The hand-rolled transports are not. Fixing them is mechanical; the better long-term answer is probably routing them through the builder, which is a larger refactor.A shared
networking.ForwardCloseIdlehelper would make the wrapper half hard to get wrong.Context