A batch-optimized scaling manager for Kubernetes


Build Status


kubernetes-ec2-autoscaler is a node-level autoscaler for Kubernetes on AWS EC2 that is designed for batch jobs. Kubernetes is a container orchestration framework that schedules Docker containers on a cluster, and kubernetes-ec2-autoscaler can scale AWS Auto Scaling Groups based on the pending job queue.

The key features are:

  • Scaling on flexible resource requirements: the autoscaler determines the resources it needs from the pending job queue, and scales up the appropriate ASGs while respecting job constraints such as node selectors
  • Multi-Region Support: the autoscaler can detect scaling errors and overflow to secondary AWS regions
  • Draining nodes on scale in: the autoscaler makes sure to not kill in-flight jobs


Architecture Diagram


The autoscaler can be run anywhere as long as it can access the AWS and Kubernetes APIs, but the recommended way is to set it up as a Kubernetes Pod.

Auto Scaling Groups

Your Auto Scaling Groups must be tagged with KubernetesCluster, whose value should be passed to the flag --cluster-name, and Role with a value of minion. If you use kube-up to set up your cluster, those will be set automatically.

You must also enable Instance Protection on all your Auto Scaling Groups, since instance termination will be handled by the kubernetes-ec2-autoscaler.

IAM User

It is highly recommended that you make an AWS IAM user for this service, instead of using your worker's instance profile, since it will need permissions to terminate instances. Here is the minimal IAM policy required by the autoscaler:

  "Version": "2012-10-17",
  "Statement": [
      "Effect": "Allow",
      "Action": [
      "Resource": [
      "Effect": "Allow",
      "Action": [
      "Resource": [


Once you have an IAM user, you will need its access key. The best way to use the access key in Kubernetes is with a secret. Here is a sample autoscaler-secret.yaml:

apiVersion: v1
kind: Secret
  name: autoscaler
  namespace: kube-system
  aws-access-key-id: [base64 encoded access key]
  aws-secret-access-key: [base64 encoded secret access key]
  slack-hook: [optional slack incoming webhook]

Create Kubernetes secret:

$ kubectl create -f autoscaler-secret.yaml


autoscaler-dep.yaml is an example Deployment that configures Kubernetes to always run exactly one copy of the autoscaler. To create the Deployment:

$ kubectl create -f autoscaler-dep.yaml

To update/replace the Deployment:

$ kubectl replace -f autoscaler-dep.yaml

You should then be able to inspect the pod's status and logs:

$ kubectl get pods --namespace kube-system -l app=autoscaler
NAME               READY     STATUS    RESTARTS   AGE
autoscaler-opnax   1/1       Running   0          3s

$ kubectl logs autoscaler-opnax --namespace kube-system
2016-08-25 20:36:45,985 - autoscaler.cluster - DEBUG - Using kube service account
2016-08-25 20:36:45,987 - autoscaler.cluster - INFO - ++++++++++++++ Running Scaling Loop ++++++++++++++++
2016-08-25 20:37:04,221 - autoscaler.cluster - INFO - ++++++++++++++ Scaling Up Begins ++++++++++++++++
2016-08-25 20:37:04,255 - autoscaler.autoscaling_groups - DEBUG - c4.2xlarge kubernetes-worker - 0 has no timeout


$ python main.py [options]
  • --cluster-name: Name of the Kubernetes cluster. Must match the value of the KubernetesCluster tag on Auto Scaling Groups.
  • --aws-regions: List of comma-separated regions in order of preference. E.g. us-west-2,us-east-1 will use "us-west-2" as the primary region and "us-east-1" as the secondary.
  • --kubeconfig: Path to kubeconfig YAML file. Leave blank if running in Kubernetes to use service account.
  • --pod-namespace: The namespace to look for out-of-resource pods in. By default, this will look in all namespaces.
  • --idle-threshold: This defines the maximum duration (in seconds) for an instance to be kept idle.
  • --type-idle-threshold: For each instance type, we keep a few running and idle so the cluster has spare capacity for different types of requests. This defines the maximum duration (in seconds) for an instance to be kept idle.
  • --aws-access-key: AWS access key. Can also be specified in environment variable AWS_ACCESS_KEY
  • --aws-secret-key: AWS secret access key. Can also be specified in environment variable AWS_SECRET_ACCESS_KEY
  • --use-aws-iam-role: (default: False) If you want to use IAM roles instead of aws credentials, set this to True
  • --instance-init-time: Maximum duration (in seconds) after an instance is launched before being considered unhealthy (running in EC2 but not joining the Kubernetes cluster)
  • --sleep: Time (in seconds) to sleep between scaling loops (to be careful not to run into AWS API limits)
  • --slack-hook: Optional Slack incoming webhook for scaling notifications
  • --dry-run: Flag for testing so resources aren't actually modified. Actions will instead be logged only.
  • -v: Sets the verbosity. Specify multiple times for more log output, e.g. -vvv



# in your virtual env
$ pip install -r requirements.txt
$ python main.py --aws-regions us-west-2,us-east-1,us-west-1 --cluster-name my-kubernetes --aws-access-key 'XXXXXXX' --aws-secret-key 'XXXXXXXXXXXXX' --dry-run -vvv --kubeconfig ~/.kube/config
$ nosetests test/


$ docker build -t autoscaler .
$ docker run -v $HOME/.kube/config:/root/.kube/config autoscaler python main.py --aws-regions us-west-2,us-east-1,us-west-1 --cluster-name my-kubernetes --aws-access-key 'XXXXXXXXX' --aws-secret-key 'XXXXXXXXXXXXX' --dry-run -vvv --kubeconfig /root/.kube/config
$ docker run -v $HOME/.kube/config:/root/.kube/config autoscaler nosetests test/