Skip to content

Commit

Permalink
Merge pull request #72 from schleyfox/allow-ladder-to-go-to-zero
Browse files Browse the repository at this point in the history
Allow ladder to support setting replicas to 0
  • Loading branch information
k8s-ci-robot authored Apr 14, 2020
2 parents a70a8f4 + 183c26b commit 9d59990
Show file tree
Hide file tree
Showing 3 changed files with 57 additions and 13 deletions.
23 changes: 19 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -129,15 +129,30 @@ The ladder controller gives out the desired replicas count by using a step funct
The step ladder function uses the datapoint for core and node scaling from the ConfigMap.
The lookup which yields the higher number of replicas will be used as the target scaling number.

For instance, given a cluster comes with `100` nodes and `400` cores and it is using above ConfigMap.
The replicas derived from "cores_to_replicas_map" would be `3` (because `64` < `400` < `512`).
The replicas derived from "nodes_to_replicas_map" would be `2` (because `100` > `2`).
For instance, given a cluster comes with `100` nodes and `400` cores and it is using above ConfigMap.
The replicas derived from "cores_to_replicas_map" would be `3` (because `64` < `400` < `512`).
The replicas derived from "nodes_to_replicas_map" would be `2` (because `100` > `2`).
And we would choose the larger one `3`.

Either one of the `coresToReplicas` or `nodesToReplicas` could be omitted. All elements in them should
be int.

The lowest number of replicas is set to 1.
Replicas can be set to 0 (unlike in linear mode).

Scaling to 0 replicas could be used to enable optional features as a cluster grows. For example, this
ladder would create a single replica once the cluster reaches six nodes.

```
data:
ladder: |-
{
"nodesToReplicas":
[
[ 0, 0 ],
[ 6, 1 ]
]
}
```

## Comparisons to the Horizontal Pod Autoscaler feature

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -92,15 +92,15 @@ func parseParams(data []byte) (*ladderParams, error) {
if len(e) != 2 {
return nil, fmt.Errorf("invalid element %v in cores_to_replicas_map", e)
}
if e[0] < 1 || e[1] < 1 {
if e[0] < 0 || e[1] < 0 {
return nil, fmt.Errorf("invalid negative values in entry %v in cores_to_replicas_map", e)
}
}
for _, e := range p.NodesToReplicas {
if len(e) != 2 {
return nil, fmt.Errorf("invalid element %b in nodes_to_replicas_map", e)
}
if e[0] < 1 || e[1] < 1 {
if e[0] < 0 || e[1] < 0 {
return nil, fmt.Errorf("invalid negative values in entry %v in nodes_to_replicas_map", e)
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -68,11 +68,6 @@ func TestControllerParser(t *testing.T) {
true,
&ladderParams{},
},
{ // Invalid value 0 in list
`{ "coresToReplicas" : [[ 0, 1]] }`,
true,
&ladderParams{},
},
{ // Invalid negative in list
`{ "coresToReplicas" : [[:-200]] }`,
true,
Expand All @@ -82,7 +77,8 @@ func TestControllerParser(t *testing.T) {
`{
"coresToReplicas":
[
[1, 1],
[0, 0],
[1, 0],
[2, 2],
[3, 3],
[512, 5],
Expand All @@ -102,7 +98,8 @@ func TestControllerParser(t *testing.T) {
false,
&ladderParams{
CoresToReplicas: []paramEntry{
{1, 1},
{0, 0},
{1, 0},
{2, 2},
{3, 3},
{512, 5},
Expand Down Expand Up @@ -270,3 +267,35 @@ func TestControllerScaler(t *testing.T) {
}
}
}

func TestControllerScalerFromZero(t *testing.T) {
testEntries := []paramEntry{
{0, 0},
{3, 3},
}

testEntriesFromOne := []paramEntry{
{1, 0},
{3, 3},
}

testCases := []struct {
numResources int
expReplicas int
}{
{0, 0},
{1, 0},
{2, 0},
{3, 3},
{4, 3},
}

for _, tc := range testCases {
if replicas := getExpectedReplicasFromEntries(tc.numResources, testEntries); tc.expReplicas != replicas {
t.Errorf("Scaler Lookup failed Expected %d, Got %d", tc.expReplicas, replicas)
}
if replicas := getExpectedReplicasFromEntries(tc.numResources, testEntriesFromOne); tc.expReplicas != replicas {
t.Errorf("Scaler Lookup failed Expected %d, Got %d", tc.expReplicas, replicas)
}
}
}

0 comments on commit 9d59990

Please sign in to comment.