Updated 9 October 2026
About Coral
What is Coral?
- Coral is Kubernetes cost optimization for Azure Kubernetes Service (AKS) and Amazon Elastic Kubernetes Service (EKS).
- It sizes each container’s CPU and memory requests to what it really uses, and drains spare nodes one at a time so your autoscaler can remove them. No code changes.
- More on the product page: Kubernetes cost optimization on AKS and EKS.
Which clusters does Coral work on?
- AKS and EKS on Kubernetes 1.30 or later, with at least one Linux node (amd64 or arm64).
- Running pods are resized in place on 1.33+ nodes. On older nodes they restart one at a time.
- Windows nodes are listed and costed, but their workloads are not right-sized.
What does connecting a cluster change?
- One zoorikctl command installs the agent, its webhook and a node daemon, two CRDs and admission policies.
- In your cloud it creates one identity: on AKS, a role on that cluster that can read it and delete its machines; on EKS, an IAM role that can only terminate instances in its Auto Scaling groups. If the cluster has no autoscaler, it sets up NAP on AKS or Karpenter on EKS, with your approval.
- On AKS, connect turns on workload identity and the OIDC issuer if they are off, and the OIDC issuer can’t be turned off again. On an EKS cluster that uses only aws-auth, installing Karpenter switches authentication to API_AND_CONFIG_MAP for good.
- It lists every cloud change and asks once.
--dry-runprints everything and changes nothing. - Node optimization and the Evictor start at connect. Pod sizing waits until you switch on “Automatically optimize”.
What leaves my cluster?
- Per-container usage summaries and an inventory every 5 minutes, events with pod and node names, and a heartbeat every 60 seconds.
- No env var values, commands, image names or request payloads. The agent can’t read your Secrets or ConfigMaps.
- Details: What leaves your cluster.
How is the saving worked out?
- At your cloud’s published list price for the region, with spot nodes at the spot rate and a 730-hour month. Discounts, reservations and savings plans are left out.
- A smaller request reaches your bill when the freed capacity lets a node go.
- Every figure says where it comes from. Until data exists, figures read “Calculating”.
Do I need Coral with Karpenter or NAP?
- They do a different job. Karpenter and NAP choose and remove machines from pod requests; they don’t change the requests.
- Coral sizes requests to real use, so the same autoscaler can run fewer or smaller nodes. Pools that Karpenter or NAP consolidate are left to them.
- Compared in full: Coral and the native Kubernetes autoscalers.
How much can Coral save?
- We estimate 40–50% off AKS and EKS cost. It is an estimated range, not a promise.
- The free AKS and EKS cost assessment works out your own figure from your clusters, at list price.
Where can I buy Coral?
- Coral is available in AWS Marketplace and Microsoft Marketplace.
- If you pay for Coral, the price, billing period and payment terms are in your order or your marketplace purchase.
How Coral sizes workloads
Is the recommendation based on Average, P95, P99, Max, or a mix?
- CPU: a percentile of the last 3 days (P80 by default), plus 10% headroom.
- With a CPU-based HPA, the CPU request comes from replaying 3 days of load through your HPA instead.
- Memory: the peak of the last 8 days, plus 10% headroom, because running out of memory kills the container.
- During a surge or CPU pressure, the CPU target is raised for a while, up to P99.
- You can change the target per workload or in a custom policy, up to P99.9 or max.
How much history is needed before the first recommendation?
- A first recommendation appears within the first hour.
- It is trusted after 24 hours of data. Jobs and CronJobs need 3 runs.
- The window then grows to 3 days for CPU and 8 days for memory.
CPU is 100m at night and 2000m from 10 AM to 2 PM. What does Coral recommend?
- Without an HPA, the base request sits near the night level: the 4 busy hours are only 17% of the day, and P80 leaves out the busiest 20%.
- At 10 AM Coral detects the surge within minutes and raises the request. It drops back a few hours after the peak.
- With a CPU-based HPA, Coral sizes the CPU request by replaying 3 days of load through your HPA instead.
- To reserve 2000m all day, use the Stability policy or set a CPU minimum.
A workload is idle for 6 days and busy every Monday. Will Coral cut resources before Monday?
- Memory: no. Coral keeps last Monday’s peak, because it looks back 8 days (unless more than about 10% of the data is missing).
- CPU: yes. A short Monday peak doesn’t hold the CPU request up, so it returns to the idle level after the peak.
- On Monday Coral starts raising CPU within minutes. To be ready from the first minute, set a CPU minimum.
How are workloads handled that spike only at month-end or quarter-end?
- Coral looks back at most 8 days, so it doesn’t remember last month’s peak.
- When the spike comes, Coral raises CPU within minutes, and raises memory after any OOM kill.
- For known month-end workloads, set minimums or use a more conservative policy.
How does Coral learn Black Friday, Diwali or holiday traffic patterns?
- It doesn’t forecast or use a calendar. It reacts to live usage.
- Your HPA adds pods, your autoscaler adds nodes, and Coral raises requests that run hot.
- Before a known event, set minimums on critical workloads.
- For the event window, pause node optimization and the Evictor.
A workload needs 4 CPUs during startup but only 500m afterwards. How is it handled?
- By default Coral ignores the first 2 minutes of CPU after a container starts, so the request ends up near 500m.
- Startup can still go above the request, using free CPU on the node, because Coral doesn’t lower CPU limits on regular pods.
- If startup must be fast, set a CPU minimum or use a policy that counts startup CPU.
- Guaranteed StatefulSet pods and workloads with a CPU-based HPA are sized differently.
Safety, memory and rollback
How does Coral decide a change is safe to apply automatically?
- Only workloads with “Automatically optimize” on are changed. Zoorik’s own namespace is never changed.
- Through a policy, cuts in the first 24 hours of data are capped at 10%, 25%, then 35%. After that Coral needs at least 90% of the expected samples.
- Every change respects your minimums, LimitRanges and quotas. Routine changes under 10% are skipped.
- Pods are resized in place where possible. Otherwise they are replaced one at a time, within your PDBs.
Is there a warm-up period before automation?
- For pod sizing, yes. When you turn it on through a policy, cuts in the first 24 hours of data are capped at 10%, then 25%, then 35%.
- Workloads that already have 24 hours of good data get the full recommendation straight away.
- Turning on a single workload directly skips this warm-up.
- Node optimization has no warm-up. It starts at install.
Memory spikes can cause OOM kills. How much safety buffer is kept?
- Memory is set from the highest usage of the last 8 days, plus 10% (15 to 25% on some other policies).
- Coral never lowers a memory limit on regular pods, so a container with a limit is OOM-killed at the same point.
- A container with no memory limit can be evicted sooner if the node runs short of memory.
- If an OOM kill still happens, Coral raises that container’s memory straight away, by 20% per kill and at least 100 MiB.
What happens if an optimized pod starts getting OOM-killed?
- Coral raises that container’s memory by 20% per OOM kill (at least 100 MiB), straight away.
- Crash-looping pods are recreated at the new size, and the extra margin fades over 24 hours.
- Raises stop at 2.5× the base size. If the kills look like a memory leak, Coral stops raising and holds that cap for 24 hours.
If optimization causes performance degradation, how is it rolled back automatically?
- OOM kills, failing probes and CPU pressure make Coral raise requests back up automatically.
- If a pod can’t be scheduled at its new size, Coral caps the request to fit.
- A replacement pod that isn’t Ready within 10 minutes goes back to its original size (except in StatefulSets).
- Coral doesn’t read latency or error rates.
- To roll back by hand, turn automation off. New pods start at your manifest’s size; running pods keep theirs until they restart.
Stateful and single-replica workloads
How are databases, Kafka, Elasticsearch, Redis and StatefulSets optimized?
- Coral changes only CPU and memory, never app settings such as JVM heap or Redis maxmemory.
- StatefulSet pods are resized in place, or replaced one at a time, highest ordinal first, within the PDB.
- When a node is removed, a StatefulSet pod gets a short restart within its PDB. Nodes with local data or do-not-disrupt pods are kept.
- For a careful start, put databases on the Read-only policy and mark them do-not-disrupt.
Can optimization happen without downtime for applications that have only one replica?
- Usually, yes. Coral resizes the pod in place (Kubernetes 1.33+), or starts a new pod and waits until it’s Ready before removing the old one.
- Where that isn’t safe (for example Recreate strategy or a ReadWriteOnce volume), the new size waits for the pod’s next natural restart.
- When a node is removed, a pod whose replacement can’t start first gets a short restart. Mark it do-not-disrupt to prevent that.
Working with HPA
If the HPA wants to scale up while Coral wants to reduce CPU requests, which one wins?
- There is no conflict. The HPA decides how many pods run, and Coral decides how big each pod is.
- While the HPA is scaling and below its max, Coral holds back its surge and CPU-pressure raises (OOM raises still apply), and pauses pod replacements until every pod is Ready.
- For CPU-based HPAs, Coral picks the request by replaying the last 3 days of load through your HPA’s own settings.
Could reducing CPU requests make the HPA scale more aggressively?
- It could, because HPA utilization is usage divided by request.
- So for workloads with a CPU-based HPA, Coral replays the last 3 days of load through your HPA’s own settings.
- A smaller request wins only if its saving beats the cost of unserved load and extra scaling.
Does optimization ever modify HPA minReplicas or maxReplicas?
- Only on HPAs Coral manages: ones it creates for safe Deployments, with minReplicas of 2 or more, and ones you created by hand that it takes over.
- On an HPA it takes over, Coral keeps minReplicas, only raises maxReplicas, and restores your values when it lets go.
- An HPA that Coral creates can scale a steady Deployment down to its minimum.
- It never changes min or max on HPAs from Helm, Argo CD, Flux, KEDA or kubectl apply.
Nodes and spare capacity
If workload optimization reduces requests, how soon are nodes consolidated and removed?
- Within minutes of the running pods carrying the smaller requests. Coral checks every 5 minutes and drains nodes gradually, never in bulk.
- An emptied node waits 5 minutes (you can change this), then your autoscaler deletes it. Coral deletes it itself only in fixed-size pools that nothing else manages.
- Pools that Karpenter or NAP already consolidates are left to them.
How do you make sure node consolidation doesn’t cause scheduling failures later?
- Before draining, Coral simulates the scheduler on the live cluster. Every pod must fit elsewhere, with its affinity, taints, spread, ports and zones.
- It respects PDBs, do-not-disrupt and your autoscaler’s minimum pool size.
- Room for future growth is your autoscaler’s job.
- Known gap: per-node disk-attach limits aren’t checked yet.
How much spare capacity is kept for sudden workload growth?
- Coral keeps no idle spare nodes. The headroom sits inside each pod’s request.
- Sudden growth is handled by your autoscaler adding nodes.
- To keep warm spare capacity, run a low-priority placeholder deployment. Put it on the Read-only policy so Coral doesn’t shrink it.
During cluster upgrades, is optimization paused or does it continue?
- It continues, but steps around the upgrade. It skips cordoned, NotReady or deleting nodes, and never drains a node someone else cordoned.
- We recommend pausing node optimization and the Evictor during the upgrade window.
Autoscalers and traffic surges
How does Coral interact with Cluster Autoscaler or Karpenter decisions?
- Coral never changes your autoscaler’s settings and never adds nodes for demand.
- Karpenter, NAP or the Cluster Autoscaler deletes the nodes Coral empties, within your autoscaler’s minimums.
- Pools that Karpenter or NAP already consolidates are left to them. Coral deletes VMs itself only in fixed-size pools that nothing else manages.
After node and workload optimization move us from larger machines to smaller ones, how do we get back to bigger machines in a sudden surge?
- Coral never adds capacity for demand. Scale-up belongs to your Karpenter, NAP or Cluster Autoscaler, and Coral doesn’t change or fight it.
- In a surge, the HPA adds pods, pending pods trigger your autoscaler, and Karpenter or NAP can pick bigger machines.
- If you have no autoscaler, we set up NAP (AKS) or Karpenter (EKS) during onboarding, with your approval.
- If one can’t be set up (for example AKS with kubenet networking), nothing adds nodes until an autoscaler exists.
- Coral moves workloads to smaller machine types only with Karpenter or NAP. With only the Cluster Autoscaler, Coral removes nodes but never changes their size.
Getting started
Can optimization be restricted to one namespace or application first?
- Yes. Create a policy with automation on and assign it to a namespace or by labels. Everything else stays recommendation-only.
- That policy can also create HPAs. Turn HPA optimization off in it if you want sizing only.
- Node optimization is scoped by node pool, not namespace. Enable only the pools you want, and start with the Evictor in dry-run.
DownloadFAQ PDF5 pages · 0.1 MB