autoscaler

package
v0.1.7 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Apr 16, 2026 License: Apache-2.0 Imports: 12 Imported by: 0

Documentation

Overview

pkg/autoscaler/autoscale_metrics.go

AutoMetrics — live operatorbox metrics read directly from the runtime.

The autoscaler evaluates conditions against these metrics on every tick. All reads are atomic — no locks, no API calls, no informer lookups.

Metric fields are exposed under the "metrics.*" namespace in autoscale conditions and resolve through AutoMetrics.Get(field).

pkg/autoscaler/autoscale_semaphore.go

ResizableSemaphore — a weighted semaphore whose capacity can be changed at runtime.

The worker pool in Orkestra is gated by this semaphore rather than being a fixed goroutine count. All worker goroutines run continuously in a loop; the semaphore controls how many may enter the reconcile section simultaneously.

Increasing capacity: new goroutines can acquire immediately. Decreasing capacity: goroutines currently inside reconcile finish their current work. Goroutines blocked at Acquire wait until capacity is available. In-flight reconciles are never interrupted.

This is the correct primitive for operator autoscaling because:

  • Resize is O(1) — no goroutine creation or cancellation
  • In-flight reconciles complete cleanly after a scale-down
  • The semaphore is the single source of truth for concurrency

pkg/autoscaler/autoscaler.go

Operatorbox autoscaler — evaluates conditions on a ticker and applies or restores worker/queue/resync overrides.

One Autoscaler is created per operatorbox that declares autoscale: in its operatorBox: block. It runs a single goroutine for the lifetime of the operatorbox and stops cleanly when the context is cancelled.

The autoscaler has no persistent state. A restart always begins from the declared CRD baseline. Overrides applied before a restart are lost — the next evaluation tick will re-apply them if conditions are still met.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func IsMetricField

func IsMetricField(field string) bool

IsMetricField returns true when the field path refers to an autoscale metric. Used by the condition resolver to route metric lookups to AutoMetrics.Get.

Types

type AutoMetrics

type AutoMetrics struct {
	// contains filtered or unexported fields
}

AutoMetrics holds live operatorbox runtime metrics for autoscale evaluation. All counters are atomic int64 values — safe for concurrent read/write from worker goroutines and the autoscaler loop.

func NewAutoMetrics

func NewAutoMetrics(sem *ResizableSemaphore) *AutoMetrics

NewAutoMetrics returns an initialised AutoMetrics for the given semaphore.

func (*AutoMetrics) AsMap

func (m *AutoMetrics) AsMap() map[string]interface{}

func (*AutoMetrics) ErrorRatePercent

func (m *AutoMetrics) ErrorRatePercent() float64

ErrorRatePercent returns the curent error rate i percentage

func (*AutoMetrics) Get

func (m *AutoMetrics) Get(field string) string

Get returns the string representation of a metric field for condition evaluation. Field names follow the metrics.* convention:

metrics.workersBusyPercent   → "73.5"
metrics.workersIdlePercent   → "26.5"
metrics.queueDepth           → "342"
metrics.reconcileDurationP95Ms → "47"
metrics.errorRatePercent     → "0.2"

Returns "" for unknown fields — evaluates as notExists in condition checks.

func (*AutoMetrics) RecordReconcile

func (m *AutoMetrics) RecordReconcile(duration time.Duration, failed bool)

RecordReconcile records one completed reconcile with its duration and outcome. Called at the end of every reconcile, success or failure.

func (*AutoMetrics) SetQueueDepth

func (m *AutoMetrics) SetQueueDepth(depth int64)

SetQueueDepth updates the current queue depth. Called by the workqueue wrapper on every enqueue and dequeue.

type AutoscaleTarget

type AutoscaleTarget interface {
	// ResizeWorkers adjusts the worker pool to the given concurrency.
	ResizeWorkers(n int)

	// SetQueueDepthLimit adjusts the maximum queue depth.
	SetQueueDepthLimit(n int)

	// SetResyncInterval adjusts how frequently all CRs are re-enqueued.
	SetResyncInterval(d time.Duration)
}

AutoscaleTarget is implemented by the operatorbox runtime components that the autoscaler controls. Kept minimal — autoscaler only calls these three methods, nothing else.

type Autoscaler

type Autoscaler struct {
	// contains filtered or unexported fields
}

Autoscaler evaluates conditions and applies/restores overrides for one operatorbox.

func NewAutoscaler

func NewAutoscaler(
	crdKind string,
	spec *orktypes.AutoscaleSpec,
	baseline orktypes.AutoscaleBaseline,
	target AutoscaleTarget,
	metrics *AutoMetrics,
) *Autoscaler

NewAutoscaler constructs an Autoscaler for one operatorbox. baseline is captured from the CRD's declared configuration before startup.

func (*Autoscaler) Run

func (a *Autoscaler) Run(ctx context.Context)

Run starts the autoscale evaluation loop. Blocks until ctx is cancelled. Intended to be called in a dedicated goroutine.

type ResizableSemaphore

type ResizableSemaphore struct {
	// contains filtered or unexported fields
}

ResizableSemaphore is a counting semaphore whose capacity can be changed at runtime without interrupting goroutines currently holding a token.

func NewResizableSemaphore

func NewResizableSemaphore(capacity int) *ResizableSemaphore

NewResizableSemaphore returns a semaphore with the given initial capacity.

func (*ResizableSemaphore) Acquire

func (s *ResizableSemaphore) Acquire(ctx context.Context) error

Acquire acquires one token, blocking until one is available or ctx is done. Returns ctx.Err() if the context is cancelled while waiting.

func (*ResizableSemaphore) BusyPercent

func (s *ResizableSemaphore) BusyPercent() float64

BusyPercent returns the percentage of capacity currently in use.

func (*ResizableSemaphore) Capacity

func (s *ResizableSemaphore) Capacity() int

Capacity returns the current capacity.

func (*ResizableSemaphore) Current

func (s *ResizableSemaphore) Current() int

Current returns the current number of tokens.

func (*ResizableSemaphore) IdlePercent

func (s *ResizableSemaphore) IdlePercent() float64

IdlePercent returns the percentage of capacity currently available.

func (*ResizableSemaphore) InFlight

func (s *ResizableSemaphore) InFlight() int

InFlight returns the number of tokens currently held (goroutines inside reconcile).

func (*ResizableSemaphore) Release

func (s *ResizableSemaphore) Release()

Release releases one token and notifies a waiter if any are queued.

func (*ResizableSemaphore) Resize

func (s *ResizableSemaphore) Resize(newCap int)

Resize changes the semaphore capacity.

Scale up (newCap > old): immediately notifies waiting goroutines up to the new capacity. Each notification allows one waiter to proceed.

Scale down (newCap < old): the new capacity takes effect immediately for new Acquire calls. Goroutines already holding tokens complete their work normally — they are not interrupted. The effective concurrency converges to newCap as holders release.

Resize is safe to call concurrently with Acquire and Release.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL