Skip to content

webhook: skip Secret informer when ImagePullSecrets is disabled#7355

Open
EngHabu wants to merge 2 commits into
mainfrom
enghabu/webhook-secret-informer
Open

webhook: skip Secret informer when ImagePullSecrets is disabled#7355
EngHabu wants to merge 2 commits into
mainfrom
enghabu/webhook-secret-informer

Conversation

@EngHabu
Copy link
Copy Markdown
Contributor

@EngHabu EngHabu commented May 7, 2026

Tracking issue

Follow-up to #7353.

Why are the changes needed?

#7353 introduced a controller-runtime informer cache to back the embedded secret manager's k8s client, eliminating per-admission Get round-trips against kube-apiserver. Two issues with that change as merged:

  1. Cache builds even when image pull secrets are disabled. The k8s client is only consumed inside findAndAddImagePullSecret / addImagePullSecretToPod (both in embedded_secret_manager.go), which run only when EmbeddedSecretManagerConfig.ImagePullSecrets.Enabled is true. When the flag is off the informer is dead weight — it still runs a cluster-wide list/watch on Secrets that nothing in the webhook ever reads.
  2. Implicit informer scope. controller-runtime caches are type-lazy: no informer is started until something accesses a given GVK, and WaitForCacheSync only waits on currently-started informers. The previous patch added the cache to the Scheme via corev1.AddToScheme (which registers Pods, ConfigMaps, Nodes, ... on top of Secrets) and relied on the embedded secret manager being the only caller to keep the watched set restricted to Secrets. WaitForCacheSync returned immediately on an empty informer set, so the first admission paid the Secret informer's cold-start latency.

What changes were proposed in this pull request?

In flyteplugins/go/tasks/pluginmachinery/secret/secrets_injector.go:

  • Build the informer cache + cache-backed client only when ImagePullSecrets.Enabled. When the feature is disabled, fall back to a bare direct client.New(...) — same behavior as before Cache image-pull-secret reads in webhook via controller-runtime informer #7353.
  • Inside the enabled branch, explicitly register the Secret informer via secretInformerCache.GetInformer(ctx, &corev1.Secret{}) before WaitForCacheSync. This makes the cache scope explicit (Secrets only, not "whatever someone happens to read first"), and ensures WaitForCacheSync blocks on the initial Secret list so the first admission isn't a guaranteed cache miss.

How was this patch tested?

  • go build ./flyteplugins/go/tasks/pluginmachinery/secret/... ./executor/... — clean.
  • go vet ./flyteplugins/go/tasks/pluginmachinery/secret/... ./executor/... — clean.
  • go test ./flyteplugins/go/tasks/pluginmachinery/secret/... -count=1 — all pass.

Labels

  • changed

Check all the applicable boxes

  • I updated the documentation accordingly.
  • All new and existing tests passed.
  • All commits are signed-off.

Related PRs

EngHabu added 2 commits May 7, 2026 11:32
The embedded secret manager's mutating webhook issues two synchronous
kube-apiserver Gets per pod admission to resolve image pull secrets
(one against the reference namespace, one against the pod namespace
for the mirrored copy). At admission scale this is unnecessary load
on the API server.

Replace the bare controller-runtime client.New with a cache-backed
delegating client. The cache is started for the lifetime of the
webhook and watches Secrets cluster-wide; reads are served from the
informer, writes still go through the API server.

Signed-off-by: Haytham Abuelfutuh <[email protected]>
The k8s client is only used by embedded_secret_manager's image-pull-secret
path, which is gated on EmbeddedSecretManagerConfig.ImagePullSecrets.Enabled.
When the feature is disabled the informer was generating list/watch traffic
for nothing, so only build the cache when the feature is on. In the disabled
path fall back to a bare direct client.

Also explicitly register the Secret informer with the cache. controller-
runtime caches are type-lazy (an informer is only started on first access),
so the previous code relied on the embedded secret manager being the only
caller. The explicit registration:
- documents that this cache is intended only for Secret reads
- ensures WaitForCacheSync actually blocks on the initial Secret list
  rather than returning immediately on an empty informer set, so the first
  admission isn't a guaranteed cache miss

Signed-off-by: Haytham Abuelfutuh <[email protected]>
Copilot AI review requested due to automatic review settings May 7, 2026 21:09
@github-actions github-actions Bot added the flyte2 label May 7, 2026
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR adjusts the embedded secret manager’s Kubernetes client initialization in the webhook to avoid running a controller-runtime Secret informer when image pull secret injection is disabled, and to make the informer scope/sync behavior explicit when it is enabled.

Changes:

  • Conditionally create/start a controller-runtime cache only when EmbeddedSecretManagerConfig.ImagePullSecrets.Enabled is true; otherwise use a direct (non-cached) controller-runtime client.
  • When enabled, explicitly register the corev1.Secret informer before WaitForCacheSync to ensure startup blocks on the initial Secret list and the cache remains Secret-scoped.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants