Kubernetes
ServiceAccount
permissions
node access
RBAC

Kubernetes ServiceAccount cannot list nodes

Master System Design with Codemia

Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.

Introduction

If a Kubernetes ServiceAccount cannot list nodes, the problem is almost always RBAC rather than authentication. Nodes are a cluster-scoped resource, so the fix usually requires a ClusterRole and ClusterRoleBinding, not a namespaced Role.

Why Listing Nodes Is Different

Kubernetes resources fall into two broad groups:

  • namespaced resources such as pods and config maps
  • cluster-scoped resources such as nodes

That distinction matters because a regular Role only grants permissions inside one namespace. Since nodes live at the cluster level, a service account that needs to list them must be granted a cluster-scoped permission.

That is why a service account can sometimes list pods in its namespace but still fail on:

bash
kubectl get nodes

when used through the API.

Create a ClusterRole That Allows Listing Nodes

A minimal RBAC policy for reading node objects looks like this:

yaml
1apiVersion: rbac.authorization.k8s.io/v1
2kind: ClusterRole
3metadata:
4  name: node-reader
5rules:
6  - apiGroups: [""]
7    resources: ["nodes"]
8    verbs: ["get", "list", "watch"]

This allows read-only access to node metadata. It does not grant write access or broad admin privileges.

Bind the Role to the Service Account

After defining the role, bind it to the service account with a ClusterRoleBinding:

yaml
1apiVersion: rbac.authorization.k8s.io/v1
2kind: ClusterRoleBinding
3metadata:
4  name: app-node-reader
5subjects:
6  - kind: ServiceAccount
7    name: app-sa
8    namespace: default
9roleRef:
10  apiGroup: rbac.authorization.k8s.io
11  kind: ClusterRole
12  name: node-reader

Apply both manifests:

bash
kubectl apply -f node-reader-role.yaml
kubectl apply -f node-reader-binding.yaml

Now pods running as default/app-sa can authenticate as that service account and list nodes.

Verify the Permission Before Debugging the App

Kubernetes gives you a direct way to test the effective permission:

bash
kubectl auth can-i list nodes \
  --as=system:serviceaccount:default:app-sa

If this command says no, the application is not the problem. The RBAC policy is still insufficient or bound to the wrong subject.

That check is much faster than staring at client library code or pod logs first.

A Pod Example

Here is a pod that runs with the service account:

yaml
1apiVersion: v1
2kind: Pod
3metadata:
4  name: node-reader-demo
5spec:
6  serviceAccountName: app-sa
7  containers:
8    - name: app
9      image: bitnami/kubectl:latest
10      command: ["sleep", "3600"]

Once the pod is running, you can test from inside it:

bash
kubectl exec -it node-reader-demo -- kubectl get nodes

If RBAC is correct and the image has credentials mounted through the service account token, this should work.

Do Not Use a Namespaced Role for Nodes

One of the most common mistakes is writing something like this:

yaml
1kind: Role
2metadata:
3  name: node-reader
4  namespace: default

This will not solve the problem because nodes are not namespaced. Even if the rule syntax looks correct, the scope is wrong.

For nodes, the pattern is:

  • 'ClusterRole'
  • 'ClusterRoleBinding'

not:

  • 'Role'
  • 'RoleBinding'

Grant Only What You Actually Need

Listing nodes can expose cluster topology and labels, so grant it only if the workload truly needs it. Many applications do not need direct node access at all. If the requirement is actually “discover my own node name,” there may be safer alternatives such as exposing relevant data through the Downward API or specific controller logic.

RBAC fixes should be minimal, not just broad enough to make the error disappear.

Common Pitfalls

  • Using a namespaced Role when the resource is cluster-scoped.
  • Binding the permission to the wrong namespace or service account name.
  • Debugging client code before verifying the RBAC decision with kubectl auth can-i.
  • Granting broad cluster-admin access when read-only node access would be enough.
  • Forgetting that the pod must actually run as the intended service account.

Summary

  • Nodes are cluster-scoped resources, so service accounts need cluster-scoped RBAC to list them.
  • Use a ClusterRole with get, list, and watch on nodes.
  • Bind that role with a ClusterRoleBinding to the correct service account.
  • Verify the permission with kubectl auth can-i before debugging application code.
  • Keep the permission as narrow as possible, because many workloads do not need node access at all.

Course illustration
Course illustration

All Rights Reserved.