Skip to main content

Schedule One Kubernetes Namespace Instead of the Cluster

Put a qa or dev namespace to sleep with kubectl while ingress, monitoring and shared services in the same cluster keep running.

A shared EKS, GKE or AKS cluster rarely goes idle as a whole. The ingress controller, the monitoring stack and the CI runners serve everyone, but the qa namespace is empty after 7 pm. Stopping that one namespace means scaling its workloads to zero and pausing its CronJobs, then putting everything back exactly as it was. Kubernetes has no namespace “stop” object, so this page builds one from kubectl scale and kubectl patch.

Before you start

  • kubectl access with update on deployments/scale, statefulsets/scale and cronjobs in the target namespace, plus get on horizontalpodautoscalers.
  • jq for saving and replaying replica counts.
  • A plan for the nodes. Emptying a namespace frees capacity but only saves money when a cluster autoscaler (or a scheduled pool resize) removes the nodes that capacity sat on.

1. Save the current replica counts

The restore needs the numbers you had, not a guess. Store them outside the cluster:

Terminal window
NS=qa
kubectl get deployments,statefulsets -n "$NS" -o json \
| jq -r '.items[] | "\(.kind|ascii_downcase) \(.metadata.name) \(.spec.replicas)"' > "$NS-replicas.txt"
cat "$NS-replicas.txt"

2. Scale workloads to zero

Terminal window
kubectl scale deployment --all --replicas=0 -n "$NS"
kubectl scale statefulset --all --replicas=0 -n "$NS"

StatefulSet Pods terminate but their PersistentVolumeClaims stay, so data on those volumes is still there on restore, and the volumes keep billing.

Autoscaled workloads. If a HorizontalPodAutoscaler targets one of these Deployments, setting the target’s replicas to 0 while the HPA’s minReplicas is above 0 puts the HPA into an implicit maintenance mode: it stops adjusting the target and sets its ScalingActive condition to false until you change the replica count again. You do not need to delete the HPA for the night.

3. Suspend the CronJobs

Terminal window
for cj in $(kubectl get cronjobs -n "$NS" -o name); do
kubectl patch "$cj" -n "$NS" -p '{"spec":{"suspend":true}}'
done

Suspending does not touch Jobs a CronJob already started; they run to completion. Runs that fall inside the suspended window count as missed. When you unsuspend a CronJob that has no startingDeadlineSeconds, the missed runs are scheduled immediately, so a nightly report CronJob can fire the moment you wake the namespace. Set a starting deadline on CronJobs where that matters.

4. Check the namespace is quiet

Terminal window
kubectl get pods -n "$NS"
kubectl get cronjobs -n "$NS" -o custom-columns=NAME:.metadata.name,SUSPEND:.spec.suspend
kubectl get hpa -n "$NS"

Expect no running Pods apart from any bare Pods you created by hand (scale does not touch them), true in the SUSPEND column, and HPAs reporting the target at 0.

5. Wake it up

Terminal window
while read -r kind name replicas; do
kubectl scale "$kind/$name" --replicas="$replicas" -n "$NS"
done < "$NS-replicas.txt"
for cj in $(kubectl get cronjobs -n "$NS" -o name); do
kubectl patch "$cj" -n "$NS" -p '{"spec":{"suspend":false}}'
done
kubectl rollout status deployment -n "$NS" --timeout=10m

Restoring the replica count also brings any HPA out of maintenance mode.

Namespaces to leave alone

Do not run this against kube-system, kube-public, kube-node-lease or namespaces holding CNI, CSI, ingress or service-mesh control planes. Treat default with care too: any Pod created there by hand has no controller, so no scale command will bring it back.

The ZopNight version

ZopNight has a namespace-level start and stop for EKS, GKE and AKS that does the same job from a schedule. Stop scales every Deployment and StatefulSet in the namespace to zero and suspends its CronJobs, saving the prior replica counts, HPA and PDB; Start restores them. It refuses system namespaces (kube-*, zopnight-*, istio-*, helm-* and default) before making any Kubernetes call. Schedules use cron expressions in an IANA timezone, and overrides can keep a namespace running for a set window. Details are on the namespace schedule page, and namespace-level scheduling covers when this beats emptying a node pool.

Stop watching the waste.
Start cutting it.

See. Find. Fix. Automatic.

Connect your first cloud account in under 5 minutes. See your first remediation in under 7. No credit card required.

CDCR connect detect classify remediate
full audit every action traceable
read-only default access
Multi-cloud automation· Production-ready in 30 min· SOC 2 · ISO 27001· 20–60% off the bill, first month· 4 platforms · 1 console· Multi-cloud automation· Production-ready in 30 min· SOC 2 · ISO 27001· 20–60% off the bill, first month· 4 platforms · 1 console·