How to find every Kubernetes cluster in an AWS account (2026)

Akal Cloud 4 min read

Quick answer

There are three populations and one command finds only the first. Native EKS comes from eks:ListClusters. Clusters registered through EKS Connector, which can be GKE, AKS, OpenShift, Rancher or on-prem, need include=all and appear with a connectorConfig.provider value. Self-managed clusters on EC2 appear in no EKS API at all and have to be found by scanning instances for kubernetes.io/cluster/* tags, then deduped, because EKS nodes carry that tag too.

aws eks list-clusters does not list your Kubernetes clusters. It lists your Amazon EKS clusters, which is a different and usually smaller set. If you are trying to account for Kubernetes spend across an organisation, the gap between those two things is where the surprises live. There are three populations to find, and they need three different techniques.

Why doesn't list-clusters show everything?

Because it is scoped to EKS by default, and there is a flag for that. The ListClusters API reference documents an include parameter: "Indicates whether external clusters are included in the returned list. Use 'all' to return connected clusters, or blank to return only Amazon EKS clusters."

aws eks list-clusters --include all --region us-east-1

One detail that will cost you an afternoon if you miss it, and it is in the reference: "'all' must be in lowercase otherwise an error occurs." Not a validation warning, an error.

What are connected clusters?

Clusters somebody registered into the AWS console through EKS Connector. They run somewhere else entirely, and the useful part is that AWS records where. Calling DescribeCluster on one returns a connectorConfig block, whose provider field is documented as "the cluster's cloud service provider".

The registration API constrains that field to a fixed list, which is worth reading as a map of what you might find:

EKS_ANYWHERE | ANTHOS | GKE | AKS | OPENSHIFT
TANZU | RANCHER | EC2 | OTHER

So a single API call can tell you that this account is aware of a GKE cluster and an OpenShift cluster. That is a genuinely useful signal in an organisation where nobody can quite say what is running where.

The reliable way to tell a connected cluster from a native one is connectorConfig itself: a managed EKS cluster returns null for it. Do not try to infer it from the name or the ARN.

aws eks describe-cluster --name my-cluster \
  --query 'cluster.connectorConfig.provider' --output text

How do you find clusters AWS knows nothing about?

This is the third population and the hardest: a cluster somebody stood up on EC2 with kubeadm, kops or Rancher, never registered with Connector. No EKS API will return it, because as far as EKS is concerned it does not exist.

What it does have is nodes, and nodes are EC2 instances that usually carry a cluster tag. AWS documents this key on the resources it manages itself. Per the EKS security group requirements, EKS tags the cluster security group with kubernetes.io/cluster/<my-cluster> = owned, and "if you remove the tags, Amazon EKS adds them back to the security group whenever your cluster is updated."

Be clear about what is documented and what is convention. AWS documents that it applies that key. The reason a self-managed cluster usually carries it too is that the in-tree AWS cloud provider and the common installers use the same convention, not because AWS mandates it. So this technique finds most self-managed clusters, not all of them, and a cluster provisioned without the AWS cloud provider may carry nothing at all. Treat a tag scan as a strong lead, never as an inventory.

With that caveat, the scan is one DescribeInstances call per region:

aws ec2 describe-instances \
  --filters "Name=instance-state-name,Values=running,pending" \
  --query 'Reservations[].Instances[].[InstanceId,Tags[?starts_with(Key, `kubernetes.io/cluster/`)].Key | [0]]' \
  --output text --region us-east-1

The dedup step everyone forgets

Here is the trap. EKS worker nodes carry that same tag. Run the scan naively and every EKS cluster you already found through list-clusters reappears as a "self-managed" discovery, so a three-cluster account reports six.

The fix is to extract the cluster name from the tag key, everything after kubernetes.io/cluster/, and subtract the set of names list-clusters --include all already returned. What remains is genuinely unmanaged.

Two details make this less tidy than it sounds. The tag value can be owned or shared depending on whether the cluster created the resource, and either counts. And an older convention, KubernetesCluster as a bare key with the cluster name as its value, still turns up on long-lived clusters, so a scan that only matches the modern prefix will miss them.

What does the full sweep look like?

PopulationHow to find itConfidence
Native EKS eks:ListClusters Complete. This is the authoritative list
Connected (GKE, AKS, OpenShift, on-prem) eks:ListClusters with include=all, then DescribeCluster for connectorConfig.provider Complete for clusters somebody registered. Silent about the rest
Self-managed on EC2 ec2:DescribeInstances, tag scan, deduped against the two lists above Best effort. Depends on a tagging convention, not an API

Run all three per region, in parallel, with short timeouts, and treat every one as fail-soft: a region you cannot reach should narrow the answer, not break the sweep. The permissions are read-only and modest, eks:ListClusters, eks:DescribeCluster and ec2:DescribeInstances.

What can't this tell you?

Being honest about the ceiling matters more here than usual, because the gap is where the cost actually hides.

A discovery sweep tells you a cluster exists. It does not tell you what runs in it. For a connected GKE or AKS cluster, AWS knows the name and the provider and nothing about the workloads, and the spend is on another cloud's bill entirely. For a self-managed cluster on EC2, you get the instances, so you can price the compute from the CUR, but nothing splits that cost across namespaces or workloads: split cost allocation data covers ECS, AWS Batch and EKS, and a kubeadm cluster is none of those.

There is also no AWS API that enumerates clusters in another cloud. Anything claiming true multi-cloud Kubernetes discovery is either reading EKS Connector registrations, which is what this post describes, or holding credentials for that other cloud. Per-cluster visibility beyond existence needs something running inside the cluster, which is a different problem with a different answer.

See this on your own bill

Akal Cloud connects in about two minutes and shows the same numbers against your real AWS accounts.

Get started on AWS Marketplace

Related reading