From 1d87c42fc1b7b286bc9cad282eca0477dd2190f6 Mon Sep 17 00:00:00 2001 From: Ben Vincent Date: Sat, 25 Jul 2026 18:30:23 +1000 Subject: [PATCH] Add advise-mode VPA for every workload (#283) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## Why Turns on right-sizing telemetry for the whole estate. Adds a `VerticalPodAutoscaler` with `updateMode: "Off"` (recommendation-only, advise mode) for every Deployment and StatefulSet in `apps/base`. Off mode never evicts or mutates pods, so this is purely observational: the VPA recommender (added in the vpa-system PR) publishes suggested requests/limits in each VPA's status, and nothing acts on them until someone deliberately flips a mode. ## Changes - Add one `vpa.yaml` per app under `apps/base//` containing a `-vpa` VerticalPodAutoscaler for each workload, and register it in that app's `kustomization.yaml`. - Coverage: 17 workloads across 11 apps. - age-api (age-api), artifactapi (api, redis, ui), authentik (redis), bind-system (bind-operator), cephrgw-system (cephrgw-operator), encapi (encapi), kanidm (kanidm StatefulSet), litellm (litellm, redis), paperclip (paperclip), pdbmux (pdbmux), puppet (puppetboard, puppetdb, puppetserver-compiler, puppetserver-master). ## Skipped (intentionally) - **CNPG `Cluster` objects** (artifactapi, authentik, encapi, grafana, litellm, paperclip, puppet, woodpecker) — Postgres is managed by CloudNativePG, not a VPA target. - **CronJobs** (puppet g10k/generate-types, reposync x4) — not VPA-able. ## HPA / VPA caveat api, ui (artifactapi), litellm, and all four puppet deployments also carry an HPA. With `updateMode: "Off"` there is no conflict today (VPA only recommends). VPA objects targeting these carry an inline comment: do **not** flip to `Auto`/`Initial` while the HPA still autoscales on CPU/memory, or the two controllers will fight over the same resource. Move the HPA to a custom/non-resource metric first. ## Verification - `kubectl kustomize` over every touched overlay: 9/11 overlays PASS rendering all their VPAs; 2 failures are pre-existing and unrelated to this change — `authentik` fails on a local helm-tooling flag error identically on origin/main, and `paperclip` has no `apps/overlays/au-syd1/paperclip` directory yet. Both apps' base kustomizations build clean and render their VPA. ## Merge gate - **Requires the vpa-system CRDs PR (argocd-apps #281) to merge first.** These manifests use `autoscaling.k8s.io/v1 VerticalPodAutoscaler`; without the CRDs installed, ArgoCD sync fails on an unknown kind. Reviewed-on: https://git.unkin.net/unkin/argocd-apps/pulls/283 Co-authored-by: Ben Vincent Co-committed-by: Ben Vincent --- apps/base/age-api/kustomization.yaml | 1 + apps/base/age-api/vpa.yaml | 13 +++++ apps/base/artifactapi/kustomization.yaml | 1 + apps/base/artifactapi/vpa.yaml | 45 +++++++++++++++ apps/base/authentik/kustomization.yaml | 1 + apps/base/authentik/vpa.yaml | 13 +++++ apps/base/bind-system/kustomization.yaml | 1 + apps/base/bind-system/vpa.yaml | 13 +++++ apps/base/cephrgw-system/kustomization.yaml | 1 + apps/base/cephrgw-system/vpa.yaml | 13 +++++ apps/base/encapi/kustomization.yaml | 1 + apps/base/encapi/vpa.yaml | 13 +++++ apps/base/kanidm/kustomization.yaml | 1 + apps/base/kanidm/vpa.yaml | 13 +++++ apps/base/litellm/kustomization.yaml | 1 + apps/base/litellm/vpa.yaml | 29 ++++++++++ apps/base/paperclip/kustomization.yaml | 1 + apps/base/paperclip/vpa.yaml | 13 +++++ apps/base/pdbmux/kustomization.yaml | 1 + apps/base/pdbmux/vpa.yaml | 13 +++++ apps/base/puppet/kustomization.yaml | 1 + apps/base/puppet/vpa.yaml | 64 +++++++++++++++++++++ 22 files changed, 253 insertions(+) create mode 100644 apps/base/age-api/vpa.yaml create mode 100644 apps/base/artifactapi/vpa.yaml create mode 100644 apps/base/authentik/vpa.yaml create mode 100644 apps/base/bind-system/vpa.yaml create mode 100644 apps/base/cephrgw-system/vpa.yaml create mode 100644 apps/base/encapi/vpa.yaml create mode 100644 apps/base/kanidm/vpa.yaml create mode 100644 apps/base/litellm/vpa.yaml create mode 100644 apps/base/paperclip/vpa.yaml create mode 100644 apps/base/pdbmux/vpa.yaml create mode 100644 apps/base/puppet/vpa.yaml diff --git a/apps/base/age-api/kustomization.yaml b/apps/base/age-api/kustomization.yaml index ce0fbd0..0e3ba79 100644 --- a/apps/base/age-api/kustomization.yaml +++ b/apps/base/age-api/kustomization.yaml @@ -8,6 +8,7 @@ resources: - httproute.yaml - namespace.yaml - service.yaml + - vpa.yaml configMapGenerator: - name: age-api-config diff --git a/apps/base/age-api/vpa.yaml b/apps/base/age-api/vpa.yaml new file mode 100644 index 0000000..76ebfdb --- /dev/null +++ b/apps/base/age-api/vpa.yaml @@ -0,0 +1,13 @@ +--- +apiVersion: autoscaling.k8s.io/v1 +kind: VerticalPodAutoscaler +metadata: + name: age-api-vpa + namespace: age-api +spec: + targetRef: + apiVersion: apps/v1 + kind: Deployment + name: age-api + updatePolicy: + updateMode: "Off" diff --git a/apps/base/artifactapi/kustomization.yaml b/apps/base/artifactapi/kustomization.yaml index 918d19d..e7a8b79 100644 --- a/apps/base/artifactapi/kustomization.yaml +++ b/apps/base/artifactapi/kustomization.yaml @@ -17,3 +17,4 @@ resources: - ui-hpa.yaml - vaultauth.yaml - vaultstaticsecret.yaml + - vpa.yaml diff --git a/apps/base/artifactapi/vpa.yaml b/apps/base/artifactapi/vpa.yaml new file mode 100644 index 0000000..3fd37fc --- /dev/null +++ b/apps/base/artifactapi/vpa.yaml @@ -0,0 +1,45 @@ +--- +apiVersion: autoscaling.k8s.io/v1 +kind: VerticalPodAutoscaler +metadata: + name: api-vpa + namespace: artifactapi + # NOTE: this workload also has an HPA. updateMode Off is recommendation-only + # and does not act, so there is no HPA/VPA conflict today. Do not flip to Auto/ + # Initial without first moving the HPA off CPU/memory (VPA owns those under Auto). +spec: + targetRef: + apiVersion: apps/v1 + kind: Deployment + name: api + updatePolicy: + updateMode: "Off" +--- +apiVersion: autoscaling.k8s.io/v1 +kind: VerticalPodAutoscaler +metadata: + name: redis-vpa + namespace: artifactapi +spec: + targetRef: + apiVersion: apps/v1 + kind: Deployment + name: redis + updatePolicy: + updateMode: "Off" +--- +apiVersion: autoscaling.k8s.io/v1 +kind: VerticalPodAutoscaler +metadata: + name: ui-vpa + namespace: artifactapi + # NOTE: this workload also has an HPA. updateMode Off is recommendation-only + # and does not act, so there is no HPA/VPA conflict today. Do not flip to Auto/ + # Initial without first moving the HPA off CPU/memory (VPA owns those under Auto). +spec: + targetRef: + apiVersion: apps/v1 + kind: Deployment + name: ui + updatePolicy: + updateMode: "Off" diff --git a/apps/base/authentik/kustomization.yaml b/apps/base/authentik/kustomization.yaml index 3c58eee..0ba3537 100644 --- a/apps/base/authentik/kustomization.yaml +++ b/apps/base/authentik/kustomization.yaml @@ -17,3 +17,4 @@ resources: - redis-service.yaml - vaultauth.yaml - vaultstaticsecret.yaml + - vpa.yaml diff --git a/apps/base/authentik/vpa.yaml b/apps/base/authentik/vpa.yaml new file mode 100644 index 0000000..d3481dd --- /dev/null +++ b/apps/base/authentik/vpa.yaml @@ -0,0 +1,13 @@ +--- +apiVersion: autoscaling.k8s.io/v1 +kind: VerticalPodAutoscaler +metadata: + name: redis-vpa + namespace: authentik +spec: + targetRef: + apiVersion: apps/v1 + kind: Deployment + name: redis + updatePolicy: + updateMode: "Off" diff --git a/apps/base/bind-system/kustomization.yaml b/apps/base/bind-system/kustomization.yaml index 28eb339..5458594 100644 --- a/apps/base/bind-system/kustomization.yaml +++ b/apps/base/bind-system/kustomization.yaml @@ -9,3 +9,4 @@ resources: - https://git.unkin.net/unkin/bind-operator/raw/tag/v0.2.4/config/crd/install.yaml - rbac.yaml - deployment.yaml + - vpa.yaml diff --git a/apps/base/bind-system/vpa.yaml b/apps/base/bind-system/vpa.yaml new file mode 100644 index 0000000..6beb7d2 --- /dev/null +++ b/apps/base/bind-system/vpa.yaml @@ -0,0 +1,13 @@ +--- +apiVersion: autoscaling.k8s.io/v1 +kind: VerticalPodAutoscaler +metadata: + name: bind-operator-vpa + namespace: bind-system +spec: + targetRef: + apiVersion: apps/v1 + kind: Deployment + name: bind-operator + updatePolicy: + updateMode: "Off" diff --git a/apps/base/cephrgw-system/kustomization.yaml b/apps/base/cephrgw-system/kustomization.yaml index 8087c3e..90aa141 100644 --- a/apps/base/cephrgw-system/kustomization.yaml +++ b/apps/base/cephrgw-system/kustomization.yaml @@ -11,3 +11,4 @@ resources: - deployment.yaml - vaultauth.yaml - vaultstaticsecret.yaml + - vpa.yaml diff --git a/apps/base/cephrgw-system/vpa.yaml b/apps/base/cephrgw-system/vpa.yaml new file mode 100644 index 0000000..6c7f6f5 --- /dev/null +++ b/apps/base/cephrgw-system/vpa.yaml @@ -0,0 +1,13 @@ +--- +apiVersion: autoscaling.k8s.io/v1 +kind: VerticalPodAutoscaler +metadata: + name: cephrgw-operator-vpa + namespace: cephrgw-system +spec: + targetRef: + apiVersion: apps/v1 + kind: Deployment + name: cephrgw-operator + updatePolicy: + updateMode: "Off" diff --git a/apps/base/encapi/kustomization.yaml b/apps/base/encapi/kustomization.yaml index fcbf043..a307335 100644 --- a/apps/base/encapi/kustomization.yaml +++ b/apps/base/encapi/kustomization.yaml @@ -13,3 +13,4 @@ resources: - cnpg_pooler.yaml - vaultauth.yaml - vaultstaticsecret.yaml + - vpa.yaml diff --git a/apps/base/encapi/vpa.yaml b/apps/base/encapi/vpa.yaml new file mode 100644 index 0000000..f70d3e7 --- /dev/null +++ b/apps/base/encapi/vpa.yaml @@ -0,0 +1,13 @@ +--- +apiVersion: autoscaling.k8s.io/v1 +kind: VerticalPodAutoscaler +metadata: + name: encapi-vpa + namespace: encapi +spec: + targetRef: + apiVersion: apps/v1 + kind: Deployment + name: encapi + updatePolicy: + updateMode: "Off" diff --git a/apps/base/kanidm/kustomization.yaml b/apps/base/kanidm/kustomization.yaml index 7f64266..abbaeab 100644 --- a/apps/base/kanidm/kustomization.yaml +++ b/apps/base/kanidm/kustomization.yaml @@ -14,6 +14,7 @@ resources: - gateway.yaml - httproute.yaml - tlsroute.yaml + - vpa.yaml configMapGenerator: - name: kanidm-config diff --git a/apps/base/kanidm/vpa.yaml b/apps/base/kanidm/vpa.yaml new file mode 100644 index 0000000..49c5ea7 --- /dev/null +++ b/apps/base/kanidm/vpa.yaml @@ -0,0 +1,13 @@ +--- +apiVersion: autoscaling.k8s.io/v1 +kind: VerticalPodAutoscaler +metadata: + name: kanidm-vpa + namespace: kanidm +spec: + targetRef: + apiVersion: apps/v1 + kind: StatefulSet + name: kanidm + updatePolicy: + updateMode: "Off" diff --git a/apps/base/litellm/kustomization.yaml b/apps/base/litellm/kustomization.yaml index 61754ea..c73e836 100644 --- a/apps/base/litellm/kustomization.yaml +++ b/apps/base/litellm/kustomization.yaml @@ -15,6 +15,7 @@ resources: - services.yaml - vaultauth.yaml - vaultstaticsecret.yaml + - vpa.yaml configMapGenerator: - name: litellm-config diff --git a/apps/base/litellm/vpa.yaml b/apps/base/litellm/vpa.yaml new file mode 100644 index 0000000..d91050c --- /dev/null +++ b/apps/base/litellm/vpa.yaml @@ -0,0 +1,29 @@ +--- +apiVersion: autoscaling.k8s.io/v1 +kind: VerticalPodAutoscaler +metadata: + name: litellm-vpa + namespace: litellm + # NOTE: this workload also has an HPA. updateMode Off is recommendation-only + # and does not act, so there is no HPA/VPA conflict today. Do not flip to Auto/ + # Initial without first moving the HPA off CPU/memory (VPA owns those under Auto). +spec: + targetRef: + apiVersion: apps/v1 + kind: Deployment + name: litellm + updatePolicy: + updateMode: "Off" +--- +apiVersion: autoscaling.k8s.io/v1 +kind: VerticalPodAutoscaler +metadata: + name: redis-vpa + namespace: litellm +spec: + targetRef: + apiVersion: apps/v1 + kind: Deployment + name: redis + updatePolicy: + updateMode: "Off" diff --git a/apps/base/paperclip/kustomization.yaml b/apps/base/paperclip/kustomization.yaml index 0d16222..d03f2a5 100644 --- a/apps/base/paperclip/kustomization.yaml +++ b/apps/base/paperclip/kustomization.yaml @@ -12,3 +12,4 @@ resources: - services.yaml - vaultauth.yaml - vaultstaticsecret.yaml + - vpa.yaml diff --git a/apps/base/paperclip/vpa.yaml b/apps/base/paperclip/vpa.yaml new file mode 100644 index 0000000..7c45776 --- /dev/null +++ b/apps/base/paperclip/vpa.yaml @@ -0,0 +1,13 @@ +--- +apiVersion: autoscaling.k8s.io/v1 +kind: VerticalPodAutoscaler +metadata: + name: paperclip-vpa + namespace: paperclip +spec: + targetRef: + apiVersion: apps/v1 + kind: Deployment + name: paperclip + updatePolicy: + updateMode: "Off" diff --git a/apps/base/pdbmux/kustomization.yaml b/apps/base/pdbmux/kustomization.yaml index 372a7e3..fb56392 100644 --- a/apps/base/pdbmux/kustomization.yaml +++ b/apps/base/pdbmux/kustomization.yaml @@ -9,3 +9,4 @@ resources: - service.yaml - gateway.yaml - httproute.yaml + - vpa.yaml diff --git a/apps/base/pdbmux/vpa.yaml b/apps/base/pdbmux/vpa.yaml new file mode 100644 index 0000000..a2615a2 --- /dev/null +++ b/apps/base/pdbmux/vpa.yaml @@ -0,0 +1,13 @@ +--- +apiVersion: autoscaling.k8s.io/v1 +kind: VerticalPodAutoscaler +metadata: + name: pdbmux-vpa + namespace: pdbmux +spec: + targetRef: + apiVersion: apps/v1 + kind: Deployment + name: pdbmux + updatePolicy: + updateMode: "Off" diff --git a/apps/base/puppet/kustomization.yaml b/apps/base/puppet/kustomization.yaml index fc370c7..69fe8ce 100644 --- a/apps/base/puppet/kustomization.yaml +++ b/apps/base/puppet/kustomization.yaml @@ -36,6 +36,7 @@ resources: - service_puppetboard.yaml - service_puppetdb.yaml - deployment_puppetserver-compiler.yaml + - vpa.yaml configMapGenerator: - name: compiler-autosign.conf diff --git a/apps/base/puppet/vpa.yaml b/apps/base/puppet/vpa.yaml new file mode 100644 index 0000000..90107c6 --- /dev/null +++ b/apps/base/puppet/vpa.yaml @@ -0,0 +1,64 @@ +--- +apiVersion: autoscaling.k8s.io/v1 +kind: VerticalPodAutoscaler +metadata: + name: puppetboard-vpa + namespace: puppet + # NOTE: this workload also has an HPA. updateMode Off is recommendation-only + # and does not act, so there is no HPA/VPA conflict today. Do not flip to Auto/ + # Initial without first moving the HPA off CPU/memory (VPA owns those under Auto). +spec: + targetRef: + apiVersion: apps/v1 + kind: Deployment + name: puppetboard + updatePolicy: + updateMode: "Off" +--- +apiVersion: autoscaling.k8s.io/v1 +kind: VerticalPodAutoscaler +metadata: + name: puppetdb-vpa + namespace: puppet + # NOTE: this workload also has an HPA. updateMode Off is recommendation-only + # and does not act, so there is no HPA/VPA conflict today. Do not flip to Auto/ + # Initial without first moving the HPA off CPU/memory (VPA owns those under Auto). +spec: + targetRef: + apiVersion: apps/v1 + kind: Deployment + name: puppetdb + updatePolicy: + updateMode: "Off" +--- +apiVersion: autoscaling.k8s.io/v1 +kind: VerticalPodAutoscaler +metadata: + name: puppetserver-compiler-vpa + namespace: puppet + # NOTE: this workload also has an HPA. updateMode Off is recommendation-only + # and does not act, so there is no HPA/VPA conflict today. Do not flip to Auto/ + # Initial without first moving the HPA off CPU/memory (VPA owns those under Auto). +spec: + targetRef: + apiVersion: apps/v1 + kind: Deployment + name: puppetserver-compiler + updatePolicy: + updateMode: "Off" +--- +apiVersion: autoscaling.k8s.io/v1 +kind: VerticalPodAutoscaler +metadata: + name: puppetserver-master-vpa + namespace: puppet + # NOTE: this workload also has an HPA. updateMode Off is recommendation-only + # and does not act, so there is no HPA/VPA conflict today. Do not flip to Auto/ + # Initial without first moving the HPA off CPU/memory (VPA owns those under Auto). +spec: + targetRef: + apiVersion: apps/v1 + kind: Deployment + name: puppetserver-master + updatePolicy: + updateMode: "Off"