skip to content

Tenancy & Quotas

What a namespace actually scopes, what it silently shares, and how quota and default-limit objects cap what one tenant consumes. Interviewers probe it because a namespace looks like a wall and is not one.

part ofKubernetesoverview, primer and where to startread it →
on this pageshow

explore

questions

18

In Kubernetes, when and how does a namespace's LimitRange apply its default and defaultRequest values, and what happens to Pods that already exist?

level: juniorimportance: must knowfreq 62%

answer

  1. admission time, not runtime
  2. LimitRanger plugin in kube-apiserver
  3. fills only empty keys
  4. kubernetes.io/limit-ranger annotation
  5. running Pods keep old values

basics

~10 s

The LimitRanger admission plugin in kube-apiserver copies defaultRequest and default into any container missing a request or limit at Pod creation, then rejects Pods outside min and max. Running Pods are never changed.

solid answer

~40 s

A LimitRange acts only at admission. When a Pod is created, kube-apiserver's built-in `LimitRanger` plugin looks at every LimitRange in the namespace. For each container and init container, it fills in `defaultRequest` as the request and `default` as the limit, but only for resources the container left empty. Then it rejects the Pod with `403 Forbidden` if anything breaks `min`, `max` or `maxLimitRequestRatio`. The stamped values are saved in the Pod spec, and the `kubernetes.io/limit-ranger` annotation says what was set. Nothing is enforced at runtime, and it is not retroactive: Pods that already exist keep their old values. Pod templates in Deployments are never changed. Only Pods created later, including replacements after an eviction, get the new defaults and bounds.

code

yaml · 22 lines
yaml
apiVersion: v1
kind: LimitRange
metadata:
  name: container-defaults
  namespace: telemetry-ingest
spec:
  limits:
  - type: Container
    defaultRequest:
      cpu: 120m
      memory: 384Mi
    default:
      cpu: 300m
      memory: 512Mi
    min:
      cpu: 50m
      memory: 64Mi
    max:
      cpu: 1500m
      memory: 768Mi
    maxLimitRequestRatio:
      cpu: "4"

go deeper

for a junior

Remember that a LimitRange acts only when a Pod is created. It fills in missing requests and limits, rejects values outside min and max, and never touches Pods that are already running.

for a middle

Explain the two admission phases: LimitRanger fills gaps key by key during mutation, then checks bounds on the final Pod during validation. Show the kubernetes.io/limit-ranger annotation as proof of what was injected.

for a senior

Point out that it is not retroactive. A new bound silently puts running Pods out of policy, and they get refused on their next recreation, which is exactly what a drain or rollout causes.

for a principal

Frame it as a platform contract. Defaults let teams skip boilerplate, but the injected values become the scheduler's view of every undeclared workload, so choosing them is a capacity decision, not a formality.

## What a LimitRange is A **LimitRange** is a namespaced object in the core `v1` API group (its `kubectl` short name is `limits`). It holds a list of items under `spec.limits`, and each item has a `type` of `Container`, `Pod` or `PersistentVolumeClaim`. A `Container` item can carry five resource maps: - `defaultRequest` — the request written into a container that declares none for that resource. - `default` — the limit written into a container that declares none for that resource. - `min` and `max` — the smallest and largest value a container may declare. - `maxLimitRequestRatio` — the largest allowed limit divided by request. A LimitRange does nothing at runtime. Nothing reads it while the container runs, the kubelet never looks at it, and it throttles nothing. Its whole effect happens when an object is written to the API server. ## When the defaults are applied The work is done by **LimitRanger**, a built-in admission plugin inside kube-apiserver that is enabled by default. It acts in both admission phases: 1. A client (you, or the ReplicaSet controller acting for a Deployment) sends a create request for a Pod. 2. The API server decodes the Pod and applies ordinary Pod defaulting. One rule matters here: if a container sets a limit but no request for a resource, the request is set equal to the limit. 3. In the **mutating** phase, LimitRanger lists every LimitRange in the Pod's namespace and, for each container and init container, fills in `defaultRequest` and `default` values **only for keys the container left empty**. It never overwrites a value the container declared. 4. The API server validates the Pod. For example, a request larger than its limit is rejected at this step. 5. In the **validating** phase, LimitRanger checks the final Pod against every LimitRange's `min`, `max` and `maxLimitRequestRatio`, and rejects it with `403 Forbidden` if any bound fails. 6. The Pod is stored. It now carries the stamped values in its spec, as if the author had written them. When LimitRanger filled something in, it records that in the `kubernetes.io/limit-ranger` annotation, for example `LimitRanger plugin set: cpu, memory request for container gateway; cpu, memory limit for container gateway`. ## What happens to Pods that already exist LimitRanger ignores ordinary Pod updates, because a Pod's container list and resources cannot be changed through them, so there is nothing to re-default. As a result: | Situation | Effect of a new or edited LimitRange | |---|---| | Pod already running | Untouched: keeps its old requests and limits, even if they now break `max` | | Pod created afterwards | Gets the current defaults and must pass the current bounds | | Deployment / StatefulSet pod template | Never changed: LimitRanger only defaults Pods | | Deleted Pod replaced by its controller | Treated as a new Pod: new defaults and new bounds apply | | In-place resize via the Pod `resize` subresource | Checked against the current bounds | So a LimitRange is **not retroactive**. A platform team that adds one should expect old Pods to drift from policy until they are recreated by a rollout, an eviction or a node drain. At that point a Pod that used to be admitted can be refused. ## What gets defaulted and what does not - Only **Pods** are defaulted: their `containers` and `initContainers`. - A `PersistentVolumeClaim` item is only **checked** (`min`/`max` on the requested storage). No default size is ever injected, because a claim must state its size anyway. - A `Pod` item cannot carry `default` or `defaultRequest` at all. Validation rejects them, because a pod-wide total cannot be split among containers. - A controller's pod template is never touched, so the template still shows no resources while its Pods do. The defaults also change the Pod's scheduling request and its QoS class. How those work belongs with requests and limits, not with this object. ## Seeing it in practice ```yaml apiVersion: v1 kind: LimitRange metadata: name: container-defaults namespace: telemetry-ingest spec: limits: - type: Container defaultRequest: cpu: 120m memory: 384Mi default: cpu: 300m memory: 512Mi ``` A telemetry ingest gateway container created in `telemetry-ingest` with no `resources` block is stored with requests `120m`/`384Mi` and limits `300m`/`512Mi`. `kubectl describe namespace telemetry-ingest` and `kubectl describe limitrange container-defaults` show the table of values. `kubectl get pod <name> -o yaml` shows the stamped resources and the annotation. The Deployment's own YAML still shows no resources. ## Why platforms use it A LimitRange is how a platform makes sure resources are declared without relying on every team to remember. Containers that declare nothing still get a request the scheduler can plan around. Containers that ask for too much are refused at the door instead of being found later. It is also commonly paired with a quota that tracks CPU or memory. That quota refuses Pods that do not declare those resources, and the LimitRange defaults fill them in first.

  • A Kubernetes Deployment's pod template has no resources block, yet its Pods show requests and limits. Why does the Deployment not show them?
    LimitRanger only defaults Pod objects. The ReplicaSet controller creates each Pod from the unchanged template, and every Pod gets the defaults at its own admission. The template never records them. If the LimitRange changes later, new Pods get the new values while the template still shows nothing, so the template alone does not tell you what the Pods will actually run with.
  • Why is a Kubernetes LimitRange commonly paired with a ResourceQuota that tracks requests.cpu or limits.memory?
    Once a quota tracks a compute resource, Pods that do not declare that resource are refused. LimitRange defaults are written in the mutating admission phase, before the quota check, so a container that declared nothing still arrives with values and is admitted and counted. Without the LimitRange, every team would have to declare resources by hand or its Pods would fail.
  • Is a Kubernetes in-place Pod resize checked against the namespace's LimitRange?
    Yes. Ordinary Pod updates are skipped because container resources cannot change through them. A resize goes through the Pod's `resize` subresource, and LimitRanger does handle that path, so the new values must still pass the current `min`, `max` and `maxLimitRequestRatio`. A resize cannot be used to get around a namespace's bounds.

It is like a form clerk who writes in a standard value on every blank line and refuses forms that ask for too much. Forms filed before the new rules were posted stay in the cabinet unchanged.

saying these in an interview costs you the question

  • A LimitRange throttles or kills containers that use more than its max.
  • Creating a LimitRange updates the resources of Pods already running.
  • The kubelet reads the LimitRange when it starts each container.
  • LimitRange defaults are written back into the Deployment's pod template.
  • A LimitRange default replaces the values a container already declared.
  • A LimitRange caps the total CPU the whole namespace can consume.
open as a page

What does a Kubernetes namespace actually scope, and which resources, such as Nodes, PersistentVolumes and CRDs, sit outside every namespace?

level: juniorimportance: must knowfreq 72%

basics

~10 s

A Kubernetes namespace scopes object names and most workload objects: Pods, Services, Secrets, ConfigMaps, PVCs. Nodes, PersistentVolumes, StorageClasses, ClusterRoles, CRDs and Namespaces themselves are cluster-scoped. Run kubectl api-resources --namespaced=false to list them.

open as a page

What is a Kubernetes ResourceQuota, and which kinds of consumption can its spec.hard field cap for one namespace?

level: juniorimportance: must knowfreq 64%

basics

~20 s

A ResourceQuota is a namespaced object whose spec.hard caps the namespace's total CPU and memory requests and limits, storage requests and object counts. The API server rejects any create that would push usage past a cap.

open as a page

A Kubernetes namespace has been stuck in Terminating for 19 minutes; how do you find what is blocking the namespace controller's purge, and fix it?

level: middleimportance: must knowfreq 72%

basics

~20 s

Read the namespace's status.conditions. They usually point to objects held by finalizers whose controller is gone, or to an unavailable aggregated API that makes discovery fail. Restore that controller or API, or remove the stale finalizer or APIService.

open as a page

In Kubernetes, what is the difference between soft and hard multi-tenancy, and what do tenants still share when each gets only a namespace?

level: middleimportance: must knowfreq 68%

basics

~20 s

Soft multi-tenancy gives each trusted team a namespace fenced by RBAC, quota and network policy. Hard multi-tenancy assumes hostile tenants and separates clusters or nodes, because namespaces still share the kernel, nodes, control plane and cluster-scoped objects.

open as a page

Can a Kubernetes Pod use a Secret or PersistentVolumeClaim from another namespace, and how does it reach a Service in another namespace?

level: middleimportance: must knowfreq 62%

basics

~20 s

No. A Kubernetes Pod can only reference Secrets, ConfigMaps, PVCs and ServiceAccounts in its own namespace, because those fields hold a bare name. Services are different: any pod can reach one in another namespace by <svc>.<ns>.svc.cluster.local unless NetworkPolicy blocks it.

open as a page

After a ResourceQuota is added to its Kubernetes namespace, a feature-flag evaluation service's Deployment rollout stalls with no new pods, although kubectl apply succeeded. How do you diagnose and fix it?

level: seniorimportance: must knowfreq 52%

basics

~20 s

Quota rejects pods when the ReplicaSet controller creates them, so the error appears as FailedCreate events on the ReplicaSet, not at apply time. It is usually 'must specify' (containers lack requests or limits) or 'exceeded quota' (no headroom for surge pods).

open as a page

In Kubernetes, what happens when you run kubectl delete namespace, and why does the namespace show Terminating before it disappears?

level: juniorimportance: should knowfreq 58%

basics

~10 s

Deleting a Kubernetes namespace only marks it Terminating. The namespace controller deletes every object inside, pods first, then removes the kubernetes finalizer, and only then does the API server remove the namespace.

open as a page

What are the Kubernetes built-in namespaces default, kube-system, kube-public and kube-node-lease for, and which namespace does kubectl use without -n?

level: juniorimportance: should knowfreq 50%

basics

~10 s

Kubernetes creates default for objects with no namespace, kube-system for control-plane and add-on components, kube-public for world-readable data, and kube-node-lease for node heartbeat Leases. Without -n, kubectl uses the kubeconfig context's namespace, else default.

open as a page

How does a Kubernetes LimitRange merge its defaults and min, max and maxLimitRequestRatio bounds into a partially specified container, and what gets the Pod rejected?

level: middleimportance: should knowfreq 44%

basics

~20 s

Defaults fill only the request or limit keys a container left empty. A limit with no request becomes the request first. The Pod is rejected if a request exceeds its injected limit or any value breaks min, max or the ratio.

open as a page

When onboarding a team into a shared Kubernetes cluster as a namespace tenant, which objects make up the tenant bundle and what does each isolate?

level: middleimportance: should knowfreq 55%

basics

~10 s

A tenant namespace needs RBAC bindings (who can act), a ResourceQuota (how much in total), a LimitRange (per-container defaults), a default-deny NetworkPolicy (who can connect) and Pod Security Admission labels (what pods may do).

open as a page

A common fix for a Kubernetes namespace stuck in Terminating is emptying spec.finalizers through the /finalize subresource; what does that actually do, and when is it acceptable?

level: seniorimportance: should knowfreq 44%

basics

~20 s

Emptying a namespace's spec.finalizers through /finalize tells the API server the purge is done, so it deletes the namespace. Remaining objects stay in etcd and their finalizers never run. Use it only after diagnosing the cause and accepting the leftovers.

open as a page

After a new Kubernetes LimitRange lands mid-upgrade on a 48-node cluster, an IoT ingest gateway Deployment keeps losing replicas with no failing Pods visible. How do you diagnose it and roll such a LimitRange out safely?

level: seniorimportance: should knowfreq 36%

basics

~10 s

Drained Pods are being replaced by Pods that LimitRanger refuses at admission, so they never exist. Read FailedCreate events on the ReplicaSet, fix the bound or the workload, and check existing workloads before enforcing.

open as a page

A tenant's PDF-invoice renderer parses untrusted uploads in a shared 80-node Kubernetes cluster. What does moving it to a dedicated tainted node pool isolate, and what does it still share?

level: seniorimportance: should knowfreq 40%

basics

~20 s

A dedicated node pool removes kernel, kubelet and node-resource sharing with other tenants, so an escape reaches only that tenant's pods and Secrets. The API server, etcd, cluster-scoped objects, cluster DNS and platform DaemonSets stay shared.

open as a page

On a single-node Kubernetes dev cluster you clone a clinical-records portal from namespace records-dev into records-review, and the copy misbehaves; which namespace-scoping mistakes do you check, and how do you fix them?

level: seniorimportance: should knowfreq 38%

basics

~20 s

Check for manifests that hard-code metadata.namespace, cluster-scoped objects shared by both copies, a PersistentVolume already bound to the old claim, Secrets that exist only in records-dev, and fully qualified Service names still pointing at records-dev.

open as a page

As a Kubernetes platform owner, how do you decide between namespace-per-tenant in a shared cluster and a cluster per tenant, and how would you defend that choice?

level: principalimportance: should knowfreq 38%

basics

~20 s

Choose by trust and by what tenants need to control. Trusted teams that need only namespaced objects fit namespace-per-tenant. Hostile code, compliance walls, or tenants needing their own CRDs, webhooks or cluster-admin justify separate clusters, at the cost of fleet operations and unpooled capacity.

open as a page

You own ResourceQuota policy for tenant namespaces on a 16-node regulated-workload Kubernetes cluster whose etcd database has grown to 4.2 GB. How do you design the quotas, and what do they deliberately not protect?

level: principalimportance: should knowfreq 38%

basics

~20 s

Give every tenant namespace a standard quota set: compute caps sized against allocatable, per-class storage, object counts that protect etcd, and scoped priority budgets. Quotas cap namespace totals only, not runtime usage, object size, API traffic or cluster-scoped objects.

open as a page

How do a Kubernetes ResourceQuota's scopes and scopeSelector fields narrow which pods it counts, and what do the Terminating and BestEffort scopes match?

level: middleimportance: nice to knowfreq 29%

basics

~20 s

Scopes make a ResourceQuota count only matching pods: Terminating means spec.activeDeadlineSeconds is set, BestEffort means no CPU or memory requests or limits, and PriorityClass matches priorityClassName. A pod must match every listed scope and selector.

open as a page