A vertical autoscaler for Kubernetes workloads. This is a golang port of the popular (py-)kube-downscaler with improvements and quality of life changes.
These are the resources the Downscaler can scale:
Installation is done via the Helm Chart
Annotations can be applied to a workload or its namespace. See the layers concept for more details on which of the layers values will be used.
CLI arguments set layer values and runtime configuration at the start of the program. See the layers concept for more details on which of the layers values will be used.
Layer Values:
Runtime Configuration:
some-ns,other-ns
or some-ns, other-ns
)deployments,statefulsets
or deployments, statefulsets
)some-ns,other-ns,kube-.*
or some-ns, other-ns, kube-.*
)some-workload,other-workload,.*kube-downscaler
or some-workload, other-workload, .*kube-downscaler
)some-label=val,other-label=value,another-label=.*
or some-label=val, other-label=value, another-label=.*
)Environment Variables set layer values on the env layer and runtime configuration at the start of the program. See the layers concept for more details on which of the layers values will be used.
Layer Values:
Runtime Configuration:
There are two different kinds of Timespans:
<RFC3339-Timestamp>-<RFC3339-Timestamp>
or
<RFC3339-Timestamp> - <RFC3339-Timestamp>
example: 2024-07-29T08:30:00Z - 2024-07-29T16:00:00+02:00
See RFC3339 Timestamps for more information
<Weekday-From>-<Weekday-To> <Time-Of-Day-From>-<Time-Of-Day-To> <Timezone>
example:
Mon-Fri 08:00-20:00 Asia/Tokyo # From Monday to Friday: from 08:00 to 20:00
Sat-Sun 00:00-24:00 UTC # On The Weekend: the entire day
Mon-Fri 20:00-08:00 Australia/Sydney # From Monday to Friday: from Midnight to 08:00 and from 20:00 until end of day
Mon-Sun 00:00-00:00 America/New_York # The timespan never matches, this would not do anything
Mon-Tue 20:00-24:00 Africa/Johannesburg # On Monday and Tuesday: from 20:00 to midnight
Mon-Tue 20:00-00:00 Europe/Amsterdam # On Monday and Tuesday: from 20:00 to midnight
Valid Values:
Weekdays: (case-insensitive)
Timezones:
[!Note] The IANA Time Zone database mainly supports regional/city timezones (example:
Europe/Berlin
,America/Los_Angeles
) instead of abbreviations (example:CEST
,PST
,PDT
). It supports some abbreviations likeCET
,MET
andPST8PDT
but these (not includingUTC
) shouldn't be used, and only exist for backwards compatibility. Time of day: 00:00 - 24:00
In some cases you need to define multiple Timespans. You can do this like this:
<TIMESPAN>,<TIMESPAN>,<TIMESPAN>
OR with optional spaces:
<TIMESPAN>, <TIMESPAN>, <TIMESPAN>
The timespans can be absolute, relative or mixed.
Example: downscale over the weekend and at night:
Sat-Sun 00:00-24:00 Europe/Berlin, Mon-Fri 20:00-07:00 Europe/Berlin
A duration can be defined either by an integer representing seconds
"120" # 120 seconds (2 minutes)
"900" # 900 seconds (15 minutes)
Or by a duration string:
"1h30m" # 1 hour and 30 minutes
"1.5h" # 1 hour and 30 minutes
"2m" # 2 minutes
"10s" # 10 seconds
"300s" # 300 seconds
Other units:
"ns" # nanoseconds
"us"/"µs" # microseconds
"ms" # milliseconds
"s" # seconds
"m" # minutes
"h" # hours
See Golangs official documentation for more information
Layers are layers of values. If the highest Layer doesn't have a value, it falls through it and tries to get the value from the next lower layer.
Defined by the annotations on the workload every scan.
Defined by the annotations on the namespace every scan.
Defined by the command line arguments at startup.
Defined by the environemt variables at startup.
[!Note] A process line with "(...)" is a compacted form, instead of showing the process on each layer
--- Layers
Workload: (no annotations)
Namespace: exclude=true
CLI: (defaults)
ENV: (no env vars)
--- Process:
Exclusion not specified on workload layer, going to next layer
Exclusion set to true on namespace layer, excluding workload
--- Result:
Workload is excluded, no changes will be made to it
--- Layers
Workload: exclude=false
Namespace: exclude=true
CLI: downtime="Mon-Fri 08:00-16:00 Europe/Berlin"
ENV: (no env vars)
--- Process:
Exclusion set to false on workload layer, not excluding workload
No forced scaling found on any layer (...)
No scaling specified on Workload layer, going to next layer
No scaling specified on Namespace layer, going to next layer
Scaling "downtime" specified on CLI layer, scaling according to the downtime schedule on the cli layer
--- Result:
Workload will be scaled according to the downtime schedule on the cli layer
--- Layers
Workload: uptime="Mon-Fri 08:00-16:00 Europe/Berlin"
Namespace: force-downtime=true
CLI: downtime="Mon-Fri 20:00-08:00 America/Los_Angeles"
ENV: (no env vars)
--- Process:
Exclusion not set on any layer (...)
Forced scaling found on namespace layer, forcing downscale (...)
--- Result:
Workload will be forced into a down-scaled state
--- Layers
Workload: uptime="Mon-Fri 08:00-16:00 Europe/Berlin"
Namespace: force-downtime=true
CLI: downtime="Mon-Fri 20:00-08:00 America/Los_Angeles"
ENV: (no env vars)
--- Process:
Exclusion not set on any layer (...)
No forced scaling found on any layer (...)
Scaling "uptime" set on workload layer, scaling according to the uptime schedule on the cli layer
--- Result:
Workload will be scaled according to the uptime schedule on the cli layer
See the layers concept for more details on which of the layers values will be used
helm uninstall py-kube-downscaler
If you had an implementation that used some of the quirks of the py-kube-downscaler you might need to change them to work with the GoKubeDownscaler.
Some cases where this might be needed include:
2023-08-12
, 2023-233
or 2023-W34-1
)Incompatibility instead of priority:
Duration units:
Layer system:
--explicit-include cli argument:
Comfort spaces:
Uniform timestamp:
2023-08-12
, 2023-233
or 2023-W34-1
) it should be totally fine to not change anythingOverlapping relative timespans into next day:
Mon-Fri 20:00-06:00 UTC
). See Relative Timespans for information on how this behavesActual exclusion:
IANA Timezones:
Workload error events:
--deployment-time-annotation -> --time-annotation:
--deployment-time-annotation
cli argument was changed to --time-annotation
--time-annotation
Currently the GoKubeDownscaler is still a WIP. This means that there are still some features missing. You can find a list of the known-missing features here. If you think that any other features are missing or you have an idea for a new feature, feel free to open an Issue
See troubleshooting
Please read the contribution manifest
git clone https://github.com/caas-team/GoKubeDownscaler.git
cd GoKubeDownscaler
brew install pre-commit
pre-commit install
brew install golangci-lint
brew install gofumpt
go test -v --cover ./...
The downscaler can be run locally by specifying a kubeconfig to use. The kubeconfig should have at least the permissions as the Helm Charts role.yaml. The downscaler will use the current-context in the kubeconfig.
go run -k=path/to/kubeconfig # ... additional configuration