Skip to content

Commit

Permalink
✨ add factor feature (#13)
Browse files Browse the repository at this point in the history
  • Loading branch information
amitai-devops committed Dec 20, 2022
1 parent 1042650 commit 7660896
Show file tree
Hide file tree
Showing 7 changed files with 36 additions and 11 deletions.
17 changes: 14 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,10 @@

**kube-reqsizer** is a kubernetes controller that will measure the usage of pods over time and optimize (reduce/increase) their requests based on the average usage.

NOTE: This is an alternative to [Vertical-Pod-Autoscaler](https://github.com/kubernetes/autoscaler/tree/master/vertical-pod-autoscaler). The intended use of this project is to provide a simpler, more straightforward install and mechanism, without CRDs, **and that can work with [Horizontal-Pod-Autoscaler](https://kubernetes.io/docs/tasks/run-application/horizontal-pod-autoscale/).**
When all required conditions meet, the controller calculates the result requirements based on all the samples taken so far a pod.
It then goes "upstream" to the parent controller of that pod, for example *Deployment*, and updates the relevant containers for the pod inside the deployment as a reconciliation, as if its desired state is the new state with the new requirements.

Note: This is an alternative to [Vertical-Pod-Autoscaler](https://github.com/kubernetes/autoscaler/tree/master/vertical-pod-autoscaler). The intended use of this project is to provide a simpler, more straightforward install and mechanism, without CRDs, **and that can work with [Horizontal-Pod-Autoscaler](https://kubernetes.io/docs/tasks/run-application/horizontal-pod-autoscale/).**
## Deploy - Helm

```bash
Expand All @@ -17,6 +20,7 @@ helm install kube-reqsizer/kube-reqsizer
**Core Values:**

```yaml
enabledAnnotation: true
sampleSize: 1
minSeconds: 1
enableIncrease: true
Expand All @@ -25,7 +29,8 @@ maxMemory: 0
minMemory: 0
maxCPU: 0
minCPU: 0
enabledAnnotation: true
cpuFactor: 1
memoryFactor: 1
logLevel: info
```
## Prerequisites
Expand All @@ -51,7 +56,7 @@ logLevel: info

The sample size to create an average from when reconciling.

--min-seconds int (default 1)
--min-seconds float (default 1)

Minimum seconds between pod restart.
This ensures the controller will not restart a pod if the minimum time
Expand All @@ -74,6 +79,12 @@ logLevel: info

--min-memory int (default 0)
Minimum memory in (Mi) that the controller can set a pod request to. 0 is infinite

--cpu-factor float (default 1)
A factor to multiply CPU requests when reconciling.

--memory-factor float (default 1)
A factor to multiply Memory requests when reconciling.
```

### Annotations
Expand Down
2 changes: 1 addition & 1 deletion charts/kube-reqsizer/Chart.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -13,4 +13,4 @@ type: application
# This is the chart version. This version number should be incremented each time you make changes
# to the chart and its templates, including the app version.
# Versions are expected to follow Semantic Versioning (https://semver.org/)
version: 0.6.4
version: 0.6.5
2 changes: 2 additions & 0 deletions charts/kube-reqsizer/templates/deployment.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@ spec:
- --max-memory={{.Values.maxMemory}}
- --min-cpu={{.Values.minCPU}}
- --min-memory={{.Values.minMemory}}
- --cpu-factor={{.Values.cpuFactor}}
- --memory-factor={{.Values.memoryFactor}}
resources:
{{- toYaml .Values.controllerManager.manager.resources | nindent 10 }}
command:
Expand Down
4 changes: 3 additions & 1 deletion charts/kube-reqsizer/values.yaml
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
enabledAnnotation: true
sampleSize: 1
minSeconds: 1
enableIncrease: true
Expand All @@ -6,7 +7,8 @@ maxMemory: 0
minMemory: 0
maxCPU: 0
minCPU: 0
enabledAnnotation: true
cpuFactor: 1
memoryFactor: 1
logLevel: info

controllerManager:
Expand Down
12 changes: 6 additions & 6 deletions controllers/pod_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -162,17 +162,17 @@ func (r *PodReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.R
switch r.GetPodMode(pod, ctx) {
case "average":
if r.ValidateCPU(currentC.CPU, AverageUsageCPU) {
pod.Spec.Containers[i].Resources.Requests[v1.ResourceCPU] = resource.MustParse(fmt.Sprintf("%dm", AverageUsageCPU))
pod.Spec.Containers[i].Resources.Requests[v1.ResourceCPU] = resource.MustParse(fmt.Sprintf("%dm", int(float64(AverageUsageCPU)*r.CPUFactor)))
PodChange = true
}
case "min":
if r.ValidateCPU(currentC.CPU, c.MinCPU) {
pod.Spec.Containers[i].Resources.Requests[v1.ResourceCPU] = resource.MustParse(fmt.Sprintf("%dm", c.MinCPU))
pod.Spec.Containers[i].Resources.Requests[v1.ResourceCPU] = resource.MustParse(fmt.Sprintf("%dm", int(float64(c.MinCPU)*r.CPUFactor)))
PodChange = true
}
case "max":
if r.ValidateCPU(currentC.CPU, c.MaxCPU) {
pod.Spec.Containers[i].Resources.Requests[v1.ResourceCPU] = resource.MustParse(fmt.Sprintf("%dm", c.MaxCPU))
pod.Spec.Containers[i].Resources.Requests[v1.ResourceCPU] = resource.MustParse(fmt.Sprintf("%dm", int(float64(c.MaxCPU)*r.CPUFactor)))
PodChange = true
}
}
Expand All @@ -182,17 +182,17 @@ func (r *PodReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.R
switch r.GetPodMode(pod, ctx) {
case "average":
if r.ValidateMemory(currentC.Memory, AverageUsageMemory) {
pod.Spec.Containers[i].Resources.Requests[v1.ResourceCPU] = resource.MustParse(fmt.Sprintf("%dm", AverageUsageMemory))
pod.Spec.Containers[i].Resources.Requests[v1.ResourceCPU] = resource.MustParse(fmt.Sprintf("%dm", int(float64(AverageUsageMemory)*r.MemoryFactor)))
PodChange = true
}
case "min":
if r.ValidateMemory(currentC.Memory, c.MinMemory) {
pod.Spec.Containers[i].Resources.Requests[v1.ResourceCPU] = resource.MustParse(fmt.Sprintf("%dm", c.MinMemory))
pod.Spec.Containers[i].Resources.Requests[v1.ResourceCPU] = resource.MustParse(fmt.Sprintf("%dm", int(float64(c.MinMemory)*r.MemoryFactor)))
PodChange = true
}
case "max":
if r.ValidateMemory(currentC.Memory, c.MaxMemory) {
pod.Spec.Containers[i].Resources.Requests[v1.ResourceCPU] = resource.MustParse(fmt.Sprintf("%dm", c.MaxMemory))
pod.Spec.Containers[i].Resources.Requests[v1.ResourceCPU] = resource.MustParse(fmt.Sprintf("%dm", int(float64(c.MaxMemory)*r.MemoryFactor)))
PodChange = true
}
}
Expand Down
2 changes: 2 additions & 0 deletions controllers/pod_controller_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@ type PodReconciler struct {
MaxCPU int64
MinMemory int64
MinCPU int64
CPUFactor float64
MemoryFactor float64
}

type PodRequests struct {
Expand Down
8 changes: 8 additions & 0 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -63,10 +63,16 @@ func main() {
var minMemory int64
var minCPU int64

var cpuFactor float64
var memoryFactor float64

flag.BoolVar(&enableIncrease, "enable-increase", true, "Enables the controller to increase pod requests")
flag.BoolVar(&enableReduce, "enable-reduce", true, "Enables the controller to reduce pod requests")
flag.Int64Var(&maxMemory, "max-memory", 0, "Maximum memory in (Mi) that the controller can set a pod request to. 0 is infinite")
flag.Int64Var(&maxCPU, "max-cpu", 0, "Maximum CPU in (m) that the controller can set a pod request to. 0 is infinite")
flag.Float64Var(&cpuFactor, "cpu-factor", 1, "A factor to multiply CPU requests when reconciling. 1 By default.")
flag.Float64Var(&memoryFactor, "memory-factor", 1, "A factor to multiply Memory requests when reconciling. 1 By default.")

flag.Int64Var(&minMemory, "min-memory", 0, "Minimum memory in (Mi) that the controller can set a pod request to. 0 is infinite")
flag.Int64Var(&minCPU, "min-cpu", 0, "Minimum CPU in (m) that the controller can set a pod request to. 0 is infinite")

Expand Down Expand Up @@ -132,6 +138,8 @@ func main() {
MaxCPU: maxCPU,
MinMemory: minMemory,
MinCPU: minCPU,
CPUFactor: cpuFactor,
MemoryFactor: memoryFactor,
}).SetupWithManager(mgr); err != nil {
setupLog.Error(err, "unable to create controller", "controller", "Pod")
log.Error(err, err.Error())
Expand Down

0 comments on commit 7660896

Please sign in to comment.