All Articles

kubectl exec: Permission Denied — How to Fix It (2026)

Getting 'permission denied' when running kubectl exec? Here are all the real reasons it happens and exactly how to fix each one.

DevOpsBoysMar 31, 20264 min read
Share:Tweet

You run kubectl exec -it my-pod -- /bin/bash and get slapped with:

Error from server (Forbidden): pods "my-pod" is forbidden: User "dev-user" cannot create resource "pods/exec"

Or worse — it just hangs. Or you get permission denied inside the container. Let's fix all of these.


Case 1: RBAC — Your User Can't exec Into Pods

This is the most common one in team clusters. The user doesn't have pods/exec permission.

Check what permissions you have:

bash
kubectl auth can-i create pods/exec --namespace default
# no

Fix: Create a Role and RoleBinding

yaml
# exec-role.yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  name: pod-exec-role
  namespace: default
rules:
  - apiGroups: [""]
    resources: ["pods/exec", "pods"]
    verbs: ["create", "get", "list"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: pod-exec-binding
  namespace: default
subjects:
  - kind: User
    name: dev-user
    apiGroup: rbac.authorization.k8s.io
roleRef:
  kind: Role
  name: pod-exec-role
  apiGroup: rbac.authorization.k8s.io
bash
kubectl apply -f exec-role.yaml

Now test again:

bash
kubectl auth can-i create pods/exec --namespace default
# yes

Case 2: The Shell Doesn't Exist in the Container

Many minimal images (distroless, Alpine-based) don't have /bin/bash. You'll see:

OCI runtime exec failed: exec failed: unable to start container process: exec: "/bin/bash": stat /bin/bash: no such file or directory

Try /bin/sh instead:

bash
kubectl exec -it my-pod -- /bin/sh

If even /bin/sh doesn't exist (distroless images):

Use the debug sidecar pattern:

bash
kubectl debug -it my-pod --image=busybox --target=my-container

Or for Kubernetes 1.25+, use ephemeral containers:

bash
kubectl debug -it my-pod --image=ubuntu:22.04 --target=app-container -- bash

Case 3: Pod Not Running

You can only exec into a Running pod. Check pod state:

bash
kubectl get pod my-pod
# NAME      READY   STATUS      RESTARTS   AGE
# my-pod    0/1     Completed   0          5m

A Completed or CrashLoopBackOff pod can't be exec'd into.

Check logs instead:

bash
kubectl logs my-pod --previous

If the pod keeps crashing, fix the crash first. Common causes:

  • Missing env variables
  • Config file not found
  • OOMKilled (check kubectl describe pod my-pod)

Case 4: Network Policy Blocking the Exec Tunnel

Less common, but some strict network policies block the API server → kubelet connection used for exec.

Check if you have NetworkPolicies:

bash
kubectl get networkpolicy -n default

The exec tunnel goes through the kubelet on port 10250. If your network policy blocks this, exec won't work.

Temporary test — check if the kubelet port is reachable from the API server. If you're in a managed cluster (EKS, GKE, AKS), contact your platform team.


Case 5: permission denied Inside the Container

You exec'd successfully but get permission denied when running commands inside.

bash
kubectl exec -it my-pod -- cat /etc/secret-config
# cat: /etc/secret-config: Permission denied

This is a container-level Linux permission issue, not Kubernetes RBAC.

Check what user the container runs as:

bash
kubectl exec -it my-pod -- id
# uid=1000(appuser) gid=1000(appuser)

Options:

  1. Run exec as root:
bash
kubectl exec -it my-pod --user root -- /bin/bash

(only works if your container image has a root user and cluster allows it)

  1. Fix the file permissions in your Dockerfile:
dockerfile
RUN chmod 644 /etc/secret-config && chown appuser:appuser /etc/secret-config
  1. Use a SecurityContext in the deployment to match UID:
yaml
spec:
  securityContext:
    runAsUser: 1000
    fsGroup: 1000

Case 6: --stdin / -i Flag Issues

Sometimes exec hangs because of missing -t (TTY) or -i (stdin) flags.

bash
# Use both -i and -t for interactive shells
kubectl exec -it my-pod -- /bin/bash
 
# Non-interactive command (no TTY needed)
kubectl exec my-pod -- ls /app

If you're running from a CI script:

bash
# No TTY in CI — don't use -t
kubectl exec -i my-pod -- /bin/bash -c "echo hello"

Quick Diagnosis Checklist

bash
# 1. Can you exec at all?
kubectl auth can-i create pods/exec -n <namespace>
 
# 2. Is the pod running?
kubectl get pod <pod-name>
 
# 3. Does the shell exist?
kubectl exec <pod-name> -- which bash
kubectl exec <pod-name> -- which sh
 
# 4. What user is running?
kubectl exec <pod-name> -- id
 
# 5. Network policy blocking?
kubectl get networkpolicy -n <namespace>

Want to Go Deeper?

If you're managing Kubernetes clusters day-to-day, these courses will sharpen your debugging skills fast:


The exec permission issues mostly come down to RBAC or missing shell. Fix the RBAC first, then check if the shell exists. Everything else is edge cases.

Newsletter

Stay ahead of the curve

Get the latest DevOps, Kubernetes, AWS, and AI/ML guides delivered straight to your inbox. No spam — just practical engineering content.

Related Articles

Comments