Cluster Autoscaling

Nodes are added and removed for you as your workloads grow and shrink. This
article explains how that works on AWS environments, what the node pools are,
how to pin a workload that must never be interrupted, and what to check when
scaling does not behave as you expect.

How autoscaling works

AWS environments use Karpenter for node autoscaling. No action is required
from your team for routine scaling.

When a pod cannot be scheduled because no node has enough available resources,
Karpenter:

  1. Selects an appropriate node type based on the pod's resource requests.
  2. Launches a new instance and registers it with the cluster.
  3. The pod is scheduled onto the new node.

When nodes are underutilised, Karpenter consolidates workloads onto fewer nodes
and terminates the excess.

Autoscaling decisions are driven entirely by your resource requests, so
accurate requests matter more here than anywhere else. Setting them is covered
in Workload Management.

Node pools

Each cluster has two default node pools.

Node poolPurposeInstance type
mainGeneral-purpose stateless workloadsSPOT instances
dataStateful or data-intensive workloadsOn-demand

Your Components are scheduled onto the appropriate pool based on their
configuration. Node pool settings for your Environment are adjustable in SVIEW.

SPOT instances can be reclaimed by AWS at two minutes' notice. Stateless
workloads should be written to tolerate a restart at any time — handle SIGTERM
and shut down cleanly. Stateful workloads belong on the data pool.

Configuration — pinning workloads off SPOT nodes

Some workloads must not tolerate a SPOT interruption at all: a long-running
batch job that cannot resume from a partial state, or a migration that must run
to completion.

This requires a dedicated non-interruptible node pool provisioned for your
Environment. Such a pool is not created by default — if you do not have one and
you need one, raise a request and CTO2B will provision it and tell you the pool
name to use.

Once the pool exists, pin the deployment or pod to it with a matching node
affinity and toleration:

affinity:
  nodeAffinity:
    requiredDuringSchedulingIgnoredDuringExecution:
      nodeSelectorTerms:
        - matchExpressions:
            - key: pool-type
              operator: In
              values:
                - uninterruptible-jobs
tolerations:
  - key: "nodepool-type"
    operator: "Equal"
    value: "uninterruptible-jobs"
    effect: "NoSchedule"

Replace uninterruptible-jobs with the actual pool name configured for your
Environment. Both blocks are needed: the affinity sends the pod to that pool,
and the toleration lets it past the taint that keeps other workloads off it.

Troubleshooting scaling issues

SymptomLikely cause
Pods stuck in PendingThe resource request cannot be satisfied by any node size — review requests and limits
Pods stuck in Pending after pinning to a poolThe affinity value or toleration does not match the actual pool name, or the pool does not exist
Nodes not scaling downPods have no resource requests, or a disruption budget is preventing eviction
SPOT interruption causing downtimeThe application is not shutting down gracefully — add SIGTERM handling, and run more than one replica

If the problem persists after these checks, raise a request with the affected
namespace, the Component name, and the pod status you are seeing.

Related articles


Did this page help you?