Kubernetes is a powerful container orchestration platform that allows you to manage and scale containerized applications. When managing workloads in a Kubernetes cluster, it’s important to control resource usage to ensure fair sharing of resources, prevent any single workload from over-consuming cluster resources, and ensure that your applications run reliably.
Two key concepts in Kubernetes help with resource management: Resource Quotas and Limit Ranges. These are applied within a Namespace, which is a way to organize and isolate resources within a cluster. In this blog, we will explain these concepts in simple terms and show you how to configure them using Kubernetes manifests.
What is a Namespace in Kubernetes?
A Namespace in Kubernetes is a way to partition cluster resources into logically named groups. It provides a mechanism for isolating resources (like pods, services, deployments, etc.) so that they don’t interfere with each other. Namespaces help you manage resources for different teams, projects, or environments (e.g., dev
, staging
, prod
) within the same Kubernetes cluster.
For example, a namespace could be created for each department in an organization:
dev
staging
production
By grouping resources under namespaces, it becomes easier to manage permissions, policies, and quotas.
What is a Resource Quota?
A ResourceQuota in Kubernetes is a policy that limits the amount of resources (such as CPU, memory, number of pods, etc.) that can be consumed within a specific namespace. It helps prevent a single user or application from consuming all the resources in the cluster, thus ensuring fair resource allocation.
Key Properties of a ResourceQuota:
- CPU: Limits the total CPU usage within a namespace.
- Memory: Limits the total memory usage within a namespace.
- Pods: Limits the number of Pods that can be created in a namespace.
- Services, Deployments, etc.: Limits the number of specific types of resources that can be created.
Example: Resource Quota Manifest
Let’s say we want to limit a namespace (dev-namespace
) so that it can use at most 4 CPUs, 16Gi of memory, and can create a maximum of 10 Pods. Below is an example ResourceQuota
manifest for this use case:
apiVersion: v1
kind: ResourceQuota
metadata:
name: dev-namespace-quota
namespace: dev-namespace
spec:
hard:
requests.cpu: "4"
requests.memory: 16Gi
limits.cpu: "4"
limits.memory: 16Gi
pods: "10"
In this example:
- The
requests.cpu
andlimits.cpu
specify the maximum CPU the namespace can request or use. - The
requests.memory
andlimits.memory
specify the maximum amount of memory the namespace can request or use. - The
pods
field limits the number of Pods that can be created in thedev-namespace
.
If the resources exceed the defined limits, Kubernetes will prevent new resources from being created until resources within the namespace are freed up.
What is a LimitRange?
A LimitRange is a policy that defines the minimum and maximum resource limits for individual containers running within a namespace. Unlike ResourceQuota, which applies to the entire namespace, a LimitRange applies to individual containers within that namespace. This ensures that each container is constrained to using a defined range of resources.
Key Properties of a LimitRange:
- Limit: Defines the maximum amount of resources that a container can request or use.
- Request: Defines the minimum amount of resources that a container should request when it starts.
- Default: Defines the default resource requests and limits for containers that don’t specify them explicitly.
Example: LimitRange Manifest
Let’s say we want to define a LimitRange
in the dev-namespace
to ensure each container can have a minimum of 128Mi of memory and 100m (0.1) CPUs, and a maximum of 1Gi of memory and 1 CPU. We also want to set default values if the user doesn’t specify them.
apiVersion: v1
kind: LimitRange
metadata:
name: dev-namespace-limits
namespace: dev-namespace
spec:
limits:
- type: Container
max:
memory: 1Gi
cpu: "1"
min:
memory: 128Mi
cpu: "100m"
default:
memory: 512Mi
cpu: "500m"
defaultRequest:
memory: 256Mi
cpu: "200m"
In this example:
- The
max
field specifies the maximum resources a container can request. - The
min
field sets the minimum resources a container can request. - The
default
field sets default resource requests for containers that don’t specify them explicitly. - The
defaultRequest
field specifies the default resource requests for containers.
If a container is created without explicitly defining resource limits or requests, Kubernetes will automatically apply the defaults defined in the LimitRange
.
How ResourceQuota and LimitRange Work Together
ResourceQuotas and LimitRanges complement each other:
- ResourceQuota limits the total usage of resources within a namespace.
- LimitRange defines the constraints for individual containers within that namespace.
For example:
- A ResourceQuota can prevent a namespace from consuming too many resources overall (e.g., 4 CPUs and 16Gi of memory).
- A LimitRange can enforce individual container-level limits (e.g., containers in the namespace can only use up to 1Gi of memory).
Together, they ensure that resources are used efficiently, and prevent users or applications from over-consuming resources in a shared cluster environment.
Practical Use Cases
- Preventing Resource Overuse: If you have multiple teams or applications running in the same cluster, you can use ResourceQuota to make sure no team can consume all available resources.
- Consistent Resource Allocation: Using LimitRange, you can ensure that each team’s containers have a reasonable amount of resources, avoiding cases where containers are too resource-hungry and causing performance degradation for others.
- Automatic Defaults: By setting defaults in the LimitRange, you can ensure that all containers have consistent resource requests and limits, even if users forget to specify them.
Conclusion
In Kubernetes, Resource Quotas and Limit Ranges are powerful tools for managing resource usage and ensuring that applications run efficiently and fairly within a namespace. By setting resource limits at both the namespace and container levels, you can prevent one application from consuming too many resources, while also ensuring that containers have the resources they need to run smoothly.