Skip to content
Open
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
4 changes: 2 additions & 2 deletions charts/base/Chart.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,13 @@ type: application
# This is the chart version. This version number should be incremented each time you make changes
# to the chart and its templates, including the app version.
# Versions are expected to follow Semantic Versioning (https://semver.org/)
version: 0.3.28
version: 0.3.29

# This is the version number of the application being deployed. This version number should be
# incremented each time you make changes to the application. Versions are not expected to
# follow Semantic Versioning. They should reflect the version the application is using.
# It is recommended to use it with quotes.
appVersion: "0.3.28"
appVersion: "0.3.29"

dependencies:
- name: gateway-api
Expand Down
62 changes: 62 additions & 0 deletions charts/base/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -645,6 +645,68 @@ autoscaling:
awsRegion: <aws-region>
```

### Migrating from plain HPA to KEDA without deleting the existing HPA

When this chart is rendered with `autoscaling.enabled: true` and no `trigger`/`triggers`,
it produces a plain `HorizontalPodAutoscaler` named `{{ include "base.fullname" . }}`.
When `triggers` is set, the same template path produces a KEDA `ScaledObject` with the
same name. Flipping a release between the two modes via `helm upgrade` is rejected by
KEDA's `vscaledobject.kb.io` admission webhook because the same-named HPA still exists
when the new ScaledObject is created (Helm creates new resources before deleting old
ones during upgrade). See [kedacore/keda#6250](https://github.com/kedacore/keda/issues/6250)
for background.

The chart now exposes the two fields KEDA's
[transfer-hpa-ownership](https://keda.sh/docs/2.19/concepts/scaling-deployments/#transfer-ownership-of-an-existing-hpa)
migration path needs:

```yaml
autoscaling:
enabled: true
minReplicas: 2
maxReplicas: 50
scaledObjectAnnotations:
scaledobject.keda.sh/transfer-hpa-ownership: "true"
hpaName: my-release-name # must match the existing HPA's metadata.name
triggers:
- type: cpu
metricType: Utilization
metadata:
value: "70"
```

With the annotation, the webhook skips its duplicate-HPA check, and KEDA claims the
existing HPA in place by rewriting its `ownerReferences`.

There is one residual subtlety: Helm still deletes the old HPA at the end of the
upgrade (because the chart no longer renders an HPA template when `triggers` is set),
which leaves a brief metrics-blind window of up to `pollingInterval` seconds before
KEDA's reconciler recreates the HPA. The deployment's replica count stays put during
this window because Kubernetes does not autoscale a Deployment without an autoscaler;
only metrics evaluation pauses.

For a zero-gap migration, also tell Helm to keep the old HPA before the upgrade:

```bash
kubectl annotate hpa/<existing-hpa-name> -n <namespace> helm.sh/resource-policy=keep
helm upgrade <release> dasmeta/base --version <new-version> -f values.yaml
```

After the upgrade has completed and KEDA owns the HPA, you can remove the annotation:

```bash
kubectl annotate hpa/<existing-hpa-name> -n <namespace> helm.sh/resource-policy-
```

#### Reverse direction (KEDA → plain HPA)

There is no equivalent transfer mechanism for going back from a `ScaledObject` to a
plain HPA via this chart. KEDA owns its managed HPA via `ownerReferences`, so deleting
the `ScaledObject` triggers garbage collection of the underlying HPA. Tracking issue:
[kedacore/keda#6250](https://github.com/kedacore/keda/issues/6250). If you need to
reverse, expect to manually recreate the HPA after the chart upgrade has removed the
ScaledObject.

### custom rollout strategy(canary,blue/gree) configs by using flagger
```yaml
# This config allows to enable custom rollout strategies by using different providers/operators
Expand Down
13 changes: 11 additions & 2 deletions charts/base/templates/keda.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,10 @@ metadata:
name: {{ include "base.fullname" . }}
labels:
{{- include "base.labels" . | nindent 4 }}
{{- with .Values.autoscaling.scaledObjectAnnotations }}
annotations:
{{- toYaml . | nindent 4 }}
{{- end }}
spec:
scaleTargetRef:
name: {{ include "base.fullname" . }}
Expand Down Expand Up @@ -42,10 +46,15 @@ spec:
{{ $key }}: "{{ $value }}"
{{- end }}
{{- end }}
{{- if .Values.autoscaling.behavior }}
{{- if or .Values.autoscaling.behavior .Values.autoscaling.hpaName }}
advanced:
horizontalPodAutoscalerConfig:
{{- with .Values.autoscaling.hpaName }}
name: {{ . }}
{{- end }}
{{- with .Values.autoscaling.behavior }}
behavior:
{{ toYaml .Values.autoscaling.behavior | nindent 8 }}
{{ toYaml . | nindent 8 }}
{{- end }}
{{- end }}
{{- end }}
29 changes: 29 additions & 0 deletions charts/base/values.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -240,6 +240,16 @@ autoscaling:
maxReplicas: 100
targetCPUUtilizationPercentage: 80

# Optional. Annotations to apply to the rendered ScaledObject (KEDA mode only).
# Useful for KEDA's transfer-hpa-ownership migration path.
# scaledObjectAnnotations:
# scaledobject.keda.sh/transfer-hpa-ownership: "true"

# Optional. Custom name for the HPA that KEDA manages on behalf of the ScaledObject.
# Defaults to "keda-hpa-{release-name}". Set to the existing HPA's name when migrating
# from plain HPA to KEDA via transfer-hpa-ownership (see README).
# hpaName: my-existing-hpa

# Optional HPA scale up/down behavior (Kubernetes autoscaling/v2+).
# If set, it will be rendered under `spec.behavior` in the generated HPA.
#
Expand Down Expand Up @@ -314,6 +324,25 @@ autoscaling:
# queueName: my-queue
# queueLength: "50"

# Example: Migrate an existing plain HPA to a KEDA ScaledObject without manually
# deleting the old HPA. KEDA's vscaledobject.kb.io webhook normally rejects creating
# a ScaledObject when an HPA already manages the same workload; the transfer-hpa-ownership
# annotation, paired with `hpaName` matching the existing HPA's name, tells KEDA to
# claim the existing HPA in place. See charts/base/README.md for the full recipe
# (including the optional `helm.sh/resource-policy: keep` step for zero-gap migration).
# autoscaling:
# enabled: true
# minReplicas: 2
# maxReplicas: 50
# scaledObjectAnnotations:
# scaledobject.keda.sh/transfer-hpa-ownership: "true"
# hpaName: my-release-name # must match the existing HPA's metadata.name
# triggers:
# - type: cpu
# metricType: Utilization
# metadata:
# value: "70"

nodeSelector: {}

tolerations: []
Expand Down
Loading