Skip to main content

Create Administrative Boundaries Between Resources Using

More Info:

Namespaces provide administrative and security boundaries between groups of resources. Use them to segregate workloads.

Risk Level

Low

Address

Security

Compliance Standards

  • CIS Kubernetes

Triage and Remediation

Remediation

Manual Steps
  1. Inventory current namespaces and workloads

    • Run on: any machine with kubectl access
    • Command:
      kubectl get namespaces
      kubectl get all --all-namespaces
    • Purpose: Identify what namespaces exist and which Pods/Services/Deployments are concentrated in default or other shared namespaces.
  2. Identify security/administrative domains that should be isolated

    • Run on: any machine with kubectl access
    • Commands (to help group by label/owner):
      kubectl get pods --all-namespaces -o wide --show-labels
      kubectl get deployments --all-namespaces -o wide --show-labels
    • Review points:
      • Which teams, environments (dev/test/stage/prod), or applications share a namespace?
      • Which workloads have different data sensitivity, access requirements, or change-control rules but share a namespace?
  3. Decide and document a namespace model

    • No command; design decision.
    • Suggested patterns to evaluate:
      • Per-environment (e.g., dev, staging, prod)
      • Per-team (e.g., team-a, team-b)
      • Per-application or domain (e.g., payments, analytics)
    • Ensure future objects will be created in these namespaces (CI/CD changes, Helm values, etc.).
  4. Create required namespaces

    • Run on: any machine with kubectl access
    • Commands (example – adjust names to your model):
      kubectl create namespace dev
      kubectl create namespace staging
      kubectl create namespace prod
    • For GitOps/manifest-driven clusters, create YAML instead and apply via your pipeline:
      apiVersion: v1
      kind: Namespace
      metadata:
      name: dev
      ---
      apiVersion: v1
      kind: Namespace
      metadata:
      name: staging
      ---
      apiVersion: v1
      kind: Namespace
      metadata:
      name: prod
      Apply:
      kubectl apply -f namespaces.yaml
  5. Plan and migrate workloads out of shared/default namespaces

    • Run on: any machine with kubectl access
    • Evidence to gather for each namespace you intend to clean up:
      # Workloads in default and any other shared namespace
      kubectl get all -n default
      kubectl get all -n <shared-namespace>

      # ConfigMaps, Secrets, RBAC bindings that may need moving or duplicating
      kubectl get configmaps,secrets,serviceaccounts,roles,rolebindings -n default
      kubectl get configmaps,secrets,serviceaccounts,roles,rolebindings -n <shared-namespace>
    • For each application, update its manifests/Helm values/CI to set metadata.namespace: <target-namespace>, then re-deploy there. Clean up old objects after validating functionality.
  6. Verify namespace-based segregation is in place

    • Run on: any machine with kubectl access
    • Commands:
      kubectl get namespaces
      kubectl get all --all-namespaces
    • Review points:
      • Sensitive or production workloads run in dedicated namespaces, not default.
      • Distinct teams/environments/applications have their own namespaces according to your model.
      • New deployments (from CI/CD) are landing in the intended namespaces, not in default.
Using kubectl

Using kubectl

1. List all namespaces and look for over‑concentration of workloads

Run on: any machine with kubectl access

kubectl get namespaces

Review guidance (possible problems):

  • Everything (system and all apps) is running in just default (and maybe kube-* system namespaces).
  • Business‑critical, dev, and test workloads are all in the same non‑system namespace.

2. See what’s running in the default namespace

Run on: any machine with kubectl access

kubectl get all -n default

Review guidance (possible problems):

  • Application workloads for multiple teams or environments are all in default.
  • Sensitive workloads (e.g., production databases) run in default instead of a dedicated namespace.

3. Get a cross‑namespace view of workloads

Run on: any machine with kubectl access

kubectl get pods --all-namespaces

Review guidance (possible problems):

  • A small number of namespaces containing a large mix of unrelated workloads.
  • No clear separation by environment (e.g., prod/stage/dev) or by tenant/team when that is a requirement.

To go deeper for specific kinds:

kubectl get deploy,sts,ds,job,cronjob --all-namespaces

Look for:

  • Deployments/StatefulSets/DaemonSets from multiple teams or tenants sharing one namespace without justification.

4. Inspect labeling/ownership patterns

Run on: any machine with kubectl access

kubectl get ns --show-labels

Review guidance (possible problems):

  • No labels to indicate environment (env=prod|stage|dev) or owner/team when such separation is expected.
  • Namespaces used as a “dumping ground” with unclear purpose.

5. Spot potential multi‑tenant or shared admin issues

Run on: any machine with kubectl access

Check for role bindings that span many subjects in a shared namespace:

kubectl get rolebindings,clusterrolebindings -A

Review guidance (possible problems):

  • A single shared namespace where many different user groups are granted broad access, instead of each having their own namespace.
  • Cluster‑wide roles used where namespace‑scoped roles and separate namespaces would provide better isolation.

If these reviews show that unrelated workloads, tenants, or environments are co‑located in the same namespace without a clear reason, that indicates missing or insufficient administrative boundaries and may require a namespace design change (performed via manifests/kubectl and aligned with your org’s requirements).

Automation
#!/usr/bin/env bash
#
# cis-5.6.1-namespaces-inventory.sh
#
# Purpose:
# Provide a cluster-wide view of namespace usage so you can manually review
# whether administrative boundaries are being used appropriately.
#
# Requirements:
# - Run on any machine with kubectl configured and RBAC rights to list
# namespaces, pods, deployments, statefulsets, daemonsets, jobs, cronjobs.
# - kubectl v1.20+ recommended.

set -euo pipefail

echo "=== [1/5] Namespaces and basic metadata ==="
kubectl get ns -o wide

echo
echo "=== [2/5] Namespaces with counts of core workload objects ==="
# For each namespace, show counts of Pods, Deployments, StatefulSets,
# DaemonSets, Jobs, and CronJobs.
kubectl get ns -o json \
| jq -r '
.items[]
| .metadata.name as $ns
| {
namespace: $ns,
pods: (try (.pods // 0) catch 0),
deploys: (try (.deploys // 0) catch 0),
ssets: (try (.ssets // 0) catch 0),
dsets: (try (.dsets // 0) catch 0),
jobs: (try (.jobs // 0) catch 0),
cjobs: (try (.cjobs // 0) catch 0)
}
' 2>/dev/null || {
# Fallback without jq pre-processing if jq is unavailable
echo "jq not found or failed; using slower kubectl-based fallback..." >&2
for ns in $(kubectl get ns -o jsonpath='{.items[*].metadata.name}'); do
pods=$(kubectl get pods -n "$ns" --no-headers 2>/dev/null | wc -l || echo 0)
deploys=$(kubectl get deploy -n "$ns" --no-headers 2>/dev/null | wc -l || echo 0)
ssets=$(kubectl get sts -n "$ns" --no-headers 2>/dev/null | wc -l || echo 0)
dsets=$(kubectl get ds -n "$ns" --no-headers 2>/dev/null | wc -l || echo 0)
jobs=$(kubectl get job -n "$ns" --no-headers 2>/dev/null | wc -l || echo 0)
cjobs=$(kubectl get cronjob -n "$ns" --no-headers 2>/dev/null | wc -l || echo 0)
printf "%-25s pods=%-4s deploys=%-4s sts=%-4s ds=%-4s jobs=%-4s cjobs=%-4s\n" \
"$ns" "$pods" "$deploys" "$ssets" "$dsets" "$jobs" "$cjobs"
done
exit 0
'

echo
echo "=== [3/5] Workloads still running in the default namespace ==="
kubectl get all -n default

echo
echo "=== [4/5] Cluster-scoped workloads (no namespace boundary) ==="
echo "# Cluster-scoped controllers:"
kubectl get clusterrole,clusterrolebinding,crd,storageclass -A

echo
echo "=== [5/5] Heuristic: namespaces that may be mixing unrelated workloads ==="
echo "# This highlights namespaces with many different apps (based on labels)."
echo "# Review namespaces with many distinct app labels for possible overloading."
kubectl get pods -A -o json \
| jq -r '
.items[]
| {
ns: .metadata.namespace,
app: (
.metadata.labels.app
// .metadata.labels."app.kubernetes.io/name"
// "UNLABELED"
)
}
| "\(.ns) \(.app)"
' 2>/dev/null | sort | uniq -c | sort -k2,2 -k1,1nr

echo
echo "=== Interpretation guidance ==="
cat <<'EOF'
Use this output to manually decide if you are creating appropriate administrative
boundaries with namespaces:

- Potential problems include:
- Most or all application workloads running in the 'default' namespace.
- A single namespace containing many unrelated applications/teams
(look at the heuristic app-label listing).
- Lack of clear separation between environments (e.g., dev/test/prod all in
one namespace).
- Sensitive or privileged workloads sharing namespaces with general workloads.

This script does NOT change the cluster; it only reports current state for review.
Creating or refactoring namespaces and moving workloads must be planned and
performed manually (updating manifests, Helm values, or other IaC).
EOF