Manage Pod Resources in Kubernetes
Managing Pod resources, such as CPU, memory, and storage, is critical for ensuring that your Redpanda cluster runs well in Kubernetes. In this guide, you’ll learn how to define and configure resource requests and limits using the Redpanda Helm chart and Redpanda CRD. Setting these values before deployment helps guarantee predictable scheduling, enforces the Guaranteed QoS classification, and minimizes the risk of performance issues such as resource contention or unexpected evictions.
Prerequisites
-
See Kubernetes Cluster Requirements and Recommendations for the minimum worker node, memory, CPU, and storage requirements.
-
Make sure that your physical or virtual machines have enough resources to give to Redpanda. To see the available resources on the worker nodes that you have provisioned:
kubectl describe nodes
Production considerations
-
Enable the
Guaranteedquality of service class for Pods that run Redpanda. This setup ensures that the CPU and memory allocated to Redpanda are not subject to throttling or other contention issues, providing a stable and predictable performance environment. -
Ensure you give each Redpanda broker at least 4 CPU cores. This configuration ensures that Redpanda has enough CPU resources to run efficiently.
-
Ensure you give Redpanda at least 2 Gi of memory per core. This configuration ensures that Redpanda has enough memory to run efficiently.
-
Ensure that the number of CPU cores you allocate to Redpanda is an even integer. This configuration allows Redpanda to leverage the static CPU manager policy, granting the Pod exclusive access to the requested cores for optimal performance.
Configure memory resources
When deploying Redpanda, you must reserve sufficient memory for both Redpanda and other system processes. Redpanda uses the Seastar framework to manage memory through two important flags. In Kubernetes, the values of these flags are usually set for you, depending on how you configure the Redpanda CRD or the Helm chart.
-
--memory: When set, explicitly defines the Redpanda heap size. -
--reserve-memory: When set, reserves a specific amount of memory for system overhead. If not set, a reserve is automatically calculated.
Learn more about these Seastar flags
|
|
|
|
Heap size = available memory - calculated reserve |
Heap size = exactly M (if M plus calculated reserve ≤ available memory). Otherwise, startup fails |
|
Heap size = available memory - R |
Heap size = exactly M (if M + R ≤ available memory). Otherwise, startup fails |
Definitions and behavior:
-
Available memory: The memory remaining after subtracting system requirements, such as
/proc/sys/vm/min_free_kbytes, from the total or cgroup-limited memory. -
Calculated reserve: The greater of 1.5 GiB or 7% of available memory used when
--reserve-memoryis not explicitly set.
These flags are set for you by default when using the Redpanda Helm chart or Operator. However, you can manually set these flags using the statefulset.additionalRedpandaCmdFlags configuration if needed.
Avoid manually setting the --memory and --reserve-memory flags unless absolutely necessary. Incorrect settings can lead to performance issues, instability, or data loss.
|
You don’t need to enable memory locking (the --lock-memory flag or resources.memory.enable_memory_locking) for production. When you tune the worker nodes with rpk redpanda tune, the swappiness tuner sets vm.swappiness to 1, which makes the operating system avoid swapping Redpanda’s memory to disk.
Legacy Behavior (Default) |
Production Recommendation |
||
|
Use These options ensure:
|
-
Operator
-
Helm
redpanda-cluster.yamlapiVersion: cluster.redpanda.com/v1alpha2
kind: Redpanda
metadata:
name: redpanda
spec:
chartRef: {}
clusterSpec:
resources:
requests:
cpu: <number-of-cpu-cores> (1)
memory: <number><unit> (2)
limits:
cpu: <number-of-cpu-cores>
memory: <number><unit> (3)
kubectl apply -f redpanda-cluster.yaml --namespace <namespace>
-
--values
-
--set
memory.yamlresources:
requests:
cpu: <number-of-cpu-cores> (1)
memory: <number><unit> (2)
limits:
cpu: <number-of-cpu-cores>
memory: <number><unit> (3)
helm upgrade --install redpanda redpanda/redpanda --namespace <namespace> --create-namespace \
--values memory.yaml --reuse-values
helm upgrade --install redpanda redpanda/redpanda --namespace <namespace> --create-namespace \
--reuse-values \
--set resources.requests.cpu=<number-of-cpu-cores> \ (1)
--set resources.requests.memory=<number><unit> \ (2)
--set resources.limits.cpu=<number-of-cpu-cores> \
--set resources.limits.memory=<number><unit> (3)
| 1 | Set the CPU request and limit to the same whole number of cores. When you set resources.requests and resources.limits, the chart ignores resources.cpu.cores and sets --smp from the CPU request. If you leave out CPU, the Redpanda container has no CPU request or limit, and Redpanda starts one shard for every core on the worker node. See Configure CPU resources. |
| 2 | Request at least 2.22 Gi of memory per core to ensure Redpanda has the 2 Gi per core it requires after accounting for the 90% allocation to the --memory flag.
Redpanda supports the following memory resource units: B, K, M, G, Ki, Mi, and Gi. Memory units are truncated to the nearest whole MiB. For example, a memory request of 1024 KiB will result in 1 MiB being allocated. For a description of memory resource units, see the Kubernetes documentation. |
| 3 | Set the CPU and memory limits to match the requests. This ensures Kubernetes enforces a strict upper bound on memory usage and helps maintain the Guaranteed QoS classification. |
When the StatefulSet is deployed, make sure that the memory request and limit are set:
kubectl --namespace=<namespace> get pod <pod-name> -o jsonpath='{.spec.containers[?(@.name=="redpanda")].resources}{"\n"}'
Configure CPU resources
Redpanda uses the Seastar framework to manage CPU usage through the --smp flag, which sets the number of CPU cores available to Redpanda. How the chart sets --smp depends on how you configure resources:
-
If you set
resources.requestsandresources.limits, as recommended in Configure memory resources, setcpuin both. The chart sets--smpto the CPU request rounded down to a whole number, with a minimum of 1, and ignoresresources.cpu.cores. -
Otherwise, the chart uses
resources.cpu.cores, which applies the same value to both the CPU request and the CPU limit.
| Default Configuration | Production Recommendation |
|---|---|
|
Set Set CPU cores to an even integer to leverage the static CPU manager policy, granting the Pod exclusive access to the requested cores for optimal performance. |
-
Operator
-
Helm
redpanda-cluster.yamlapiVersion: cluster.redpanda.com/v1alpha2
kind: Redpanda
metadata:
name: redpanda
spec:
chartRef: {}
clusterSpec:
resources:
requests:
cpu: <number-of-cpu-cores> (1)
memory: <redpanda-container-memory>
limits:
cpu: <number-of-cpu-cores>
memory: <redpanda-container-memory>
kubectl apply -f redpanda-cluster.yaml --namespace <namespace>
-
--values
-
--set
cpu-cores.yamlresources:
requests:
cpu: <number-of-cpu-cores> (1)
memory: <redpanda-container-memory>
limits:
cpu: <number-of-cpu-cores>
memory: <redpanda-container-memory>
helm upgrade --install redpanda redpanda/redpanda --namespace <namespace> --create-namespace \
--values cpu-cores.yaml --reuse-values
helm upgrade --install redpanda redpanda/redpanda --namespace <namespace> --create-namespace \
--reuse-values \
--set resources.requests.cpu=<number-of-cpu-cores> \ (1)
--set resources.requests.memory=<redpanda-container-memory> \
--set resources.limits.cpu=<number-of-cpu-cores> \
--set resources.limits.memory=<redpanda-container-memory>
| 1 | Set the CPU request and limit to the same whole number of cores for Redpanda. Matching CPU and memory requests and limits keep the Pod in the Guaranteed QoS classification by enforcing a strict upper bound on CPU usage. Because the chart reads CPU from resources.requests and resources.limits only when both are set, include the memory request and limit as well. |
When the StatefulSet is deployed, make sure that the CPU request and limit are set:
kubectl --namespace <namespace> get pod <pod-name> -o jsonpath='{.spec.containers[?(@.name=="redpanda")].resources}{"\n"}'
Quality of service and resource guarantees
To ensure that Redpanda receives stable and consistent resources, set the quality of service (QoS) class to Guaranteed by matching resource requests and limits on all containers in the Pods that run Redpanda.
Kubernetes uses QoS to decide which Pods to evict from a worker node that runs out of resources. When a worker node runs out of resources, Kubernetes evicts Pods with a Guaranteed QoS last. This stability is crucial for Redpanda because it requires consistent computational and memory resources to maintain high performance.
Kubernetes gives a Pod a Guaranteed QoS class when every container inside it has identical resource requests and limits set for both CPU and memory. This strict configuration signals to Kubernetes that these resources are critical and should not be throttled or reclaimed under normal operating conditions. To configure the Pods that run Redpanda with Guaranteed QoS, specify both resource requests and limits for all enabled containers in the Pods.
The following example sets matching requests and limits on the Redpanda container, the sidecar container, and the init containers that the chart adds by default:
-
Operator
-
Helm
redpanda-cluster.yamlapiVersion: cluster.redpanda.com/v1alpha2
kind: Redpanda
metadata:
name: redpanda
spec:
chartRef: {}
clusterSpec:
resources:
requests:
cpu: <number-of-cpu-cores>
memory: <redpanda-container-memory>
limits:
cpu: <number-of-cpu-cores> # Matches the request
memory: <redpanda-container-memory> # Matches the request
statefulset:
podTemplate:
spec:
containers:
- name: sidecar
resources:
requests:
cpu: <sidecar-container-cpu>
memory: <sidecar-container-memory>
limits:
cpu: <sidecar-container-cpu> # Matches the request
memory: <sidecar-container-memory> # Matches the request
initContainers:
- name: tuning
resources:
requests:
cpu: <tuning-container-cpu>
memory: <tuning-container-memory>
limits:
cpu: <tuning-container-cpu> # Matches the request
memory: <tuning-container-memory> # Matches the request
- name: redpanda-configurator
resources:
requests:
cpu: <configurator-container-cpu>
memory: <configurator-container-memory>
limits:
cpu: <configurator-container-cpu> # Matches the request
memory: <configurator-container-memory> # Matches the request
kubectl apply -f redpanda-cluster.yaml --namespace <namespace>
qos.yamlresources:
requests:
cpu: <number-of-cpu-cores>
memory: <redpanda-container-memory>
limits:
cpu: <number-of-cpu-cores> # Matches the request
memory: <redpanda-container-memory> # Matches the request
statefulset:
podTemplate:
spec:
containers:
- name: sidecar
resources:
requests:
cpu: <sidecar-container-cpu>
memory: <sidecar-container-memory>
limits:
cpu: <sidecar-container-cpu> # Matches the request
memory: <sidecar-container-memory> # Matches the request
initContainers:
- name: tuning
resources:
requests:
cpu: <tuning-container-cpu>
memory: <tuning-container-memory>
limits:
cpu: <tuning-container-cpu> # Matches the request
memory: <tuning-container-memory> # Matches the request
- name: redpanda-configurator
resources:
requests:
cpu: <configurator-container-cpu>
memory: <configurator-container-memory>
limits:
cpu: <configurator-container-cpu> # Matches the request
memory: <configurator-container-memory> # Matches the request
helm upgrade --install redpanda redpanda/redpanda --namespace <namespace> --create-namespace \
--values qos.yaml --reuse-values
Entries in statefulset.podTemplate.spec.containers and statefulset.podTemplate.spec.initContainers are merged into the containers that the chart renders, matched by name. List only containers that exist in your Pods. An entry with a name that the chart does not render becomes a new container with no image, and Kubernetes rejects the StatefulSet. The set of init containers depends on your configuration. For example, the chart adds a set-tiered-storage-cache-dir-ownership init container when Tiered Storage is enabled, and the bootstrap-yaml-envsubst init container sets matching requests and limits by default. To list the containers in a running Pod:
kubectl --namespace <namespace> get pod <pod-name> -o jsonpath='{.spec.containers[*].name}{"\n"}{.spec.initContainers[*].name}{"\n"}'
When the StatefulSet is deployed, make sure that the QoS for the Pods is set to Guaranteed:
kubectl --namespace=<namespace> get pod <pod-name> -o jsonpath='{ .status.qosClass}{"\n"}'
Configure storage capacity
Make sure to provision enough disk storage for your streaming workloads.
If you use PersistentVolumes, you can set the storage capacity for each volume. For instructions, see Configure Storage for the Redpanda data directory in Kubernetes.
Run Redpanda in shared environments
If Redpanda runs in a shared environment, where multiple applications run on the same worker node, you can make Redpanda less aggressive in CPU usage by enabling overprovisioning. This adjustment ensures a fairer distribution of CPU time among all processes, improving overall system efficiency at the cost of Redpanda’s performance.
You can enable overprovisioning by either setting the CPU request to a fractional value less than 1 or enabling the --overprovisioned flag.
You cannot enable overprovisioning using resources.cpu.overprovisioned when both resources.requests and resources.limits are set. When both of these configurations are set, the resources.cpu parameter (including cores) is ignored. Instead, use the statefulset.additionalRedpandaCmdFlags configuration to enable overprovisioning.
|
-
Operator
-
Helm
redpanda-cluster.yamlapiVersion: cluster.redpanda.com/v1alpha2
kind: Redpanda
metadata:
name: redpanda
spec:
chartRef: {}
clusterSpec:
statefulset:
additionalRedpandaCmdFlags:
- '--overprovisioned'
resources:
cpu:
cores: <number-of-cpu-cores>
kubectl apply -f redpanda-cluster.yaml --namespace <namespace>
-
--values
-
--set
cpu-cores-overprovisioned.yamlstatefulset:
additionalRedpandaCmdFlags:
- '--overprovisioned'
resources:
cpu:
cores: <number-of-cpu-cores>
helm upgrade --install redpanda redpanda/redpanda --namespace <namespace> --create-namespace \
--values cpu-cores-overprovisioned.yaml --reuse-values
helm upgrade --install redpanda redpanda/redpanda --namespace <namespace> --create-namespace \
--reuse-values \
--set-string resources.cpu.cores=<number-of-cpu-cores> \
--set statefulset.additionalRedpandaCmdFlags="{--overprovisioned}"
If you already set resources.requests and resources.limits, for example by following Configure memory resources, --reuse-values keeps them. In that case, the chart ignores resources.cpu.cores and only --overprovisioned takes effect, as described in the note above.
If you’re experimenting with Redpanda in Kubernetes, you can also set the number of CPU cores to millicores to automatically enable overprovisioning.
cpu-cores.yamlresources:
cpu:
cores: 200m
Configure config-watcher sidecar resources
Each Redpanda Pod includes a container named sidecar that runs the config watcher, which monitors for SASL user changes and configuration updates. The sidecar polls a Secret for user credential changes and synchronizes them with the running brokers.
The sidecar container does not set any CPU or memory resource requests or limits by default. For most clusters, this is acceptable because the sidecar spends most of its time idle.
Configure explicit resource requests and limits for the config-watcher sidecar in the following cases:
-
Your namespace enforces a LimitRange policy that requires all containers to specify resource requests or limits.
-
Your namespace enforces a ResourceQuota that accounts for resource requests across all containers.
-
You want to ensure the Guaranteed QoS class for your Redpanda Pods. Kubernetes requires every container in a Pod to have matching requests and limits to qualify.
-
Operator
-
Helm
redpanda-cluster.yamlapiVersion: cluster.redpanda.com/v1alpha2
kind: Redpanda
metadata:
name: redpanda
spec:
chartRef: {}
clusterSpec:
statefulset:
podTemplate:
spec:
containers:
- name: sidecar
resources:
requests:
cpu: 10m (1)
memory: 256Mi (2)
limits:
cpu: 100m
memory: 256Mi
kubectl apply -f redpanda-cluster.yaml --namespace <namespace>
config-watcher-resources.yamlstatefulset:
podTemplate:
spec:
containers:
- name: sidecar
resources:
requests:
cpu: 10m (1)
memory: 256Mi (2)
limits:
cpu: 100m
memory: 256Mi
helm upgrade --install redpanda redpanda/redpanda --namespace <namespace> --create-namespace \
--values config-watcher-resources.yaml --reuse-values
| 1 | A CPU request of 10m (10 millicores) is sufficient for typical config-watcher workloads. The sidecar spends most of its time idle between polling intervals. |
| 2 | Memory usage of the sidecar depends on the Redpanda Operator version and the size of your cluster. Before you set a memory limit, check the sidecar’s actual usage, for example with kubectl top pod <pod-name> --containers, and leave headroom. If the sidecar exceeds its memory limit, Kubernetes restarts it with the OOMKilled reason. |
When the StatefulSet is deployed, verify that the sidecar container has the expected resource configuration:
kubectl --namespace <namespace> get pod <pod-name> -o jsonpath='{.spec.containers[?(@.name=="sidecar")].resources}{"\n"}'