Practical example of how to set requests and limits on Kubernetes
In this post, I will share my thoughts on how to properly set requests and limits for your workloads on Kubernetes.
So, why should we care about requests/limits at all?
Setting the right resource requests and limits for your workloads is important for stability and cost efficiency. If your Pod resource sizes are smaller than your workloads require, your application can either be throttled or it can fail due to out-of-memory errors. If your resource sizes are too large, you have waste and, therefore, larger bills.
https://cloud.google.com/kubernetes-engine/docs/concepts/verticalpodautoscaler
To put it simply, if you not set requests/limits properly, your application might fail/be throttled, or you will overprovision your resources and it will cost you a lot.
Prerequisites
-
Existing k8s cluster, EKS in my case.
-
Prometheus/Grafana Installed to your cluster, I am using kube-prometheus-stack for my cluster.
kube-prometheus-stack
Installs the kube-prometheus-stack, a collection of Kubernetes manifests, Grafana dashboards, and Prometheus rules combined with documentation and scripts to provide easy to operate end-to-end Kubernetes cluster monitoring with Prometheus using the Prometheus Operator.
Cloudify
Cloudify is an open source, multi-cloud orchestration platform featuring a unique ‘Environment as a Service’ technology that has the power to connect, automate and manage new & existing infrastructure and networking environments of entire application pipelines. Using Cloudify, DevOps teams (& infrastructure &operations groups) can effortlessly make a swift transition to public cloud and cloud-native architecture, and have a consistent way to manage all private & public environments. Cloudify is driven by a multidisciplinary team of industry experts and hero-talent.
https://cloudify.co/
Let’s Install Cloudify Manager and VPA.
To be practical, I will deploy cloudify manager application to EKS using this helm chart: https://github.com/cloudify-cosmo/cloudify-helm
Install cloudify manager to EKS cluster
I will use this setup for deployment:
A good explanation of how to install it, you can find here: https://github.com/cloudify-cosmo/cloudify-helm/tree/master/cloudify-manager-worker
-
Need to generate a self signed certificate to encrypt communication between all components inside of EKS cluster.
-
Install cloudify manager / postgresql / rabbitmq with helm charts to specific namespace
Vertical Pod Autoscaler
Vertical Pod Autoscaler (VPA) frees the users from necessity of setting up-to-date resource limits and requests for the containers in their pods. When configured, it will set the requests automatically based on usage and thus allow proper scheduling onto nodes so that appropriate resource amount is available for each pod. It will also maintain ratios between limits and requests that were specified in initial containers configuration.
It can both down-scale pods that are over-requesting resources, and also up-scale pods that are under-requesting resources based on their usage over time.
https://github.com/kubernetes/autoscaler/tree/master/vertical-pod-autoscaler
Install Vertical Pod Autoscaler
A good explanation of how to install it, you can find here: https://github.com/kubernetes/autoscaler/tree/master/vertical-pod-autoscaler
One of the problems I found immediately after installation is ‘vpa-admission-controller’ in ‘ContainerCreating’ state:
To fix that you need to upgrade openssl to version 1.1.1
please upgrade openssl to version 1.1.1 or higher (needs to support -addext option) or use ./hack/vpa-up.sh on the 0.8 release branch.
In my case it’s less relevant because I am using VPA in ‘recommendation’ mode, I will explain why in a couple of minutes.
Deploying VPA manifest for cloudify manager
updateMode: ‘Off’, means we using VPA in recommendation mode only.
How to properly calculate requests for your workloads?
Run cloudify manager on EKS and observe metrics from prometheus/grafana
Let’s run different workflows with cloudify manager and observe CPU/Memory usage in prometheus/grafana.
Cloudify Manager’s dashboard after deployment
Let’s run a couple of blueprints(workflows) in parallel to increase CPU/Memory usage of the application and to get a better picture of resource consumption.
Let’s look at prometheus/grafana:
I am using kube-prometheus-stack with already preinstalled dashboards
We can use also different load testing tools to get more realsitic CPU/Memory resource consumption, but it’s sufficient to run multiple workloads with Cloudify Manager for the showcase.
Ok, so looking at metrics of prometheus/grafana we can see CPU usage peaks during application start and when executing different workloads (blueprints deployment), based on those metrics I would try to set requests for CPU/Memory as:
Of course, need to do some tuning and tests around those requests, but for me it will be around those values, also need to be more carefull with limits, because if we set memory limits less than 1.4G it may result in OOMKilled.
Getting the recommendations from deployed VPA manifest
Much easier would be to look at recommendations of VPA:
Look at the Recommendation/Target section, this is the recommended CPU requests and memory requests for the container.
Easy enough, and the only thing you need to do is to deploy cm-vpa.yaml manifest.
Using Goldilocks
https://goldilocks.docs.fairwinds.com/
Goldilocks is a utility that can help you identify a starting point for resource requests and limits.
Installation
https://goldilocks.docs.fairwinds.com/installation/#requirements
Enable Namespace to appear in Dashboard
Pick an application namespace and label it like so in order to see some data:
After that, you should start to see VPA objects in that namespace.
Viewing the Dashboard
The default installation creates a ClusterIP service for the dashboard. You can access via port forward:
Then open your browser to http://localhost:8080
I installed cloudify manager to ‘iupnqnkfab43’ namespace.
I took snapshot after all workflows finished to run and CPU/Memory usage decreased, that why CPU requests recomendations is lower in snaphot.
Encountered issues
Numerous restarts of ‘goldilocks-controller’ (OOMKilled), to fix the issue I increased CPU/Memory limits to:
Great tool for requests recommendations, which automatically deploys VPA manifests to labeled namespace, only thing needed is to install helm chart and then label needed namespace with ‘goldilocks.fairwinds.com/enabled=true’.
Using VPA with dynamic requests tuning enabled
One of the most difficult problems faced by DevOps is how many resources need to allocate for a workloads to make it operate optimally. Imagine you have a tool that will tune resources of a workload dynamically, based on usage?
VPA with updateMode: “Auto”, may potentially be this tool in the future, but not currently.
So why not to use updateMode: “Auto” in production?
- Updating running pods is an experimental feature of VPA. Whenever VPA updates the pod resources the pod is recreated, which causes all running containers to be restarted. The pod may be recreated on a different node.
Meaning we can experience a ‘downtime’, which obviously is not good.
One of the possible improvements may be ‘in-place updates’ of resource parameters, which is currently a limitation of Kubernetes, and to change resource parameters you need to recreate the pod with new params.
‘in-place updates’ discussion happens in the Kubernetes community for already a couple of years: https://github.com/kubernetes/community/pull/1719
-
I didn’t find any real use cases of VPA usage with ‘auto’ mode in production.
-
Not many examples and poor documentation meantime, hope this will be improved in the future, cause it’s a very promising project.
-
I want to have more control over VPA with ‘auto’ mode, for example actively update resources for workflows in a specific window of time or use some schedules to do that…
In this post, I touched one of the most difficult problems faced by DevOps/SRE: How to set proper requests for your workloads, how to allocate enough resources for a workloads to operate optimally and not to overprovision in the same time.
We looked at three options to find proper requests for your workloads which may be very useful. Thank you for reading, I hope you enjoyed it, see you in the next post.
Please subscribe to my YT channel
If you want to be notified when the next post of this tutorial is published, please follow me on Twitter @warolv.
Medium account: warolv.medium.com