Namespace resource policy in Kubernetes keeps CPU and memory expectations close to the workloads that enter the namespace. A LimitRange supplies default requests and limits for Pods that omit them, and it rejects objects that sit outside the allowed bounds.

LimitRange admission runs when an object is created or updated in the namespace. Defaults are injected before constraint checks, so a Pod with no resource block can receive policy values, while a Pod with limits above the maximum is refused by the API server.

Apply the policy before tenant workloads are created, because existing Pods are not rewritten just because a namespace policy changes. Choose CPU and memory values from workload measurements and platform policy, then use a server-side dry run to test the rejection path before handoff.

Steps to configure a Kubernetes LimitRange:

  1. Create the namespace that will receive the policy.
    $ kubectl create namespace team-a
    namespace/team-a created

    Use an existing namespace when the tenant namespace already exists. A LimitRange affects new and updated API objects in that namespace, not Pods that were already admitted.

  2. Save the container LimitRange manifest.
    team-a-limits.yaml
    apiVersion: v1
    kind: LimitRange
    metadata:
      name: team-a-container-defaults
    spec:
      limits:
      - type: Container
        default:
          cpu: 500m
          memory: 256Mi
        defaultRequest:
          cpu: 100m
          memory: 128Mi
        min:
          cpu: 50m
          memory: 64Mi
        max:
          cpu: "1"
          memory: 512Mi

    defaultRequest values become missing container requests, and default values become missing container limits. min and max values bound accepted container resource settings.

  3. Apply the LimitRange to the namespace.
    $ kubectl apply -f team-a-limits.yaml --namespace team-a
    limitrange/team-a-container-defaults created
  4. Inspect the saved LimitRange policy.
    $ kubectl describe limitrange team-a-container-defaults --namespace team-a
    Name:       team-a-container-defaults
    Namespace:  team-a
    Type        Resource  Min   Max    Default Request  Default Limit  Max Limit/Request Ratio
    ----        --------  ---   ---    ---------------  -------------  -----------------------
    Container   cpu       50m   1      100m             500m           -
    Container   memory    64Mi  512Mi  128Mi            256Mi          -
  5. Create a Pod without explicit resource requests or limits.
    $ kubectl run defaulted --image=nginx --restart=Never --namespace team-a
    pod/defaulted created

    The Pod does not need to reach Running for this admission check. The API server stores the resource fields before the kubelet pulls the image.

  6. Check the admitted Pod resources.
    $ kubectl get pod defaulted -n team-a --output=jsonpath='{.spec.containers[0].resources}'
    {"limits":{"cpu":"500m","memory":"256Mi"},"requests":{"cpu":"100m","memory":"128Mi"}}

    The output shows the default request and limit values injected into the container specification.

  7. Save a Pod manifest that exceeds the CPU maximum.
    too-large-pod.yaml
    apiVersion: v1
    kind: Pod
    metadata:
      name: too-large
    spec:
      containers:
      - name: too-large
        image: nginx
        resources:
          requests:
            cpu: 100m
            memory: 128Mi
          limits:
            cpu: "2"
            memory: 256Mi
  8. Run a server-side dry run for the over-limit Pod.
    $ kubectl apply --dry-run=server -f too-large-pod.yaml --namespace team-a
    Error from server (Forbidden): error when creating "too-large-pod.yaml": pods "too-large" is forbidden: maximum cpu usage per Container is 1, but limit is 2

    --dry-run=server sends the object through API validation and admission without saving it.

  9. Remove the temporary verification Pod.
    $ kubectl delete pod defaulted --namespace team-a --ignore-not-found
    pod "defaulted" deleted from team-a namespace
  10. Delete the over-limit test manifest if it was created only for verification.
    $ rm too-large-pod.yaml

    Keep team-a-limits.yaml in source control or the platform configuration repo so the namespace policy can be reviewed and reapplied.