Skip to main content

Kubernetes Ep 12: Namespaces, Resource Quotas & LimitRanges

Rachmat Hidayat
Author
Rachmat Hidayat
Learn & sharing insights on TypeScript, Go, Kubernetes, DevOps, DevSecOps, SRE, Platform Engineering, AI/ML Engineering, and MLOps.
kubernetes - This article is part of a series.
Part 12: This Article
In enterprise environments, a single Kubernetes cluster is shared across multiple development teams, environments (dev, staging, prod), and microservices. Without resource governance, a single misbehaving application can consume all cluster CPU and memory, crashing critical workloads.

TL;DR (Quick Summary)
#

  • Namespace: Virtual cluster isolation dividing physical cluster resources logically.
  • Requests vs Limits:
    • Requests: Guaranteed CPU/Memory reserved for the Pod during scheduling (kube-scheduler).
    • Limits: Maximum CPU/Memory cap the container is allowed to consume. CPU exceeding limit is throttled; Memory exceeding limit triggers OOMKilled (Exit Code 137).
  • ResourceQuota: Cap total aggregate CPU, RAM, and Pod counts per Namespace.
  • LimitRange: Enforce default requests/limits for Pods created without explicit specs.

1. Multi-Tenancy Governance Architecture
#


graph TD
    subgraph Cluster["Kubernetes Physical Cluster (64 Core CPU, 256GB RAM)"]
        subgraph NS1["Namespace: payments-prod"]
            RQ1["ResourceQuota: max 16 CPU, 64GB RAM"]
            P1["Pod A (Req: 2 CPU, Lim: 4 CPU)"]
            P2["Pod B (Req: 4 CPU, Lim: 8 CPU)"]
        end

        subgraph NS2["Namespace: marketing-dev"]
            RQ2["ResourceQuota: max 4 CPU, 16GB RAM"]
            P3["Pod C (Req: 500m CPU, Lim: 1 CPU)"]
        end
    end

2. Resource Requests, Limits & Quality of Service (QoS)
#

Every container specification should define requests and limits:

resources:
  requests:
    cpu: "250m"      # 0.25 CPU Core
    memory: "256Mi"   # 256 Megabytes RAM
  limits:
    cpu: "500m"      # 0.50 CPU Core
    memory: "512Mi"   # 512 Megabytes RAM

Kubernetes Quality of Service (QoS) Classes
#

  1. Guaranteed: Every container in the Pod has requests == limits for both CPU and RAM. (Highest eviction priority protection).
  2. Burstable: Pod has requests specified, but limits > requests.
  3. BestEffort: Pod has NO requests or limits specified. First to be killed when host runs low on RAM!

3. Creating a Namespace with ResourceQuota
#

Create namespace-quota.yaml:

apiVersion: v1
kind: Namespace
metadata:
  name: team-payments
  labels:
    environment: production
---
apiVersion: v1
kind: ResourceQuota
metadata:
  name: payments-quota
  namespace: team-payments
spec:
  hard:
    requests.cpu: "4"
    requests.memory: 8Gi
    limits.cpu: "8"
    limits.memory: 16Gi
    pods: "10"
    services.loadbalancers: "2"

Apply manifest:

kubectl apply -f namespace-quota.yaml
kubectl get resourcequota -n team-payments

Expected Terminal Output:

NAME             AGE   REQUESTS                                    LIMITS
payments-quota   15s   requests.cpu: 0/4, requests.memory: 0/8Gi   limits.cpu: 0/8, limits.memory: 0/16Gi

4. Enforcing Defaults via LimitRange
#

If a user tries to deploy a Pod without specifying resources in a namespace governed by a ResourceQuota, the API server rejects the request. A LimitRange solves this by injecting default requests and limits automatically.

Create limitrange.yaml:

apiVersion: v1
kind: LimitRange
metadata:
  name: default-limits
  namespace: team-payments
spec:
  limits:
  - default: # Default limits
      cpu: "500m"
      memory: "512Mi"
    defaultRequest: # Default requests
      cpu: "200m"
      memory: "256Mi"
    max: # Maximum allowed limit per container
      cpu: "2"
      memory: "4Gi"
    min: # Minimum allowed request per container
      cpu: "50m"
      memory: "64Mi"
    type: Container

Apply manifest:

kubectl apply -f limitrange.yaml

5. Troubleshooting OOMKilled (Exit Code 137)
#

If an application attempts to allocate more RAM than its defined limits.memory, the Linux kernel OOM Killer immediately terminates the process with Exit Code 137.

Diagnose OOMKilled Pods:

kubectl get pod -n team-payments -o jsonpath='{range .items[*]}{.metadata.name}{"\t"}{.status.containerStatuses[*].state.terminated.reason}{"\t"}{.status.containerStatuses[*].state.terminated.exitCode}{"\n"}{end}'
payment-api-7d4f9b-2x9lq   OOMKilled   137
Tip

To fix OOMKilled, inspect real-time metrics using kubectl top pod -n team-payments and increase limits.memory in your manifest!


6. Summary & Next Steps
#

Namespaces, ResourceQuotas, and LimitRanges establish clean resource boundaries across teams and namespaces.

In Episode 13: RBAC, ServiceAccounts & Security, we will tackle security governance, learning how to configure Role-Based Access Control (RBAC), Roles, ClusterRoles, and ServiceAccounts to secure cluster access!

kubernetes - This article is part of a series.
Part 12: This Article