Create Administrative Boundaries Between Resources
More Info:
Use namespaces to isolate your Kubernetes objects.
Risk Level
Low
Address
Security
Compliance Standards
- CIS Kubernetes
Triage and Remediation
- Remediation
Remediation
Manual Steps
-
Inventory current namespaces and workloads
Run on: any machine with kubectl accesskubectl get namespaceskubectl get all --all-namespaceskubectl get deploy,sts,ds,job,cronjob,pod,svc,ingress -AReview whether application, platform, and system components are clearly separated (for example:
kube-system,monitoring,logging,team-a,team-b, etc.). -
Map workloads to teams/environments and desired boundaries
Run on: any machine with kubectl accesskubectl get deploy,sts,ds,job,cronjob -A -o wideFor each workload, decide which administrative boundary it should belong to (per team, per environment like dev/stage/prod, per application, or per data classification). Document the target namespace layout (e.g.,
team-a-dev,team-a-prod,shared-infra). -
Identify objects in inappropriate or overly shared namespaces
Run on: any machine with kubectl access# Example: list non-system workloads in the default namespacekubectl get all -n defaultkubectl get configmap,secret,svc,ingress,pvc -n defaultFlag any non-system workloads running in
defaultor in a namespace that does not match the intended boundary from step 2. -
Define or create the required namespaces
Run on: any machine with kubectl access
For each desired namespace that does not yet exist:kubectl get namespace <target-namespace> || kubectl create namespace <target-namespace>Optionally prepare namespace manifests for GitOps/IaC:
apiVersion: v1kind: Namespacemetadata:name: <target-namespace>Apply with:
kubectl apply -f <namespace-manifest>.yaml -
Plan and execute workload relocation into proper namespaces
Run on: any machine with kubectl access
For each object identified in step 3, update its manifest to setmetadata.namespace: <target-namespace>and re-apply:# Export current manifest (example for a deployment in default)kubectl get deploy <name> -n default -o yaml > <name>.yaml# Edit metadata.namespace in the file to the desired namespacesed -i 's/namespace: default/namespace: <target-namespace>/' <name>.yaml# Apply to new namespacekubectl apply -f <name>.yaml# Then delete from old namespace after confirming new instance is healthykubectl delete deploy <name> -n defaultRepeat similarly for services, configmaps, secrets, ingresses, and other namespaced resources, ensuring references (service names, configMapRefs, secretRefs, PVCs) remain valid in the new namespace.
-
Verify namespace-based boundaries are in place
Run on: any machine with kubectl accesskubectl get namespaceskubectl get all -AConfirm that:
defaultcontains no long-lived application workloads unless explicitly intended.- Workloads are grouped into namespaces that reflect the documented administrative boundaries (teams, environments, or applications) and that cross-team/environment sharing is limited to explicitly designated shared namespaces.
Using kubectl
Using kubectl
1. List all namespaces and their basic metadata
Run on: any machine with kubectl access
kubectl get namespaces -o wide
Review for:
- Only
defaultplus system namespaces (kube-system,kube-public,kube-node-lease, any cloud-provider system namespaces) in a busy cluster. - Many unrelated apps or teams apparently all using
default.
Both suggest missing administrative boundaries.
2. See what is running in each namespace
Run on: any machine with kubectl access
kubectl get pods --all-namespaces -o wide
Look for:
- Multiple unrelated applications (different teams, environments, or tenants) mixed in the same non-system namespace.
- Business-critical workloads running in
default.
This can indicate insufficient isolation between applications or tenants.
3. Inventory higher-level objects by namespace
Run on: any machine with kubectl access
Workloads:
kubectl get deploy,sts,ds,job,cronjob --all-namespaces
Services, ingresses, and configs:
kubectl get svc,ingress,cm,secret --all-namespaces
Indicators of a problem:
- Namespaces that act as “junk drawers” for many unrelated workloads/configs.
- Shared namespace holding both production and non-production resources.
- Shared namespace used by multiple teams/tenants (you’ll identify this by naming conventions or labels from your environment).
4. Check for labeling that reflects ownership or environment
Run on: any machine with kubectl access
kubectl get namespaces --show-labels
You may also want:
kubectl get ns -L team -L environment -L tenant
Potential issues:
- No labels reflecting owner/team, environment (
prod,dev,test), or tenant where that separation is expected in your organization. - Single namespace apparently serving multiple environments or tenants based on object names inside it (e.g.,
prod-*anddev-*resources mixed together).
5. Review access control by namespace (for context)
While this check is about namespaces themselves, RBAC use can show whether namespaces are being used as an administrative boundary.
Run on: any machine with kubectl access
kubectl get rolebindings,clusterrolebindings --all-namespaces -o wide
What may indicate a problem:
- Heavy use of
ClusterRoleBindingto grant broad access, instead ofRoleBindingscoped to specific namespaces, suggesting that namespaces are not being used as boundaries. - Same service account or user bound to roles across many unrelated namespaces without a clear reason.
6. Focus review on the default namespace
Run on: any machine with kubectl access
kubectl get all -n default
kubectl get cm,secret,sa,role,rolebinding -n default
Red flags:
- Application workloads from multiple teams or environments all live in
default. - Critical workloads live in
defaultinstead of a clearly named, dedicated namespace.
kubectl cannot decide the correct namespace design for you. Use the above outputs to determine whether your current namespace layout reflects your organizational boundaries (teams, tenants, environments, or applications) and adjust your manifests and deployment processes accordingly.
Automation
#!/usr/bin/env bash
# Run on: any machine with kubectl access and appropriate RBAC
# Purpose: Summarize namespaces, what runs in them, and basic isolation indicators
set -euo pipefail
echo "=== Cluster-wide namespace and workload summary ==="
echo
# 1) High-level namespace list with age and labels (used to infer purpose/tenancy)
echo "[1] Namespaces (name, age, labels)"
kubectl get ns --show-labels
echo
echo "-> REVIEW:"
echo " - Namespaces that mix unrelated purposes (e.g., team=multiple, env=dev+prod)."
echo " - Namespaces clearly used for multiple tenants or critical+noncritical workloads."
echo
# 2) Workload density per namespace (pods, deployments, statefulsets, daemonsets, jobs, cronjobs)
echo "[2] Workload counts per namespace"
kubectl get ns -o json \
| jq -r '
.items[]
| .metadata.name as $ns
| "Namespace: \($ns)" ,
(
[ "pods","deploy","sts","ds","jobs","cj" ]
| map(
. as $kind
| " \($kind): " +
( try ([
"kubectl","-n",$ns,"get",$kind,"--no-headers"
] | @sh) catch "" )
) | .[]
)
' 2>/dev/null | while read -r line; do
case "$line" in
*"kubectl -n"*)
# Execute the embedded kubectl commands constructed by jq
eval "${line#*\"}" 2>/dev/null | wc -l | awk '{print " "prev $1}' prev="${line%%:*}: "
;;
*)
echo "$line"
;;
esac
done
echo
echo "-> REVIEW:"
echo " - Namespaces with a very high variety of workloads (many unrelated apps)."
echo " - Namespaces mixing system and application workloads."
echo
# 3) Identify namespaces with both system and non-system indicators
echo "[3] Possible mixing of system and application workloads"
echo "System-like namespaces (by prefix/known names):"
kubectl get ns | awk '$1 ~ /^(kube-|default$|kube-system$|kube-public$|kube-node-lease$)/ {print " " $1}'
echo
echo "Non-system namespaces:"
kubectl get ns | awk '$1 !~ /^(kube-|default$|kube-system$|kube-public$|kube-node-lease$)/ {print " " $1}'
echo
echo "-> REVIEW:"
echo " - Application pods deployed in kube-system or other system namespaces."
echo " - Critical shared services deployed only in default instead of a dedicated namespace."
echo
# 4) ServiceAccounts per namespace (indicates possible shared admin boundaries)
echo "[4] ServiceAccounts per namespace"
for ns in $(kubectl get ns -o jsonpath='{.items[*].metadata.name}'); do
echo "Namespace: $ns"
kubectl -n "$ns" get sa --no-headers 2>/dev/null || true
echo
done
echo "-> REVIEW:"
echo " - Single ServiceAccount reused by many unrelated workloads (broad admin boundary)."
echo " - 'default' ServiceAccount heavily used instead of specific, per-app accounts."
echo
# 5) NetworkPolicies per namespace (coarse indicator of network isolation)
echo "[5] NetworkPolicies per namespace"
for ns in $(kubectl get ns -o jsonpath='{.items[*].metadata.name}'); do
count=$(kubectl -n "$ns" get networkpolicy --no-headers 2>/dev/null | wc -l | tr -d ' ')
echo "Namespace: $ns NetworkPolicies: $count"
done
echo
echo "-> REVIEW:"
echo " - Namespaces with many different apps but zero NetworkPolicies (likely flat network)."
echo
# 6) RBAC: ClusterRoles/ClusterRoleBindings that span multiple namespaces (coarse admin boundary)
echo "[6] ClusterRoleBindings (who has cluster-scoped powers)"
kubectl get clusterrolebinding -o wide
echo
echo "-> REVIEW:"
echo " - Subjects (users/groups/serviceaccounts) that administer many namespaces at once."
echo " - ServiceAccounts from application namespaces bound to powerful ClusterRoles."
echo
echo "=== Interpretation Guidelines ==="
echo "- A PROBLEM is indicated when:"
echo " * Multiple teams, tenants, or environments share a single namespace."
echo " * System and application workloads run in the same namespace."
echo " * Critical or sensitive apps share namespaces with unrelated, less-trusted apps."
echo " * Namespaces have many diverse workloads but no NetworkPolicies or fine-grained RBAC."
echo "- The remedy is design-driven: define clear per-team/per-app/per-env namespaces and"
echo " reorganize workloads; this cannot be safely auto-fixed and requires human decisions."
How to run
- Run on any machine with
kubectlandjqinstalled and access to the cluster:chmod +x namespace-boundaries-audit.sh./namespace-boundaries-audit.sh
What output indicates a problem
- Namespaces where:
- Many unrelated apps and teams share the same namespace.
- Application pods are present in
kube-systemor other system namespaces. - Critical shared services live only in
default. - Only the
defaultServiceAccount is used for many workloads. - There are many workloads but zero
NetworkPolicies. - ClusterRoleBindings grant broad privileges to subjects from many namespaces.
These patterns suggest weak administrative boundaries; decisions on new namespace layout and workload moves must be made manually.