Kubernetes autoscaling in 2026: revisit Karpenter, Cluster Autoscaler and KEDA before you scale another node

Picture a mid-size ecommerce SaaS in Ahmedabad with about 2,200 active sellers (an invented example, not a real client). Its platform team of eight runs checkout, catalogue, search and about 55 other services on Kubernetes on a public cloud. Sale events three or four times a year push traffic hard. Between sales the cluster sits over-provisioned: large node groups sized for the last flash sale, many nodes half empty, and a cloud bill that the finance team now questions every month. During the last sale, pending pods sat for minutes while a node group slowly grew, and one worker Deployment scaled on CPU long after the checkout queue had already backed up. Three proposals are on the whiteboard. One engineer wants Cluster Autoscaler because the managed node groups already exist. A second wants Karpenter because consolidation and flexible instance selection should cut idle cost. A third wants KEDA because the real pain is queue depth and cron-shaped batch jobs, not node shape. They are arguing as if these were three products that do the same job. They are not.

Kubernetes autoscaling has two layers that teams keep mixing up. Cluster Autoscaler and Karpenter provision and remove nodes so that pending pods can schedule, and so that empty or wasteful capacity can leave. KEDA scales pods (and related ScaledObjects and ScaledJobs) from events and metrics, usually by owning or feeding a Horizontal Pod Autoscaler (HPA). KEDA does not replace a node provisioner. HPA alone does not add nodes. If pods need more CPU than the current nodes hold, something still has to launch machines. This post compares where Karpenter, Cluster Autoscaler and KEDA stand on 13 October 2026: history, what each actually does, architecture, cloud and provider support, consolidation and disruption, metrics and triggers, cost and bin-packing, security, and a decision guide. Facts come from GitHub releases, official docs, LICENSE files and CVE or GitHub advisory records. The drill near the end is my own run on this Linux box without a cloud account or a live cluster, and I label clearly what I could not run.

The short version

  • Decide first what you are scaling: pods, nodes, or both. Node tools and pod tools solve different bottlenecks. Using only one when you need both is a common path to pending pods or idle spend.
  • Karpenter (core kubernetes-sigs/karpenter and the AWS provider aws/karpenter-provider-aws) is at v1.15.0 (10 October 2026, 11:12 AM IST for core; 12:05 PM IST for the AWS provider). It watches unschedulable pods, launches right-sized nodes from flexible constraints, and removes nodes through consolidation, drift, expiration and related disruption controls. The vendor-neutral core lives under Kubernetes SIG Autoscaling; cloud providers ship their own integrations. Apache 2.0.
  • Cluster Autoscaler (kubernetes/autoscaler) latest patch lines on 13 October 2026 include 1.36.1, 1.35.2, 1.34.5 and 1.33.6 (all published 23 July 2026, late evening IST). Match the Cluster Autoscaler minor version to your Kubernetes minor version and take the latest patch for that minor. It grows and shrinks existing node groups when pods are pending or nodes are unneeded. Apache 2.0. Broad multi-cloud coverage.
  • KEDA (kedacore/keda) is at v2.21.0 (23 September 2026, 9:50 PM IST), a CNCF graduated project. It scales Deployments, StatefulSets, custom resources and Jobs from event sources and metrics, including scale to and from zero, by working with HPA rather than replacing it. Apache 2.0. Docs list on the order of seventy-plus built-in scalers plus External and External Push.
  • They are not three equal alternatives. For the Ahmedabad team: KEDA (or HPA) for queue and traffic shaped pod counts; Karpenter or Cluster Autoscaler for nodes. Running Cluster Autoscaler and Karpenter on the same node groups is something both projects warn against in practice; pick one node provisioner per set of nodes.
  • Security in 2025-2026 is uneven across the trio. KEDA shipped three notable advisories, including critical CVE-2026-77524 (privilege escalation via TriggerAuthentication / bound service account tokens), fixed in 2.21.0. I found no GitHub security advisories and no NVD hits for Karpenter or Cluster Autoscaler under those project names in this research pass. Node provisioners still need strong cloud IAM and admission control around who can create NodePools or change autoscaler flags.

Where things stand on 13 October 2026

Dates are from each project’s GitHub release published_at unless marked otherwise; times are converted from UTC to IST (UTC+5:30). Licences are from the LICENSE files at the tagged releases.

Project

Release

Date (IST)

Notes

Licence

Karpenter core (kubernetes-sigs/karpenter)

v1.15.0

10 October 2026, 11:12 AM

Current core release; DRA prioritized alternatives, VPA prediction controller (feature work), topology spread awareness, node repair as voluntary disruption, metrics for disruption

Apache 2.0

Karpenter AWS provider (aws/karpenter-provider-aws)

v1.15.0

10 October 2026, 12:05 PM

Tracks core; EC2NodeClass / NodePool examples at tag

Apache 2.0

Karpenter Azure provider (Azure/karpenter-provider-azure)

v1.14.5

13 October 2026, 12:13 AM

Latest Azure provider tag at research time; not the same version line as AWS 1.15.0

Apache 2.0 (provider repo)

Karpenter core

v1.14.1

22 August 2026, 4:05 AM

Previous patch on 1.14

Apache 2.0

Karpenter core

v1.14.0

11 July 2026, 5:47 AM

Prior minor

Apache 2.0

Karpenter AWS / core

v1.0.0

15 August 2024, 1:29 AM / 12:36 AM

Stable v1 APIs announced

Apache 2.0

Cluster Autoscaler

1.36.1

23 July 2026, 11:33 PM

Latest 1.36 patch; image registry.k8s.io/autoscaling/cluster-autoscaler:v1.36.1

Apache 2.0

Cluster Autoscaler

1.35.2

23 July 2026, 11:32 PM

Latest 1.35 patch

Apache 2.0

Cluster Autoscaler

1.34.5

23 July 2026, 11:26 PM

Latest 1.34 patch

Apache 2.0

Cluster Autoscaler

1.33.6

23 July 2026, 11:24 PM

Latest 1.33 patch

Apache 2.0

Cluster Autoscaler chart

9.59.0

22 July 2026, 2:50 AM

Helm chart release in the same repository

Apache 2.0

KEDA

v2.21.0

23 September 2026, 9:50 PM

Current release; fixes CVE-2026-77524; three breaking changes vs 2.20

Apache 2.0

KEDA

v2.20.2

31 July 2026, 1:44 PM

Last 2.20 patch before 2.21

Apache 2.0

KEDA

v2.20.0

1 June 2026, 8:16 PM

Includes fix path for CVE-2026-53572 (PostgreSQL scaler)

Apache 2.0

KEDA

v2.18.3 / v2.17.3

22 December 2025, about 5:14 PM / 5:12 PM

Fixes for CVE-2025-68476 (Vault SA path)

Apache 2.0

Two practical notes on the table. Cluster Autoscaler’s README still says to match the CA minor to the Kubernetes minor and to use the latest CA release for that minor; the README compatibility table checked at tag cluster-autoscaler-1.36.1 listed rows through 1.34.x even though 1.35.x and 1.36.x release tags exist, so trust the release tags for your minor and the “latest patch for your minor” rule more than a stale table row. Second, Karpenter’s Azure provider version can lag the AWS provider: on this research day Azure was at v1.14.5 while AWS and core were at v1.15.0. Pin and read the provider changelog for your cloud, not only the core tag.

Timeline

Date (IST)

Event

17 November 2019

KEDA v1.0.0

4 November 2020

KEDA v2.0.0

27 November 2021

Karpenter AWS provider v0.5.0 (early public line)

22 November 2023

Karpenter added as a Kubernetes SIG Autoscaling subproject (kubernetes/community PR 7624)

Late 2023

Vendor-neutral Karpenter core migrates toward kubernetes-sigs/karpenter; AWS keeps the AWS provider

22 August 2023

KEDA announced as a CNCF Graduated project

15 August 2024

Karpenter v1.0.0 (stable v1 APIs)

22 December 2025

KEDA CVE-2025-68476 advisory published (Vault service account file read)

1 June 2026

KEDA v2.20.0; GHSA for CVE-2026-53572 published the same day (PostgreSQL connection string)

23 July 2026

Cluster Autoscaler 1.36.1 / 1.35.2 / 1.34.5 / 1.33.6 patch set

21 August 2026

CVE-2026-53572 published in CVE record (mitre / NVD path)

23 September 2026

KEDA v2.21.0; GHSA for CVE-2026-77524 published

10 October 2026

Karpenter core and AWS provider v1.15.0

13 October 2026

Azure Karpenter provider v1.14.5

Cluster Autoscaler is the oldest of the three as a Kubernetes SIG project: it has tracked Kubernetes minor versions for years and ships multi-cloud providers in-tree. Karpenter started at AWS and split into a SIG-hosted core plus cloud providers. KEDA started at Microsoft and Red Hat and is now CNCF graduated. That history shows up in APIs: CA talks to node groups; Karpenter talks to NodePool / NodeClaim / cloud NodeClass objects; KEDA talks to ScaledObject / ScaledJob / TriggerAuthentication.

First question: what are you scaling?

Before comparing tools, write down the failure you saw in the last sale (or the idle cost you hate between sales). For the Ahmedabad team the honest list is:

  • Checkout and notification workers should track RabbitMQ and Kafka lag, including scale to zero at night, not only Deployment CPU.
  • When HPA (or KEDA) adds pods, those pods must schedule within a short time, or the sale is already lost.
  • Between sales, nodes should shrink without a human resizing three node groups by hand.

These are three different problems:

  1. Pod count and activation (including to/from zero): HPA and/or KEDA.
  2. Node capacity for pending pods: Cluster Autoscaler or Karpenter.
  3. Node waste after demand falls: Cluster Autoscaler scale-down, or Karpenter consolidation / emptiness, plus correct requests and PDBs.

If you only install Karpenter, queue-driven workers still will not scale from a RabbitMQ depth metric by themselves. If you only install KEDA, pending pods still wait when the node pool is full. If you only install Cluster Autoscaler on fixed instance types, you may add capacity slowly and leave expensive shapes running for weeks. The first design choice is the layer, not the logo.

Related reading on this site when you wire the edges: admission policy for who may create NodePools or ScaledObjects; Prometheus long-term storage if KEDA’s Prometheus scaler is in play; container image builds when node churn makes cold image pulls painful.

What each tool actually is

Cluster Autoscaler 1.36.x (match your Kubernetes minor)

Cluster Autoscaler adjusts the size of a Kubernetes cluster when pods fail to schedule for lack of resources, or when nodes have been underutilized for long enough that their pods can move elsewhere. That definition is from the project README. It does not invent new machine shapes on every pending pod. It scales node groups that already exist in the cloud provider (or Cluster API, and so on), within min and max sizes you configure.

Important behaviours from the FAQ:

  • Scale-up happens for unschedulable pods when adding a node similar to nodes already in a group would help.
  • Scale-down happens when nodes are consistently unneeded: low utilization and movable pods.
  • Restrictive PodDisruptionBudgets, certain kube-system pods, naked pods, local storage (unless annotated), and unschedulable constraints can block scale-down.
  • CA terminates the cloud instance; it does not delete the Node object itself. The cloud node controller cleans Node objects up.
  • The project recommends matching CA’s minor version to the Kubernetes minor and using the latest CA patch for that minor.
  • Do not run another node-group autoscaler on the same groups (including the cloud provider’s own node autoscaler) alongside CA.

CA remains the default mental model on many managed Kubernetes offerings because node groups are already first-class. Its strength is breadth of cloud providers and predictable group-based operations. Its limits are the ones the FAQ states: group templates, expander choice, and scale-down rules that depend on utilization and PDB friendliness.

Karpenter 1.15.0

Karpenter’s README states the loop clearly: watch pods the scheduler marked unschedulable, evaluate scheduling constraints (requests, node selectors, affinities, tolerations, topology spread), provision nodes that meet those requirements, and remove nodes when they are no longer needed.

Conceptual pieces from the docs:

  • NodePool: constraints and behaviour for how Karpenter manages unschedulable pods and configures nodes (requirements, limits, disruption, weight).
  • NodeClass (cloud-specific, for example EC2NodeClass on AWS): how to join the cluster (subnets, security groups, AMI, role).
  • NodeClaim: the claim for capacity Karpenter is launching or has launched.
  • Disruption: consolidation, drift, expiration, interruption handling, optional node auto repair, with NodePool disruption budgets (default nodes: 10% if undefined) rate-limiting voluntary disruption.

Consolidation policies in current docs include WhenEmpty, Balanced, and the more aggressive underutilized path (docs describe WhenEmptyOrUnderutilized in the trade-off table). consolidateAfter controls how long a node must stay stable before consolidation considers it; Never disables consolidation for that NodePool. Default expireAfter is described as 720h (30 days) unless you change it. Interruption handling (when enabled) watches spot interruption warnings, scheduled maintenance-style health events, and terminating/stopping/status-check failure events, then taints, drains and terminates ahead of the event.

Karpenter started at AWS. The vendor-neutral core is now under kubernetes-sigs/karpenter as a SIG Autoscaling subproject. AWS maintains karpenter-provider-aws. Other providers exist with different maturity: Azure’s AKS provider, community or vendor providers for GCP, Alibaba Cloud, Cluster API, OCI, Proxmox, Hetzner, IBM Cloud and more are listed on the core README. Treat non-AWS providers as separately versioned products. On this research day the Azure provider latest tag was v1.14.5 while AWS was v1.15.0.

KEDA 2.21.0

KEDA (Kubernetes Event-driven Autoscaling) scales applications from real-world events. The concepts docs say it was created by Microsoft and Red Hat, is lightweight, works alongside HPA, and does not replace Kubernetes components. You can adopt it for some apps and leave others alone.

Architecture (from the 2.21 concepts docs):

  • keda-operator: watches ScaledObjects and related resources, manages HPA lifecycle, and handles scaling between zero and one replica directly.
  • keda-metrics-apiserver: exposes external metrics to HPA so replica counts above one follow event metrics.
  • keda-admission-webhooks: validate KEDA resources at apply time (for example catching two ScaledObjects on the same Deployment).

KEDA also supports ScaledJobs for event-driven Job creation. Authentication for scalers goes through TriggerAuthentication / ClusterTriggerAuthentication, which is also where several CVEs concentrated (Vault paths and bound service account tokens). The project is CNCF Graduated (announced 22 August 2023).

Architecture comparison

Concern

Cluster Autoscaler

Karpenter

KEDA

Primary object scaled

Node groups / nodes

Nodes (NodeClaim / Node)

Pods (Deployment, StatefulSet, custom scale target) or Jobs

Trigger to add capacity

Unschedulable pods

Unschedulable pods

Event source / metric via scaler; activation then HPA

Trigger to remove capacity

Underutilized nodes, pods movable

Consolidation, emptiness, drift, expiration, interruption, repair

Metric idle / cooldown; operator scales 1 to 0

Works with HPA

Indirectly (HPA creates pods that may pend)

Indirectly (same)

Directly (owns/feeds HPA; 0-1 special path)

Instance flexibility

Limited by pre-created group templates

Chooses from requirements / offerings at provision time

Not a node provisioner

Scale to zero nodes

Possible for supported providers/groups when conditions met

Yes, when nodes empty and disruption allows

Scales pods to zero; nodes need a node tool

Typical install surface

Deployment + cloud IAM + group tags/config

Controller + NodePool + NodeClass + cloud IAM

Operator + metrics apiserver + webhooks + ScaledObjects

Governance

Kubernetes SIG Autoscaling / kubernetes/autoscaler

SIG Autoscaling core + cloud providers

CNCF Graduated (kedacore)

Pod path vs node path (same table, different verbs)

Symptom

Likely layer

Tool to evaluate first

Queue depth high, replica count flat

Pod

KEDA scaler or custom metrics HPA

Replicas rising, pods Pending Insufficient cpu/memory

Node

Karpenter or Cluster Autoscaler

Sale over, nodes still large for days

Node

CA scale-down tuning or Karpenter consolidation

Cron batch needs 0 replicas most of day

Pod

KEDA ScaledObject / ScaledJob

Spot reclamation kills nodes mid-checkout

Node

Karpenter interruption handling and PDBs; CA group mixed-capacity practices

Cloud and provider support

Cluster Autoscaler ships many in-tree cloud providers. The cloudprovider directory at tag cluster-autoscaler-1.36.1 includes directories such as aws, azure, gce, clusterapi, digitalocean, hetzner, oci, scaleway, bizflycloud, externalgrpc, kwok and others (dozens of entries including test helpers). The README also links provider-specific notes. Breadth is CA’s historical advantage. Behaviour still varies by provider; read that provider’s README before you assume scale-to-zero or expander features work the same everywhere. The project notes that combination testing is centred on GCP for version pairing, and that other environments may differ.

Karpenter is multi-cloud at the project level through separate provider repositories. The core README lists implementations including AWS, Azure, Alibaba Cloud, Cluster API, GCP (cloudpilot-ai), OCI (Oracle and a Zoom-maintained repo), Proxmox, Hetzner, IBM Cloud, Huawei, Exoscale, Bizfly, Clever Cloud, Akamai/Linode (alpha) and UpCloud variants. AWS remains the reference provider and usually leads features. Azure’s provider is actively released (v1.14.5 on 13 October 2026 IST morning). For production outside AWS, verify the provider’s release cadence, supported Kubernetes versions and disruption feature parity yourself; do not assume core v1.15.0 behaviour is present on every provider the same week.

KEDA is cloud-agnostic as a controller. Its cloud coupling is in scalers and auth providers (AWS SQS, CloudWatch, Azure Service Bus, Event Hubs, GCP Pub/Sub, and many others). You can run KEDA on any conformant cluster; the limit is whether your event source has a scaler or an External scaler.

Managed Kubernetes notes (high level, from how these tools are usually offered, not a pricing claim): EKS documentation and AWS blogs treat Karpenter as a first-class alternative to CA on AWS; AKS has an Azure Karpenter provider; GKE historically leans on its own node auto-provisioning / CA patterns. Always check your managed service’s supported version matrix for the week you upgrade.

Consolidation, interruption and disruption budgets

This section is mostly about nodes. KEDA’s “disruption” is pod replica change and HPA behaviour; it does not drain nodes.

Cluster Autoscaler scale-down

CA removes nodes that stay unneeded. Pods that block removal include restrictive PDBs, some kube-system pods without suitable PDBs, pods not backed by a controller, local-storage pods (unless annotated safe), and pods that cannot reschedule elsewhere. Graceful termination during scale-down is bounded (FAQ: from CA 1.0, default at most 10 minutes via --max-graceful-termination-sec, then the node may be terminated anyway). Annotation cluster-autoscaler.kubernetes.io/scale-down-disabled: "true" can protect a node. Utilization thresholds and delay flags control how quickly empty-ish nodes disappear. If scale-down never fires in Ahmedabad between sales, the first debug targets are PDBs, local volumes on Deployments that should be emptyDir-safe, and pods stuck without owners.

Karpenter disruption

Karpenter’s disruption docs describe a Disruption Controller that runs automated methods in order (node repair when enabled, then drift, then consolidation), respecting disruption budgets, simulating reschedule, tainting with karpenter.sh/disrupted:NoSchedule, pre-spinning replacements when possible, then deleting. A Termination Controller drains with the Eviction API, respects PDBs, and terminates the cloud NodeClaim.

Useful controls to name correctly:

  • consolidationPolicy / consolidateAfter: how eagerly underutilized or empty nodes go away.
  • expireAfter: forceful maximum lifetime (docs default 720h); budgets do not block expiration the way they block voluntary consolidation/drift/emptiness.
  • Interruption (when enabled): react early to spot and related infrastructure events.
  • NodePool disruption budgets: default one budget with nodes: 10% if undefined; can be scoped by reason (Drifted, Underutilized, Empty).
  • karpenter.sh/do-not-disrupt on pods: blocks voluntary disruption paths; docs note it does not stop expiration, interruption, node repair or manual deletion.
  • Terminate-first paths (feature-gated in recent work): for capacity-constrained cases where a replacement cannot be pre-spun (for example full capacity reservations or static NodePools at node limit).

v1.15.0 release notes include more voluntary node repair behaviour, terminate-first drift/repair for capacity-constrained pools, and richer disruption metrics. Read the upgrade notes before you enable feature gates in production.

KEDA and pod disruption

KEDA changes replica counts. PodDisruptionBudgets still matter when those pods share nodes that Karpenter or CA want to drain. A ScaledObject that scales a Deployment to 40 replicas during a sale can make CA/Karpenter scale nodes out; when KEDA scales back, node consolidation only works if PDBs and topology constraints allow eviction. Pod and node autoscaling share the cluster’s disruption budget whether you planned that or not.

Metrics and triggers (KEDA scalers)

HPA native metrics cover CPU, memory and custom/external metrics. KEDA’s job is to make external event sources easy to plug into that model, including activation from zero.

The KEDA 2.21 docs scaler index lists a large built-in set. Counting the named scaler entries on the docs page (from ActiveMQ through Temporal, including variant rows such as Redis Cluster/Sentinel and excluding the separate Authentication Providers list) gives 78 entries. That includes External, External Push, CPU, Memory, Cron, Prometheus, RabbitMQ Queue, Apache Kafka, AWS SQS, Azure Service Bus, GCP Pub/Sub, PostgreSQL, NATS JetStream and many more. Treat the number as “docs index rows on that day”, not a marketing score. Prefer the scaler that matches your system of record:

  • Queue depth or lag: RabbitMQ, Kafka, SQS, NATS, and similar.
  • HTTP or business QPS already in Prometheus: Prometheus scaler (query must return a single-element vector/scalar per docs).
  • Time of day: Cron scaler for known sale windows, with care not to fight event-driven triggers.
  • CPU/Memory: available as KEDA triggers too, but native HPA may be enough; use KEDA when you also need scale-to-zero or mixed triggers.

KEDA 2.21 breaking changes to know before upgrade (from the v2.21.0 release notes):

  1. Service account token audience enforcement for CVE-2026-77524: TriggerAuthentication paths that use bound service account tokens (including some Vault Kubernetes auth and metrics receivers) need explicit audiences. Review the 2.20 to 2.21 migration guide.
  2. Azure Pipelines scaleOnInFlight defaults to true (queue length includes assigned unfinished jobs).
  3. Temporal scaler removes deprecated buildId, selectAllActive, selectUnversioned settings.

Authentication belongs in TriggerAuthentication objects, not copied secrets in every ScaledObject. That design is good for operations and is also why auth code has been a CVE hotspot.

Cost and bin-packing

No invented benchmark numbers here. Cost behaviour follows design:

  • Cluster Autoscaler adds another node of a template you already chose. Bin-packing quality depends on how many group shapes you maintain and which expander you use. Too few shapes means pending pods or oversized nodes. Too many groups means operational sprawl.
  • Karpenter bin-packs pending pods onto instance offerings that match requirements, and later consolidates. You pay for the flexibility with disruption: consolidation that is too aggressive churns pods; consolidation that is too timid leaves waste. Prefer correct resource requests and limits before you blame the provisioner. DaemonSets and service mesh sidecars shrink allocatable capacity on every node; if you run a mesh, revisit that cost in the service mesh post.
  • KEDA reduces cost when workloads can sleep (scale to zero) or track true demand instead of peak CPU. It can also increase node spend temporarily when it launches many pods at once; the node provisioner must keep up.

For the Ahmedabad sale pattern, a practical cost stack is: KEDA on queue workers and cron-shaped jobs; Karpenter (on AWS) or CA (if groups are mandatory) for nodes; PodDisruptionBudgets that allow consolidation after the sale; and a hard look at request inflation “just to be safe” that forces extra nodes forever.

Security and CVEs

Research on 13 October 2026 used GitHub Security Advisories APIs for kedacore/keda, kubernetes-sigs/karpenter, aws/karpenter-provider-aws and kubernetes/autoscaler, plus NVD keyword searches for keda, karpenter and cluster-autoscaler, and CVE records where available.

KEDA

ID

Severity (advisory)

Published (IST)

Summary

Fix (per advisory / release notes)

CVE-2026-77524 / GHSA-637c-6jxx-4rwm

Critical (CVSS 3.1 score 9.9)

Advisory 23 September 2026, 3:39 PM

Namespace admin can escalate via TriggerAuthentication so the operator sends its high-privilege service account token to a tenant-controlled URL

Release notes: fixed in 2.21.0; advisory lists vulnerable <= 2.20.2. Migration requires explicit token audiences

CVE-2026-53572 / GHSA-6w3m-4hhp-775q

Medium (CVSS 3.1 score 5.9)

Advisory 1 June 2026, 11:19 AM; CVE record 21 August 2026

PostgreSQL scaler connection string parameter injection via incomplete whitespace escaping

Fixed in 2.20.0 (affected < 2.20.0)

CVE-2025-68476 / GHSA-c4p6-qg4m-9jmr

High (CVSS 4.0 score 8.2 in CVE record)

Advisory 22 December 2025, 5:28 PM

Arbitrary file read via Vault service account credential path validation

Fixed in 2.17.3, 2.18.3, and >= 2.19.0

If you run KEDA below 2.21.0 with Vault Kubernetes auth or boundServiceAccountToken TriggerAuthentications, treat upgrade planning as urgent. Also restrict who can create TriggerAuthentication and ScaledObject objects (RBAC plus admission policy).

Karpenter and Cluster Autoscaler

GitHub Security Advisories list for kubernetes-sigs/karpenter, aws/karpenter-provider-aws and kubernetes/autoscaler returned empty in this pass. NVD keyword search for karpenter and cluster-autoscaler returned zero vulnerabilities. That is not a promise of zero risk. Node autoscalers hold cloud credentials powerful enough to create and destroy compute. Practical controls:

  • Least-privilege IAM / workload identity for the controller.
  • Separate node roles from controller roles.
  • Admission policies on NodePool, EC2NodeClass (or cloud equivalent), and CA ConfigMaps/flags.
  • Pin versions; watch SIG and provider release notes.
  • Network policies around metrics endpoints KEDA scrapes.

Decision guide

Situation

Lean toward

AWS EKS, flexible instance selection, want consolidation and interruption handling

Karpenter (AWS provider), often with KEDA/HPA for pods

Must use existing managed node groups / ASGs / VMSS with min-max, many clouds

Cluster Autoscaler matched to Kubernetes minor

Queue, cron, Kafka lag, scale-to-zero workers

KEDA (+ a node provisioner)

Only CPU/memory HPA today, nodes already fine

Keep HPA; add KEDA only when events matter

Azure AKS interested in Karpenter

Azure Karpenter provider; verify version vs core features you need

GCP / other cloud without a mature Karpenter provider for your needs

Cluster Autoscaler (or the cloud’s supported node autoscaler), plus KEDA for pods

Already on CA, pain is pending pod latency and idle waste on AWS

Plan a migration with Karpenter’s migrating-from-CA docs; do not dual-drive the same nodes

Security review flagged TriggerAuthentication

Upgrade KEDA to 2.21+, tighten RBAC, complete audience migration

A workable Ahmedabad plan (invented)

  1. Write the sale and off-sale questions (queue lag, pending pods, idle node hours).
  2. Put checkout workers and notification consumers on KEDA 2.21 ScaledObjects (RabbitMQ / Kafka / Prometheus as appropriate), with PDBs that allow post-sale drain.
  3. Keep API Deployments on HPA CPU/memory unless an event metric is clearly better.
  4. On AWS, move worker node capacity to Karpenter NodePools with conservative consolidation first (WhenEmpty or Balanced), interruption handling on, explicit disruption budgets for sale weekends.
  5. Leave a small on-demand NodePool or managed group for system add-ons if you want blast-radius separation.
  6. If not on AWS, stay on Cluster Autoscaler for nodes, still add KEDA for queues.
  7. After one sale event, compare pending-pod time, node hours, and consolidation or scale-down events before widening NodePool requirements.

Checklist before you change production

  1. State whether the bottleneck is pods, nodes, or both.
  2. Pin versions: Karpenter provider + core, or CA minor matching Kubernetes, and KEDA 2.21+ if you use it.
  3. Inventory PDBs, local volumes, and naked pods that block node scale-down.
  4. Confirm only one node autoscaler owns each node group / NodePool set.
  5. For KEDA upgrades from 2.20, complete the service account token audience migration guide.
  6. Restrict RBAC on TriggerAuthentication, NodePool, NodeClass and CA configuration.
  7. Load-test sale traffic in a non-prod cluster with the same autoscaler versions.
  8. Watch pending pods, HPA/KEDA metrics, and node churn during the test, not only average CPU.
  9. Document interruption behaviour for spot (Karpenter) or mixed capacity (CA).
  10. Schedule a post-sale review of idle node hours within 48 hours.

Common mistakes

  1. Treating KEDA as a Cluster Autoscaler replacement.
  2. Running CA and Karpenter on the same nodes.
  3. Scaling pods on CPU while the real backlog is a queue.
  4. Setting minReplicas: 1 everywhere and wondering why scale-to-zero never happens.
  5. Huge PDBs that block all consolidation and CA scale-down.
  6. Requests set to peak-of-peaks so every node looks full and nothing consolidates.
  7. Ignoring KEDA TriggerAuthentication CVEs because “it only reads metrics”.
  8. Assuming Azure/GCP Karpenter providers match AWS features on the same day.
  9. Using CA without matching its minor to Kubernetes.
  10. Turning on aggressive Karpenter consolidation for the first time on a sale weekend.

A drill I ran on 13 October 2026

Environment: shared Linux VM, kernel 6.12, 8 vCPU, about 15 GiB RAM with roughly 2.8 GiB available, no cloud credentials, no Docker, kind or k3d, no Kubernetes API server. Port 8766 was left alone.

What I did:

  1. Verified release tags over the GitHub API for kubernetes-sigs/karpenter v1.15.0, aws/karpenter-provider-aws v1.15.0, Azure/karpenter-provider-azure v1.14.5, kedacore/keda v2.21.0 and kubernetes/autoscaler cluster-autoscaler-1.36.1. All were non-draft, non-prerelease. Results saved under /workspace/revisit/drill36/version-verify.json.
  2. Downloaded upstream examples and CRDs from those tags: Karpenter examples/v1/general-purpose.yaml and spot.yaml (NodePool + EC2NodeClass), inflate Deployment, nodepools.karpenter.sh CRD, and KEDA scaledobjects.keda.sh CRD.
  3. Authored two ScaledObject manifests shaped like the KEDA 2.21 Prometheus and RabbitMQ scaler docs (not applied to any cluster).
  4. Parsed every YAML file with PyYAML. All documents loaded; CRDs report served versions v1 for NodePool and v1alpha1 for ScaledObject.
  5. Briefly fetched kubectl v1.34.1 to attempt client dry-run. Without an API server, kubectl still tried localhost:8080 and failed. I removed the kubectl binary afterwards. Offline validation for this drill is the PyYAML parse and CRD inspection, not live schema admission.

What I did not run: no kind cluster, no Karpenter or CA controller, no KEDA operator, no real scale-up latency, no consolidation timing, no spot interruption simulation. Those need a cloud account or at least a local multi-node cluster larger than this shared VM comfortably allowed today.

Finding that is still useful: the public examples and CRDs at the pinned tags are coherent and parse cleanly, Azure’s provider tag can lag AWS, and kubectl client dry-run is not a substitute for a cluster when CRDs are involved. Artefacts live in /workspace/revisit/drill36/.

Unlearn

  • Unlearn the idea that “autoscaling” is one checkbox. Pods and nodes are different control loops.
  • Unlearn replacing CA with KEDA. Different layer.
  • Unlearn that more node groups always mean more flexibility. Sometimes they mean slower scale-up and more idle capacity.
  • Unlearn that scale-to-zero is free. Cold starts, image pulls and node joins still cost time; see also image build and pull practise in the image builds post.
  • Unlearn ignoring TriggerAuthentication RBAC because it looks like config glue.

Re-learn

  • Re-learn pending pods as the primary signal for node autoscalers, and event metrics as the primary signal for KEDA.
  • Re-learn PDBs as part of autoscaling design, not only of voluntary maintenance.
  • Re-learn version pinning: CA minor to Kubernetes minor; Karpenter core to provider; KEDA to migration notes.
  • Re-learn multi-cloud honesty: CA is broad; Karpenter is provider-specific; KEDA is scaler-specific.
  • Re-learn that cost wins usually come from correct requests plus sleep-when-idle pods plus consolidation, not from one tool alone.

Closing

Kubernetes autoscaling in 2026 is still two problems wearing one word. Cluster Autoscaler and Karpenter add and remove nodes. KEDA scales pods from events and metrics beside HPA. The Ahmedabad team’s sale pain needs both layers named correctly before anyone wins a tool argument. Learn what each controller watches. Unlearn treating them as interchangeable. Re-learn version and CVE hygiene, especially on KEDA 2.21. Practise in a non-prod sale rehearsal with pending-pod and queue metrics on the same dashboard. Apply one change at a time: pod triggers first if queues are the truth, node provisioner next if pods pend, consolidation last if idle cost is the complaint.

Sources

Karpenter

Cluster Autoscaler

KEDA

Internal

comments powered by Disqus

Releted Posts

Fluent Bit, Vector and the OpenTelemetry Collector: revisit your log pipeline before you ship more logs

A logistics company in Pune runs about 600 pods across three Kubernetes clusters. A Fluentd DaemonSet, set up in 2019 with a dozen Ruby plugins, ships about 25 crore log lines a day to Loki.

Read more

Continuous profiling in 2026: revisit Grafana Pyroscope, Parca and the OpenTelemetry eBPF profiler before you store another flame graph

Picture a GST invoicing SaaS in Pune with about 1,800 business customers (an invented example, not a real client). Its platform team of six runs about 40 services, mostly Go with a few Java and Python ones, on a 12-node Kubernetes cluster.

Read more

Data pipeline orchestration in 2026: revisit Apache Airflow, Dagster and Prefect before you schedule another DAG

Picture a two-wheeler loan company in Coimbatore with about ninety branches (an invented example, not a real client). Its data team of five runs about 140 cron jobs on two Linux VMs: shell scripts that pull collections files from a payment gateway SFTP, Python scripts that clean them, and SQL that loads a PostgreSQL reporting database every night.

Read more