Skip to content

Add namespace exclusion for watchers#623

Merged
winromulus merged 11 commits intoemberstack:mainfrom
seatgeek:feature/excluded-namespaces
Apr 25, 2026
Merged

Add namespace exclusion for watchers#623
winromulus merged 11 commits intoemberstack:mainfrom
seatgeek:feature/excluded-namespaces

Conversation

@komapa
Copy link
Copy Markdown
Contributor

@komapa komapa commented Mar 27, 2026

The reflector watches all ConfigMaps and Secrets across every namespace in the cluster. In large clusters with thousands of ConfigMaps, this creates massive event volume — the vast majority of which are for resources with no reflector annotations. This unnecessary traffic saturates the internal bounded channel (256 slots) and can contribute to silent stalls.

This PR adds a new excludedNamespaces configuration option that accepts comma-separated glob patterns. Events from matching namespaces are dropped before entering the bounded channel, eliminating noise at the earliest possible point.

@github-actions
Copy link
Copy Markdown

Automatically marked as stale due to no recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

@komapa
Copy link
Copy Markdown
Contributor Author

komapa commented Apr 21, 2026

@winromulus would love to get this reviewed/merged if possible

Copy link
Copy Markdown
Contributor

@winromulus winromulus left a comment

Choose a reason for hiding this comment

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

Thanks for tackling this — the bounded-channel pressure in large clusters is a real operational pain point, and filtering at the producer side before the channel is the right layer to catch it.

A few observations from reading through, mostly small refinements plus one larger ask around test coverage.

What works well

  • Good choice of filter location — dropping events before WriteAsync means the channel never sees the noise.
  • Logging is thoughtful: patterns at session start, excluded count at session close when non-zero. Useful operational signal.
  • IOptionsMonitor.CurrentValue captured at session start matches how WatcherTimeout already behaves — consistent with the existing pattern.
  • Helm wiring is complete across both deployment.yaml and cron.yaml, values.yaml has an explanatory comment, README table updated.
  • Regex.Escape before replacing \* / \? is the correct glob-to-regex translation; RegexOptions.Compiled is appropriate for a per-event matcher.

Main ask: tests

The feature currently has no coverage. Given the integration suite already uses Testcontainers.K3s with a clean builder pattern (see MirroringIntegrationTests.AutoReflect_To_AllowedNamespaces), this feels like a good candidate for:

  • A unit-level test of the glob parser/matcher covering edge cases like empty strings, whitespace, * alone, multiple patterns, ? wildcards, and namespace names containing regex metacharacters. ParseGlobPatterns and IsNamespaceExcluded are private static in the base class today — extracting them to a small GlobMatcher helper would make them trivially testable and slightly more reusable.
  • An integration test mirroring the shape of AutoReflect_To_AllowedNamespaces: set ES_Reflector__Watcher__ExcludedNamespaces=excluded-*, create a source in an excluded namespace and verify no mirrors appear; create one in an allowed namespace and verify they do.

Without coverage, a future well-meaning simplification of the escape sequence could silently change ? matching or similar.

Scope clarification worth adding to the docs

One thing an operator might reasonably misread: this setting drops watch events originating in the listed namespaces, but it doesn't stop auto-reflection from creating mirrors into them — target-side filtering still runs off the source's reflection-auto-namespaces annotation. A sentence in the README covering that distinction would head off confusion.

On NamespaceWatcher

Since V1Namespace is cluster-scoped, item.Metadata.NamespaceProperty is null for namespace events and the filter short-circuits. That's actually correct — you want NamespaceWatcher to keep seeing events so auto-reflection fires on new namespace creation — just flagging it so the interaction is explicit in the review record.

Smaller notes left inline. Overall a focused, well-scoped change solving a concrete problem.


Thanks again for the contribution — this is clearly solving a real-world pain point, and I appreciate the care taken with the Helm wiring and observability. Happy to merge once the items above are addressed.

Comment thread README.md Outdated
Comment thread src/ES.Kubernetes.Reflector/Watchers/Core/WatcherBackgroundService.cs Outdated
Comment thread src/ES.Kubernetes.Reflector/Watchers/Core/WatcherBackgroundService.cs Outdated
Comment thread src/helm/reflector/values.yaml
komapa and others added 3 commits April 22, 2026 19:46
Extract namespace glob matching into a shared internal helper,
expose internals to the test assembly, and add unit and
integration coverage for skipping reflection from excluded
namespaces.
@komapa komapa requested a review from winromulus April 23, 2026 01:33
@komapa
Copy link
Copy Markdown
Contributor Author

komapa commented Apr 23, 2026

Thank you so much for the detailed review and directions.

I have to admit, I used quite a lot of AI for the unit/integration tests so please take a closer look there:

❯ dotnet test tests/ES.Kubernetes.Reflector.Tests/ES.Kubernetes.Reflector.Tests.csproj --no-build -verbosity:minimal 2>&1
[xUnit.net 00:00:00.00] xUnit.net VSTest Adapter v3.1.5+1b188a7b0a (64-bit .NET 10.0.5)
[xUnit.net 00:00:00.14]   Discovering: ES.Kubernetes.Reflector.Tests
[xUnit.net 00:00:00.25]   Discovered:  ES.Kubernetes.Reflector.Tests
[xUnit.net 00:00:00.36]   Starting:    ES.Kubernetes.Reflector.Tests
[xUnit.net 00:00:28.48]   Finished:    ES.Kubernetes.Reflector.Tests (ID = 'e0bea2b0f8b2c51a4d44fa5fcb5344e51fd55832d3ed1872674304864c6cfc26')
  ES.Kubernetes.Reflector.Tests test net10.0 succeeded (28.9s)

Test summary: total: 27, failed: 0, succeeded: 27, skipped: 0, duration: 28.9s
Build succeeded in 29.0s

winromulus
winromulus previously approved these changes Apr 24, 2026
Copy link
Copy Markdown
Contributor

@winromulus winromulus left a comment

Choose a reason for hiding this comment

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

Really appreciate the engagement here — this is a clean, well-tested response. Walked through each of the earlier asks against the current code:

  • Drop redundant .WhereGlobMatcher.ParseGlobPatterns uses only Split(RemoveEmptyEntries | TrimEntries).Select(...). ✓
  • README wording → now "exclude from reflection processing." ✓
  • Case sensitivity → patterns normalized to lowercase at parse time. ✓
  • NamespaceWatcher no-op comment → clear 3-line explanation inline. ✓
  • Extract to helper classGlobMatcher with a clean static surface. ✓
  • Unit tests → 19 tests in GlobMatcherTests with good coverage; the metacharacter cases (ns.special as literal, ns[1] with brackets) are the ones that would catch a future refactor breaking the escape-before-substitute order. Nice.
  • Integration testExcludedNamespacesIntegrationTests with its own fixture wiring. ✓

On the AI-assisted tests: honest take — the unit tests are genuinely solid, especially the metacharacter edge cases. The integration test is functionally correct with one structural observation left inline.

Three small things, none blocking — all covered inline. Otherwise this is in really good shape.

Comment thread src/ES.Kubernetes.Reflector/Watchers/Core/WatcherBackgroundService.cs Outdated
Comment thread src/helm/reflector/values.yaml Outdated
@winromulus
Copy link
Copy Markdown
Contributor

Heads up — the channel-buffer bump (256 → 1024) just landed on main as part of e6ba44f (same commit that closed #624 earlier today). That touches the same area of WatcherBackgroundService.cs you're editing, which is where the conflict is coming from. On rebase, take the 1024 value from main and keep your exclusion-filter additions around it — nothing else should collide.

komapa added 2 commits April 24, 2026 18:41
Update excludedNamespaces docs to describe reflection processing
rather than watching, and expand integration coverage to verify
excluded source namespaces do not auto-reflect while excluded target
namespaces still receive reflections.
@komapa
Copy link
Copy Markdown
Contributor Author

komapa commented Apr 24, 2026

Really appreciate the engagement here — this is a clean, well-tested response. Walked through each of the earlier asks against the current code:

  • Drop redundant .WhereGlobMatcher.ParseGlobPatterns uses only Split(RemoveEmptyEntries | TrimEntries).Select(...). ✓
  • README wording → now "exclude from reflection processing." ✓
  • Case sensitivity → patterns normalized to lowercase at parse time. ✓
  • NamespaceWatcher no-op comment → clear 3-line explanation inline. ✓
  • Extract to helper classGlobMatcher with a clean static surface. ✓
  • Unit tests → 19 tests in GlobMatcherTests with good coverage; the metacharacter cases (ns.special as literal, ns[1] with brackets) are the ones that would catch a future refactor breaking the escape-before-substitute order. Nice.
  • Integration testExcludedNamespacesIntegrationTests with its own fixture wiring. ✓

On the AI-assisted tests: honest take — the unit tests are genuinely solid, especially the metacharacter edge cases. The integration test is functionally correct with one structural observation left inline.

Three small things, none blocking — all covered inline. Otherwise this is in really good shape.

I believe all the latest requests have been addressed now. 🙇🏼

@winromulus winromulus enabled auto-merge (squash) April 25, 2026 07:51
Copy link
Copy Markdown
Contributor

@winromulus winromulus left a comment

Choose a reason for hiding this comment

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

Thanks for sticking with this through the back-and-forth — really appreciate the responsiveness on every piece of feedback.

The expanded integration test landed exactly where I was hoping, and I particularly like that the second test reads like inline documentation for the source-vs-target distinction. The unit tests on the regex metacharacter cases are great too — exactly the kind of thing that'll catch a well-meaning future refactor breaking the escape order.

Approving. Thanks again for solving a real operational pain point for folks running this at scale.

@winromulus winromulus merged commit 4488fa2 into emberstack:main Apr 25, 2026
4 checks passed
eleboucher pushed a commit to eleboucher/homelab that referenced this pull request Apr 27, 2026
… (10.0.35 → 10.0.39) (#293)

This PR contains the following updates:

| Package | Update | Change |
|---|---|---|
| [ghcr.io/emberstack/helm-charts/reflector](https://github.com/emberstack/kubernetes-reflector) | patch | `10.0.35` → `10.0.39` |

---

### Release Notes

<details>
<summary>emberstack/kubernetes-reflector (ghcr.io/emberstack/helm-charts/reflector)</summary>

### [`v10.0.39`](https://github.com/emberstack/kubernetes-reflector/releases/tag/v10.0.39)

[Compare Source](emberstack/kubernetes-reflector@v10.0.38...v10.0.39)

The release process is automated.

#### What's Changed

- Add namespace exclusion for watchers by [@&#8203;komapa](https://github.com/komapa) in [#&#8203;623](emberstack/kubernetes-reflector#623)

#### New Contributors

- [@&#8203;komapa](https://github.com/komapa) made their first contribution in [#&#8203;623](emberstack/kubernetes-reflector#623)

**Full Changelog**: <emberstack/kubernetes-reflector@v10.0.38...v10.0.39>

### [`v10.0.38`](https://github.com/emberstack/kubernetes-reflector/releases/tag/v10.0.38)

[Compare Source](emberstack/kubernetes-reflector@v10.0.37...v10.0.38)

The release process is automated.

#### What's Changed

- Add namespace label selector support for reflection by [@&#8203;davidswimbird](https://github.com/davidswimbird) in [#&#8203;620](emberstack/kubernetes-reflector#620)

#### New Contributors

- [@&#8203;davidswimbird](https://github.com/davidswimbird) made their first contribution in [#&#8203;620](emberstack/kubernetes-reflector#620)

**Full Changelog**: <emberstack/kubernetes-reflector@v10.0.37...v10.0.38>

### [`v10.0.37`](https://github.com/emberstack/kubernetes-reflector/releases/tag/v10.0.37)

[Compare Source](emberstack/kubernetes-reflector@v10.0.36...v10.0.37)

The release process is automated.

#### What's Changed

- Bump the all-dependencies group with 8 updates by [@&#8203;dependabot](https://github.com/dependabot)\[bot] in [#&#8203;642](emberstack/kubernetes-reflector#642)

**Full Changelog**: <emberstack/kubernetes-reflector@v10.0.36...v10.0.37>

### [`v10.0.36`](https://github.com/emberstack/kubernetes-reflector/releases/tag/v10.0.36)

[Compare Source](emberstack/kubernetes-reflector@v10.0.35...v10.0.36)

The release process is automated.

#### What's Changed

- Bump the all-dependencies group with 6 updates by [@&#8203;dependabot](https://github.com/dependabot)\[bot] in [#&#8203;641](emberstack/kubernetes-reflector#641)

**Full Changelog**: <emberstack/kubernetes-reflector@v10.0.35...v10.0.36>

</details>

---

### Configuration

📅 **Schedule**: Branch creation - "before 6am on Monday" in timezone Europe/Paris, Automerge - At any time (no schedule defined).

🚦 **Automerge**: Disabled because a matching PR was automerged previously.

♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox.

🔕 **Ignore**: Close this PR and you won't be reminded about this update again.

---

 - [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check this box

---

This PR has been generated by [Renovate Bot](https://github.com/renovatebot/renovate).
<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0My4xMDEuMSIsInVwZGF0ZWRJblZlciI6IjQzLjEwMS4xIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6WyJyZW5vdmF0ZS9jb250YWluZXIiLCJ0eXBlL3BhdGNoIl19-->

Reviewed-on: https://git.erwanleboucher.dev/eleboucher/homelab/pulls/293
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

2 participants