Create Administrative Boundaries Between Resources Using
More Info:
Namespaces provide administrative and security boundaries for segregating cluster resources. Objects should be organized into dedicated namespaces rather than sharing a single namespace.
Risk Level
Low
Address
Security
Compliance Standards
- CIS GKE
Triage and Remediation
- Remediation
Remediation
Manual Steps
-
Inventory current namespaces and workloads
Run on any machine with kubectl access:kubectl get namespaceskubectl get all --all-namespacesReview which namespaces exist, which are system/managed (e.g.,
kube-system,gke-system,istio-system,gatekeeper-system), and where your application workloads currently run. -
Identify workloads running in inappropriate or shared namespaces
Focus ondefault,kube-system, and any “catch‑all” namespaces:kubectl get all -n defaultkubectl get all -n kube-systemDecide which applications, environments (dev/test/prod), or teams are mixed together and should be separated (e.g., multiple apps sharing
default, non-system apps inkube-system). -
Design a namespace structure aligned to admin and security boundaries
On a planning machine (no commands):- Define namespaces per application, per environment, or per tenant/team (e.g.,
app1-prod,app1-dev,payments-prod,analytics-dev). - Decide which namespaces require stronger controls (e.g., separate namespace for internet-facing workloads, sensitive data, or admin tooling).
Document the desired namespace layout and which workloads should live where.
- Define namespaces per application, per environment, or per tenant/team (e.g.,
-
Create or update namespace definitions
Run on any machine with kubectl access:- To create missing namespaces:
kubectl create namespace app1-prodkubectl create namespace app1-dev
- Or define them declaratively in a manifest file (example):
Apply with:apiVersion: v1kind: Namespacemetadata:name: app1-prod---apiVersion: v1kind: Namespacemetadata:name: app1-devkubectl apply -f namespaces.yaml
- To create missing namespaces:
-
Relocate workloads into the appropriate namespaces
For each workload that should move (Deployments, Services, Jobs, etc.):- Export its manifest and edit the
metadata.namespace(and any namespace-qualified references such as ConfigMaps, Secrets, ServiceAccounts):Editkubectl get deploy my-app -n default -o yaml > my-app.yamlmy-app.yamlto set:metadata:namespace: app1-prod - Delete the old object and recreate it in the new namespace (ensure you understand the downtime impact):
kubectl delete deploy my-app -n defaultkubectl apply -f my-app.yaml
Repeat for Services, ConfigMaps, Secrets, etc., ensuring all required dependencies exist in the target namespace.
- Export its manifest and edit the
-
Verify namespace boundaries are in place
Run on any machine with kubectl access:kubectl get namespaceskubectl get all -n app1-prodkubectl get all -n app1-devkubectl get all -n defaultConfirm that:
- Application workloads are no longer concentrated in
defaultor mixed with system components. - Workloads are organized according to the designed boundaries (per app/environment/team) and system namespaces contain only system components.
- Application workloads are no longer concentrated in
Using kubectl
# 1) List all namespaces and their age
# Run on: any machine with kubectl access
kubectl get namespaces --show-labels
Review guidance:
- Potential problems if:
- Almost all workloads are in
default,kube-system, orkube-public. - Many namespaces exist but have no clear purpose or labels (e.g., missing
env=,team=,app=style labels). - System namespaces (
kube-system,kube-public,kube-node-lease,gke-*) are used for custom application workloads.
- Almost all workloads are in
# 2) See which namespaces actually contain workloads
kubectl get all --all-namespaces
Review guidance:
- Potential problems if:
- Most
Deployment,StatefulSet,DaemonSet,Job, orPodobjects are in a single shared namespace likedefault. - Unrelated applications or teams share the same namespace with no separation.
- Most
# 3) Summarize workload kinds per namespace
kubectl get pods,deploy,sts,ds,job,cronjob -A \
-o custom-columns='NAMESPACE:.metadata.namespace,KIND:.kind,NAME:.metadata.name' \
| sort -u
Review guidance:
- Potential problems if:
- You see many unrelated applications (by name) co-located in the same namespace.
- There is no visible pattern (e.g., per-team, per-environment, or per-application grouping).
# 4) Inspect labels/annotations on a specific busy namespace (example: default)
kubectl describe namespace default
Review guidance:
- Potential problems if:
- The namespace lacks labels that indicate ownership, environment, or purpose.
- The namespace mixes “shared” or “misc” workloads with no clear boundary.
# 5) Identify which namespaces are used for user workloads vs system
kubectl get ns \
-o custom-columns='NAME:.metadata.name,AGE:.metadata.creationTimestamp,LABELS:.metadata.labels'
Review guidance:
- Potential problems if:
- User workloads appear in system namespaces (names beginning with
kube-orgke-). - There is no clear distinction between system and application namespaces.
- User workloads appear in system namespaces (names beginning with
# 6) For one or two key namespaces, list owners via labels
# Replace <namespace> as needed
kubectl get deploy,sts,ds,svc,ingress -n <namespace> \
-o custom-columns='KIND:.kind,NAME:.metadata.name,TEAM:.metadata.labels.team,APP:.metadata.labels.app,ENV:.metadata.labels.env'
Review guidance:
- Potential problems if:
- Multiple teams (
TEAMlabel) or environments (ENVlabel) share the same namespace. - No labels are present to show who owns resources or what boundary they belong to.
- Multiple teams (
Interpreting issues for this control:
- You likely fail the intent of CISGKE 4.6.1 if:
- Most or all application workloads run in
default. - Different applications, teams, or environments are not separated into distinct namespaces.
- System and application workloads are mixed in the same namespaces.
- Most or all application workloads run in
- A healthy pattern usually shows:
- Dedicated namespaces per application, team, or environment.
- System namespaces used only for system components.
Automation
#!/usr/bin/env bash
# Report namespace usage and potential issues for CIS GKE 4.6.1
# Run on: any machine with kubectl access and appropriate RBAC
set -euo pipefail
echo "=== Cluster-wide Namespace Overview ==="
kubectl get namespaces -o wide
echo
echo "=== Namespace Annotations & Labels (for admin boundaries) ==="
kubectl get ns -o json \
| jq -r '
.items[]
| {
name: .metadata.name,
labels: .metadata.labels,
annotations: .metadata.annotations
}' \
| jq .
echo
echo "=== Workloads per Namespace (pods, deployments, statefulsets, daemonsets, jobs, cronjobs) ==="
# Summarize main workload objects per namespace
kubectl get ns -o jsonpath='{range .items[*]}{.metadata.name}{"\n"}{end}' \
| while read -r ns; do
echo "--- Namespace: ${ns} ---"
kubectl get pods,deployments,statefulsets,daemonsets,jobs,cronjobs -n "${ns}" --ignore-not-found
echo
done
echo
echo "=== Namespaces with Mixed 'types' of Workloads (heuristic) ==="
echo "Note: This heuristic flags namespaces that mix system, infra, and app workloads by label patterns."
echo "You must manually review and decide if separation is required."
# Heuristic: classify workloads by label keys commonly used to denote ownership/type
kubectl get pods --all-namespaces -o json \
| jq -r '
.items[]
| {
ns: .metadata.namespace,
name: .metadata.name,
labels: (.metadata.labels // {}),
owner: (
if .metadata.labels["app.kubernetes.io/part-of"] then "app"
elif .metadata.labels["k8s-app"] then "system-or-infra"
elif .metadata.labels["app"] then "app"
else "unknown"
end
)
}' \
| jq -s '
group_by(.ns)
| map({
namespace: .[0].ns,
counts: (group_by(.owner) | map({(.[0].owner): length}) | add)
})' \
| jq -r '
.[]
| select((.counts["app"] != null and .counts["system-or-infra"] != null) or (.counts["unknown"] != null and (.counts["app"] != null or .counts["system-or-infra"] != null)))
'
echo
echo "=== Namespaces with Both System and Application-Looking Objects (by name pattern) ==="
echo "Patterns used: kube-*, istio-*, linkerd, logging, monitoring, prometheus, envoy, ingress"
echo "Review these for possible separation of system/infra from application workloads."
patterns='kube-|istio-|linkerd|logging|monitoring|prometheus|envoy|ingress'
kubectl get pods --all-namespaces -o wide \
| awk 'NR==1 {next} {print $1, $2}' \
| while read -r ns pod; do
if [[ "${pod}" =~ ${patterns} ]]; then
echo "${ns} SYSTEM_OR_INFRA_POD ${pod}"
else
echo "${ns} APP_OR_OTHER_POD ${pod}"
fi
done \
| awk '
{
ns=$1; type=$2
has[ns][type]=1
}
END {
for (n in has) {
if (has[n]["SYSTEM_OR_INFRA_POD"] && has[n]["APP_OR_OTHER_POD"]) {
print n ": has both system/infra-looking and app-looking pods"
}
}
}' \
| sort
echo
echo "=== Namespaces with No Clear Labeling for Ownership/Boundary (candidates for review) ==="
kubectl get ns -o json \
| jq -r '
.items[]
| {
name: .metadata.name,
labels: .metadata.labels
}
| select(.name != "kube-system" and .name != "kube-public" and .name != "kube-node-lease" and .name != "default")
| select(
(.labels["team"] == null)
and (.labels["owner"] == null)
and (.labels["app.kubernetes.io/part-of"] == null)
and (.labels["environment"] == null)
)
| .name' \
| sort
echo
echo "=== Objects in the 'default' Namespace (strong candidates for re-namespacing) ==="
echo "These commonly indicate missing administrative boundaries."
kubectl get all -n default --show-kind --ignore-not-found
echo
echo "=== Summary & Interpretation Guidance ==="
cat <<'EOF'
Review guidance (CIS GKE 4.6.1 - MANUAL):
Potential problems you should investigate:
1) Heavy use of the 'default' namespace:
- If many applications, services, or jobs are in 'default', they likely lack
clear administrative boundaries. Consider moving them into dedicated
namespaces per app, team, environment, or trust level.
2) Namespaces that mix system/infra and application workloads:
- The sections "Namespaces with Mixed 'types' of Workloads" and
"Namespaces with Both System and Application-Looking Objects" list
namespaces that appear to host both:
* cluster/system/infra components (e.g., kube-*, istio-*, logging/monitoring)
* regular application pods
- Consider separating system/infra components from business applications
into distinct namespaces.
3) Namespaces with no ownership/boundary labels:
- The "Namespaces with No Clear Labeling" section lists namespaces
that lack common labels to denote owner, team, or environment.
- While not a hard failure, unclear ownership often correlates with
weak administrative boundaries.
4) General organization:
- Review whether you have a namespace strategy (e.g. by team, by app,
by environment: dev/stage/prod, by sensitivity).
- For each multi-tenant/shared cluster, ensure tenants do not share
namespaces unless intentionally designed.
This script only reports; it does NOT change any resources.
You must decide, per finding, whether to create new namespaces and
move workloads, following your operational and security requirements.
EOF
What output indicates a problem (to be manually reviewed):
- Many user workloads listed under
=== Objects in the 'default' Namespace ===. - Namespaces listed under:
=== Namespaces with Mixed 'types' of Workloads (heuristic) ====== Namespaces with Both System and Application-Looking Objects ===
- Namespaces listed under
=== Namespaces with No Clear Labeling for Ownership/Boundary ===in a multi-tenant or complex environment.