Back to blog
AWSBest PracticesCloud SecurityCompute & ContainersKubernetes

EKS Kubernetes Version Outdated: Why It Matters and How to Fix It

Learn why an outdated EKS Kubernetes version is a security and cost risk, how to upgrade your cluster safely, and how to prevent version drift with CI gates.

TL;DR

This check flags EKS clusters running a Kubernetes version that AWS no longer fully supports, leaving you without security patches and at risk of forced upgrades. Plan a staged upgrade through each minor version and keep clusters within one or two releases of the latest supported version.

Amazon EKS tracks the upstream Kubernetes release cadence closely, but it does not support every version forever. Each minor version gets a standard support window, after which it moves to extended support (at additional cost) and eventually drops off entirely. The eks_outdatedversion check looks at the control plane version of every EKS cluster in your account and raises a finding when that version has aged past AWS's standard support window.

If you have ever logged into the EKS console and seen a yellow banner warning that your cluster version reaches end of support in 30 days, this check is the automated, account-wide version of that nudge.


What this check detects

The check inspects the Kubernetes version reported by each EKS cluster's control plane and compares it against the list of versions currently in standard support from AWS. A cluster is flagged when its version is:

  • In extended support, meaning standard support has ended and you are now paying a premium for patches
  • Approaching end of standard support within the warning window
  • Already end of life, where AWS may auto-upgrade your cluster on your behalf

Note: The check looks at the control plane version, not your node groups. Worker nodes can drift behind the control plane and that is a separate problem. Kubernetes only supports a version skew of up to three minor versions between the kubelet and the API server, so an outdated control plane often hides outdated nodes too.

The version string EKS reports looks like 1.28 or 1.31. You can see it for a single cluster with:

aws eks describe-cluster \
  --name my-cluster \
  --query "cluster.version" \
  --output text

To list every cluster and its version across a region at once:

for c in $(aws eks list-clusters --query "clusters[]" --output text); do
  v=$(aws eks describe-cluster --name "$c" --query "cluster.version" --output text)
  echo "$c -> $v"
done

Why it matters

An outdated Kubernetes version is not just a hygiene problem. It compounds into security, cost, and reliability risk over time.

You stop getting security patches

Once a version exits standard support, the stream of CVE fixes and security backports slows down or stops. Kubernetes has a real history of serious vulnerabilities, including the kubelet and API server flaws that allowed privilege escalation and container escape. Running an unsupported version means you are exposed to known issues with no official fix available on your release line.

AWS will eventually upgrade you anyway

Danger: When a Kubernetes version reaches the end of extended support on EKS, AWS automatically upgrades the control plane to the next supported version on a schedule you do not control. An unplanned, automatic minor version bump can break workloads that depend on deprecated APIs, with no rollback path. EKS upgrades cannot be downgraded.

This is the scenario that bites teams hardest. A forced upgrade during business hours, removing an API your manifests still use, can take down deployments and Helm releases that were working fine the day before.

Extended support costs real money

Warning: Clusters in extended support are billed at a higher per-cluster, per-hour rate than standard support. If you run dozens of clusters and let them all drift into extended support, the surcharge adds up quickly. Upgrading is often the cheaper option as well as the safer one.

You fall behind on features and ecosystem support

Add-ons, CSI drivers, ingress controllers, and tools like the AWS Load Balancer Controller test against current versions. The further behind you are, the more likely you hit a compatibility wall when you finally do upgrade, and the more painful that upgrade becomes.


How to fix it

EKS upgrades are one minor version at a time. You cannot jump from 1.27 to 1.30 in a single step. Plan the path: 1.27, then 1.28, then 1.29, then 1.30, validating between each hop.

Step 1: Check for deprecated APIs before upgrading

This is the step most people skip and then regret. Use kubent (kube-no-trouble) to find manifests using APIs that the target version removes:

sh -c "$(curl -sSL https://git.io/install-kubent)"
kubent

It reports objects using deprecated or removed API versions, such as a batch/v1beta1 CronJob or an old networking.k8s.io Ingress. Fix those before you touch the control plane.

Tip: The Kubernetes deprecation guide lists exactly which API versions are removed in each release. Cross-reference it with kubent output so nothing slips through. Pluto is a good alternative scanner if you want to run it as part of CI against your Helm charts.

Step 2: Upgrade the control plane

With the AWS CLI:

aws eks update-cluster-version \
  --name my-cluster \
  --kubernetes-version 1.31

Track the update until it completes:

aws eks describe-update \
  --name my-cluster \
  --update-id <update-id-from-previous-command>

Control plane upgrades take roughly 25 to 45 minutes and the API server stays available throughout, but expect brief control plane latency.

Step 3: Upgrade your managed node groups

The control plane and nodes should not drift far apart. Upgrade managed node groups after the control plane:

aws eks update-nodegroup-version \
  --cluster-name my-cluster \
  --nodegroup-name my-nodegroup

Warning: Node group upgrades drain and replace nodes, which causes pod evictions. Set sensible PodDisruptionBudgets and make sure your workloads tolerate rolling replacement before running this in production. Run it during a maintenance window for stateful workloads.

Step 4: Update your add-ons

Core add-ons like CoreDNS, kube-proxy, and the VPC CNI have version compatibility tied to the Kubernetes version. Update them to match:

aws eks update-addon \
  --cluster-name my-cluster \
  --addon-name vpc-cni \
  --addon-version v1.18.5-eksbuild.1

Use aws eks describe-addon-versions --kubernetes-version 1.31 --addon-name vpc-cni to find the compatible version for your target.

Doing it with Terraform

If you manage clusters as code, bump the version attribute and let your pipeline apply it:

module "eks" {
  source          = "terraform-aws-modules/eks/aws"
  cluster_name    = "my-cluster"
  cluster_version = "1.31"

  # node groups inherit the cluster version unless overridden
  eks_managed_node_groups = {
    default = {
      instance_types = ["m6i.large"]
      min_size       = 2
      max_size       = 6
      desired_size   = 3
    }
  }
}

Still run the deprecated API scan first. Terraform will happily upgrade a control plane that is about to break your workloads.


How to prevent it from happening again

The root cause of this finding is almost always that nobody owns upgrades, so versions quietly age out. Fix the process, not just the cluster.

Treat version as code and gate it in CI

If your cluster version lives in Terraform or a Helm values file, you can lint it. Write a policy that fails the pipeline when the declared version is more than N releases behind the latest supported version. Here is a simple OPA Conftest example checking a parsed config:

package eks.version

# pin the minimum acceptable version for your org
min_version := "1.30"

deny[msg] {
  input.cluster_version < min_version
  msg := sprintf("EKS cluster version %s is below the minimum %s", [input.cluster_version, min_version])
}

Scan for deprecated APIs continuously

Run kubent or Pluto as a scheduled job, not just before an upgrade. Catching a deprecated API the day a developer commits it is far cheaper than discovering it the morning AWS force-upgrades you.

Set a recurring upgrade cadence

Kubernetes ships three minor releases a year. Pick a quarterly rhythm where you upgrade every cluster, and put it on the calendar as a standing commitment. Staying within one release of the latest supported version means you are never caught by a forced upgrade.

Tip: Subscribe to the EKS version lifecycle calendar and wire the end-of-support dates into your team's alerting. Lensix re-runs this check continuously, so a cluster that drifts into the warning window shows up as a finding well before AWS starts the forced-upgrade clock.


Best practices

  • Stay within the standard support window. Aim to be no more than one minor version behind the latest EKS-supported release at any time.
  • Upgrade in lower environments first. Run the full upgrade in dev and staging, validate workloads, then promote the same path to production.
  • Keep node groups close to the control plane. Do not let the version skew grow. Upgrade nodes within days of the control plane, not months.
  • Pin and test add-on versions. CoreDNS, kube-proxy, and the VPC CNI must move with the cluster. Mismatches cause DNS and networking failures that are hard to diagnose.
  • Use PodDisruptionBudgets. They protect availability during the node replacement that every upgrade triggers.
  • Never rely on the automatic upgrade. Treat the AWS auto-upgrade as a backstop you should never hit, not a strategy.

An EKS cluster that is one version behind is routine maintenance. A cluster three versions behind in extended support, using removed APIs, is an incident waiting for a date on AWS's calendar. Keep the cadence tight and the upgrades stay boring, which is exactly what you want.