Skip to content

Commit

Permalink
Updating README.md (#31)
Browse files Browse the repository at this point in the history
  • Loading branch information
Hedingber authored Dec 2, 2019
1 parent 083c8b8 commit 7a0c5c4
Showing 1 changed file with 66 additions and 44 deletions.
110 changes: 66 additions & 44 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,53 +1,75 @@
# Scaler
[![Build Status](https://travis-ci.org/v3io/scaler.svg?branch=master)](https://travis-ci.org/v3io/scaler)
# Scale to Zero

Building blocks to create a scaler (to and from zero instances) based on custom metrics.
Infrastructure to scale any resource to and from zero

Prerequisites:
## Design:
![Design scheme](https://www.lucidchart.com/publicSegments/view/b01741e1-cb15-438e-8bd7-e5865dcc2043/image.jpeg)

https://github.com/prometheus/prometheus <br>
https://github.com/kubernetes-incubator/metrics-server <br>
https://github.com/DirectXMan12/k8s-prometheus-adapter <br>
**Resource** - A generic name for the component which is being scaled by this mechanism.
Will mostly include pod/s (that will be scaled when needed) wrapped by one or many deployment/daemon set/replica set,
and k8s service/s that can be used to route incoming requests.

Schema:
```
**Resource-scaler** - An implementation of the `ResourceScaler` interface defined in
[scaler-types](https://github.com/v3io/scaler-types). It is transplanted inside the autoscaler and dlx using
[Go plugins](https://appliedgo.net/plugins/). They use them to perform actions on the specific resource.<br>
For example, when the autoscaler decides it needs to scale some resource to zero, it executes the resource-scaler's
`SetScale` function which has the knowledge how to scale to zero its specific resource.

Your Pod
To scale
------------ ------------ ------------ ------------ ------------ ------------
| | | /metrics | | Prometheus | | Prometheus | | Metrics | | Metrics |
| Service |-> | |<--- | |<--- | Adapter |<--- | Aggregator |---> | Server |
| | | | | | | | | | | |
------------ ------------ ------------ ------------ ------------ ------------
| /\
| ------------
| Resource | |
| Scaled to zero | Autoscaler |
| | |
| ------------
|
| ------------
| | |
------------------> | DLX |
| |
------------
```
**The autoscaler** - Responsible for periodically checking whether some resources should be scaled to zero. this is
performed by by querying the custom metrics API. Upon deciding a resource should be scaled to zero, it uses the internal
resource-scaler module to scale the resource to zero.
The resource-scaler will first route all incoming traffic to the DLX, which in terms of K8s is done by changing a
service selector, after that, it will scale the resource to zero.

### Autoscaler
Based on custom metric name, will call `ResourceScaler` interface function `Scale` with a `Resource` from a list of known `Resource`'s (`GetResources` function)
Config for service includes:
```
Namespace - kubernetes namespace of the resources
ScaleWindow - an allowed period for the resource to be inactive before calling the `Scale` function
MetricName - name of the metric to monitor for the resource
Threshold - A threshold for a metric to concider the resource being inactive
ScaleInterval - an interval to call scale function which checks if a resource has passed the scale window, if not the scale window is being considered the longest duration of time where the metric for the resource is under the threshold
**The DLX** - Responsible for receiving and buffering requests of scaled to zero resources, Upon receiving an incoming
request it creates a buffer for the messages, and tells the resource-scaler to scale the service back from zero.
The resource-scaler will scale the resource back up and then route the traffic back to the service (by modifying the k8s
service selector).

## Prerequisites

**Custom metrics API implementation:**

The Autoscaler makes decisions based on data queried from Kubernetes
[custom metrics API.](https://github.com/kubernetes/community/blob/master/contributors/design-proposals/instrumentation/custom-metrics-api.md)
There are several possible tools that implement it, we internally use
[Prometheus](https://prometheus.io/) with the [Prometheus-Adapter](https://github.com/DirectXMan12/k8s-prometheus-adapter)
but you can use which ever you want! You can find some recommended implementations
[here](https://github.com/kubernetes/metrics/blob/master/IMPLEMENTATIONS.md#custom-metrics-api)

## Getting Started
The infrastructure is designed to be generic, flexible and extendable, so as to serve any resource we'd wish to scale
to/from zero. All you have to do is implement the specific resource-scaler for your resource. The interface between your
resource-scaler and the scale-to-zero infrastructure's components is defined in
[scaler-types](https://github.com/v3io/scaler-types)

**Note:** Incompatibility between this scaler vendor dir and your resource-scale vendor dir may break things,
therefore it's suggested to put your resource-scaler in its own repo

Examples:
* [Nuclio functions resource-scaler](https://github.com/nuclio/nuclio/blob/master/pkg/platform/kube/resourcescaler/resourcescaler.go)
* [Iguazio's app service resource-scaler](https://github.com/v3io/app-resource-scaler/blob/development/resourcescaler.go)

## Installing
[Go plugins](https://appliedgo.net/plugins/) is the magic that glues the resource-scaler and this infrastructure
components together.<br>
First you'll need to build the resource-scaler as a Go plugin, for example: <br>
```sh
GOOS=linux GOARCH=amd64 go build -buildmode=plugin -a -installsuffix cgo -ldflags="-s -w" -o ./plugin.so ./resourcescaler.go
```
Scaler should change the resource service to point to DLX service and not to the scaled down pod (to be changed by `ResourceScaler` or some other external entity)
The autoscaler/dlx looks for the plugin using this path (from the execution directory) `./plugins/*.so` so you should
move the binary artifact of the build command (the `plugin.so` file) to the `plugins` directory
It is much easier to do everything using Dockerfiles, here are some great examples:
* [Nuclio function Autoscaler dockerfile](https://github.com/nuclio/nuclio/blob/master/cmd/autoscaler/Dockerfile)
* [Nuclio function DLX dockerfile](https://github.com/nuclio/nuclio/blob/master/cmd/dlx/Dockerfile)
* [Iguazio's app service Autoscaler dockerfile](https://github.com/v3io/app-resource-scaler/blob/development/autoscaler/Dockerfile)
* [Iguazio's app service DLX dockerfile](https://github.com/v3io/app-resource-scaler/blob/development/dlx/Dockerfile)

You can install the components using the [scaler helm chart](https://github.com/v3io/helm-charts/tree/development/stable/scaler)<br>
`$ helm install --name my-release v3io-stable/scaler`


### DLX
A service that listens on http requests for a given namespace, when a request is received, it's being saved in-memory until `Scale` function returns, this is an indication that the resource is ready and any changes that were made by autoscaler were reverted (i.e. changing where service points to), that request is then being proxied to the new instance and the response from it returns to the user.
## Versioning

We use [SemVer](http://semver.org/) for versioning. For the versions available, see the
[releases on this repository](https://github.com/v3io/scaler/releases).

0 comments on commit 7a0c5c4

Please sign in to comment.