Skip to content

[BUG] BYO agent deployments.go always defaults replicas to 1, breaking HPA integration #1844

@logeshs92

Description

@logeshs92

📋 Prerequisites

  • I have searched the existing issues to avoid creating a duplicate
  • By submitting this issue, you agree to follow our Code of Conduct
  • I am using the latest version of the software
  • I have tried to clear cache/cookies or used incognito mode (if ui-related)
  • I can consistently reproduce this issue

🎯 Affected Service(s)

Not Sure

🚦 Impact/Severity

No impact (Default)

🐛 Bug Description

For type: BYO agents, the kagent controller continuously overrides HPA-managed replica counts, causing a fight loop between the HPA and the controller. The Deployment replicas are reset to 1 on every reconcile cycle even when replicas is intentionally omitted from the Agent CR.

🔄 Steps To Reproduce

Deploy a type: BYO Agent without a replicas field in spec.byo.deployment
Attach a Kubernetes HPA targeting the kagent-created Deployment with minReplicas: 2
Observe kubectl describe deployment -n kagent events — the controller repeatedly scales down what the HPA scales up

🤔 Expected Behavior

When replicas is not set in spec.byo.deployment, the controller should leave the Deployment's replica count untouched, allowing an HPA (or KEDA) to own replica management — consistent with the HPA-awareness comment already present in mutate.go.

📱 Actual Behavior

The controller resets the Deployment to 1 replica on every reconcile, overriding any HPA scaling. Observed in Deployment events:

Scaled up replica set xxxx-agent-v1-xxx from 1 to 2 ← HPA
Scaled down replica set xxxx-agent-v1-xxx from 2 to 1 ← controller
Scaled up replica set xxxx-agent-v1-xxx from 1 to 2 ← HPA
Scaled down replica set xxxx-agent-v1-xxx from 2 to 1 ← controller
(repeating every ~2 minutes)

💻 Environment

kagent version: v1alpha2
Agent type: BYO
Kubernetes: GKE

🔧 CLI Bug Report

No response

🔍 Additional Context

Root cause

go/core/internal/controller/translator/agent/deployments.go in resolveByoDeployment() always fills in a default of 1 when spec.Replicas is nil:

replicas := spec.Replicas
if replicas == nil {
replicas = new(int32(1)) // ← forces replicas=1 into desired Deployment
}
This means desired.Spec.Replicas is never nil for BYO agents. As a result, the guard in mutate.go always fires and overrides:

if desired.Spec.Replicas != nil {
// only set replicas if explicitly specified, so not to override HPA settings
existing.Spec.Replicas = desired.Spec.Replicas // always triggers for BYO
}
The HPA-awareness in mutate.go works correctly in isolation but is bypassed for BYO agents because deployments.go prevents Replicas from ever being nil.

Note: This does not affect type: Declarative agents where this default-filling logic is absent.

Suggested fix

Remove the default fallback in deployments.go so that a nil spec.Replicas propagates through to the desired Deployment spec, allowing mutate.go's existing HPA-awareness check to function as intended:

// Before
replicas := spec.Replicas
if replicas == nil {
replicas = new(int32(1))
}

// After
replicas := spec.Replicas
// Leave nil if unset — mutate.go will preserve existing (HPA-managed) replicas

📋 Logs

📷 Screenshots

No response

🙋 Are you willing to contribute?

  • I am willing to submit a PR to fix this issue

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    Projects

    Status

    Backlog

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions