Skip to main content

Fine-grained Kubelet API Authorization

Required knowledge for the CKS certification.

The kubelet exposes an HTTPS API on port 10250 covering endpoints for stats, metrics, logs, pod listings, health checks, configuration, and container command execution. Before Kubernetes v1.36, any client that needed access to an endpoint such as /pods or /healthz was forced to be granted nodes/proxy, which covers all kubelet APIs including container command execution.

Kubernetes v1.36 graduates the KubeletFineGrainedAuthz feature to stable, enabling roles to be scoped to specific endpoint groups without granting the overly broad nodes/proxy permission. The official Kubernetes documentation states: "FEATURE STATE: Kubernetes v1.36 [stable] (enabled by default). Kubelet performs a fine-grained check before falling back to the proxy subresource for the /pods, /runningPods, /configz and /healthz endpoints."


1. Why nodes/proxy Was the Only Option

Before: The kubelet mapped every endpoint that did not already have a dedicated subresource (stats, metrics, log, spec, checkpoint) to the proxy subresource. Clients needing /pods, /healthz, or /configz had to be granted nodes/proxy — the same permission that authorizes /exec, /attach, and /run.
After: With KubeletFineGrainedAuthz enabled (the default since v1.36), the kubelet performs a dedicated authorization check for /pods, /runningPods, /configz, and /healthz against new fine-grained subresources before falling back to proxy. Monitoring and observability workloads can be scoped to only those subresources without any access to command execution.

Pre-v1.36 subresource mapping

Kubelet endpointRequired subresource
/stats/*stats
/metrics/*metrics
/logs/*log
/spec/*spec
/checkpoint/*checkpoint
all other endpointsproxy

Under this mapping, any role needing /pods, /runningPods, /healthz, or /configz had to request nodes/proxy.


2. KubeletFineGrainedAuthz Feature Progression

Kubernetes versionStatus
v1.32Alpha
v1.33Beta
v1.36Stable (enabled by default)

Version Skew and Managed Clusters

On clusters older than v1.32 the KubeletFineGrainedAuthz feature gate does not exist — the fine-grained subresources (pods, healthz, configz) are unknown to the kubelet, and requests to the affected endpoints are authorized against proxy. On v1.32 and v1.33 the feature is opt-in: the gate must be set to true for the RBAC check against the new subresources to take effect. Managed offerings such as EKS, GKE, and AKS typically lag upstream by several minor releases, so cluster operators should confirm their control plane version before relying on the fine-grained subresources.


3. Kubelet API Subresource Mappings (v1.36)

With KubeletFineGrainedAuthz enabled, the kubelet resolves endpoints as follows:

Kubelet endpointResourceAccepted subresources
/stats/*nodesstats
/metrics/*nodesmetrics
/logs/*nodeslog
/spec/*nodesspec
/checkpoint/*nodescheckpoint
/podsnodespods, proxy
/runningPods/nodespods, proxy
/healthznodeshealthz, proxy
/configznodesconfigz, proxy
all other endpointsnodesproxy

For endpoints that list both a fine-grained subresource and proxy, granting the fine-grained subresource alone is sufficient — proxy is not required.

/pods vs /runningPods/

Both endpoints map to the pods subresource, but they return different data:

  • /pods returns the kubelet's desired state — the pods the kubelet has been told to run.
  • /runningPods/ returns the container runtime's view — pods the CRI reports as actually running on the node.

They are not interchangeable. Choose the endpoint that matches what the consumer actually needs.

Endpoints That Still Require nodes/proxy

Endpoints that fall into the "all others" bucket continue to require nodes/proxy. The set includes (non-exhaustively):

  • /exec/*
  • /attach/*
  • /portForward/*
  • /run/*
  • /cri/*
  • /debug/*

Any workload that legitimately calls one of these — a cluster diagnostic tool, an ephemeral debugging controller — will still need nodes/proxy after migration.


4. Least-privilege RBAC for Monitoring and Observability

Issue: Monitoring systems that only need metrics, pod listings, and health checks previously required nodes/proxy, which also grants container command execution access.
Fix: Scope monitoring and observability ClusterRoles to specific subresources.

Authentication prerequisite

RBAC decides what a caller may do; it does not authenticate the caller to the kubelet in the first place. ServiceAccount token-based clients such as Prometheus also require the kubelet to be configured with --authentication-token-webhook=true, otherwise token-authenticated requests return 401 Unauthorized regardless of the role. See the Kubelet Security Overview for the authentication flags.

Metrics-only role

apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: kubelet-metrics-reader
rules:
- apiGroups: [""]
resources: ["nodes/metrics", "nodes/stats", "nodes/log"]
verbs: ["get"]

Pod listing without proxy access

apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: kubelet-pod-reader
rules:
- apiGroups: [""]
resources: ["nodes/pods"]
verbs: ["get"]

Full observability role (no container execution)

apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: kubelet-observability
rules:
- apiGroups: [""]
resources:
- "nodes/metrics"
- "nodes/stats"
- "nodes/log"
- "nodes/pods"
- "nodes/healthz"
- "nodes/configz"
verbs: ["get"]

This role grants access to metrics, stats, logs, pod information, health status, and kubelet configuration without any access to container command execution.

Bind the role to a monitoring service account

apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: prometheus-kubelet-metrics
subjects:
- kind: ServiceAccount
name: prometheus
namespace: monitoring
roleRef:
kind: ClusterRole
name: kubelet-metrics-reader
apiGroup: rbac.authorization.k8s.io

5. The system:kubelet-api-admin ClusterRole

The built-in system:kubelet-api-admin ClusterRole is automatically updated to include permissions for all subresources (proxy, stats, log, metrics, configz, healthz, pods) when KubeletFineGrainedAuthz is enabled. No manual changes are required for the API server's own access to the kubelet.


6. Audit and Verify

Find ClusterRoles that grant nodes/proxy

kubectl get clusterroles -o json \
| jq -r '.items[]
| select(.rules[]?.resources[]? == "nodes/proxy")
| .metadata.name'

Find ClusterRoleBindings that reference those ClusterRoles

kubectl get clusterrolebindings -o json \
| jq -r --argjson names "$(kubectl get clusterroles -o json \
| jq '[.items[] | select(.rules[]?.resources[]? == "nodes/proxy") | .metadata.name]')" '
.items[]
| select(.roleRef.kind == "ClusterRole" and (.roleRef.name | IN($names[])))
| "\(.metadata.name) -> \(.roleRef.name)"'

Review each binding: keep nodes/proxy only where the subject genuinely needs /exec, /attach, /portForward, /run, /cri, or /debug/*.

Verify a new role grants the expected access

Use kubectl auth can-i against the target ServiceAccount to confirm the fine-grained grants and the absence of proxy:

kubectl auth can-i get nodes/metrics \
--as=system:serviceaccount:monitoring:prometheus
# yes

kubectl auth can-i get nodes/pods \
--as=system:serviceaccount:monitoring:prometheus
# yes

kubectl auth can-i get nodes/proxy \
--as=system:serviceaccount:monitoring:prometheus
# no

A no on nodes/proxy combined with yes on the fine-grained subresources confirms the old broad grant has been fully replaced.


Security Checklist

  • Control plane is on Kubernetes v1.36+ (KubeletFineGrainedAuthz is enabled by default). On v1.32 or v1.33, enable the feature gate explicitly.
  • Audited ClusterRoles and ClusterRoleBindings that reference nodes/proxy.
  • Replaced broad nodes/proxy grants with specific subresources for monitoring and observability tools.
  • Verified the replacement role with kubectl auth can-i — fine-grained subresources return yes, nodes/proxy returns no.
  • Confirmed the kubelet is configured for the caller's authentication method (for ServiceAccount tokens, --authentication-token-webhook=true).
  • Reviewed membership of any ClusterRoleBindings that reference system:kubelet-api-admin.

References

This article is based on information from the following official sources:

  1. Kubelet Authentication and Authorization - Kubernetes Documentation
  2. Kubernetes v1.36 Sneak Peek - Kubernetes Blog
  3. Kubernetes v1.36 Release - Kubernetes Blog