Create Administrative Boundaries Between Resources Using
More Info:
Namespaces provide administrative and security boundaries between groups of resources. Create namespaces for the objects in your deployment as needed.
Risk Level
Medium
Address
Security
Compliance Standards
- CIS AKS
Triage and Remediation
- Remediation
Remediation
Manual Steps
-
Inventory current namespaces and workloads
- Run on: any machine with kubectl access
- Commands:
kubectl get namespaceskubectl get pods --all-namespaces -o widekubectl get deployments --all-namespaceskubectl get statefulsets --all-namespaceskubectl get daemonsets --all-namespaceskubectl get services --all-namespaces
- Review which user workloads (apps) are running in
default,kube-system, or other shared namespaces instead of dedicated ones.
-
Map workloads to organizational or security boundaries
- Decide how to group workloads into namespaces, for example by:
- Environment:
dev,test,staging,prod - Team/owner:
payments,analytics,platform - Sensitivity:
public,internal,restricted
- Environment:
- Document for each application which namespace it should belong to and which other workloads it should be administratively separated from.
- Decide how to group workloads into namespaces, for example by:
-
Design the namespace layout and policies
- For each planned namespace, decide:
- Purpose and owner
- Required access controls (RBAC) and network separation (if using NetworkPolicies)
- Any resource quotas/limits that should apply
- Optionally draft a namespace manifest template, for example:
apiVersion: v1kind: Namespacemetadata:name: payments-prodlabels:environment: prodowner: payments-team
- For each planned namespace, decide:
-
Create the required namespaces
- Run on: any machine with kubectl access
- For a simple namespace:
kubectl create namespace payments-prodkubectl label namespace payments-prod environment=prod owner=payments-team
- Or apply a manifest (repeat per namespace):
kubectl apply -f namespace-payments-prod.yaml
-
Refactor workloads to use the new namespaces
- Update manifests/Helm charts/IaC so each workload specifies the intended namespace and is no longer deployed into
defaultor other shared namespaces. Examples:- With kubectl:
kubectl apply -n payments-prod -f deployment-payments.yaml
- In a manifest, omit
namespaceundermetadataand deploy with-n, or set an explicitmetadata.namespacealigned to your design.
- With kubectl:
- Carefully migrate existing workloads:
- Export current manifest, adjust namespace, re-apply, then delete the old object:
kubectl get deploy payments -n default -o yaml > payments-export.yaml# edit metadata.namespace: payments-prod (and any labels/annotations as desired)kubectl apply -f payments-export.yamlkubectl delete deploy payments -n default
- Export current manifest, adjust namespace, re-apply, then delete the old object:
- Ensure dependent objects (Services, ConfigMaps, Secrets, RBAC bindings) are created in the same namespace and references are updated.
- Update manifests/Helm charts/IaC so each workload specifies the intended namespace and is no longer deployed into
-
Verify namespace-based separation is in place
- Run on: any machine with kubectl access
- Commands:
kubectl get namespaceskubectl get pods --all-namespaceskubectl get deployments --all-namespaceskubectl get services --all-namespaces
- Confirm that:
- User workloads are not running in
defaultorkube-system. - Workloads are grouped into the intended namespaces that reflect your administrative and security boundaries.
- User workloads are not running in
Using kubectl
Using kubectl
1. List all namespaces and basic metadata
Run on: any machine with kubectl access
kubectl get namespaces -o wide
Review:
- Problem indicators:
- Only
default,kube-system,kube-public,kube-node-lease, and a small number of broad “catch‑all” namespaces likedevorprod, but many unrelated apps in each. - Business‑critical and non‑critical workloads mixed in the same namespace.
- Security‑sensitive workloads (e.g., with elevated permissions) sharing a namespace with general apps.
- Only
2. See what runs in each namespace
Run on: any machine with kubectl access
All workloads per namespace:
kubectl get all -A
By specific namespace (example for default):
kubectl get all -n default
Review:
- Problem indicators:
- Many unrelated applications coexisting in a single namespace (e.g., multiple teams’ apps, shared test and production workloads).
- System components or operators deployed in
defaultinstead of their own namespaces. - Lack of clear grouping (names don’t suggest ownership, environment, or function).
3. Identify applications still using the default namespace
Run on: any machine with kubectl access
kubectl get deployments,statefulsets,daemonsets,cronjobs,jobs,services,ingresses,pods -n default
Review:
- Problem indicators:
- Long list of application resources in
default(not just small test/demo items). - Multi-team or multi-tenant workloads all deployed to
default.
- Long list of application resources in
4. Inspect labels to infer ownership and boundaries
Run on: any machine with kubectl access
kubectl get pods -A --show-labels
For a specific namespace:
kubectl get pods -n <namespace> --show-labels
Review:
- Problem indicators:
- Pods from different teams or applications (as indicated by labels like
app,team,owner) mixed in the same namespace when they should be administratively separated. - Lack of consistent labeling, making it hard to reason about who owns what in each namespace.
- Pods from different teams or applications (as indicated by labels like
5. Review namespace-level policies and their scope
Run on: any machine with kubectl access
NetworkPolicies:
kubectl get networkpolicy -A
ResourceQuotas and LimitRanges:
kubectl get resourcequota -A
kubectl get limitrange -A
RBAC bindings by namespace:
kubectl get rolebindings,roles -A
Review:
- Problem indicators:
- Few namespaces with NetworkPolicies, ResourceQuotas, or RBAC bindings, implying broad, shared namespaces with weak administrative separation.
- Single namespace where many different RoleBindings/roles are used to approximate per-team isolation instead of using separate namespaces.
6. Inspect specific namespaces in detail
Run on: any machine with kubectl access
kubectl describe namespace <namespace-name>
kubectl get all -n <namespace-name>
kubectl get rolebindings,roles -n <namespace-name>
kubectl get resourcequota,limitrange -n <namespace-name>
Review:
- Problem indicators:
- Namespace description and contents show mixed environments (e.g., both
devandprodworkloads). - Shared namespace used by multiple teams or tenants with no corresponding isolation mechanisms, suggesting missing administrative boundaries.
- Namespace description and contents show mixed environments (e.g., both
These commands surface how workloads are currently grouped and where namespaces are being used as broad buckets instead of clear administrative/security boundaries; a human must decide where new namespaces are needed and how to reorganize workloads.
Automation
#!/usr/bin/env bash
# Report namespace usage and obvious boundary issues across the cluster.
# Run on: any machine with kubectl access and current context set.
set -euo pipefail
echo "=== 1) Namespaces and basic metadata ==="
kubectl get ns -o wide
echo
echo "=== 2) Namespaces with potentially risky labels/annotations (e.g. shared, default) ==="
kubectl get ns -o json \
| jq -r '
.items[]
| {
name: .metadata.name,
labels: .metadata.labels,
annotations: .metadata.annotations
}
'
echo
echo "=== 3) Workloads per namespace (Pods, Deployments, StatefulSets, DaemonSets, Jobs, CronJobs) ==="
kubectl get pods,deploy,sts,ds,job,cronjob -A -o wide
echo
echo "=== 4) ClusterRoles and ClusterRoleBindings (cluster-wide privileges) ==="
kubectl get clusterrole,clusterrolebinding -o wide
echo
echo "=== 5) RoleBindings that reference ClusterRoles (cluster-wide perms bound into namespaces) ==="
kubectl get rolebinding -A -o json \
| jq -r '
.items[]
| select(.roleRef.kind=="ClusterRole")
| [.metadata.namespace, .metadata.name, .roleRef.name]
| @tsv
' \
| awk 'BEGIN { printf "NAMESPACE\tROLEBINDING\tCLUSTERROLE\n" } { print }'
echo
echo "=== 6) ServiceAccounts per namespace ==="
kubectl get sa -A -o wide
echo
echo "=== 7) NetworkPolicies per namespace (namespaces without any policy) ==="
echo "--- All NetworkPolicies ---"
kubectl get networkpolicy -A || echo "No NetworkPolicies defined."
echo
echo "--- Namespaces without any NetworkPolicy (potentially flat network) ---"
ALL_NS=$(kubectl get ns -o jsonpath='{range .items[*]}{.metadata.name}{"\n"}{end}')
NS_WITH_NP=$(kubectl get networkpolicy -A -o jsonpath='{range .items[*]}{.metadata.namespace}{"\n"}{end}' | sort -u || true)
echo "$ALL_NS" | while read -r ns; do
if ! grep -qx "$ns" <<< "$NS_WITH_NP"; then
echo "$ns"
fi
done
echo
echo "=== 8) Pods running in shared or catch‑all namespaces (default, kube-system, kube-public) ==="
kubectl get pods -n default -o wide || true
kubectl get pods -n kube-system -o wide || true
kubectl get pods -n kube-public -o wide || true
echo
echo "=== 9) Nodes: taints and labels (used to separate workloads) ==="
kubectl get nodes -o wide
kubectl get nodes -o json \
| jq -r '
.items[]
| [
.metadata.name,
( .spec.taints // [] | map(.key + "=" + .value + ":" + .effect) | join(",") ),
( .metadata.labels // {} | to_entries | map(.key + "=" + .value) | join(",") )
]
| @tsv
' | awk 'BEGIN { print "NODE\tTAINTS\tLABELS" } { print }'
How to interpret the output (what indicates a problem)
Reviewers should look for:
-
Workloads in shared / system namespaces
- Output section 8: non‑platform application pods running in
default,kube-system, orkube-publicindicate missing administrative boundaries. - Expected: only core components and intentionally shared infra in these namespaces.
- Output section 8: non‑platform application pods running in
-
Single namespace hosting unrelated applications
- Output sections 1 and 3: many distinct applications or teams sharing the same namespace (especially
default) suggests boundaries are not defined by function, environment, or owner.
- Output sections 1 and 3: many distinct applications or teams sharing the same namespace (especially
-
Lack of NetworkPolicies
- Output section 7: namespaces listed as “without any NetworkPolicy” are likely on a flat network with no namespace‑level traffic controls, weakening isolation.
-
ClusterRoles used inside many namespaces
- Output sections 4 and 5: the same
ClusterRolereferenced in manyRoleBindingsacross several namespaces can indicate that a nominal namespace boundary is bypassed by broad RBAC.
- Output sections 4 and 5: the same
-
System and user workloads mixed on the same nodes without taints/labels
- Output section 9: no meaningful taints/labels separating system and user workloads can make it harder to enforce different policies per boundary.
-
Catch‑all / ambiguous namespaces
- Output sections 1–3: namespaces with vague names (e.g.,
misc,shared,tools) containing many different workloads usually indicate missing per‑team or per‑app namespaces.
- Output sections 1–3: namespaces with vague names (e.g.,
Use these findings to decide where new namespaces (and corresponding RBAC and NetworkPolicies) should be introduced; any move/creation must be planned and applied manually with updated manifests and policies.