fix(controller): remove redundant scheme registration from NewController - #2046
Open
Haseeb-1698 wants to merge 1 commit into
Open
fix(controller): remove redundant scheme registration from NewController#2046Haseeb-1698 wants to merge 1 commit into
Haseeb-1698 wants to merge 1 commit into
Conversation
NewController registered the SealedSecret types into client-go's global scheme on every call. The v1alpha1 package init() already registers the same types into the same scheme at process start, so the call was redundant. It was also harmless while the additional-namespace bootstrap was serial. Since bitnami#2018 made it parallel, prepareController runs in up to 16 goroutines, each reaching NewController and writing runtime.Scheme's internal maps concurrently. That aborts the process with "fatal error: concurrent map writes" whenever --additional-namespaces lists two or more namespaces. Single-namespace deployments call it once and are unaffected. Drop the registration and its now-unused import. Add a regression test that builds controllers from 64 goroutines, and one asserting the global registration the controller's decoders rely on still happens without it. Fixes bitnami#2045. Signed-off-by: Muhammad Haseeb <i221698@nu.edu.pk>
Haseeb-1698
force-pushed
the
fix/concurrent-scheme-registration
branch
from
September 4, 2026 14:40
cac5c15 to
eda8a99
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #2045.
NewControllerregistered the SealedSecret types into client-go's globalscheme.Schemeon every call:That registration has already happened by then.
ssscheme.AddToSchemeis aSchemeBuilderwhose only member isv1alpha1.AddToScheme(pkg/client/clientset/versioned/scheme/register.go:17-18), and the v1alpha1 package's owninit()runs exactly that againstscheme.Scheme(pkg/apis/sealedsecrets/v1alpha1/register.go:24).controller.goimports that package directly, so theinit()has run before any controller is built.The redundancy was harmless while startup was serial. #2018 made the additional-namespace bootstrap parallel (
pkg/controller/main.go:321-343, concurrency 16), soprepareController— and through itNewController— now runs from many goroutines at once.runtime.Scheme.AddKnownTypeswrites the scheme's internal maps; identical values still count as concurrent map writes, so the process aborts. A single namespace only ever calls it once, which matches default deployments being unaffected.The fix is to drop the call and its now-unused import.
utilruntime(used at lines 267/280/312/320) andscheme(99/543/563/585/604) both stay.Tests
TestPrepareControllerConcurrently— builds controllers from 64 goroutines, mirroring the parallel bootstrap.TestSealedSecretTypesAreRegisteredGlobally— asserts the registration thatscheme.Codecs.UniversalDecoderdepends on still happens without the removed call, so the deletion cannot silently break decoding.Measured on linux/amd64, Go 1.27.1,
go test -count=1 -run TestPrepareControllerConcurrently ./pkg/controller/...:fatal error: concurrent map writesFull package:
go test ./pkg/controller/...passes (9.8s),go vetandgofmtclean.At 16 goroutines the crash only reproduced in 2 of 3 runs, so the test uses 64 to make the failure reliable on unpatched code. It is deterministic in the direction that matters for CI — green on the fixed tree.
One unrelated data race, noted but not fixed here
While validating under
-raceI hit a second, pre-existing race on the same path, independent of this bug:NewControllerassigns the package-levelmaxRetries(pkg/controller/controller.go:122before this change), so every parallel bootstrap goroutine writes one shared global thatprocessNextItemreads at line 313. All callers currently write the same flag-derived value, so it does not crash —go test -racereports it, plaingo testdoes not, andmake testdoes not use-race.I have deliberately left it out to keep this PR to the reported crash. Happy to send it as a follow-up if you'd like it fixed — the obvious shape is moving
maxRetriesonto theControllerstruct.