Skip to content

feat: add namespace-scoped silence enforcement (v1alpha2)#698

Open
splattner wants to merge 2 commits into
giantswarm:mainfrom
splattner:feature/namespace-enforcement
Open

feat: add namespace-scoped silence enforcement (v1alpha2)#698
splattner wants to merge 2 commits into
giantswarm:mainfrom
splattner:feature/namespace-enforcement

Conversation

@splattner

Copy link
Copy Markdown

What

Adds a selector-gated, off-by-default multi-tenancy control for the
observability.giantswarm.io/v1alpha2 API. When one or more rules are configured,
a Silence created in a namespace matching a rule's namespaceSelector gets an
authoritative namespace="<namespace>" matcher (plus any custom matchers from the
rule) injected into the Alertmanager silence — so a silence can only ever mute
alerts belonging to its own namespace.

Why

By default a Silence in one namespace can mute alerts from any namespace, since
a silence is just a set of Alertmanager matchers. This provides lightweight
namespace isolation for shared-Alertmanager, multi-tenant setups.

How it works

  • Configured via a mounted YAML file (--namespace-enforcement-config), rendered by
    Helm from namespaceEnforcement values into a ConfigMap.
  • Rules use native metav1.LabelSelector. A namespace is enforced if it matches
    any rule (OR). Empty rules ⇒ no enforcement (the default).
  • Rules are first-match-wins (top-to-bottom); the first matching rule's custom
    matchers apply.
  • Enforcement is authoritative: a user-supplied matcher on an enforced label is
    overridden, logged, and surfaced as a MatcherOverridden Kubernetes Event on the
    Silence.
  • Evaluated at reconcile time and fail-closed — if the namespace lookup fails,
    the silence is not synced.

Example

namespaceEnforcement:
  matcherLabel: "namespace"
  rules:
    - namespaceSelector:
        matchLabels:
          tenant-isolation: "enabled"
    - namespaceSelector:
        matchExpressions:
          - key: team
            operator: In
            values: [platform]
      matchers:
        - name: cluster_id
          value: prod
          matchType: "="

Add a selector-gated, off-by-default multi-tenancy control for the
observability.giantswarm.io/v1alpha2 API. When one or more rules are
configured, a Silence created in a namespace matching a rule's
namespaceSelector gets an authoritative "namespace=<namespace>" matcher
(plus any custom matchers from the rule) injected into the Alertmanager
silence, so it can only mute alerts from its own namespace.

- pkg/enforce: config loader (mounted YAML) + first-match-wins rule
  evaluation and override-on-collision matcher application
- v2 controller: apply enforcement at reconcile time (fail-closed on
  namespace lookup), emit a MatcherOverridden Event when a user matcher
  is overridden
- alertmanager.NewMatcher: shared match-type conversion helper
- Helm: namespaceEnforcement values, ConfigMap, volume mount, checksum
  rollout; RBAC read access to namespaces (also fixes the pre-existing
  gap for the namespaceSelector predicate)
- Unit + envtest integration tests; README documentation

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@splattner
splattner requested a review from a team as a code owner July 23, 2026 06:59
The enforcement config loader imports sigs.k8s.io/yaml directly, so
`go mod tidy` moves it out of the indirect block.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant