The initial open-source release of this project is provided as-is. That implies that the codebase is only a slightly modified version of what we at ING are using. In the future we would like to extend this Open Source repository with the appropriate pipelines and contribution mechanics. This does imply that your journey for using this project for your own purposes can use some improvement, and we will work on that.
This project is part of the ING Neoria. Neoria contains parts of the ING Container Hosting Platform (ICHP) stack which is used to deliver Namespace-as-a-Service on top of OpenShift.
This project is intended to be used for multi-tenant clusters, where each tenant of that cluster owns a namespace that has limited resources via a ResourceQuota. The idea of Quota Autoscaling is to have Namespace ResourceQuota resize requests automatically issued to a resize endpoint based on resource usage of Pods. This endpoint should handle the charging of that namespace and also the resize of that ResourceQuota. Basically, scaling Pods will trigger resize requests for a namespaced ResourceQuota.
You should change the resize endpoint of this program for it to function, read more below. A custom certificate for a custom resize API endpoint can be added in build/tls-ca-bundle.pem..
In the current implementation the QuotaScaler expects a 10x ratio between Namespace ResourceQuota CPU Requests and Limits.
Its aim is to encourage users to create burstable Pods. This value is a constant REQ_LIM_RATIO
in internal/watchers.go
In a nutshell:
- clone this repository
- implement your resize API in
internal/resize_api.go
- build your own image
- update values file with that image name
- helm deploy to your target cluster
In internal/resize_api.go
you can find the function pointer:
var ResizeApiFunc = InvokeResizeApiStub // func(ns NamespaceResizeEvent) error
The ResizeApiFunc
will be called with information about a resize when this namespace needs more/less resources.
By default, the function InvokeResizeApiStub
is called. This stub function just patches the Namespace ResourceQuota
directly so that the component is functional without modification. In practise, this function should be replaced with
a custom Resize API functionality that resizes the ResourceQuota, and does charging for your stack. An example of this
is leftover in the InvokeResizeApi
function, which calls an ING specific stack. A custom certificate
for a custom resize API endpoint can be added in build/tls-ca-bundle.pem (mounted under /etc/pki/tls/certs/ca-bundle.crt
).
- Offers a namespaced QuotaAutoscaler custom resource
- Operator monitors ResourceQuotas
- Operator monitors FailedCreate Pod Events
- Operator calls a (custom) resize endpoint based on QuotaAutoscaler defined behavior
The QuotaScaler needs the following cluster-scoped permissions:
watch, list
onichp.ing.net/quotaautoscalers
to be able to operate on the CRDwatch, list, get, patch
onresourcequotas
to monitor namespace resource limits. Patch is needed for stub resize function, can be removed after custom resize API implementation.get
onreplicasets, replicationcontrollers, statefulsets, daemonsets, jobs
to find out required resources after PodFailedCreate
event.watch, list, get, create
onevents
to monitor PodFailedCreate
events, and to (optionally) produce resize events in the namespace.
Users of a multi-tenant cluster can enable this functionality in their Namespace via an instance of
a QuotaAutoscaler custom resource, e.g. for a namespace called saca-dev
:
apiVersion: ichp.ing.net/v1
kind: QuotaAutoscaler
metadata:
name: saca-dev-scaler
namespace: saca-dev
spec:
behavior: # Optional
scaleDown:
policies:
- method: cpu
value: 100
- method: memory
value: 100
scaleUp:
policies:
- method: cpu
value: 100
- method: memory
value: 100
minCpu: "400m" # Optional, this is the default and minimal value
maxCpu: "35" # Optional, this is the default and maximum value
minMemory: "1G" # Optional, this is the default and minimal value
maxMemory: "150G" # Optional, this is the default and maximum value
resourceQuota: saca-dev-quota # Your ResourceQuota (note: NOT an object quota)
The QuotaAutoscaler watches a QuotaScaler object in your namespace. Changing the min/max CPU and Memory values will act just as updating values in a namespaced ResourceQuota (via the resize endpoint that you configure yourself).
On top of that, you can also specify a behavior. A behavior specifies in what percentage of usage you would like to keep. For example setting a scaleDown policy of 50 CPU and scaleUp policy of 70 CPU means that the QuotaAutoscaler will keep your namespace ResourceQuota CPU between 50-70% usage. If your have less Pods running in your namespace the QuotaScaler will resize your namespace so that the quota is at least used for 50%. On the other hand, if you add more pods, and you use more than 70%, the QuotaAutoscaler will scale up your namespace so that maximally 70% if your quota is used.
Setting all scaleDown and scaleUp policies to 100% will ensure that the namespace ResourceQuota is always fully utilized, there will not be any “unspent” resources. The QuotaAutoscaler will detect when Pods cannot be scheduled ( quota limit exceeded error message), and scale up your quota based on those events. This is the value used when the QuotaScaler object is generated for you when a new namespace is created.
The purpose of the QuotaAutoscaler is to dynamically charge based on the resource usage of Pods without manual intervention. This opens up the floor for scaling mechanisms such as Horizontal Pod Autoscalers.
DaemonSets are currently not supported by the QuotaAutoscaler.
A ResourceQuota defines the maximum amount of resources that the Pods in your namespaces can consume. The sum of all Pod resources cannot exceed the ResourceQuota.
Possible causes are:
- Failure in resize endpoint
- A resize request has already been issued recently. You can only scale down after a couple of minutes of inactivity with the QuotaAutoscaler. There is no time limitation on scaling up.
For production namespaces ING recommends to have a 50-70% behavior policy in the QuotaAutoscaler. This will allow you to do rolling updates without impact from Quota scaling. In addition, such a behavior policy allows you to increase the ReplicaCount (Horizontal Pod Autoscaling) of your Deployments without impact from Quota scaling. If you want guarantees of a minimal ResourceQuota, you can configure this in the QuotaAutoscaler object.
- Pod FailedCreate events are always added to the maximum quota, this may result in an excessive quota.
daemonsets
are not supported
Integrations tests were pruned from this repository because they were too specific to ING's stack.