Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

v1.0.0 Release: General Availability #84

Merged
merged 15 commits into from
Jul 1, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 21 additions & 5 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,14 @@ UNIQUE:=$(shell date +%s)
# Where to push the docker image.
REGISTRY := practodev

BASE_BRANCH := master
CURRENT_BRANCH := $(shell git rev-parse --abbrev-ref HEAD)
# This version-strategy uses git tags to set the version string
VERSION := $(shell git describe --tags --always --dirty)
MAJOR_VERSION = $(shell git describe --tags --dirty | \
awk -F'.' '{print $$1}')
MAJOR_MINOR_VERSION = $(shell git describe --tags --dirty | \
awk -F'.' '{print $$1"."$$2}')
#
# This version-strategy uses a manual value to set the version string
#VERSION := 1.2.3
Expand All @@ -30,13 +36,23 @@ ARCH := $(if $(GOARCH),$(GOARCH),$(shell go env GOARCH))
BASEIMAGE ?= gcr.io/distroless/static

IMAGE := $(REGISTRY)/$(BIN)

TAG := $(VERSION)
BETA := v1.0-beta
MAJOR_TAG := $(MAJOR_VERSION)
MAJOR_MINOR_TAG := $(MAJOR_MINOR_VERSION)

ifneq (,$(findstring v1.0,$(TAG))$(findstring -beta,$(TAG)))
PUBLISH_TAGS := $(IMAGE):$(TAG) $(IMAGE):$(BETA)
else
PUBLISH_TAGS := $(IMAGE):$(TAG)
PUBLISH_TAGS := $(IMAGE):$(TAG) $(IMAGE):$(MAJOR_MINOR_VERSION) $(IMAGE):$(MAJOR_VERSION)
ifneq (,$(findstring -beta,$(TAG)))
PUBLISH_TAGS := $(IMAGE):$(TAG) $(IMAGE):$(MAJOR_MINOR_VERSION)-beta $(IMAGE):$(MAJOR_VERSION)-beta
endif
ifneq (,$(findstring -alpha,$(TAG)))
PUBLISH_TAGS := $(IMAGE):$(TAG) $(IMAGE):$(MAJOR_MINOR_VERSION)-alpha $(IMAGE):$(MAJOR_VERSION)-alpha
endif
ifneq ($(CURRENT_BRANCH), $(BASE_BRANCH))
PUBLISH_TAGS := $(IMAGE):$(TAG)
endif
ifneq (,$(findstring -dirty,$(TAG)))
PUBLISH_TAGS := $(IMAGE):$(TAG)
endif

define \n
Expand Down
46 changes: 28 additions & 18 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,14 @@ Currently the supported Message Queueing Services are:
- [AWS SQS](https://aws.amazon.com/sqs/)
- [Beanstalkd](https://beanstalkd.github.io/)

There is a plan to integrate other commonly used message queing services.
There is a plan to integrate other commonly used message queuing services.

----

# Install the WorkerPodAutoscaler

### Install
Running the below script will create the WPA [CRD](https://kubernetes.io/docs/concepts/extend-kubernetes/api-extension/custom-resources/) and start the controller. The controller watches over all the specified queues in AWS SQS and scales the Kubernetes deployments based on the specification.
Running the below script will create the WPA [CRD](https://kubernetes.io/docs/concepts/extend-kubernetes/api-extension/custom-resources/) and install the worker pod autoscaler deployment.

```bash
export AWS_REGIONS='ap-south-1,ap-southeast-1'
Expand All @@ -28,7 +28,7 @@ export AWS_SECRET_ACCESS_KEY='sample-aws-secret-acesss-key'
./hack/install.sh
```

Note: IAM policy required is [this](artifacts/iam-policy.json).
Note: IAM policy required is [this](artifacts/iam-policy.json)

### Verify Installation
Check the wpa resource is accessible using kubectl
Expand All @@ -37,8 +37,12 @@ Check the wpa resource is accessible using kubectl
kubectl get wpa
```

### Upgrade

Please follow [this document](UPGRADE.md) for upgrading Worker Pod Autoscaler.

# Example
Do install the controller before going with the example.
Do install the wpa crd and wpa deployment before going with the example. (Please check above.)

- Create Deployment that needs to scale based on queue length.
```bash
Expand All @@ -56,7 +60,7 @@ This will start scaling `example-deployment` based on SQS queue length.

## WPA Resource
```yaml
apiVersion: k8s.practo.dev/v1alpha1
apiVersion: k8s.practo.dev/v1
kind: WorkerPodAutoScaler
metadata:
name: example-wpa
Expand All @@ -71,14 +75,19 @@ spec:
```
Beanstalk's queueURI would be like: `beanstalk://beanstalkDNSName:11300/test-tube`

### WPA Spec documentation:
- **minReplicas**: minimum number of workers you want to run. (mandatory)
- **maxReplicas**: maximum number of workers you want to run. (mandatory)
- **deploymentName**: name of the kubernetes deployment in the same namespace as WPA object. (mandatory)
- **queueURI**: full URL of the queue. (mandatory)
- **targetMessagesPerWorker**: Number of jobs in the queue which have not been picked up by the workers. This also used to calculate the desired number of workers. (mandatory)
- **secondsToProcessOneJob:**: This metric is useful to calculate the desired number of workers more accurately. It is particularly very useful for workers which have `targetMessagesPerWorker` as always zero. `secondsToProcessOneJob` in the combination with `messagesSentPerMinute`(queue RPM) helps in calculating the minimum workers that is expected to be running to handle `messagesSentPerMinute`(RPM) with every job being processed in `secondsToProcessOneJob` seconds. (optional, highly recommended, default=0.0 i.e. disabled)
- **maxDisruption:** amount of disruption that can be tolerated in a single scale down activity. Number of pods or percentage of pods that can scale down in a single down scale down activity. Using this you can control how fast a scale down can happen. This can be expressed both as an absolute value and a percentage. Explained with the help of some examples: (optional, default is the WPA flag `wpa-default-max-disruption`)
### WPA Spec Documentation:

| Spec | Description | Mandatory |
| :------------ | :----------- |:------------|
| minReplicas | Minimum number of workers you want to run. | Yes |
| maxReplicas | Maximum number of workers you want to run | Yes |
| deploymentName | Name of the kubernetes deployment in the same namespace as WPA object. | Yes |
| queueURI | Full URL of the queue. | Yes |
| targetMessagesPerWorker | Number of jobs in the queue which have not been picked up by the workers. This is also used to calculate the desired number of workers. | Yes |
| secondsToProcessOneJob | This metric is useful to calculate the desired number of workers more accurately. It is particularly very useful for workers which have `targetMessagesPerWorker` as always zero. `secondsToProcessOneJob` in the combination with `messagesSentPerMinute`(queue RPM) helps in calculating the minimum workers that is expected to be running to handle `messagesSentPerMinute`(RPM) with every job being processed in `secondsToProcessOneJob` seconds. (highly recommended, default=0.0 i.e. disabled). | No |
| maxDisruption | Amount of disruption that can be tolerated in a single scale down activity. Number of pods or percentage of pods that can scale down in a single down scale down activity. Using this you can control how fast a scale down can happen. This can be expressed both as an absolute value and a percentage. (default is the WPA flag `--wpa-default-max-disruption`). | No |

`maxDisruption` explained with the help of some examples:
```
min=2, max=1000, current=500, maxDisruption=50%: then the scale down cannot bring down more than 250 pods in a single scale down activity.
```
Expand Down Expand Up @@ -127,7 +136,7 @@ If you need to enable multiple queue support, you can add queues comma separated

Running WPA at scale require changes in `--k8s-api-burst` and `--k8s-api-qps` flags.

WPA makes update to Kubernetes API to update the WPA status. WPA uses [client-go](https://github.com/kubernetes/client-go) as the kubernetes client to make Kubernetes API calls. This client allows 5QPS and 10Burst requests to Kubernetes API by default. The defaults can be changed by using `k8s-api-burst` and `k8s-api-qps` flags.
WPA makes call to the Kubernetes API to update the WPA resource status. [client-go](https://github.com/kubernetes/client-go) is used as the kubernetes client to make the Kubernetes API calls. This client allows 5QPS and 10Burst requests to Kubernetes API by default. The defaults can be changed by using `k8s-api-burst` and `k8s-api-qps` flags.

You may need to increase the `--k8s-api-qps` and `k8s-api-burst` if [wpa_controller_loop_duration_seconds](https://github.com/practo/k8s-worker-pod-autoscaler/tree/master#wpa-metrics) is greater than 200ms (wpa_controller_loop_duration_seconds>0.200)

Expand Down Expand Up @@ -183,11 +192,12 @@ git pull origin master
- Build and push the image to `hub.docker.com/practodev`. Note: practodev push access is required.
```
git fetch --tags
git tag v1.0.0-beta
git tag v1.0.0
make push
```
Note: For every tag major and major minor versions tags also available. For example: `v1` and `v1.0`

- Create a Release in Github. Refer this https://github.com/practo/k8s-worker-pod-autoscaler/releases/tag/v1.0.0-beta and create a release. Release should contain the Changelog information of all the issues and pull request after the last release.
- Create a Release in Github. Refer [this](https://github.com/practo/k8s-worker-pod-autoscaler/releases/tag/v1.0.0) and create a release. Release should contain the Changelog information of all the issues and pull request after the last release.

- Publish the release in Github 🎉

Expand All @@ -199,7 +209,7 @@ kubectl edit deployment -n kube-system workerpodautoscaler
```

## Contributing
It would be really helpful to add all the major message queuing service providers. This [interface](https://github.com/practo/k8s-worker-pod-autoscaler/blob/master/pkg/queue/queueing_service.go#L5-L14) implementation needs to be written down to make that possible.
It would be really helpful to add all the major message queuing service providers. This [interface](https://github.com/practo/k8s-worker-pod-autoscaler/blob/master/pkg/queue/queue_service.go) implementation needs to be written down to make that possible.

- After making code changes, run the below commands to build and run locally.
```
Expand All @@ -217,7 +227,7 @@ $ bin/darwin_amd64/workerpodautoscaler run --kube-config /home/user/.kube/config

## Thanks

Thanks to kubernetes team for making [crds](https://kubernetes.io/docs/concepts/extend-kubernetes/api-extension/custom-resources/) and [sample controller](https://github.com/kubernetes/sample-controller)
Thanks to kubernetes team for making [crds](https://kubernetes.io/docs/concepts/extend-kubernetes/api-extension/custom-resources/) and [sample controller](https://github.com/kubernetes/sample-controller). Thanks for [go-build-template](https://github.com/thockin/go-build-template).

[latest-release]: https://github.com/practo/k8s-worker-pod-autoscaler/releases
[GoDoc]: https://godoc.org/github.com/practo/k8s-worker-pod-autoscaler
Expand Down
18 changes: 18 additions & 0 deletions UPGRADE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# Upgrade Worker Pod Autoscaler

## Upgrade from v0.2 to v1

### Breaking Changes
There is no backward breaking change from `v0.2` to `v1`.

### Recommended Actions
Update the WorkerPodAutoScaler CRD from `v1alpha1` to `v1` using below:
```
kubectl apply -f ./artifacts/crd.yaml
```

Note: Support for `v1alpha1` CRD version is still there, but it would be discontinued in the future releases.

### Changes
- [v1.0.0](https://github.com/practo/k8s-worker-pod-autoscaler/releases/tag/v1.0.0)
- [v1.0.0-beta](https://github.com/practo/k8s-worker-pod-autoscaler/releases/tag/v1.0.0-beta)
74 changes: 74 additions & 0 deletions artifacts/crd.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
apiVersion: apiextensions.k8s.io/v1beta1
kind: CustomResourceDefinition
metadata:
name: workerpodautoscalers.k8s.practo.dev
spec:
conversion:
strategy: None
group: k8s.practo.dev
names:
kind: WorkerPodAutoScaler
listKind: WorkerPodAutoScalerList
plural: workerpodautoscalers
shortNames:
- wpa
- wpas
singular: workerpodautoscaler
preserveUnknownFields: true
scope: Namespaced
versions: v1
versions:
- name: v1
served: true
storage: true
schema:
openAPIV3Schema:
type: object
required:
- spec
properties:
apiVersion:
type: string
kind:
type: string
metadata:
type: object
spec:
type: object
required:
- deploymentName
- minReplicas
- maxReplicas
- queueURI
- targetMessagesPerWorker
properties:
deploymentName:
type: string
description: 'Name of the kubernetes deployment in the same namespace as WPA object'
maxDisruption:
type: string
nullable: true
description: 'Amount of disruption that can be tolerated in a single scale down activity. Number of pods or percentage of pods that can scale down in a single down scale down activity'
maxReplicas:
type: integer
format: int32
description: 'Maximum number of workers you want to run'
minReplicas:
type: integer
format: int32
description: 'Minimum number of workers you want to run'
queueURI:
type: string
description: 'Full URL of the queue'
targetMessagesPerWorker:
type: integer
format: int32
description: 'Number of jobs in the queue which have not been picked up by the workers. This also used to calculate the desired number of workers'
secondsToProcessOneJob:
type: number
format: float
nullable: true
description: 'This metric is useful to calculate the desired number of workers more accurately. It is particularly very useful for workers which have `targetMessagesPerWorker` as always zero. `secondsToProcessOneJob` in the combination with `messagesSentPerMinute`(queue RPM) helps in calculating the minimum workers that is expected to be running to handle `messagesSentPerMinute`(RPM) with every job being processed in `secondsToProcessOneJob` seconds'
- name: v1alpha1
served: true
storage: false
2 changes: 1 addition & 1 deletion artifacts/deployment-template.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ spec:
value: {{ WPA_AWS_ACCESS_KEY_ID }}
- name: AWS_SECRET_ACCESS_KEY
value: {{ WPA_AWS_SECRET_ACCESS_KEY }}
image: practodev/workerpodautoscaler:v1.0.0-beta
image: practodev/workerpodautoscaler:{{ WPA_TAG }}
imagePullPolicy: Always
command:
- /workerpodautoscaler
Expand Down
2 changes: 1 addition & 1 deletion artifacts/examples/example-wpa.yaml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
apiVersion: k8s.practo.dev/v1alpha1
apiVersion: k8s.practo.dev/v1
kind: WorkerPodAutoScaler
metadata:
name: example-wpa
Expand Down
12 changes: 0 additions & 12 deletions cmd/workerpodautoscaler/run.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ import (
"k8s.io/client-go/rest"
"k8s.io/client-go/tools/clientcmd"

"github.com/practo/k8s-worker-pod-autoscaler/pkg/apis/workerpodautoscaler/v1alpha1"
"github.com/practo/k8s-worker-pod-autoscaler/pkg/cmdutil"
"github.com/practo/k8s-worker-pod-autoscaler/pkg/signals"
"github.com/prometheus/client_golang/prometheus/promhttp"
Expand All @@ -24,7 +23,6 @@ import (
clientset "github.com/practo/k8s-worker-pod-autoscaler/pkg/generated/clientset/versioned"
informers "github.com/practo/k8s-worker-pod-autoscaler/pkg/generated/informers/externalversions"
queue "github.com/practo/k8s-worker-pod-autoscaler/pkg/queue"
apiextensionsclient "k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset"
)

type runCmd struct {
Expand Down Expand Up @@ -137,16 +135,6 @@ func (v *runCmd) run(cmd *cobra.Command, args []string) {
klog.Fatalf("Error building custom clientset: %s", err.Error())
}

apiExtensionClient, err := apiextensionsclient.NewForConfig(cfg)
if err != nil {
klog.Fatalf("Error creating api extension client: %s", err.Error())
}

err = v1alpha1.CreateCRD(apiExtensionClient)
if err != nil {
klog.Fatalf("Error creating crd: %s", err.Error())
}

queues := queue.NewQueues()
go queues.Sync(stopCh)

Expand Down
25 changes: 13 additions & 12 deletions hack/install.sh
Original file line number Diff line number Diff line change
Expand Up @@ -2,32 +2,33 @@

set -e

if [ $# -eq 0 ]; then
WPA_TAG=`curl -s https://api.github.com/repos/practo/k8s-worker-pod-autoscaler/releases/latest|python -c "import json;import sys;sys.stdout.write(json.load(sys.stdin)['tag_name']+'\n')"`
else
WPA_TAG=$1
fi

crd='./artifacts/crd.yaml'
serviceaccount='./artifacts/serviceaccount.yaml'
clusterrole='./artifacts/clusterrole.yaml'
clusterrolebinding='./artifacts/clusterrolebinding.yaml'
new_deployment='./artifacts/deployment.yaml'
template_deployment='./artifacts/deployment-template.yaml'

if [ -z "${AWS_REGIONS}" ]; then
echo "AWS_REGIONS not set in environment, exiting"
exit 1
fi
if [ -z "${AWS_ACCESS_KEY_ID}" ]; then
echo "AWS_ACCESS_KEY_ID not set in environment, exiting"
exit 1
fi
if [ -z "${AWS_SECRET_ACCESS_KEY}" ]; then
echo "AWS_SECRET_ACCESS_KEY not set in environment, exiting"
exit 1
fi
echo "Creating CRD..."
kubectl apply -f ${crd}

echo "Generating Deployment Manifest..."
export WPA_AWS_REGIONS="${AWS_REGIONS}"
export WPA_AWS_ACCESS_KEY_ID="${AWS_ACCESS_KEY_ID}"
export WPA_AWS_SECRET_ACCESS_KEY="${AWS_SECRET_ACCESS_KEY}"

echo "Image to be used: practodev/${WPA_TAG}"

cp -f $template_deployment $new_deployment
./hack/generate.sh ${new_deployment}

echo "Applying manifests.."
kubectl apply -f ${serviceaccount}
kubectl apply -f ${clusterrole}
kubectl apply -f ${clusterrolebinding}
Expand Down
5 changes: 5 additions & 0 deletions pkg/apis/workerpodautoscaler/v1/doc.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
// +k8s:deepcopy-gen=package
// +groupName=k8s.practo.dev

// Package v1 is the v1 version of the API.
package v1 // import "github.com/practo/k8s-worker-pod-autoscalers/pkg/apis/workerpodautoscaler/v1"
8 changes: 8 additions & 0 deletions pkg/apis/workerpodautoscaler/v1/get_default.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package v1

func (w *WorkerPodAutoScaler) GetMaxDisruption(defaultDisruption string) *string {
if w.Spec.MaxDisruption == nil {
return &defaultDisruption
}
return w.Spec.MaxDisruption
}
Loading