Microsoft Defender for Cloud · Azure Kubernetes Service
Container CPU and memory limits should be enforced
Written and reviewed by Emnode · Last reviewed
What does the recommendation "Container CPU and memory limits should be enforced" check?
Flags AKS clusters running containers that do not declare both a CPU limit and a memory limit in their pod spec, meaning 'resources.limits.cpu' and 'resources.limits.memory' are set on every container. Evaluation depends on the Azure Policy add-on (Gatekeeper) being installed: it inspects live and admitted pods through the constraint, not the cluster's RBAC, image provenance or network policy. It does not check 'requests' values, namespace ResourceQuotas, LimitRange defaults, or whether the limits you set are sensibly sized. A pod that sets a huge limit still passes, because the control only confirms a limit exists, not that it is right.
Why does "Container CPU and memory limits should be enforced" matter?
A container with no memory limit can consume every spare byte on its node. When the kernel's OOM killer steps in it evicts neighbouring pods, so one leaking workload takes down unrelated services sharing that node and the failure spreads as the scheduler reschedules onto the next victim. An unbounded CPU consumer starves the same neighbours of cycles. This is the classic noisy-neighbour and resource-exhaustion failure mode, and on a shared production cluster it turns a single buggy or hostile deployment into a multi-tenant outage. Enforcing limits caps the blast radius and makes capacity planning and cost attribution honest.
How do I fix "Container CPU and memory limits should be enforced"?
- Install the Azure Policy add-on so Gatekeeper can evaluate and enforce the constraint: 'az aks enable-addons --addons azure-policy --resource-group <rg> --name <cluster>'. Without the add-on the recommendation cannot assess the cluster.
- Set explicit limits on every container, for example 'resources.limits.cpu: 410m' and 'resources.limits.memory: 512Mi' in the pod spec, then re-evaluate. You can confirm current state with 'kubectl describe k8sazurecontainerlimits' and trigger an on-demand compliance scan rather than waiting for the next cycle.
- Assign the built-in policy 'Kubernetes cluster containers CPU and memory resource limits should not exceed the specified limits' in Deny mode so unbounded pods are rejected at admission. Look the definition up by name rather than pasting a GUID: pid=$(az policy definition list --query "[?displayName=='Kubernetes cluster containers CPU and memory resource limits should not exceed the specified limits'].name" -o tsv); az policy assignment create --name aks-container-limits --policy "$pid" --scope <cluster-scope>.
Remediation script · bash
# 1. Turn on the Azure Policy add-on so Gatekeeper starts auditing the cluster.
az provider register --namespace Microsoft.PolicyInsights
az aks enable-addons --addons azure-policy \
--resource-group rg-prod --name aks-prod
# Confirm the policy and gatekeeper pods are running.
kubectl get pods -n kube-system -l app=azure-policy
kubectl get pods -n gatekeeper-system
# 2. Assign the built-in pod security baseline initiative in AUDIT first.
# Look the initiative up by its exact display name, never paste a GUID.
SCOPE=$(az aks show -g rg-prod -n aks-prod --query id -o tsv)
SETID=$(az policy set-definition list \
--query "[?displayName=='Kubernetes cluster pod security baseline standards for Linux-based workloads'].name" -o tsv)
az policy assignment create \
--name aks-pod-baseline \
--policy-set-definition "$SETID" \
--scope "$SCOPE" \
--params '{"effect":{"value":"audit"},"excludedNamespaces":{"value":["kube-system","gatekeeper-system","azure-arc"]}}'
# 3. Fix the workloads (in each pod spec, securityContext):
# privileged: false | runAsNonRoot: true | runAsUser: 1000
# allowPrivilegeEscalation: false | readOnlyRootFilesystem: true
# capabilities: { drop: ["ALL"] } and add back only what is needed.
# 4. Once audit is clean except for named exceptions, ENFORCE.
az policy assignment update --name aks-pod-baseline \
--set parameters.effect.value=deny Full walkthrough (console steps, edge cases and verification) in the lesson Enforce AKS pod security.
Is "Container CPU and memory limits should be enforced" a false positive?
A dedicated single-tenant cluster running one trusted batch job that is deliberately allowed to use the whole node, for example a nightly data-processing run sized to the machine, may legitimately omit limits so the kernel scheduler hands it everything spare. Exempt that namespace through the policy's excludedNamespaces parameter rather than leaving limits off cluster-wide, so the safe default still applies everywhere else.
More Azure Kubernetes Service controls
- Azure Kubernetes Service clusters should have Defender profile enabled
- Azure Kubernetes Service clusters should have the Azure Policy add-on for Kubernetes installed
- Azure running container images should have vulnerabilities resolved (powered by Microsoft Defender Vulnerability Management)
- Container images should be deployed from trusted registries only
- Container with privilege escalation should be avoided
- Containers sharing sensitive host namespaces should be avoided
- Diagnostic logs in Kubernetes services should be enabled
- Immutable (read-only) root filesystem should be enforced for containers
- Kubernetes API server should be configured with restricted access
- Kubernetes clusters should be accessible only over HTTPS
- Kubernetes clusters should disable automounting API credentials
- Kubernetes clusters should not use the default namespace