Skip to content
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
1 change: 0 additions & 1 deletion api/v1/deployment_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@ type ApplicationSpec struct {
// Ignored when HorizontalPodAutoscaler is configured.
// +optional
// +kubebuilder:validation:Minimum=0
// +kubebuilder:default=1
Replicas *int32 `json:"replicas,omitempty"`

// Resources specifies compute resource requirements.
Expand Down
19 changes: 19 additions & 0 deletions api/v1/logicflowruntime_webhook.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,25 @@ import (
"sigs.k8s.io/controller-runtime/pkg/webhook/admission"
)

// +kubebuilder:webhook:path=/mutate-logic-kubesmarts-org-v1-logicflowruntime,mutating=true,failurePolicy=fail,sideEffects=None,groups=logic.kubesmarts.org,resources=logicflowruntimes,verbs=create;update,versions=v1,name=mlogicflowruntime-v1.kb.io,admissionReviewVersions=v1

// +kubebuilder:object:generate=false
type LogicFlowRuntimeDefaulter struct{}

var _ admission.Defaulter[*LogicFlowRuntime] = &LogicFlowRuntimeDefaulter{}

// Default sets Replicas to 1 if not specified.
// We use a webhook instead of +kubebuilder:default=1 because ApplicationSpec is also used by LogicPlatform.DataIndex,
// which needs to support HPA management without operator enforcement. The webhook allows us to apply the default
// conditionally only for LogicFlowRuntime, leaving DataIndex.Application.Replicas nil for HPA to manage freely.
func (d *LogicFlowRuntimeDefaulter) Default(_ context.Context, obj *LogicFlowRuntime) error {
if obj.Spec.Replicas == nil {
one := int32(1)
obj.Spec.Replicas = &one
}
return nil
}

// +kubebuilder:webhook:path=/validate-logic-kubesmarts-org-v1-logicflowruntime,mutating=false,failurePolicy=fail,sideEffects=None,groups=logic.kubesmarts.org,resources=logicflowruntimes,verbs=create;update,versions=v1,name=vlogicflowruntime-v1.kb.io,admissionReviewVersions=v1

type LogicFlowRuntimeValidator struct{}
Expand Down
1 change: 1 addition & 0 deletions api/v1/webhook_integration_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@ func TestWebhookIntegration(t *testing.T) {
t.Fatalf("register LFD webhook: %v", err)
}
if err := builder.WebhookManagedBy(mgr, &LogicFlowRuntime{}).
WithDefaulter(&LogicFlowRuntimeDefaulter{}).
WithValidator(&LogicFlowRuntimeValidator{}).
Complete(); err != nil {
t.Fatalf("register LFR webhook: %v", err)
Expand Down
1 change: 1 addition & 0 deletions cmd/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -248,6 +248,7 @@ func main() {
os.Exit(1)
}
if err := builder.WebhookManagedBy(mgr, &logicv1.LogicFlowRuntime{}).
WithDefaulter(&logicv1.LogicFlowRuntimeDefaulter{}).
WithValidator(&logicv1.LogicFlowRuntimeValidator{}).
Complete(); err != nil {
setupLog.Error(err, "unable to create webhook", "webhook", "LogicFlowRuntime")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9474,7 +9474,6 @@ spec:
type: array
type: object
replicas:
default: 1
description: |-
Replicas is the desired number of pod replicas.
Ignored when HorizontalPodAutoscaler is configured.
Expand Down
3 changes: 0 additions & 3 deletions config/crd/bases/logic.kubesmarts.org_logicplatforms.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -9500,7 +9500,6 @@ spec:
type: array
type: object
replicas:
default: 1
description: |-
Replicas is the desired number of pod replicas.
Ignored when HorizontalPodAutoscaler is configured.
Expand Down Expand Up @@ -19276,7 +19275,6 @@ spec:
type: array
type: object
replicas:
default: 1
description: |-
Replicas is the desired number of pod replicas.
Ignored when HorizontalPodAutoscaler is configured.
Expand Down Expand Up @@ -28834,7 +28832,6 @@ spec:
type: array
type: object
replicas:
default: 1
description: |-
Replicas is the desired number of pod replicas.
Ignored when HorizontalPodAutoscaler is configured.
Expand Down
20 changes: 20 additions & 0 deletions config/webhook/manifests.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,26 @@ kind: MutatingWebhookConfiguration
metadata:
name: mutating-webhook-configuration
webhooks:
- admissionReviewVersions:
- v1
clientConfig:
service:
name: webhook-service
namespace: system
path: /mutate-logic-kubesmarts-org-v1-logicflowruntime
failurePolicy: Fail
name: mlogicflowruntime-v1.kb.io
rules:
- apiGroups:
- logic.kubesmarts.org
apiVersions:
- v1
operations:
- CREATE
- UPDATE
resources:
- logicflowruntimes
sideEffects: None
- admissionReviewVersions:
- v1
clientConfig:
Expand Down
72 changes: 70 additions & 2 deletions docs/antora/modules/ROOT/pages/deployment/production.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -90,13 +90,81 @@ spec:

== Horizontal Pod Autoscaling

The operator sets `spec.replicas` on the managed `Deployment`.
Create an `HorizontalPodAutoscaler` targeting that `Deployment` to scale based on CPU or custom metrics.
The operator exposes the Kubernetes scale subresource on LogicFlowRuntime and does not enforce default replicas on LogicPlatform.DataIndex, enabling HPA management for both.

=== LogicFlowRuntime Autoscaling

Target LogicFlowRuntime directly (not the Deployment).
HPA updates `spec.replicas` on the CR, which the operator uses to reconcile both the Deployment AND lease pool.
If you target the Deployment directly, leases won't track replica changes.

Example HPA for a LogicFlowRuntime named `hello-runtime`:

[source,yaml]
----
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: hello-runtime-autoscaler
namespace: default
spec:
scaleTargetRef:
apiVersion: logic.kubesmarts.org/v1
kind: LogicFlowRuntime
name: hello-runtime
minReplicas: 1
maxReplicas: 10
metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 70
----

[NOTE]
====
When PostgreSQL persistence is enabled, scale-up is safe — leases ensure each workflow instance is owned by exactly one pod.
Without persistence, scale-up creates duplicate in-memory state for in-flight workflows.

The operator manages lease assignment/cleanup automatically when replica count changes.
====

=== Data Index Autoscaling

Target the generated Data Index Deployment directly (`flow-platform-data-index` or similar).
Leave `spec.dataIndex.application.replicas` unset in LogicPlatform so the operator doesn't enforce a value.

Example HPA for Data Index:

[source,yaml]
----
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: data-index-autoscaler
namespace: data-index-system
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: flow-platform-data-index # Deployment created by operator
minReplicas: 1
maxReplicas: 5
metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 75
----

[NOTE]
====
Do not set `spec.dataIndex.application.replicas` when using HPA.
The operator respects the value if set, but will override HPA scaling.
====

== cert-manager
Expand Down
Loading