Skip to main content

Create Administrative Boundaries Between Resources Using

More Info:

Namespaces provide administrative and access-control boundaries between groups of resources. Create namespaces to segregate resources and place new resources in a specific namespace.

Risk Level

Low

Address

Security

Compliance Standards

  • CIS OKE

Triage and Remediation

Remediation

Manual Steps
  1. Inventory current namespaces and their workloads
    Run on any machine with kubectl access:

    kubectl get namespaces
    kubectl get all --all-namespaces

    Review whether business-critical applications, shared infrastructure, and testing workloads are clearly separated into different namespaces instead of using default.

  2. Identify workloads in the default namespace or other catch‑all namespaces

    kubectl get all -n default

    If you have any custom workloads in default (or a single large shared namespace), decide how they should be grouped (e.g., by application, environment such as dev/stage/prod, or team/tenant).

  3. Design the namespace model and create required namespaces
    Decide and document which namespaces you need (for example: app1-prod, app1-dev, shared-infra, team-a, team-b).
    Create them:

    kubectl create namespace app1-prod
    kubectl create namespace app1-dev
    kubectl create namespace shared-infra
    # add or adjust names as per your design
  4. Plan and apply resource re-homing into the new namespaces
    For each workload currently in default (or another overly broad namespace), export and adjust its manifests:

    # example for a deployment in default
    kubectl get deployment my-deployment -n default -o yaml > my-deployment.yaml

    Edit my-deployment.yaml to set:

    metadata:
    namespace: app1-prod # or your chosen namespace

    Then re-apply in the target namespace and delete the old resource if needed:

    kubectl apply -f my-deployment.yaml
    kubectl delete deployment my-deployment -n default

    Repeat for Services, ConfigMaps, Secrets, Jobs, etc., as appropriate, verifying dependencies (e.g., Service selectors, config references).

  5. Align access control and policies with the new namespaces
    For each new namespace, ensure RBAC and policies match the intended boundary:

    kubectl get role,rolebinding,networkpolicy,resourcequota,limitrange -n app1-prod

    Create or adjust Role, RoleBinding, NetworkPolicy, ResourceQuota, and LimitRange objects so that teams/apps can only access their own namespaces and appropriate resource limits are enforced.

  6. Verify namespace-based separation is in effect
    Confirm that application workloads now reside in their intended namespaces and that default contains no (or only minimal/expected) workloads:

    kubectl get all --all-namespaces
    kubectl get all -n default

    Review that resources are grouped according to your designed boundaries and that cross-namespace access (via RBAC and policies) matches your administrative intent.

Using kubectl
# 1) List all namespaces and age
# Run on: any machine with kubectl access
kubectl get namespaces -o wide

Review guidance:

  • Potential problem if you see only the default/system namespaces (default, kube-system, kube-public, kube-node-lease, any cloud-provider system namespaces) and no application- or team-specific namespaces.
  • Also a problem if there is a single custom namespace that appears to host all workloads, suggesting no meaningful separation.
# 2) List all pods in ALL namespaces to see how workloads are distributed
kubectl get pods --all-namespaces -o wide

Review guidance:

  • Potential problem if most or all non-system workloads are in the default namespace.
  • Potential problem if unrelated applications (different teams, environments, or sensitivity levels) all run in the same namespace.
# 3) Inspect which namespaces individual workloads are using by type
kubectl get deploy,sts,ds,job,cronjob --all-namespaces

Review guidance:

  • Look for patterns like:
    • All Deployments in default.
    • Shared namespaces mixing dev/test/prod or internal/external workloads.
  • This suggests missing administrative boundaries.
# 4) Check RBAC bindings per namespace (to see if boundaries are being used)
kubectl get rolebindings,roles -A
kubectl get clusterrolebindings,clusterroles

Review guidance:

  • If access control is mostly via ClusterRoleBinding to wide roles (e.g., cluster-admin) and there are few or no namespace-scoped Role/RoleBinding objects, namespaces are likely not being used as effective boundaries.
  • If a single namespace’s roles grant broad access to many unrelated resources, it may indicate poor separation.
# 5) Optionally, count non-system workloads by namespace
kubectl get pods --all-namespaces \
| grep -vE 'kube-system|kube-public|kube-node-lease|NAME' \
| awk '{print $1}' \
| sort | uniq -c | sort -nr

Review guidance:

  • If the vast majority of non-system pods are in the default namespace (or a single shared namespace), administrative boundaries are likely inadequate.
# 6) Verify after any namespace restructuring
kubectl get namespaces -o wide
kubectl get deploy,sts,ds,job,cronjob --all-namespaces
kubectl get pods --all-namespaces -o wide

Verification guidance:

  • You should see multiple, clearly named namespaces (e.g., per environment, team, or application).
  • Non-system workloads should be spread across those namespaces in a way that matches your intended administrative and access-control boundaries.
Automation
#!/usr/bin/env bash
# Report namespace usage to help review administrative boundaries
# Runs on: any machine with kubectl access and current-context pointing to the target cluster

set -euo pipefail

echo "=== 1) Namespaces overview ==="
kubectl get namespaces -o custom-columns=NAME:.metadata.name,STATUS:.status.phase,AGE:.metadata.creationTimestamp

echo
echo "=== 2) Workloads per namespace (Deployments, StatefulSets, DaemonSets, Jobs, CronJobs) ==="
kubectl get deploy,sts,ds,job,cronjob -A \
-o custom-columns=KIND:.kind,NAMESPACE:.metadata.namespace,NAME:.metadata.name \
| sort -k2,2 -k1,1 -k3,3

echo
echo "=== 3) Services per namespace ==="
kubectl get svc -A \
-o custom-columns=NAMESPACE:.metadata.namespace,NAME:.metadata.name,TYPE:.spec.type,CLUSTER_IP:.spec.clusterIP \
| sort -k1,1 -k2,2

echo
echo "=== 4) Pods running in the 'default' namespace (focus area) ==="
kubectl get pods -n default \
-o custom-columns=NAME:.metadata.name,OWNER_KIND:.metadata.ownerReferences[*].kind,OWNER_NAME:.metadata.ownerReferences[*].name \
--ignore-not-found

echo
echo "=== 5) ClusterRoles / RoleBindings to detect broad access across namespaces ==="
echo "--- ClusterRoles (cluster-wide permissions) ---"
kubectl get clusterrole -o custom-columns=NAME:.metadata.name,AGE:.metadata.creationTimestamp \
| sort

echo
echo "--- ClusterRoleBindings and their subjects (who can access across namespaces) ---"
kubectl get clusterrolebinding -o yaml | awk '
$1=="kind:"{kind=$2}
$1=="name:"&&kind=="ClusterRoleBinding"{crb=$2}
/roleRef:/ {inRoleRef=1; next}
inRoleRef && $1=="name:"{role=$2; inRoleRef=0}
/subjects:/ {inSubjects=1; next}
inSubjects && $1=="-"{
getline; gsub("kind:",""); sub(/^[ \t]+/,""); sKind=$0
getline; gsub("name:",""); sub(/^[ \t]+/,""); sName=$0
getline; gsub("namespace:",""); sub(/^[ \t]+/,""); sNs=$0
if(sNs=="") sNs="-"
printf "%-40s %-30s %-12s %-30s %-20s\n", crb, role, sKind, sName, sNs
}
' | sort

echo
echo "=== 6) Roles / RoleBindings per namespace (for detailed review) ==="
for ns in $(kubectl get ns -o jsonpath='{.items[*].metadata.name}'); do
echo "--- Namespace: ${ns} ---"
echo "Roles:"
kubectl get role -n "${ns}" \
-o custom-columns=NAME:.metadata.name,AGE:.metadata.creationTimestamp \
--ignore-not-found \
| sed 's/^/ /'
echo "RoleBindings:"
kubectl get rolebinding -n "${ns}" \
-o custom-columns=NAME:.metadata.name,ROLE:.roleRef.name \
--ignore-not-found \
| sed 's/^/ /'
echo
done

echo "=== 7) Summary: workloads per namespace (counts) ==="
kubectl get deploy,sts,ds,job,cronjob -A -o custom-columns=NAMESPACE:.metadata.namespace,NAME:.metadata.name \
| awk 'NR>1{count[$1]++} END{printf "%-30s %s\n","NAMESPACE","WORKLOAD_COUNT"; for (ns in count) printf "%-30s %d\n", ns, count[ns] | "sort"}'

Explanation of what indicates a potential problem:

  • Many application Pods/Deployments/Services appear in the default namespace (section 4 and summary section 7), especially if used by multiple teams or environments.
  • Critical, unrelated applications share the same namespace (check section 2 and 3 for “crowded” namespaces mixing different systems or teams).
  • Broad ClusterRoles and ClusterRoleBindings in section 5 show many subjects (users, groups, service accounts) bound to powerful roles, effectively bypassing namespace isolation.
  • Namespaces with workloads but few or no Roles/RoleBindings (section 6) may lack fine-grained, namespace-scoped RBAC.

Use this report to decide where to:

  • Create additional namespaces to separate teams, environments (dev/test/prod), or applications.
  • Move workloads out of default into specific namespaces.
  • Tighten RBAC so access is appropriately constrained per namespace.