caas-team / GoKubeDownscaler

A horizontal autoscaler for Kubernetes workloads
GNU General Public License v3.0
9 stars 4 forks source link
autoscaler downscaling go golang kube-downscaler kubernetes scaling

GoKubeDownscaler

GitHub Release GitHub License Contributers Stars Slack Workspace

A vertical autoscaler for Kubernetes workloads. This is a golang port of the popular (py-)kube-downscaler with improvements and quality of life changes.

Table of contents

Scalable Resources

These are the resources the Downscaler can scale:

Installation

Installation is done via the Helm Chart

Configuration

Annotations

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.

Arguments

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:

Environment Variables

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:

Timespans

There are two different kinds of Timespans:

Configuration of an Absolute Timespan

<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

Configuration of a Relative Timespan

<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 like CET, MET and PST8PDT but these (not including UTC) shouldn't be used, and only exist for backwards compatibility. Time of day: 00:00 - 24:00

Multiple/Complex Timespans

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

Duration

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

Concepts

Layers

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.

Layer Hierarchy

  1. Workload Layer
  2. Namespace Layer
  3. CLI Layer
  4. ENV Layer

Workload Layer

Defined by the annotations on the workload every scan.

Namespace Layer

Defined by the annotations on the namespace every scan.

CLI Layer

Defined by the command line arguments at startup.

ENV Layer

Defined by the environemt variables at startup.

Examples

[!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

Values

See the layers concept for more details on which of the layers values will be used

Migrating from py-kube-downscaler

Basic migration

  1. Remove the old kube-downscaler
helm uninstall py-kube-downscaler
  1. Make sure all programs/non-default use cases support the breaking changes
  2. Make sure all timestamps are RFC 3339 compatible
  3. Install the new downscaler

Edge cases

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:

Differences to py-kube-downscaler

Incompatibility instead of priority:

Duration units:

Layer system:

--explicit-include cli argument:

Comfort spaces:

Uniform timestamp:

Overlapping relative timespans into next day:

Actual exclusion:

IANA Timezones:

Workload error events:

--deployment-time-annotation -> --time-annotation:

Missing Features

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

Troubleshooting

See troubleshooting

Developing

Please read the contribution manifest

Cloning the Repository

git clone https://github.com/caas-team/GoKubeDownscaler.git
cd GoKubeDownscaler

Setting up Pre-Commit

brew install pre-commit
pre-commit install
brew install golangci-lint
brew install gofumpt

Testing the downscaler

running the unit tests

go test -v --cover ./...

running the downscaler locally

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