Skip to content

chore: apply the ai-namespace consistency conventions repo-wide - #4211

Merged
Tanguille merged 9 commits into
mainfrom
chore/repo-consistency
Jul 27, 2026
Merged

chore: apply the ai-namespace consistency conventions repo-wide#4211
Tanguille merged 9 commits into
mainfrom
chore/repo-consistency

Conversation

@Tanguille

@Tanguille Tanguille commented Jul 27, 2026

Copy link
Copy Markdown
Owner

Follow-up to #4209, applying the same conventions to the other ten namespaces. No runtime behaviour change.

Scope

namespace files
network 28
observability 24
media 13
database 6
kube-system 5
default 4
flux-system, rook-ceph, web3, security 7

87 files, +59/-143.

Proof

flate build hr over every HelmRelease in the repo, before and after. Rendered chart output vs origin/main:

changed 0
removed 0
added 1ConfigMap kube-system/spegel-dashboard, the intended spegel change

So apart from that one deliberate addition, the rendered output is byte-identical. CRD-default removals were separately confirmed with kubectl apply --dry-run=server, and rendered Kustomizations were compared per namespace as well.

Reverted by that check

Four proposals passed adversarial verification but changed real behaviour, and were dropped:

Proposal Why it was wrong
metrics-server --kubelet-preferred-address-types, --kubelet-use-node-status-port found in the chart's defaultArgs, but this release sets args, which replaces defaultArgs; both flags vanished from the rendered Deployment
external-dns --crd-source-apiversion, --crd-source-kind match the binary's CLI defaults, not chart defaults, so they left the rendered args
nextcloud nginx comment lives inside the rendered config, so it moves the ConfigMap and forces a restart
k8s-gateway fullnameOverride names and ConfigMap data identical, but checksum/config moved, rolling cluster DNS for no gain

Also

default/karakeep hostname to {{ .Release.Name }} — the last of three app-template hostnames repo-wide duplicating their release name. Verified by rendering the HTTPRoute before and after.

Merges cleanly with #4210, which touches the same karakeep file.

Summary by CodeRabbit

  • New Features

    • External service endpoints now use headless service discovery across multiple applications.
    • Application routes can derive hostnames from their deployment release names.
    • Service account token access is enabled where required.
  • Bug Fixes

    • Updated Ceph configuration to ensure values are accepted correctly.
    • Improved dashboard sourcing and startup probe behavior.
    • Disabled unsupported NVMe-over-Fabrics storage integration.
  • Documentation

    • Added or updated schema hints and operational guidance across Kubernetes resources for improved validation and editor support.
    • Clarified database password rotation behavior and GPU fan monitoring alerts.

Follow-ups added after review

Issue Fix
Three ks.yaml got an anchor declared but never dereferenced (brrpolice, victoria-logs, crowdsec) the dereference was a separate finding my applier skipped as ambiguous; completed both halves
kepler-power-monitor gained a targetNamespace its only resource is a cluster-scoped PowerMonitor (Flux inventory _power-monitor_..); forcing a namespace is rejected by the API server. Reverted
amdgpu-undervolt comment rewritten restored the original measured wording; the rewrite added an interpretation that was not what was measured
Renovate's GrafanaDashboard URL manager never matched anything matchStringsStrategy: recursive made the second pattern search inside the first pattern's match, where the version does not appear. Both tracked dashboards had drifted (spegel v0.7.2 vs chart 0.7.4, klipper-exporter v0.15.0 vs v0.16.0). Replaced with one combined pattern, verified to match exactly the 2 version-pinned URLs and none of the 23 branch-tracking ones

Rendered Kustomizations were also compared per namespace against origin/main, not just HelmReleases. The only remaining rendered difference is imagePullPolicy on amdgpu-undervolt, which --dry-run=server refills as IfNotPresent.

The literal `karakeep.${SECRET_DOMAIN}` duplicates the release name. Ten-plus
app-template HelmReleases in the repo already use `{{ .Release.Name }}`, so
this was the odd one out.

Verified rather than assumed, since a wrong hostname takes the app offline:
rendering the HelmRelease through helm template before and after yields the
same HTTPRoute hostname, confirming app-template tpl-renders the value.

This was the last of three such hostnames repo-wide; the other two, ai/odysseus
and ai/opencode, are on #4209.
Same pass as #4209, applied to the other ten namespaces: restated CRD and chart
defaults, ks.yaml house shape, stale or duplicated comments, and dead config.

Every change is proven inert by rendering EVERY HelmRelease in the repo through
helm template before and after: the output is byte-identical to origin/main.

Four proposals were reverted because that render check caught them changing
real behaviour, despite each having passed an adversarial verification pass:

- metrics-server: `--kubelet-preferred-address-types` and
  `--kubelet-use-node-status-port` were found in the chart's `defaultArgs`, but
  this HelmRelease sets `args`, which REPLACES defaultArgs rather than extending
  it. Removing them dropped both flags from the rendered Deployment.
- external-dns: `--crd-source-apiversion` / `--crd-source-kind` match the
  binary's own CLI defaults but are not chart defaults, so they vanished from
  the rendered args. Not worth gambling on cluster DNS records.
- nextcloud: the flagged comment lives inside the rendered nginx config, so
  removing it changes the ConfigMap and forces a restart.
- k8s-gateway: dropping `fullnameOverride` left every object name and the
  ConfigMap data identical, but moved the chart's `checksum/config`, which
  would roll cluster DNS for no gain.

Also carries the karakeep hostname change: the last of three app-template
hostnames repo-wide that duplicated their release name.
@coderabbitai

coderabbitai Bot commented Jul 27, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@Tanguille, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 12 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 2d568696-499b-4dc2-a832-53a64f0defaf

📥 Commits

Reviewing files that changed from the base of the PR and between e273e46 and 0bb2edd.

📒 Files selected for processing (9)
  • .renovaterc.json5
  • kubernetes/apps/kube-system/amdgpu-undervolt.yaml
  • kubernetes/apps/kube-system/etcd-defrag/app/helmrelease.yaml
  • kubernetes/apps/kube-system/spegel/app/grafanadashboard.yaml
  • kubernetes/apps/kube-system/spegel/app/helmrelease.yaml
  • kubernetes/apps/media/brrpolice/ks.yaml
  • kubernetes/apps/observability/exporters/kepler/ks.yaml
  • kubernetes/apps/observability/victoria-logs/ks.yaml
  • kubernetes/apps/security/crowdsec/ks.yaml
📝 Walkthrough

Walkthrough

This change updates Kubernetes schema hints, namespace handling, headless external services, Helm workload defaults, persistence mounts, probes, database policies, Ceph settings, and observability configuration across cluster manifests.

Changes

Kubernetes manifest normalization

Layer / File(s) Summary
Schema hints and manifest structure
kubernetes/apps/**/
Adds or updates YAML schema directives, anchors, namespace references, formatting, and selected application metadata.
External service networking
kubernetes/apps/network/external-service/**, kubernetes/apps/flux-system/flux-instance/app/httproute.yaml
Converts external Services to headless Services, removes explicit EndpointSlice TCP protocols, and updates HTTPRoute backend routing.
Workload defaults and storage mappings
kubernetes/apps/default/**, kubernetes/apps/media/**, kubernetes/apps/web3/**, kubernetes/apps/kube-system/**
Adjusts pod defaults, startup probes, persistence mounts, service monitors, routes, retry settings, and Helm values.
Platform observability and storage configuration
kubernetes/apps/database/**, kubernetes/apps/observability/**, kubernetes/apps/rook-ceph/**
Updates database policies and comments, scheduled workload settings, observability resources, Ceph values, exporter settings, and namespace configuration.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Possibly related PRs

  • Tanguille/cluster#4195: Both changes modify the etcd-defrag HelmRelease schedule or related CronJob configuration.
  • Tanguille/cluster#4209: Both changes update YAML language-server schema directives in CloudNativePG manifests.
🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately summarizes the repo-wide convention cleanup across namespaces and matches the main intent of the PR.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch chore/repo-consistency

Comment @coderabbitai help to get the list of available commands.

@tanguille-cluster

tanguille-cluster Bot commented Jul 27, 2026

Copy link
Copy Markdown
@@ spec @@
# postgresql.cnpg.io/v1/Database/database/litellm
! - one map entry removed:
- databaseReclaimPolicy: retain

@@ spec.values.defaultPodOptions @@
# helm.toolkit.fluxcd.io/v2/HelmRelease/default/homepage
! - one map entry removed:
- enableServiceLinks: false

@@ data.settings.yaml @@
# v1/ConfigMap/default/homepage-configmap
! ± value change in multiline text (no inserts, one deletion)
  ---
  title: Cluster
  favicon: https://raw.githubusercontent.com/homarr-labs/dashboard-icons/main/png/kubernetes.png
  theme: dark
  
  [26 lines unchanged)]
  
    Management: { tab: Media, style: row, columns: 4 }
    Processing: { tab: Media, style: row, columns: 3 }
  
    # AI tab
-   Interfaces: { tab: AI, style: row, columns: 3 }
-   Models: { tab: AI, style: row, columns: 3 }
    Agents: { tab: AI, style: row, columns: 3 }
  
    # Apps tab
    Portals: { tab: Apps, style: row, columns: 4 }
  
  [six lines unchanged)]
  
  
    # Infra tab
    Security: { tab: Infra, style: row, columns: 3 }
    External: { tab: Infra, style: row, columns: 3 }

@@ spec.values.route.app.hostnames.0 @@
# helm.toolkit.fluxcd.io/v2/HelmRelease/default/karakeep
! ± value change
- karakeep...PLACEHOLDER_SECRET_DOMAIN..
+ {{ .Release.Name }}...PLACEHOLDER_SECRET_DOMAIN..

@@ spec.values.defaultPodOptions @@
# helm.toolkit.fluxcd.io/v2/HelmRelease/default/moonraker-obico
! - one map entry removed:
- automountServiceAccountToken: false

@@ spec.values.persistence.config @@
# helm.toolkit.fluxcd.io/v2/HelmRelease/default/moonraker-obico
! - one map entry removed:
- enabled: true

@@ spec.values.defaultPodOptions @@
# helm.toolkit.fluxcd.io/v2/HelmRelease/default/searxng
! - one map entry removed:
- enableServiceLinks: false

@@ spec.template.spec.containers.app @@
# apps/v1/DaemonSet/kube-system/amdgpu-undervolt
! - one map entry removed:
- imagePullPolicy: IfNotPresent

@@ spec.values.instance @@
# helm.toolkit.fluxcd.io/v2/HelmRelease/flux-system/flux-instance
! - one map entry removed:
- components:
- - source-controller
- - kustomize-controller
- - helm-controller
- - notification-controller

@@ spec.rules.0.backendRefs.webhook-receiver @@
# gateway.networking.k8s.io/v1/HTTPRoute/flux-system/github-webhook
! - one map entry removed:
- namespace: flux-system

@@ spec.values.cgroup @@
# helm.toolkit.fluxcd.io/v2/HelmRelease/kube-system/cilium
! - one map entry removed:
- automount:
-   enabled: false

@@ spec.values.controllers.etcd-defrag.cronjob @@
# helm.toolkit.fluxcd.io/v2/HelmRelease/kube-system/etcd-defrag
! - three map entries removed:
- concurrencyPolicy: Forbid
- failedJobsHistory: 1
- successfulJobsHistory: 1

@@ spec.values.defaultPodOptions @@
# helm.toolkit.fluxcd.io/v2/HelmRelease/kube-system/etcd-defrag
! - one map entry removed:
- automountServiceAccountToken: false

@@ spec @@
# grafana.integreatly.org/v1beta1/GrafanaDashboard/kube-system/spegel
! - one map entry removed:
- url: "https://raw.githubusercontent.com/spegel-org/spegel/v0.7.2/charts/spegel/monitoring/grafana-dashboard.json"
! + one map entry added:
+ configMapRef:
+   name: spegel-dashboard
+   key: spegel.json

@@ spec.values @@
# helm.toolkit.fluxcd.io/v2/HelmRelease/kube-system/spegel
! + one map entry added:
+ grafanaDashboard:
+   enabled: true
+   mode: Sidecar

@@ spec.values.controllers.deduparr.containers.app.probes.startup.spec @@
# helm.toolkit.fluxcd.io/v2/HelmRelease/media/deduparr
! - one map entry removed:
- periodSeconds: 10

@@ spec.values.persistence.config.globalMounts.0 @@
# helm.toolkit.fluxcd.io/v2/HelmRelease/media/fileflows
! - one map entry removed:
- readOnly: false

@@ spec.values.persistence.temp @@
# helm.toolkit.fluxcd.io/v2/HelmRelease/media/fileflows
! - one map entry removed:
- globalMounts:
- - path: /temp
-   readOnly: false

@@ spec.values.controllers.jellyfin.containers.app.probes.startup.spec @@
# helm.toolkit.fluxcd.io/v2/HelmRelease/media/jellyfin
! - one map entry removed:
- periodSeconds: 10

@@ spec.values.persistence.config @@
# helm.toolkit.fluxcd.io/v2/HelmRelease/media/jellyfin
! - one map entry removed:
- advancedMounts:
-   jellyfin:
-     app:
-     - path: /config

@@ spec.values.persistence.library @@
# helm.toolkit.fluxcd.io/v2/HelmRelease/media/jellyfin
! - one map entry removed:
- globalMounts:
- - path: /var/mnt/merged/

@@ spec.values.persistence.media.globalMounts.0 @@
# helm.toolkit.fluxcd.io/v2/HelmRelease/media/jellyfin
! - one map entry removed:
- readOnly: false

@@ spec.values.defaultPodOptions @@
# helm.toolkit.fluxcd.io/v2/HelmRelease/media/prowlarr
! - one map entry removed:
- enableServiceLinks: false

@@ spec.values.persistence.config @@
# helm.toolkit.fluxcd.io/v2/HelmRelease/media/qbitrr
! - two map entries removed:
- type: persistentVolumeClaim
- globalMounts:
- - path: /config
-   readOnly: false

@@ spec.values.persistence.config-template.globalMounts.0 @@
# helm.toolkit.fluxcd.io/v2/HelmRelease/media/qbitrr
! - one map entry removed:
- path: /config-template

@@ spec.values.persistence.downloads.globalMounts.0 @@
# helm.toolkit.fluxcd.io/v2/HelmRelease/media/qbitrr
! - one map entry removed:
- readOnly: false

@@ spec.values.controllers.qbittorrent.containers.app.probes.startup.spec @@
# helm.toolkit.fluxcd.io/v2/HelmRelease/media/qbittorrent
! - one map entry removed:
- periodSeconds: 10

@@ spec.values.persistence.config @@
# helm.toolkit.fluxcd.io/v2/HelmRelease/media/qbittorrent
! - one map entry removed:
- advancedMounts:
-   qbittorrent:
-     app:
-     - path: /config

@@ spec.values.route.app @@
# helm.toolkit.fluxcd.io/v2/HelmRelease/media/qbittorrent
! - one map entry removed:
- rules:
- - backendRefs:
-   - identifier: app
-     port: 80

@@ spec.values.controllers.qui.containers.app.probes.startup.spec @@
# helm.toolkit.fluxcd.io/v2/HelmRelease/media/qui
! - one map entry removed:
- periodSeconds: 10

@@ spec.values.defaultPodOptions @@
# helm.toolkit.fluxcd.io/v2/HelmRelease/media/qui
! - one map entry removed:
- enableServiceLinks: false

@@ spec.values.persistence.config @@
# helm.toolkit.fluxcd.io/v2/HelmRelease/media/qui
! - one map entry removed:
- globalMounts:
- - path: /config

@@ spec.values.route.app @@
# helm.toolkit.fluxcd.io/v2/HelmRelease/media/qui
! - one map entry removed:
- rules:
- - backendRefs:
-   - identifier: app
-     port: 7476

@@ spec.values.defaultPodOptions @@
# helm.toolkit.fluxcd.io/v2/HelmRelease/media/radarr
! - one map entry removed:
- enableServiceLinks: false

@@ spec.values.controllers.recyclarr.cronjob @@
# helm.toolkit.fluxcd.io/v2/HelmRelease/media/recyclarr
! - two map entries removed:
- failedJobsHistory: 1
- successfulJobsHistory: 1

@@ spec.values.persistence.config @@
# helm.toolkit.fluxcd.io/v2/HelmRelease/media/recyclarr
! - one map entry removed:
- type: persistentVolumeClaim

@@ spec.values.defaultPodOptions @@
# helm.toolkit.fluxcd.io/v2/HelmRelease/media/sonarr
! - one map entry removed:
- enableServiceLinks: false

@@ spec.values.serviceMonitor.app @@
# helm.toolkit.fluxcd.io/v2/HelmRelease/media/unpackerr
! - one map entry removed:
- serviceName: unpackerr

@@ spec.retry @@
# gateway.envoyproxy.io/v1alpha1/BackendTrafficPolicy/network/envoy
! - one map entry removed:
- numRetries: 2

@@ spec @@
# v1/Service/network/internal-arm
! - one map entry removed:
- type: ClusterIP

@@ ports.http @@
# discovery.k8s.io/v1/EndpointSlice/network/internal-arm
! - one map entry removed:
- protocol: TCP

@@ spec @@
# v1/Service/network/internal-avr
! - one map entry removed:
- type: ClusterIP

@@ ports.http @@
# discovery.k8s.io/v1/EndpointSlice/network/internal-avr
! - one map entry removed:
- protocol: TCP

@@ spec @@
# v1/Service/network/internal-centauri-carbon
! - one map entry removed:
- type: ClusterIP

@@ ports.http @@
# discovery.k8s.io/v1/EndpointSlice/network/internal-centauri-carbon
! - one map entry removed:
- protocol: TCP

@@ spec @@
# v1/Service/network/external-homeassistant
! - one map entry removed:
- type: ClusterIP

@@ ports.http @@
# discovery.k8s.io/v1/EndpointSlice/network/external-homeassistant
! - one map entry removed:
- protocol: TCP

@@ spec @@
# v1/Service/network/internal-ipmi
! - one map entry removed:
- type: ClusterIP

@@ ports.https @@
# discovery.k8s.io/v1/EndpointSlice/network/internal-ipmi
! - one map entry removed:
- protocol: TCP

@@ spec @@
# v1/Service/network/internal-ntopg
! - one map entry removed:
- type: ClusterIP

@@ ports.http @@
# discovery.k8s.io/v1/EndpointSlice/network/internal-ntopg
! - one map entry removed:
- protocol: TCP

@@ spec @@
# v1/Service/network/internal-opnsense
! - one map entry removed:
- type: ClusterIP

@@ ports.https @@
# discovery.k8s.io/v1/EndpointSlice/network/internal-opnsense
! - one map entry removed:
- protocol: TCP

@@ spec @@
# v1/Service/network/internal-scrutiny
! - one map entry removed:
- type: ClusterIP

@@ ports.http @@
# discovery.k8s.io/v1/EndpointSlice/network/internal-scrutiny
! - one map entry removed:
- protocol: TCP

@@ spec @@
# v1/Service/network/internal-truenas
! - one map entry removed:
- type: ClusterIP

@@ ports.https @@
# discovery.k8s.io/v1/EndpointSlice/network/internal-truenas
! - one map entry removed:
- protocol: TCP

@@ spec @@
# v1/Service/network/internal-vaultwarden
! - one map entry removed:
- type: ClusterIP

@@ ports.http @@
# discovery.k8s.io/v1/EndpointSlice/network/internal-vaultwarden
! - one map entry removed:
- protocol: TCP

@@ spec.values.gatus.securityContext @@
# helm.toolkit.fluxcd.io/v2/HelmRelease/observability/gatus
! - two map entries removed:
- allowPrivilegeEscalation: false
- readOnlyRootFilesystem: true

@@ spec.values.gatus.securityContext.capabilities @@
# helm.toolkit.fluxcd.io/v2/HelmRelease/observability/gatus
! - one map entry removed:
- drop:
- - ALL

@@ spec.kepler @@
# kepler.system.sustainable.computing.io/v1alpha1/PowerMonitor/observability/power-monitor
! - one map entry removed:
- config:
-   logLevel: info

@@ spec.values.cephFileSystems.ceph-filesystem.storageClass @@
# helm.toolkit.fluxcd.io/v2/HelmRelease/rook-ceph/rook-ceph-cluster
! - two map entries removed:
- isDefault: false
- pool: data0

@@ spec.values.drivers.nfs @@
# helm.toolkit.fluxcd.io/v2/HelmRelease/rook-ceph/ceph-csi-drivers
! - one map entry removed:
- name: rook-ceph.nfs.csi.ceph.com

@@ spec.values.drivers.nvmeof @@
# helm.toolkit.fluxcd.io/v2/HelmRelease/rook-ceph/ceph-csi-drivers
! - one map entry removed:
- name: rook-ceph.nvmeof.csi.ceph.com

@Tanguille
Tanguille marked this pull request as ready for review July 27, 2026 17:24
Three ks.yaml files got a YAML anchor declared but never dereferenced, which is
strictly worse than not touching them - it adds a token that reads like it means
something and does not.

Cause: the dereference was a separate finding that my applier skipped because
the literal it had to replace appears twice per file (both documents), so the
"exactly one match" guard rejected it and only the anchor half landed.

- brrpolice: postBuild.substitute.APP duplicated the release name, so &app now
  has a real referent (APP: *app), matching ai/hermes.
- victoria-logs, crowdsec: targetNamespace was literal in both documents; now
  *namespace in each.

Rendered Kustomization specs are unchanged - name, namespace and targetNamespace
resolve to the same strings as before.
Comparing every rendered Kustomization against origin/main, not just the
HelmReleases, surfaced two problems the earlier pass missed.

kepler-power-monitor gained a targetNamespace it never had. Its only resource
is a PowerMonitor, and that CRD is CLUSTER scoped - Flux's own inventory records
it as `_power-monitor_..._PowerMonitor`, with the leading underscore standing in
for the empty namespace. Forcing a namespace onto a cluster-scoped object gets
rejected by the API server, so this would have broken the Kustomization rather
than tidied it. Reverted, along with the anchor that only existed to feed it.

amdgpu-undervolt: restored the original comment. The rewrite turned a plain
measured statement, "210 remains the best tok/W on both metrics", into one
carrying an interpretation about why 250 is set. The reasoning is defensible
from the surrounding numbers but it is not what was measured, and these comments
are meant to record measurements.

The imagePullPolicy removal in the same file is kept: `kubectl apply
--dry-run=server` returns IfNotPresent for that digest-pinned image, so it is
genuinely the default.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🧹 Nitpick comments (1)
kubernetes/apps/observability/victoria-logs/ks.yaml (1)

7-7: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Use the declared namespace anchors consistently.

Each Kustomization introduces &namespace but leaves targetNamespace as a duplicated literal. Replace those literals with *namespace to prevent metadata and target namespace values from drifting.

  • kubernetes/apps/observability/victoria-logs/ks.yaml#L7-L7: change the first document’s targetNamespace to *namespace.
  • kubernetes/apps/observability/victoria-logs/ks.yaml#L27-L27: change the second document’s targetNamespace to *namespace.
  • kubernetes/apps/security/crowdsec/ks.yaml#L7-L7: change the first document’s targetNamespace to *namespace.
  • kubernetes/apps/security/crowdsec/ks.yaml#L27-L27: change the second document’s targetNamespace to *namespace.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@kubernetes/apps/observability/victoria-logs/ks.yaml` at line 7, Replace each
duplicated targetNamespace literal with the declared *namespace anchor in both
documents of kubernetes/apps/observability/victoria-logs/ks.yaml (lines 7 and
27) and kubernetes/apps/security/crowdsec/ks.yaml (lines 7 and 27), keeping the
existing namespace declarations unchanged.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@kubernetes/apps/kube-system/amdgpu-undervolt.yaml`:
- Line 33: Correct the tuning comment near the 210W/250W guidance to state that
330W is roughly 19% worse in PP/W based on the measurements on lines 29–30, or
explicitly identify the comparison baseline if retaining a different percentage.

In `@kubernetes/apps/kube-system/etcd-defrag/app/helmrelease.yaml`:
- Around line 33-34: Update the CronJob comment above the schedule in the etcd
defragmentation configuration to say “Daily” instead of “Weekly,” keeping the
rest of the explanation unchanged and aligned with the existing `0 3 * * *`
schedule.

---

Nitpick comments:
In `@kubernetes/apps/observability/victoria-logs/ks.yaml`:
- Line 7: Replace each duplicated targetNamespace literal with the declared
*namespace anchor in both documents of
kubernetes/apps/observability/victoria-logs/ks.yaml (lines 7 and 27) and
kubernetes/apps/security/crowdsec/ks.yaml (lines 7 and 27), keeping the existing
namespace declarations unchanged.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: dc6471fc-75ca-45bf-bde5-1abe55c9add2

📥 Commits

Reviewing files that changed from the base of the PR and between 7f352ce and e273e46.

📒 Files selected for processing (88)
  • kubernetes/apps/database/cloudnative-pg/barman-cloud/helmrelease.yaml
  • kubernetes/apps/database/cloudnative-pg/cluster/cluster.yaml
  • kubernetes/apps/database/cloudnative-pg/cluster/pooler-ro.yaml
  • kubernetes/apps/database/cloudnative-pg/cluster/pooler-session.yaml
  • kubernetes/apps/database/cloudnative-pg/cluster/pooler.yaml
  • kubernetes/apps/database/cloudnative-pg/databases/litellm.yaml
  • kubernetes/apps/default/homepage/app/helmrelease.yaml
  • kubernetes/apps/default/homepage/app/resources/settings.yaml
  • kubernetes/apps/default/karakeep/app/helmrelease.yaml
  • kubernetes/apps/default/obico/moonraker-obico/helmrelease.yaml
  • kubernetes/apps/default/searxng/app/helmrelease.yaml
  • kubernetes/apps/flux-system/flux-instance/app/helmrelease.yaml
  • kubernetes/apps/flux-system/flux-instance/app/httproute.yaml
  • kubernetes/apps/kube-system/amdgpu-undervolt.yaml
  • kubernetes/apps/kube-system/cilium/app/helmrelease.yaml
  • kubernetes/apps/kube-system/etcd-defrag/app/helmrelease.yaml
  • kubernetes/apps/kube-system/spegel/app/grafanadashboard.yaml
  • kubernetes/apps/kube-system/spegel/ks.yaml
  • kubernetes/apps/media/brrpolice/ks.yaml
  • kubernetes/apps/media/deduparr/app/helmrelease.yaml
  • kubernetes/apps/media/fileflows/app/helmrelease.yaml
  • kubernetes/apps/media/jellyfin/app/helmrelease.yaml
  • kubernetes/apps/media/prowlarr/app/helmrelease.yaml
  • kubernetes/apps/media/qbittorrent/app/helmrelease.yaml
  • kubernetes/apps/media/qbittorrent/tools/qbitrr/helmrelease.yaml
  • kubernetes/apps/media/qbittorrent/tools/qbitrr/ks.yaml
  • kubernetes/apps/media/qui/app/helmrelease.yaml
  • kubernetes/apps/media/radarr/app/helmrelease.yaml
  • kubernetes/apps/media/recyclarr/app/helmrelease.yaml
  • kubernetes/apps/media/sonarr/app/helmrelease.yaml
  • kubernetes/apps/media/unpackerr/app/helmrelease.yaml
  • kubernetes/apps/network/envoy-gateway/app/envoy.yaml
  • kubernetes/apps/network/external-service/arm/endpointslice.yaml
  • kubernetes/apps/network/external-service/arm/httproute.yaml
  • kubernetes/apps/network/external-service/arm/service.yaml
  • kubernetes/apps/network/external-service/avr/endpointslice.yaml
  • kubernetes/apps/network/external-service/avr/httproute.yaml
  • kubernetes/apps/network/external-service/avr/service.yaml
  • kubernetes/apps/network/external-service/centauri-carbon/endpointslice.yaml
  • kubernetes/apps/network/external-service/centauri-carbon/httproute.yaml
  • kubernetes/apps/network/external-service/centauri-carbon/service.yaml
  • kubernetes/apps/network/external-service/homeassistant/endpointslice.yaml
  • kubernetes/apps/network/external-service/homeassistant/httproute.yaml
  • kubernetes/apps/network/external-service/homeassistant/service.yaml
  • kubernetes/apps/network/external-service/ipmi/endpointslice.yaml
  • kubernetes/apps/network/external-service/ipmi/service.yaml
  • kubernetes/apps/network/external-service/ntopg/endpointslice.yaml
  • kubernetes/apps/network/external-service/ntopg/httproute.yaml
  • kubernetes/apps/network/external-service/ntopg/service.yaml
  • kubernetes/apps/network/external-service/opnsense/endpointslice.yaml
  • kubernetes/apps/network/external-service/opnsense/service.yaml
  • kubernetes/apps/network/external-service/scrutiny/endpointslice.yaml
  • kubernetes/apps/network/external-service/scrutiny/service.yaml
  • kubernetes/apps/network/external-service/truenas/endpointslice.yaml
  • kubernetes/apps/network/external-service/truenas/service.yaml
  • kubernetes/apps/network/external-service/vaultwarden/endpointslice.yaml
  • kubernetes/apps/network/external-service/vaultwarden/httproute.yaml
  • kubernetes/apps/network/external-service/vaultwarden/service.yaml
  • kubernetes/apps/network/smtp-relay/app/kustomization.yaml
  • kubernetes/apps/observability/exporters/drm-exporter/app/prometheusrule.yaml
  • kubernetes/apps/observability/exporters/kepler/ks.yaml
  • kubernetes/apps/observability/exporters/kepler/powermonitor/powermonitor.yaml
  • kubernetes/apps/observability/exporters/nut-exporter/ks.yaml
  • kubernetes/apps/observability/exporters/opnsense-exporter/app/helmrelease.yaml
  • kubernetes/apps/observability/exporters/prowlarr-exporter/ks.yaml
  • kubernetes/apps/observability/exporters/qbittorrent-exporter/ks.yaml
  • kubernetes/apps/observability/exporters/scraparr/app/helmrelease.yaml
  • kubernetes/apps/observability/exporters/scraparr/ks.yaml
  • kubernetes/apps/observability/exporters/sonarr-exporter/ks.yaml
  • kubernetes/apps/observability/exporters/speedtest-exporter/app/helmrelease.yaml
  • kubernetes/apps/observability/exporters/speedtest-exporter/ks.yaml
  • kubernetes/apps/observability/gatus/app/helmrelease.yaml
  • kubernetes/apps/observability/keda/ks.yaml
  • kubernetes/apps/observability/kromgo/app/helmrelease.yaml
  • kubernetes/apps/observability/kromgo/app/kustomization.yaml
  • kubernetes/apps/observability/kromgo/app/ocirepository.yaml
  • kubernetes/apps/observability/silence-operator/silences/silences.yaml
  • kubernetes/apps/observability/siren/app/helmrelease.yaml
  • kubernetes/apps/observability/siren/app/kustomization.yaml
  • kubernetes/apps/observability/siren/ks.yaml
  • kubernetes/apps/observability/victoria-logs/ks.yaml
  • kubernetes/apps/observability/victoria-metrics/app/kustomization.yaml
  • kubernetes/apps/observability/victoria-metrics/app/scrapeconfig.yaml
  • kubernetes/apps/rook-ceph/rook-ceph/cluster/helmrelease.yaml
  • kubernetes/apps/rook-ceph/rook-ceph/csi/helmrelease.yaml
  • kubernetes/apps/security/crowdsec/ks.yaml
  • kubernetes/apps/web3/monero/xmrig/helmrelease.yaml
  • kubernetes/apps/web3/monero/xmrig/scaledobject.yaml
🔗 Linked repositories identified

CodeRabbit considers these linked repositories for cross-repo context during reviews:

  • Tanguille/LLMKube (auto-detected)
💤 Files with no reviewable changes (45)
  • kubernetes/apps/default/homepage/app/helmrelease.yaml
  • kubernetes/apps/network/external-service/vaultwarden/service.yaml
  • kubernetes/apps/default/homepage/app/resources/settings.yaml
  • kubernetes/apps/kube-system/cilium/app/helmrelease.yaml
  • kubernetes/apps/network/external-service/opnsense/service.yaml
  • kubernetes/apps/default/obico/moonraker-obico/helmrelease.yaml
  • kubernetes/apps/media/qbittorrent/tools/qbitrr/ks.yaml
  • kubernetes/apps/media/radarr/app/helmrelease.yaml
  • kubernetes/apps/network/external-service/centauri-carbon/endpointslice.yaml
  • kubernetes/apps/network/external-service/avr/service.yaml
  • kubernetes/apps/network/external-service/ipmi/service.yaml
  • kubernetes/apps/network/external-service/truenas/service.yaml
  • kubernetes/apps/media/deduparr/app/helmrelease.yaml
  • kubernetes/apps/media/unpackerr/app/helmrelease.yaml
  • kubernetes/apps/network/external-service/truenas/endpointslice.yaml
  • kubernetes/apps/network/external-service/homeassistant/service.yaml
  • kubernetes/apps/network/external-service/arm/service.yaml
  • kubernetes/apps/network/external-service/scrutiny/service.yaml
  • kubernetes/apps/network/external-service/arm/endpointslice.yaml
  • kubernetes/apps/network/external-service/ntopg/service.yaml
  • kubernetes/apps/media/sonarr/app/helmrelease.yaml
  • kubernetes/apps/network/external-service/scrutiny/endpointslice.yaml
  • kubernetes/apps/media/qbittorrent/app/helmrelease.yaml
  • kubernetes/apps/network/external-service/homeassistant/endpointslice.yaml
  • kubernetes/apps/media/fileflows/app/helmrelease.yaml
  • kubernetes/apps/database/cloudnative-pg/databases/litellm.yaml
  • kubernetes/apps/network/external-service/avr/endpointslice.yaml
  • kubernetes/apps/media/recyclarr/app/helmrelease.yaml
  • kubernetes/apps/media/prowlarr/app/helmrelease.yaml
  • kubernetes/apps/network/external-service/opnsense/endpointslice.yaml
  • kubernetes/apps/observability/victoria-metrics/app/kustomization.yaml
  • kubernetes/apps/observability/exporters/opnsense-exporter/app/helmrelease.yaml
  • kubernetes/apps/network/external-service/ntopg/endpointslice.yaml
  • kubernetes/apps/default/searxng/app/helmrelease.yaml
  • kubernetes/apps/network/external-service/ipmi/endpointslice.yaml
  • kubernetes/apps/flux-system/flux-instance/app/helmrelease.yaml
  • kubernetes/apps/network/envoy-gateway/app/envoy.yaml
  • kubernetes/apps/flux-system/flux-instance/app/httproute.yaml
  • kubernetes/apps/observability/victoria-metrics/app/scrapeconfig.yaml
  • kubernetes/apps/network/external-service/centauri-carbon/service.yaml
  • kubernetes/apps/network/external-service/vaultwarden/endpointslice.yaml
  • kubernetes/apps/media/jellyfin/app/helmrelease.yaml
  • kubernetes/apps/media/qui/app/helmrelease.yaml
  • kubernetes/apps/rook-ceph/rook-ceph/csi/helmrelease.yaml
  • kubernetes/apps/web3/monero/xmrig/helmrelease.yaml

# Decode is bandwidth-bound and flat at ~23 across the whole range, so
# watts only buy prefill. 250 takes +15% PP for 2.8% worse PP/W; 330
# takes +27% for 15% worse. 210 remains the best tok/W on both metrics.
# takes +27% for 15% worse. 210 is best tok/W; 250 buys prefill headroom.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Correct the PP/W percentage in the tuning comment.

The measurements on Line 29 and Line 30 imply roughly 19% worse PP/W for 330W versus 210W, not 15%. Correct the percentage or state the comparison baseline explicitly.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@kubernetes/apps/kube-system/amdgpu-undervolt.yaml` at line 33, Correct the
tuning comment near the 210W/250W guidance to state that 330W is roughly 19%
worse in PP/W based on the measurements on lines 29–30, or explicitly identify
the comparison baseline if retaining a different percentage.

Comment on lines +33 to +34
# Weekly let fragmentation cross the 50% alert threshold by day 4; a
# full 3-member pass costs ~95s.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Keep the CronJob comment aligned with its schedule.

The schedule on Line 36 is daily (0 3 * * *), but the new comment says “Weekly.” Replace that wording so operators do not infer the wrong defragmentation cadence. (kubernetes.io)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@kubernetes/apps/kube-system/etcd-defrag/app/helmrelease.yaml` around lines 33
- 34, Update the CronJob comment above the schedule in the etcd defragmentation
configuration to say “Daily” instead of “Weekly,” keeping the rest of the
explanation unchanged and aligned with the existing `0 3 * * *` schedule.

…atched

The manager used matchStringsStrategy "recursive", where each matchString
searches inside the text matched by the previous one. The first pattern ended at
the slash after the repo name, so the version sat outside its match and the
second pattern could never capture currentValue. The manager therefore extracted
nothing and has never produced an update.

Both dashboards it was meant to track had silently drifted: spegel pinned v0.7.2
against chart 0.7.4, and klipper-exporter v0.15.0 against upstream v0.16.0.

Replaced with a single non-recursive pattern capturing depName and currentValue
together, and dropped autoReplaceStringTemplate - it replaced the whole match
with just the version, which is wrong once the URL is part of the match.

Verified with Renovate's own escaped string compiled as a RegExp: it matches
exactly the two version-pinned URLs and none of the 23 that deliberately track
main/master or a commit sha.
The dashboard JSON was fetched from a hand-pinned raw GitHub URL, which had
drifted to v0.7.2 while the chart ran 0.7.4, because the Renovate manager meant
to bump it never matched anything.

Enabling the chart's Sidecar mode makes it emit ConfigMap spegel-dashboard with
the JSON that ships with the chart, and the existing GrafanaDashboard now reads
that via configMapRef. The JSON is therefore versioned with the chart and cannot
drift again, with nothing left for Renovate to track here.

Not the chart's GrafanaOperator mode, because it cannot express spec.datasources.
Verified live rather than assumed: applying the chart's own GrafanaDashboard
under a throwaway uid left ${DS_PROMETHEUS} unresolved and 16 panels pointing at
a datasource that does not exist. The same JSON via configMapRef with the
datasources mapping resolved all 16 to uid "prometheus". Both test objects were
deleted; the live dashboard was never touched and still reports
"Dashboard was successfully applied to 1 instances" on uid 1iY4QMJVk-psee.
@tanguille-cluster

Copy link
Copy Markdown
@@ (root level) @@
# v1/ConfigMap/kube-system/spegel-dashboard
! + one document added:
+ apiVersion: v1
+ kind: ConfigMap
+ metadata:
+   name: spegel-dashboard
+   namespace: kube-system
+   labels:
+     app.kubernetes.io/instance: spegel
+     app.kubernetes.io/managed-by: Helm
+     app.kubernetes.io/name: spegel
+     helm.toolkit.fluxcd.io/name: spegel
+     helm.toolkit.fluxcd.io/namespace: kube-system
+ data:
+   spegel.json: |
+     {
+       "__inputs": [
+         {
+           "name": "DS_PROMETHEUS",
+           "label": "prometheus",
+           "description": "",
+           "type": "datasource",
+           "pluginId": "prometheus",
+           "pluginName": "Prometheus"
+         }
+       ],
+       "__elements": {},
+       "__requires": [
+         {
+           "type": "grafana",
+           "id": "grafana",
+           "name": "Grafana",
+           "version": "12.1.0"
+         },
+         {
+           "type": "datasource",
+           "id": "prometheus",
+           "name": "Prometheus",
+           "version": "1.0.0"
+         },
+         {
+           "type": "panel",
+           "id": "stat",
+           "name": "Stat",
+           "version": ""
+         },
+         {
+           "type": "panel",
+           "id": "table",
+           "name": "Table",
+           "version": ""
+         },
+         {
+           "type": "panel",
+           "id": "text",
+           "name": "Text",
+           "version": ""
+         },
+         {
+           "type": "panel",
+           "id": "timeseries",
+           "name": "Time series",
+           "version": ""
+         }
+       ],
+       "annotations": {
+         "list": [
+           {
+             "builtIn": 1,
+             "datasource": {
+               "type": "grafana",
+               "uid": "-- Grafana --"
+             },
+             "enable": true,
+             "hide": true,
+             "iconColor": "rgba(0, 211, 255, 1)",
+             "name": "Annotations & Alerts",
+             "target": {
+               "limit": 100,
+               "matchAny": false,
+               "tags": [],
+               "type": "dashboard"
+             },
+             "type": "dashboard"
+           }
+         ]
+       },
+       "description": "Spegel is a pull only OCI registry which runs locally on every Node in the Kubernetes cluster. Containerd is configured to use the local registry as a mirror, which would serve the image from within the cluster or from the source registry.",
+       "editable": true,
+       "fiscalYearStartMonth": 0,
+       "graphTooltip": 0,
+       "id": null,
+       "links": [],
+       "panels": [
+         {
+           "collapsed": false,
+           "gridPos": {
+             "h": 1,
+             "w": 24,
+             "x": 0,
+             "y": 0
+           },
+           "id": 24,
+           "panels": [],
+           "type": "row"
+         },
+         {
+           "datasource": {
+             "type": "prometheus",
+             "uid": "${datasource}"
+           },
+           "description": "",
+           "fieldConfig": {
+             "defaults": {
+               "color": {
+                 "mode": "thresholds"
+               },
+               "mappings": [],
+               "thresholds": {
+                 "mode": "absolute",
+                 "steps": [
+                   {
+                     "color": "transparent",
+                     "value": 0
+                   }
+                 ]
+               }
+             },
+             "overrides": []
+           },
+           "gridPos": {
+             "h": 4,
+             "w": 2,
+             "x": 0,
+             "y": 1
+           },
+           "id": 11,
+           "options": {
+             "colorMode": "none",
+             "graphMode": "area",
+             "justifyMode": "auto",
+             "orientation": "auto",
+             "percentChangeColorMode": "standard",
+             "reduceOptions": {
+               "calcs": [
+                 "lastNotNull"
+               ],
+               "fields": "",
+               "values": false
+             },
+             "showPercentChange": false,
+             "textMode": "auto",
+             "wideLayout": true
+           },
+           "pluginVersion": "12.1.0",
+           "targets": [
+             {
+               "datasource": {
+                 "type": "prometheus",
+                 "uid": "${DS_PROMETHEUS}"
+               },
+               "editorMode": "code",
+               "expr": "count(spegel_advertised_content_digests{instance=~\"$instance\"})",
+               "hide": false,
+               "legendFormat": "__auto",
+               "range": true,
+               "refId": "A"
+             }
+           ],
+           "title": "Registry",
+           "transparent": true,
+           "type": "stat"
+         },
+         {
+           "datasource": {
+             "type": "prometheus",
+             "uid": "${datasource}"
+           },
+           "fieldConfig": {
+             "defaults": {
+               "color": {
+                 "mode": "thresholds"
+               },
+               "mappings": [],
+               "thresholds": {
+                 "mode": "absolute",
+                 "steps": [
+                   {
+                     "color": "transparent",
+                     "value": 0
+                   }
+                 ]
+               }
+             },
+             "overrides": []
+           },
+           "gridPos": {
+             "h": 4,
+             "w": 2,
+             "x": 2,
+             "y": 1
+           },
+           "id": 29,
+           "options": {
+             "colorMode": "none",
+             "graphMode": "area",
+             "justifyMode": "auto",
+             "orientation": "auto",
+             "percentChangeColorMode": "standard",
+             "reduceOptions": {
+               "calcs": [
+                 "lastNotNull"
+               ],
+               "fields": "",
+               "values": false
+             },
+             "showPercentChange": false,
+             "textMode": "auto",
+             "wideLayout": true
+           },
+           "pluginVersion": "12.1.0",
+           "targets": [
+             {
+               "datasource": {
+                 "type": "prometheus",
+                 "uid": "${DS_PROMETHEUS}"
+               },
+               "editorMode": "code",
+               "expr": "sum(kubelet_node_name{job=\"kubelet\"})",
+               "legendFormat": "__auto",
+               "range": true,
+               "refId": "A"
+             }
+           ],
+           "title": "Running Nodes",
+           "transparent": true,
+           "type": "stat"
+         },
+         {
+           "datasource": {
+             "type": "prometheus",
+             "uid": "$datasource"
+           },
+           "fieldConfig": {
+             "defaults": {
+               "links": [],
+               "mappings": [],
+               "thresholds": {
+                 "mode": "absolute",
+                 "steps": [
+                   {
+                     "color": "transparent",
+                     "value": 0
+                   }
+                 ]
+               },
+               "unit": "none"
+             },
+             "overrides": []
+           },
+           "gridPos": {
+             "h": 4,
+             "w": 3,
+             "x": 4,
+             "y": 1
+           },
+           "id": 22,
+           "options": {
+             "colorMode": "none",
+             "graphMode": "area",
+             "justifyMode": "auto",
+             "orientation": "auto",
+             "percentChangeColorMode": "standard",
+             "reduceOptions": {
+               "calcs": [
+                 "lastNotNull"
+               ],
+               "fields": "",
+               "values": false
+             },
+             "showPercentChange": false,
+             "textMode": "auto",
+             "wideLayout": true
+           },
+           "pluginVersion": "12.1.0",
+           "targets": [
+             {
+               "datasource": {
+                 "type": "prometheus",
+                 "uid": "${DS_PROMETHEUS}"
+               },
+               "editorMode": "code",
+               "expr": "sum(kubelet_running_containers)",
+               "format": "time_series",
+               "intervalFactor": 2,
+               "legendFormat": "{{instance}}",
+               "range": true,
+               "refId": "A"
+             }
+           ],
+           "title": "Running Containers",
+           "transparent": true,
+           "type": "stat"
+         },
+         {
+           "datasource": {
+             "type": "prometheus",
+             "uid": "${datasource}"
+           },
+           "fieldConfig": {
+             "defaults": {
+               "color": {
+                 "mode": "thresholds"
+               },
+               "mappings": [],
+               "thresholds": {
+                 "mode": "absolute",
+                 "steps": [
+                   {
+                     "color": "transparent",
+                     "value": 0
+                   }
+                 ]
+               }
+             },
+             "overrides": []
+           },
+           "gridPos": {
+             "h": 4,
+             "w": 2,
+             "x": 7,
+             "y": 1
+           },
+           "id": 20,
+           "options": {
+             "colorMode": "none",
+             "graphMode": "area",
+             "justifyMode": "auto",
+             "orientation": "auto",
+             "percentChangeColorMode": "standard",
+             "reduceOptions": {
+               "calcs": [
+                 "lastNotNull"
+               ],
+               "fields": "",
+               "values": false
+             },
+             "showPercentChange": false,
+             "textMode": "auto",
+             "wideLayout": true
+           },
+           "pluginVersion": "12.1.0",
+           "targets": [
+             {
+               "datasource": {
+                 "type": "prometheus",
+                 "uid": "${DS_PROMETHEUS}"
+               },
+               "editorMode": "code",
+               "expr": "sum(kubelet_running_pods)",
+               "legendFormat": "__auto",
+               "range": true,
+               "refId": "A"
+             }
+           ],
+           "title": "Running Pods",
+           "transparent": true,
+           "type": "stat"
+         },
+         {
+           "datasource": {
+             "type": "prometheus",
+             "uid": "${DS_PROMETHEUS}"
+           },
+           "fieldConfig": {
+             "defaults": {
+               "color": {
+                 "mode": "thresholds"
+               },
+               "mappings": [],
+               "thresholds": {
+                 "mode": "absolute",
+                 "steps": [
+                   {
+                     "color": "green",
+                     "value": 0
+                   },
+                   {
+                     "color": "red",
+                     "value": 80
+                   }
+                 ]
+               }
+             },
+             "overrides": []
+           },
+           "gridPos": {
+             "h": 4,
+             "w": 2,
+             "x": 9,
+             "y": 1
+           },
+           "id": 36,
+           "options": {
+             "colorMode": "value",
+             "graphMode": "area",
+             "justifyMode": "auto",
+             "orientation": "auto",
+             "percentChangeColorMode": "standard",
+             "reduceOptions": {
+               "calcs": [
+                 "lastNotNull"
+               ],
+               "fields": "",
+               "values": false
+             },
+             "showPercentChange": false,
+             "textMode": "auto",
+             "wideLayout": true
+           },
+           "pluginVersion": "12.1.0",
+           "targets": [
+             {
+               "editorMode": "code",
+               "expr": "sum(spegel_mirror_requests_total{pod=~\"$pod\", cache=\"hit\"})",
+               "legendFormat": "__auto",
+               "range": true,
+               "refId": "A",
+               "datasource": {
+                 "type": "prometheus",
+                 "uid": "${DS_PROMETHEUS}"
+               }
+             }
+           ],
+           "title": "Cache Hits",
+           "type": "stat"
+         },
+         {
+           "datasource": {
+             "type": "prometheus",
+             "uid": "${DS_PROMETHEUS}"
+           },
+           "fieldConfig": {
+             "defaults": {
+               "color": {
+                 "mode": "thresholds"
+               },
+               "mappings": [],
+               "thresholds": {
+                 "mode": "absolute",
+                 "steps": [
+                   {
+                     "color": "green",
+                     "value": 0
+                   },
+                   {
+                     "color": "red",
+                     "value": 80
+                   }
+                 ]
+               }
+             },
+             "overrides": []
+           },
+           "gridPos": {
+             "h": 4,
+             "w": 2,
+             "x": 11,
+             "y": 1
+           },
+           "id": 37,
+           "options": {
+             "colorMode": "value",
+             "graphMode": "area",
+             "justifyMode": "auto",
+             "orientation": "auto",
+             "percentChangeColorMode": "standard",
+             "reduceOptions": {
+               "calcs": [
+                 "lastNotNull"
+               ],
+               "fields": "",
+               "values": false
+             },
+             "showPercentChange": false,
+             "textMode": "auto",
+             "wideLayout": true
+           },
+           "pluginVersion": "12.1.0",
+           "targets": [
+             {
+               "editorMode": "code",
+               "expr": "sum(spegel_mirror_requests_total{pod=~\"$pod\", cache=\"miss\"})",
+               "legendFormat": "__auto",
+               "range": true,
+               "refId": "A",
+               "datasource": {
+                 "type": "prometheus",
+                 "uid": "${DS_PROMETHEUS}"
+               }
+             }
+           ],
+           "title": "Cache Miss",
+           "type": "stat"
+         },
+         {
+           "datasource": {
+             "type": "prometheus",
+             "uid": "${datasource}"
+           },
+           "description": "",
+           "fieldConfig": {
+             "defaults": {
+               "color": {
+                 "fixedColor": "green",
+                 "mode": "fixed"
+               },
+               "mappings": [],
+               "thresholds": {
+                 "mode": "absolute",
+                 "steps": [
+                   {
+                     "color": "green",
+                     "value": 0
+                   },
+                   {
+                     "color": "red",
+                     "value": 80
+                   }
+                 ]
+               },
+               "unit": "ms"
+             },
+             "overrides": []
+           },
+           "gridPos": {
+             "h": 4,
+             "w": 3,
+             "x": 13,
+             "y": 1
+           },
+           "id": 12,
+           "options": {
+             "colorMode": "value",
+             "graphMode": "area",
+             "justifyMode": "auto",
+             "orientation": "auto",
+             "percentChangeColorMode": "standard",
+             "reduceOptions": {
+               "calcs": [
+                 "lastNotNull"
+               ],
+               "fields": "",
+               "values": false
+             },
+             "showPercentChange": false,
+             "textMode": "auto",
+             "wideLayout": true
+           },
+           "pluginVersion": "12.1.0",
+           "targets": [
+             {
+               "datasource": {
+                 "type": "prometheus",
+                 "uid": "${DS_PROMETHEUS}"
+               },
+               "editorMode": "code",
+               "exemplar": false,
+               "expr": "max(rate(http_request_duration_seconds_bucket{pod=~\"$pod\"}[$__interval]))",
+               "format": "table",
+               "instant": true,
+               "legendFormat": "__auto",
+               "range": false,
+               "refId": "A"
+             }
+           ],
+           "title": "Max Request Duration",
+           "transparent": true,
+           "type": "stat"
+         },
+         {
+           "gridPos": {
+             "h": 4,
+             "w": 3,
+             "x": 21,
+             "y": 1
+           },
+           "id": 2,
+           "options": {
+             "code": {
+               "language": "plaintext",
+               "showLineNumbers": false,
+               "showMiniMap": false
+             },
+             "content": "<br>\n<div style=\"text-align: center;\"><a href=\"https://github.com/XenitAB/spegel\" target=\"_blank\">Spegel at GitHub</a> </div>\n\n",
+             "mode": "html"
+           },
+           "pluginVersion": "12.1.0",
+           "title": "Github link",
+           "transparent": true,
+           "type": "text"
+         },
+         {
+           "collapsed": false,
+           "gridPos": {
+             "h": 1,
+             "w": 24,
+             "x": 0,
+             "y": 5
+           },
+           "id": 9,
+           "panels": [],
+           "repeat": "datasource",
+           "type": "row"
+         },
+         {
+           "datasource": {
+             "type": "prometheus",
+             "uid": "${datasource}"
+           },
+           "fieldConfig": {
+             "defaults": {
+               "color": {
+                 "mode": "thresholds"
+               },
+               "custom": {
+                 "align": "center",
+                 "cellOptions": {
+                   "type": "auto"
+                 },
+                 "inspect": false
+               },
+               "mappings": [],
+               "thresholds": {
+                 "mode": "absolute",
+                 "steps": [
+                   {
+                     "color": "green",
+                     "value": 0
+                   },
+                   {
+                     "color": "red",
+                     "value": 80
+                   }
+                 ]
+               }
+             },
+             "overrides": [
+               {
+                 "matcher": {
+                   "id": "byName",
+                   "options": "instance"
+                 },
+                 "properties": [
+                   {
+                     "id": "custom.width",
+                     "value": 226
+                   }
+                 ]
+               },
+               {
+                 "matcher": {
+                   "id": "byName",
+                   "options": "prometheus"
+                 },
+                 "properties": [
+                   {
+                     "id": "custom.width",
+                     "value": 296
+                   }
+                 ]
+               }
+             ]
+           },
+           "gridPos": {
+             "h": 7,
+             "w": 12,
+             "x": 0,
+             "y": 6
+           },
+           "id": 16,
+           "options": {
+             "cellHeight": "sm",
+             "footer": {
+               "countRows": false,
+               "enablePagination": false,
+               "fields": "",
+               "reducer": [
+                 "sum"
+               ],
+               "show": false
+             },
+             "frameIndex": 1,
+             "showHeader": true,
+             "sortBy": []
+           },
+           "pluginVersion": "12.1.0",
+           "targets": [
+             {
+               "datasource": {
+                 "type": "prometheus",
+                 "uid": "${DS_PROMETHEUS}"
+               },
+               "editorMode": "code",
+               "exemplar": false,
+               "expr": "spegel_advertised_image_digests{pod=~\"$pod\", registry=~\"$registry\"}",
+               "format": "table",
+               "instant": true,
+               "legendFormat": "__auto",
+               "range": false,
+               "refId": "A"
+             },
+             {
+               "datasource": {
+                 "type": "prometheus",
+                 "uid": "${datasource}"
+               },
+               "editorMode": "code",
+               "exemplar": false,
+               "expr": "spegel_advertised_content_digests{pod=~\"$pod\", registry=~\"$registry\"} ",
+               "format": "table",
+               "hide": false,
+               "instant": true,
+               "legendFormat": "__auto",
+               "range": false,
+               "refId": "B"
+             }
+           ],
+           "transformations": [
+             {
+               "id": "filterFieldsByName",
+               "options": {
+                 "include": {
+                   "names": [
+                     "Value #A",
+                     "Value #B",
+                     "registry",
+                     "pod"
+                   ]
+                 }
+               }
+             },
+             {
+               "id": "merge",
+               "options": {}
+             },
+             {
+               "id": "renameByRegex",
+               "options": {
+                 "regex": "Value #A",
+                 "renamePattern": "Container cache"
+               }
+             },
+             {
+               "id": "renameByRegex",
+               "options": {
+                 "regex": "Value #B",
+                 "renamePattern": "Layers cache"
+               }
+             }
+           ],
+           "transparent": true,
+           "type": "table"
+         },
+         {
+           "datasource": {
+             "type": "prometheus",
+             "uid": "${DS_PROMETHEUS}"
+           },
+           "description": "",
+           "fieldConfig": {
+             "defaults": {
+               "color": {
+                 "mode": "palette-classic"
+               },
+               "custom": {
+                 "axisBorderShow": false,
+                 "axisCenteredZero": false,
+                 "axisColorMode": "series",
+                 "axisLabel": "",
+                 "axisPlacement": "auto",
+                 "barAlignment": 0,
+                 "barWidthFactor": 0.6,
+                 "drawStyle": "line",
+                 "fillOpacity": 10,
+                 "gradientMode": "opacity",
+                 "hideFrom": {
+                   "legend": false,
+                   "tooltip": false,
+                   "viz": false
+                 },
+                 "insertNulls": false,
+                 "lineInterpolation": "smooth",
+                 "lineStyle": {
+                   "fill": "solid"
+                 },
+                 "lineWidth": 2,
+                 "pointSize": 1,
+                 "scaleDistribution": {
+                   "type": "linear"
+                 },
+                 "showPoints": "auto",
+                 "spanNulls": false,
+                 "stacking": {
+                   "group": "A",
+                   "mode": "none"
+                 },
+                 "thresholdsStyle": {
+                   "mode": "off"
+                 }
+               },
+               "mappings": [],
+               "thresholds": {
+                 "mode": "absolute",
+                 "steps": [
+                   {
+                     "color": "green",
+                     "value": 0
+                   },
+                   {
+                     "color": "red",
+                     "value": 80
+                   }
+                 ]
+               }
+             },
+             "overrides": []
+           },
+           "gridPos": {
+             "h": 7,
+             "w": 12,
+             "x": 12,
+             "y": 6
+           },
+           "id": 6,
+           "options": {
+             "legend": {
+               "calcs": [],
+               "displayMode": "list",
+               "placement": "bottom",
+               "showLegend": true
+             },
+             "tooltip": {
+               "hideZeros": false,
+               "mode": "single",
+               "sort": "none"
+             }
+           },
+           "pluginVersion": "12.1.0",
+           "targets": [
+             {
+               "datasource": {
+                 "type": "prometheus",
+                 "uid": "${datasource}"
+               },
+               "editorMode": "code",
+               "exemplar": false,
+               "expr": "spegel_advertised_image_digests{pod=~\"$pod\", registry=~\"$registry\"}",
+               "format": "time_series",
+               "instant": false,
+               "legendFormat": "{{ pod }}: {{ registry }}",
+               "range": true,
+               "refId": "A"
+             }
+           ],
+           "title": "Container Images Advertised ",
+           "transparent": true,
+           "type": "timeseries"
+         },
+         {
+           "datasource": {
+             "type": "prometheus",
+             "uid": "${DS_PROMETHEUS}"
+           },
+           "fieldConfig": {
+             "defaults": {
+               "color": {
+                 "mode": "palette-classic"
+               },
+               "custom": {
+                 "axisBorderShow": false,
+                 "axisCenteredZero": false,
+                 "axisColorMode": "series",
+                 "axisLabel": "",
+                 "axisPlacement": "auto",
+                 "barAlignment": 0,
+                 "barWidthFactor": 0.6,
+                 "drawStyle": "line",
+                 "fillOpacity": 36,
+                 "gradientMode": "opacity",
+                 "hideFrom": {
+                   "legend": false,
+                   "tooltip": false,
+                   "viz": false
+                 },
+                 "insertNulls": false,
+                 "lineInterpolation": "linear",
+                 "lineWidth": 1,
+                 "pointSize": 5,
+                 "scaleDistribution": {
+                   "type": "linear"
+                 },
+                 "showPoints": "never",
+                 "spanNulls": false,
+                 "stacking": {
+                   "group": "A",
+                   "mode": "normal"
+                 },
+                 "thresholdsStyle": {
+                   "mode": "off"
+                 }
+               },
+               "mappings": [],
+               "thresholds": {
+                 "mode": "absolute",
+                 "steps": [
+                   {
+                     "color": "green",
+                     "value": 0
+                   },
+                   {
+                     "color": "red",
+                     "value": 80
+                   }
+                 ]
+               }
+             },
+             "overrides": [
+               {
+                 "matcher": {
+                   "id": "byName",
+                   "options": "requests"
+                 },
+                 "properties": [
+                   {
+                     "id": "color",
+                     "value": {
+                       "fixedColor": "#F2495C",
+                       "mode": "fixed"
+                     }
+                   },
+                   {
+                     "id": "custom.fillOpacity",
+                     "value": 0
+                   },
+                   {
+                     "id": "custom.lineWidth",
+                     "value": 2
+                   },
+                   {
+                     "id": "custom.stacking",
+                     "value": {
+                       "group": false,
+                       "mode": "normal"
+                     }
+                   }
+                 ]
+               },
+               {
+                 "matcher": {
+                   "id": "byName",
+                   "options": "limits"
+                 },
+                 "properties": [
+                   {
+                     "id": "color",
+                     "value": {
+                       "fixedColor": "#FF9830",
+                       "mode": "fixed"
+                     }
+                   },
+                   {
+                     "id": "custom.fillOpacity",
+                     "value": 0
+                   },
+                   {
+                     "id": "custom.lineWidth",
+                     "value": 2
+                   },
+                   {
+                     "id": "custom.stacking",
+                     "value": {
+                       "group": false,
+                       "mode": "normal"
+                     }
+                   }
+                 ]
+               }
+             ]
+           },
+           "gridPos": {
+             "h": 7,
+             "w": 12,
+             "x": 0,
+             "y": 13
+           },
+           "id": 28,
+           "interval": "1m",
+           "options": {
+             "legend": {
+               "calcs": [],
+               "displayMode": "list",
+               "placement": "bottom",
+               "showLegend": false
+             },
+             "tooltip": {
+               "hideZeros": false,
+               "mode": "multi",
+               "sort": "none"
+             }
+           },
+           "pluginVersion": "12.1.0",
+           "targets": [
+             {
+               "datasource": {
+                 "uid": "$datasource"
+               },
+               "editorMode": "code",
+               "exemplar": false,
+               "expr": "sum(node_namespace_pod_container:container_cpu_usage_seconds_total:sum_irate{container=\"$container\"}) by (pod)",
+               "format": "time_series",
+               "instant": false,
+               "intervalFactor": 2,
+               "legendFormat": "{{ container }}",
+               "range": true,
+               "refId": "A",
+               "step": 10
+             }
+           ],
+           "title": "CPU Usage",
+           "transparent": true,
+           "type": "timeseries"
+         },
+         {
+           "datasource": {
+             "type": "prometheus",
+             "uid": "${DS_PROMETHEUS}"
+           },
+           "description": "",
+           "fieldConfig": {
+             "defaults": {
+               "color": {
+                 "mode": "palette-classic"
+               },
+               "custom": {
+                 "axisBorderShow": false,
+                 "axisCenteredZero": false,
+                 "axisColorMode": "series",
+                 "axisLabel": "",
+                 "axisPlacement": "auto",
+                 "barAlignment": 0,
+                 "barWidthFactor": 0.6,
+                 "drawStyle": "line",
+                 "fillOpacity": 10,
+                 "gradientMode": "opacity",
+                 "hideFrom": {
+                   "legend": false,
+                   "tooltip": false,
+                   "viz": false
+                 },
+                 "insertNulls": false,
+                 "lineInterpolation": "smooth",
+                 "lineWidth": 2,
+                 "pointSize": 1,
+                 "scaleDistribution": {
+                   "type": "linear"
+                 },
+                 "showPoints": "auto",
+                 "spanNulls": false,
+                 "stacking": {
+                   "group": "A",
+                   "mode": "none"
+                 },
+                 "thresholdsStyle": {
+                   "mode": "off"
+                 }
+               },
+               "mappings": [],
+               "thresholds": {
+                 "mode": "absolute",
+                 "steps": [
+                   {
+                     "color": "green",
+                     "value": 0
+                   },
+                   {
+                     "color": "red",
+                     "value": 80
+                   }
+                 ]
+               }
+             },
+             "overrides": []
+           },
+           "gridPos": {
+             "h": 7,
+             "w": 12,
+             "x": 12,
+             "y": 13
+           },
+           "id": 7,
+           "options": {
+             "legend": {
+               "calcs": [],
+               "displayMode": "list",
+               "placement": "bottom",
+               "showLegend": true
+             },
+             "tooltip": {
+               "hideZeros": false,
+               "mode": "single",
+               "sort": "none"
+             }
+           },
+           "pluginVersion": "12.1.0",
+           "targets": [
+             {
+               "datasource": {
+                 "type": "prometheus",
+                 "uid": "${datasource}"
+               },
+               "editorMode": "code",
+               "exemplar": false,
+               "expr": "spegel_advertised_content_digests{pod=~\"$pod\", registry=~\"$registry\"} ",
+               "format": "time_series",
+               "instant": false,
+               "legendFormat": "{{ pod }}: {{ registry }}",
+               "range": true,
+               "refId": "A"
+             }
+           ],
+           "title": "Images Layer Advertised ",
+           "transparent": true,
+           "type": "timeseries"
+         },
+         {
+           "collapsed": false,
+           "gridPos": {
+             "h": 1,
+             "w": 24,
+             "x": 0,
+             "y": 20
+           },
+           "id": 35,
+           "panels": [],
+           "title": "Kubelet",
+           "type": "row"
+         },
+         {
+           "datasource": {
+             "type": "prometheus",
+             "uid": "${DS_PROMETHEUS}"
+           },
+           "fieldConfig": {
+             "defaults": {
+               "color": {
+                 "mode": "palette-classic"
+               },
+               "custom": {
+                 "axisBorderShow": false,
+                 "axisCenteredZero": false,
+                 "axisColorMode": "text",
+                 "axisLabel": "",
+                 "axisPlacement": "auto",
+                 "barAlignment": 0,
+                 "barWidthFactor": 0.6,
+                 "drawStyle": "line",
+                 "fillOpacity": 6,
+                 "gradientMode": "none",
+                 "hideFrom": {
+                   "legend": false,
+                   "tooltip": false,
+                   "viz": false
+                 },
+                 "insertNulls": false,
+                 "lineInterpolation": "linear",
+                 "lineWidth": 1,
+                 "pointSize": 5,
+                 "scaleDistribution": {
+                   "type": "linear"
+                 },
+                 "showPoints": "never",
+                 "spanNulls": false,
+                 "stacking": {
+                   "group": "A",
+                   "mode": "none"
+                 },
+                 "thresholdsStyle": {
+                   "mode": "off"
+                 }
+               },
+               "mappings": [],
+               "thresholds": {
+                 "mode": "absolute",
+                 "steps": [
+                   {
+                     "color": "green",
+                     "value": 0
+                   },
+                   {
+                     "color": "red",
+                     "value": 80
+                   }
+                 ]
+               },
+               "unit": "ops"
+             },
+             "overrides": []
+           },
+           "gridPos": {
+             "h": 10,
+             "w": 12,
+             "x": 0,
+             "y": 21
+           },
+           "id": 31,
+           "options": {
+             "legend": {
+               "calcs": [],
+               "displayMode": "table",
+               "placement": "right",
+               "showLegend": true
+             },
+             "tooltip": {
+               "hideZeros": false,
+               "mode": "single",
+               "sort": "none"
+             }
+           },
+           "pluginVersion": "12.1.0",
+           "targets": [
+             {
+               "datasource": {
+                 "type": "prometheus",
+                 "uid": "${datasource}"
+               },
+               "editorMode": "code",
+               "expr": "sum(rate(kubelet_runtime_operations_total{job=\"kubelet\", metrics_path=\"/metrics\", operation_type=~\"list_images|pull_image|start_container|list_images|list_containers|version|exec_sync|create_container\"}[$__rate_interval])) by (operation_type)",
+               "legendFormat": "__auto",
+               "range": true,
+               "refId": "A"
+             }
+           ],
+           "title": "Kubelet Operation Rate",
+           "transparent": true,
+           "type": "timeseries"
+         },
+         {
+           "datasource": {
+             "type": "prometheus",
+             "uid": "${DS_PROMETHEUS}"
+           },
+           "fieldConfig": {
+             "defaults": {
+               "color": {
+                 "mode": "palette-classic"
+               },
+               "custom": {
+                 "axisBorderShow": false,
+                 "axisCenteredZero": false,
+                 "axisColorMode": "text",
+                 "axisLabel": "",
+                 "axisPlacement": "auto",
+                 "barAlignment": 0,
+                 "barWidthFactor": 0.6,
+                 "drawStyle": "line",
+                 "fillOpacity": 10,
+                 "gradientMode": "none",
+                 "hideFrom": {
+                   "legend": false,
+                   "tooltip": false,
+                   "viz": false
+                 },
+                 "insertNulls": false,
+                 "lineInterpolation": "linear",
+                 "lineWidth": 1,
+                 "pointSize": 5,
+                 "scaleDistribution": {
+                   "type": "linear"
+                 },
+                 "showPoints": "never",
+                 "spanNulls": false,
+                 "stacking": {
+                   "group": "A",
+                   "mode": "none"
+                 },
+                 "thresholdsStyle": {
+                   "mode": "off"
+                 }
+               },
+               "mappings": [],
+               "thresholds": {
+                 "mode": "absolute",
+                 "steps": [
+                   {
+                     "color": "green",
+                     "value": 0
+                   },
+                   {
+                     "color": "red",
+                     "value": 80
+                   }
+                 ]
+               },
+               "unit": "ops"
+             },
+             "overrides": []
+           },
+           "gridPos": {
+             "h": 10,
+             "w": 12,
+             "x": 12,
+             "y": 21
+           },
+           "id": 33,
+           "options": {
+             "legend": {
+               "calcs": [],
+               "displayMode": "list",
+               "placement": "bottom",
+               "showLegend": true
+             },
+             "tooltip": {
+               "hideZeros": false,
+               "mode": "multi",
+               "sort": "none"
+             }
+           },
+           "pluginVersion": "12.1.0",
+           "targets": [
+             {
+               "datasource": {
+                 "uid": "$datasource"
+               },
+               "editorMode": "code",
+               "expr": "sum(rate(kubelet_runtime_operations_errors_total{job=\"kubelet\", metrics_path=\"/metrics\",operation_type=~\"list_images|pull_image|start_container|list_images|list_containers|version|exec_sync|create_container\"}[$__rate_interval])) by (operation_type)",
+               "format": "time_series",
+               "intervalFactor": 2,
+               "legendFormat": "{{instance}} {{operation_type}}",
+               "range": true,
+               "refId": "A"
+             }
+           ],
+           "title": "Kubelet Operation Error Rate",
+           "transparent": true,
+           "type": "timeseries"
+         }
+       ],
+       "refresh": "30s",
+       "schemaVersion": 41,
+       "tags": [],
+       "templating": {
+         "list": [
+           {
+             "current": {},
+             "includeAll": false,
+             "label": "datasource",
+             "name": "datasource",
+             "options": [],
+             "query": "prometheus",
+             "refresh": 1,
+             "regex": "",
+             "type": "datasource"
+           },
+           {
+             "allowCustomValue": false,
+             "current": {},
+             "datasource": {
+               "type": "prometheus",
+               "uid": "${DS_PROMETHEUS}"
+             },
+             "definition": "label_values(spegel_advertised_content_digests,pod)",
+             "description": "",
+             "includeAll": true,
+             "label": "pod",
+             "multi": true,
+             "name": "pod",
+             "options": [],
+             "query": {
+               "qryType": 1,
+               "query": "label_values(spegel_advertised_content_digests,pod)",
+               "refId": "PrometheusVariableQueryEditor-VariableQuery"
+             },
+             "refresh": 2,
+             "regex": "",
+             "type": "query"
+           },
+           {
+             "allowCustomValue": false,
+             "current": {},
+             "datasource": {
+               "type": "prometheus",
+               "uid": "${datasource}"
+             },
+             "definition": "label_values(spegel_advertised_content_digests,registry)",
+             "includeAll": true,
+             "label": "registry",
+             "multi": true,
+             "name": "registry",
+             "options": [],
+             "query": {
+               "qryType": 1,
+               "query": "label_values(spegel_advertised_content_digests,registry)",
+               "refId": "PrometheusVariableQueryEditor-VariableQuery"
+             },
+             "refresh": 2,
+             "regex": "",
+             "type": "query"
+           },
+           {
+             "allowCustomValue": false,
+             "current": {
+               "text": "registry",
+               "value": "registry"
+             },
+             "description": "",
+             "hide": 2,
+             "name": "container",
+             "options": [
+               {
+                 "selected": true,
+                 "text": "registry",
+                 "value": "registry"
+               }
+             ],
+             "query": "registry",
+             "type": "custom"
+           }
+         ]
+       },
+       "time": {
+         "from": "now-3h",
+         "to": "now"
+       },
+       "timepicker": {},
+       "timezone": "",
+       "title": "Spegel stateless cluster local OCI registry mirror",
+       "uid": "1iY4QMJVk-psee",
+       "gnetId": 18089,
+       "version": 5,
+       "weekStart": ""
+     }

My earlier comment rewrite dropped "Daily at 03:00" and compressed "The previous
weekly cadence" down to "Weekly", so the note now read as if the CronJob still
ran weekly while the schedule beside it is `0 3 * * *`. Restored the meaning
without restating the cron expression.
@Tanguille

Copy link
Copy Markdown
Owner Author

Review remarks triaged.

Fixed — etcd-defrag cadence (CodeRabbit, minor). My mistake, and a real one: my comment rewrite dropped "Daily at 03:00" and compressed "The previous weekly cadence" into "Weekly", so it read as though the CronJob still ran weekly next to a 0 3 * * * schedule. Restored the meaning without restating the cron expression. Commit 0bb2edd.

Already fixed — namespace anchors (CodeRabbit, trivial). Same issue was raised on brrpolice and fixed in f729a1f, before this comment landed. victoria-logs and crowdsec both now use targetNamespace: *namespace in both documents. Cause was that the dereference was a separate finding my applier skipped as ambiguous, since the literal appears twice per file, so only the anchor half landed.

False positive — PP/W percentage (CodeRabbit, minor). The comment's 15% is right; ~19% comes from using the nominal 330W and missing the (drew 313) annotation on the same line:

point PP watts drawn PP/W
210W 1027 ~209 4.91
330W 1301 313 4.16

4.16 / 4.91 = 15.4% worse, as written. Against the nominal 330W it would be 19.8%, which is where the suggestion comes from. Leaving as-is.

@github-actions

Copy link
Copy Markdown

AI Automated Review

Analysis engine: qwen-3.6-fast@http://litellm.ai.svc.cluster.local/v1 (openai)

Recommendation: Approve

This PR is a well-scoped consistency sweep that removes redundant Kubernetes defaults, standardizes YAML anchors, adds schema hints for editor support, and fixes a broken Renovate manager. The author's verification using flate build hr confirms rendered HelmRelease output is byte-identical (except for the intentional Spegel dashboard ConfigMap addition). Four behavioural changes were correctly reverted during development.

Change-by-change findings

Renovate GrafanaDashboard URL manager fix (.renovaterc.json5)
The previous matchStringsStrategy: recursive caused the version pattern to search inside the depName match, which never contained the version tag. The new combined regex correctly captures both depName and currentValue in a single pass. This is a genuine bug fix — the old config matched zero dashboards.

Spegel dashboard sourcing (kubernetes/apps/kube-system/spegel/)
Switching from a pinned raw.githubusercontent.com URL to configMapRef prevents dashboard drift when the chart updates. The Sidecar mode emits the ConfigMap from the chart itself, keeping it in sync. The datasource mapping remains load-bearing as noted in the comment.

YAML anchor standardization (multiple ks.yaml files)
Anchors (&namespace, &app) are now declared and dereferenced consistently across Kustomizations (spegel, brrpolice, keda, victoria-logs, crowdsec). This follows repository conventions for deduplication within a single document.

Redundant default removals (media apps, external services, Cilium, etc.)

  • enableServiceLinks: false: Removed where it matched the Kubernetes default (false). No behavioural change.
  • protocol: TCP: Removed from EndpointSlice ports; TCP is the default per spec.
  • type: ClusterIP on headless services: Redundant when clusterIP: None is set; the API server infers headless type.
  • imagePullPolicy: IfNotPresent: Removed; with digest-pinned images, the policy is irrelevant.
  • automountServiceAccountToken: false: Removed for workloads that don't use SA tokens (etcd-defrag, moonraker-obico). Default is already false when no SA token volume is projected.
  • periodSeconds: 10 on startup probes: Removed; defaults to 10s per Kubernetes spec.
  • concurrencyPolicy, successfulJobsHistory, failedJobsHistory on CronJobs: Removed; these match Kubernetes defaults (Forbid, 3, 1). Note: etcd-defrag drops concurrencyPolicy: Forbid which is the default, so no change.
  • advancedMounts / globalMounts with implicit paths: Where the app-template chart mounts to /config by default, explicit mount paths are redundant.
  • numRetries: 2 on Envoy retry: Removed; 2 is the Envoy Gateway default.
  • Flux components list: Removed; the flux-operator installs all controllers by default when not explicitly restricted.
  • HTTPRoute namespace on backendRefs: Removed; same-namespace refs don't require explicit namespace.

Comment cleanups
Several operational comments were condensed or removed where they restated what the manifest already expresses. The CNPG role rotation comment was simplified without losing meaning.

Karakeep hostname (kubernetes/apps/default/karakeep/app/helmrelease.yaml)
Changed from hardcoded karakeep.${SECRET_DOMAIN} to templated {{ .Release.Name }}.${SECRET_DOMAIN}. Since the release name is karakeep, this produces identical runtime behaviour while aligning with repo-wide convention.

Standards Compliance

  • Conventional commits: All commits follow the pattern (fix(scope): ..., chore(scope): ...). ✓
  • Small, focused changes: Changes are orthogonal defaults removals and style fixes. ✓
  • No secrets committed: No .sops.yaml files modified. ✓
  • YAML anchors within single documents: Anchors are declared and used within the same --- document boundary. ✓

Must-Check Items

Check Status
validate manifest against target cluster version Changes remove redundant fields matching Kubernetes/API defaults; no version-specific features introduced. Rendered output verified identical. ✓
check for resource quota / limit changes No resource requests/limits modified. ✓
verify file path sanitization No file-serving code changed; only manifest defaults removed. Not applicable.
check for directory traversal vulnerabilities No user input handling or path construction changed. Not applicable.
verify secrets are not logged or exposed in diffs No secret values present in diff; only structural/comment changes. ✓
check secret rotation impact No secret references or rotation mechanisms modified. CNPG comment clarifies rotation is intentionally disabled. ✓

Unknowns or Needs Verification

None identified. The author's flate build hr verification provides strong evidence of behavioural neutrality.

@Tanguille
Tanguille merged commit 3c7e441 into main Jul 27, 2026
14 of 15 checks passed
@Tanguille
Tanguille deleted the chore/repo-consistency branch July 27, 2026 19:17
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant