The problem
A Pod is behaving strangely. You checked the logs. You exec’d into the container. But the issue is not inside the Pod — it is on the node itself.
Maybe it is disk pressure. Maybe host-level networking. Maybe you need kubelet logs, the container runtime, or what is happening on the actual Linux host.
Normally you would SSH into the node. In modern environments — managed EKS, GKE, AKS, or hardened on-prem — SSH to nodes is often restricted, disabled, or a multi-hop process.
Enter kubectl node-shell
kubectl node-shell launches a privileged Pod on the target node that gives you a root shell on the host — from kubectl, without SSH.
One command. Full node access. No SSH required.
It still needs RBAC permission to create privileged Pods and to use the plugin. If your role cannot run it, that is policy working as intended.
Installation
Via Krew:
kubectl krew install node-shell
Confirm context first — kubectx and kubens help. For Pod-level work, k9s and stern cover most days; node-shell is for when the problem is under the kubelet.
Basic usage
# List available nodes first
kubectl get nodes
# Get a shell on a specific node
kubectl node-shell k8s-worker-01
That is it. You are dropped into a root shell on the node within seconds.
What you can do from a node shell
Once you have node-level access, you can investigate things not visible from inside a Pod:
Check kubelet status and logs:
systemctl status kubelet
journalctl -u kubelet -n 100
Inspect disk usage at the host level:
df -h
du -sh /var/lib/containerd/*
du -sh /var/lib/kubelet/*
Check node-level networking:
ip addr show
ip route show
iptables -L -n
ss -tulpn
Inspect the container runtime directly:
# For containerd (common on modern clusters)
crictl ps
crictl logs <container-id>
crictl inspect <container-id>
# For Docker (older setups)
docker ps
docker stats
Check system resources:
top
free -h
dmesg | tail -50
Investigate OOM kills:
dmesg | grep -i "oom\|killed"
journalctl -k | grep -i oom
How it works
kubectl node-shell creates a temporary privileged Pod with hostPID: true, hostNetwork: true, and hostIPC: true, mounted to the host filesystem. It exec’s into that Pod with nsenter to enter the node’s namespaces — a shell at host level, not container level.
When you exit, the Pod is cleaned up automatically.
Important: use with care
Node-shell gives you root access to the host. Powerful and dangerous if misused:
- Prefer read-only investigation on production nodes
- Be careful with writes — you are on the actual host
- In regulated environments, access should be logged and audited
- Never leave a node-shell session open and unattended
The tool is for debugging, not routine operations. Treat it accordingly.
For ownership and YAML without SSH, kubectl tree and kubectl neat stay in the toolkit at the Pod layer.
When pod-level access is not enough
| Scenario | kubectl exec | kubectl node-shell |
|---|---|---|
| Check app logs | Yes | Yes |
| Check kubelet logs | No | Yes |
| Inspect disk at host level | No | Yes |
| Check iptables rules | No | Yes |
| Investigate OOM kills | No | Yes |
| Inspect container runtime | No | Yes |
| Check host networking | No | Yes |
Summary
| Install | kubectl krew install node-shell |
| Best for | Node-level debugging, kubelet issues, disk/network problems |
| Killer feature | Root shell on any node without SSH |
| Important | Use with care — you have full host access |
| GitHub | github.com/kvaps/kubectl-node-shell |
When the problem is below the Pod level, kubectl node-shell is the fastest path to the truth.