-
Notifications
You must be signed in to change notification settings - Fork 914
feat: implement autoscaling mechanism for prebuilds #18126
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
base: main
Are you sure you want to change the base?
Conversation
606894f
to
ff0e813
Compare
9af5e02
to
bcfbb04
Compare
3a25178
to
e0d1de7
Compare
80e52ee
to
47cb6fc
Compare
}) | ||
require.NoError(t, err, "insert preset") | ||
return preset | ||
} | ||
|
||
func PresetPrebuildSchedule(t testing.TB, db database.Store, seed database.InsertPresetPrebuildScheduleParams) database.TemplateVersionPresetPrebuildSchedule { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Typically dbgen
help funcs define default values when seed
is a zero value. Can you add those please?
CronExpression: seed.CronExpression, | ||
Instances: seed.Instances, | ||
}) | ||
require.NoError(t, err, "insert preset") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
require.NoError(t, err, "insert preset") | |
require.NoError(t, err, "insert preset prebuild schedule") |
@@ -0,0 +1,12 @@ | |||
-- Add autoscaling_timezone column to template_version_presets table | |||
ALTER TABLE template_version_presets | |||
ADD COLUMN autoscaling_timezone TEXT DEFAULT 'UTC' NOT NULL; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why do we need a default here, if the provider is not defining a default?
id UUID PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL, | ||
preset_id UUID NOT NULL, | ||
cron_expression TEXT NOT NULL, | ||
instances INTEGER NOT NULL, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit: to match template_version_presets
' definition.
instances INTEGER NOT NULL, | |
desired_instances INTEGER NOT NULL, |
@@ -69,3 +83,6 @@ SELECT tvp.*, tv.template_id, tv.organization_id FROM | |||
template_version_presets tvp | |||
INNER JOIN template_versions tv ON tvp.template_version_id = tv.id | |||
WHERE tvp.id = @preset_id; | |||
|
|||
-- name: GetPresetPrebuildSchedules :many | |||
SELECT * FROM template_version_preset_prebuild_schedules; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Don't we want to constrain this to schedules that are only associated to active template versions?
} | ||
|
||
// Look for a schedule whose cron expression matches the provided time | ||
for _, schedule := range p.PrebuildSchedules { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is my main reason for blocking this review. We have to deal with conflicting schedules here, explicitly.
If we take this current approach, and conflicting schedules are evaluated in different orders on each reconciliation loop, then that will cause a lot of churn by spinning up and down prebuilds if those schedules' instance counts differ.
spec: "* 9-18 * * 1-5", | ||
at: mustParseTime(t, time.RFC1123, "Mon, 02 Jun 2025 8:59:00 UTC"), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This would violate my expectations as an operator. If the autoscaling schedule is going to kick in 1m before my given cron expression, that would be quite surprising and unintuitive.
I think we should try address this shortcoming if we can.
Edit: I looked into the implementation and made some suggestions.
This test could also be more explicit about why 8:59:00
matches 9-18
.
|
||
//replace github.com/coder/terraform-provider-coder/v2 => /home/coder/terraform-provider-coder |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
//replace github.com/coder/terraform-provider-coder/v2 => /home/coder/terraform-provider-coder |
@@ -101,7 +101,8 @@ require ( | |||
github.com/coder/quartz v0.2.1 | |||
github.com/coder/retry v1.5.1 | |||
github.com/coder/serpent v0.10.0 | |||
github.com/coder/terraform-provider-coder/v2 v2.5.3 | |||
// TODO: release new provider version and set it here | |||
github.com/coder/terraform-provider-coder/v2 v2.5.4-0.20250611180058-d61894db8492 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Remember TODO.
The "continuous time" interpretation of the crontab makes it, I guess, relatively simple to specify spans that start and end on the hour, but consider attempting to program a span like 7:45am - 9:10am. You'd need 3 spans
Are we just kind of assuming that operators likely only want hourly precision? |
Co-authored-by: Danny Kopping <danny@coder.com>
…toscaling-mechanism
Closes coder/internal#312
Depends on coder/terraform-provider-coder#408
This PR adds support for defining an autoscaling block for prebuilds, allowing number of desired instances to scale dynamically based on a schedule.
Example usage:
Behavior
schedule
blocks perprebuilds
block are supported.prebuilds.instances
) is used as a fallback.Why
This feature allows prebuild instance capacity to adapt to predictable usage patterns, such as:
Cron specification
The cron specification is interpreted as a continuous time range.
For example, the expression:
is intended to represent a continuous range from 09:00 to 18:59, Monday through Friday.
However, due to minor implementation imprecision, it is currently interpreted as a range from 08:59:00 to 18:58:59, Monday through Friday.
This slight discrepancy arises because the evaluation is based on whether a specific point in time falls within the range, using the
github.com/coder/coder/v2/coderd/schedule/cron
library, which performs per-minute matching rather than strict range evaluation.