← Cloud & AWSfour baseline checks every kubernetes cluster needs

four baseline checks every kubernetes cluster needs

$kubectl auth can-i --list

one popped container should never equal one popped cluster

that's the whole point of this post. kubernetes gives you a ton of rope by default, and most clusters are running wide open without anyone deciding that on purpose. nobody sat down and said "let's give every pod root-level access to the node and let any pod talk to any other pod." it just happens because the defaults are permissive and nobody circled back to lock things down.

here are four checks you can run today that tell you exactly how bad your blast radius is, and what to do about each one.

1. what can your default service account actually do

every pod in kubernetes gets a service account whether you ask for one or not. if you never specified one, it's using "default," and that default account often has more permissions than anyone intended, especially if someone bound a clusterrole to it at some point and forgot.

kubectl auth can-i --list

this dumps every action that identity is allowed to perform. run it per namespace too:

kubectl auth can-i --list --namespace=your-namespace

if you see things like "create pods," "get secrets," or "delete deployments" sitting on the default service account, that's a problem. a compromised container inherits whatever that account can do. if the account can read secrets cluster-wide, your "contained" incident just became a credential leak.

fix: stop using the default service account for workloads. create scoped service accounts per app with only the rbac permissions that app needs, and set automountServiceAccountToken: false on pods that don't need api access at all.

2. count your privileged pods

a privileged pod isn't "a pod that's important." it's a pod running with privileged: true or elevated capabilities, which basically means it has root on the underlying node. if that container gets compromised, the attacker doesn't need to escape a sandbox, they're already standing on the node.

kubectl get pods --all-namespaces -o json | grep -i "privileged"

or loop through and check securitycontext fields directly. the number you're looking for is zero, or as close to zero as your workloads allow. some things genuinely need privileged mode, like certain cni plugins or storage drivers, but application workloads almost never do.

fix: audit every privileged pod and ask why. drop unnecessary capabilities, set allowPrivilegeEscalation: false, and run containers as non-root users wherever possible.

3. enforce restricted pod security on your namespaces

kubernetes has built-in pod security standards now, and the "restricted" level blocks the dangerous stuff automatically: no privileged containers, no host networking, no running as root by default. it's a seatbelt that kubernetes already built for you, you just have to buckle it.

kubectl label namespace your-namespace \
  pod-security.kubernetes.io/enforce=restricted

do this namespace by namespace, test in a non-prod environment first since it will reject pods that violate the policy. that's the point. you want those pods rejected at creation, not discovered during an incident review.

fix: roll this out namespace by namespace, starting with anything internet-facing or multi-tenant. treat any pod that fails to deploy under "restricted" as a workload that needs fixing, not an exception to grant.

4. default-deny network policies in every namespace

by default, kubernetes networking is flat. any pod can talk to any other pod in the cluster unless you tell it otherwise. that means a compromised pod in your logging namespace can potentially reach your database namespace, with nothing in between to stop it.

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: default-deny-all
  namespace: your-namespace
spec:
  podSelector: {}
  policyTypes:
    - Ingress
    - Egress

apply this in every namespace, then add specific allow rules for the traffic you actually need. this flips the model from "allow everything, block what you notice" to "block everything, allow what you've verified."

fix: start with namespaces holding sensitive data or external exposure. a default-deny policy with zero allow rules will break things on purpose, that's how you find every connection your app actually makes.

the takeaway

none of these four checks require fancy tooling or a security budget. they're built into kubernetes already, sitting there unused. the goal isn't a perfect cluster, it's a cluster where compromising one container doesn't hand an attacker the keys to everything else. run the check, read the output honestly, and fix one thing this week. send this to your platform team, they're the ones who can actually flip these switches.

watch the reel ↗
the weekly drop

one command a week that makes you harder to hack.

a single tool, explained in plain english, every week. straight to your inbox.

no spam. one email a week. unsubscribe anytime.