The project is a metrics-based autoscaler for Fly.io. The autoscaler supports polling for metrics from a Prometheus instance and then computing the number of machines based on those metrics.
The Fly Autoscaler works by performing a reconciliation loop on a regular interval. By default, it runs every 15 seconds.
-
Collect metrics from external systems (e.g. Prometheus)
-
Compute the target number of machines based on a user-provided expression.
-
Fetch a list of all Fly Machines for your application.
-
If the target number of machines is less than the number of
startedmachines, use the Fly Machines API to start new machines.
┌────────────────────┐
fly-autoscaler ──────────┐ │ │
│ ┌────────────────────┐ │ ┌──────│ Prometheus │
│ │ │ │ │ │ │
│ │ Metric Collector │◀┼────┘ └────────────────────┘
│ │ │ │
│ └──────┬─────────────┘ │
│ │ △ │
│ ▽ │ │
│ ┌────────────┴───────┐ │
│ │ │ │
│ │ Reconciler │◀┼────┐
│ │ │ │ │ ┌────────────────────┐
│ └────────────────────┘ │ │ │ │
└────────────────────────┘ └─────▶│ Fly Machines API │
│ │
└────────────────────┘
The autoscaler uses the Expr language to define the target number of machines. See the Expr Language Definition for syntax and a full list of built-in functions. The expression can utilize any named metrics that you collect and it should always return a number.
For example, if you poll for queue depth and each machine can handle 10 queue items at a time, you can compute the number of machines as:
ceil(queue_depth / 10)
The autoscaler can only start machines so it will never exceed the number of machines available for a Fly app.
First, create an app for your autoscaler:
$ fly apps create my-autoscalerThen create a fly.toml for the deployment. Update the TARGET_APP_NAME with
the name of the app that you want to scale and update MY_ORG to the
organization where your Prometheus metrics live.
app = "my-autoscaler"
[build]
image = "flyio/fly-autoscaler:0.2"
[env]
FAS_APP_NAME = "TARGET_APP_NAME"
FAS_STARTED_MACHINE_COUNT = "ceil(queue_depth / 10)"
FAS_PROMETHEUS_ADDRESS = "https://api.fly.io/prometheus/MY_ORG"
FAS_PROMETHEUS_METRIC_NAME = "queue_depth"
FAS_PROMETHEUS_QUERY = "sum(queue_depth)"
[metrics]
port = 9090
path = "/metrics"Next, set up a new deploy token for the application you want to scale:
$ fly tokens create deploy -a TARGET_APP_NAMESet the token as a secret on your application:
$ fly secrets set FAS_API_TOKEN="FlyV1 ..."
Create a token for reading your Prometheus data:
$ fly tokens create readonlySet the token as a secret on your application:
$ fly secrets set FAS_PROMETHEUS_TOKEN="FlyV1 ..."
Finally, deploy your autoscaler application:
$ fly deployThis should create a new machine and start it with the fly-autoscaler server
running.
You can perform a one-time run of metrics collection & expression evaluation for
testing or debugging purposes by using the eval command. This command does not
perform any scaling of Fly Machines. It will only print the evaluated expression
based on current metrics numbers.
$ fly-autoscaler evalYou can change the evaluated expression by setting an environment variable:
$ FAS_STARTED_MACHINE_COUNT=queue_depth fly-autoscaler evalYou can also configure fly-autoscaler with a YAML config file if you don't
want to use environment variables or if you want to configure more than one
metric collector.
Please see the reference fly-autoscaler.yml for more details.