Skip to content

feat: add automatic deploy dependency detection for KEDA ScaledObjects#631

Merged
ilya-lesikov merged 3 commits into
werf:mainfrom
Sharvash:feat/scaledobject-deploy-dependency
Jun 15, 2026
Merged

feat: add automatic deploy dependency detection for KEDA ScaledObjects#631
ilya-lesikov merged 3 commits into
werf:mainfrom
Sharvash:feat/scaledobject-deploy-dependency

Conversation

@Sharvash

@Sharvash Sharvash commented Jun 4, 2026

Copy link
Copy Markdown
Contributor

nelm now automatically deploys a KEDA ScaledObject after the workload referenced by its spec.scaleTargetRef, so the ordering no longer has to be declared by hand.

Previously, when a ScaledObject and its target workload (e.g. a Deployment) belonged to the same release, nelm put both in the same deploy stage with no ordering between them. If the ScaledObject reached the API server before its target existed, the install broke in one of two ways:

  • with a cpu/memory trigger, KEDA's validating webhook resolves the target and denies the request (the error reported in KEDA ScaledObject is trying to be deployed before deployment #456): admission webhook "vscaledobject.kb.io" denied the request: Deployment.apps "app" not found
  • with any other trigger the object is admitted, but the KEDA controller cannot reconcile it and it stays Ready=False with reason=ScaledObjectCheckFailed

The only way around it was a manual dependency annotation:

werf.io/deploy-dependency-app: state=present,kind=Deployment,name=app

internalDeployDependencies already derives implicit dependencies for built-in workloads, RBAC bindings and others. This adds a keda.sh/ScaledObject case that reads spec.scaleTargetRef and emits a present dependency on the referenced workload:

  • name - required; if it is missing the ScaledObject is left untouched
  • kind - defaults to Deployment
  • apiVersion - defaults to apps/v1, and the group is parsed from it

The dependency is present, not ready: nelm waits only for the target to exist, which is all KEDA needs, instead of blocking on its readiness. ScaledJob is intentionally left out — it uses jobTargetRef and creates its own Jobs, so it has no such dependency.

Verified against a live cluster running KEDA: with the change the ScaledObject is always created after its target and reconciles cleanly, and the #456 webhook denial reproduces without it.

Closes #456

@Sharvash Sharvash force-pushed the feat/scaledobject-deploy-dependency branch from 1fffaab to d79d614 Compare June 4, 2026 12:04
nelm now automatically deploys a KEDA `ScaledObject` after the workload referenced by its `spec.scaleTargetRef`, so the ordering no longer has to be declared by hand.

Previously, when a `ScaledObject` and its target workload (e.g. a `Deployment`) belonged to the same release, nelm put both in the same deploy stage with no ordering between them. If the `ScaledObject` reached the API server before its target existed, the install broke in one of two ways:
- with a `cpu`/`memory` trigger, KEDA's validating webhook resolves the target and denies the request (the error reported in werf#456): `admission webhook "vscaledobject.kb.io" denied the request: Deployment.apps "app" not found`
- with any other trigger the object is admitted, but the KEDA controller cannot reconcile it and it stays `Ready=False` with `reason=ScaledObjectCheckFailed`

The only way around it was a manual dependency annotation:
```yaml
werf.io/deploy-dependency-app: state=present,kind=Deployment,name=app
```

`internalDeployDependencies` already derives implicit dependencies for built-in workloads, RBAC bindings and others. This adds a `keda.sh/ScaledObject` case that reads `spec.scaleTargetRef` and emits a `present` dependency on the referenced workload:
- `name` - required; if it is missing the `ScaledObject` is left untouched
- `kind` - defaults to `Deployment`
- `apiVersion` - defaults to `apps/v1`, and the group is parsed from it

The dependency is `present`, not `ready`: nelm waits only for the target to exist, which is all KEDA needs, instead of blocking on its readiness. `ScaledJob` is intentionally left out — it uses `jobTargetRef` and creates its own Jobs, so it has no such dependency.

Verified against a live cluster running KEDA: with the change the `ScaledObject` is always created after its target and reconciles cleanly, and the werf#456 webhook denial reproduces without it.

Closes werf#456

Signed-off-by: Alexey Gorovenko <sharvashinho@gmail.com>
@Sharvash Sharvash force-pushed the feat/scaledobject-deploy-dependency branch from f03eb31 to 799c021 Compare June 6, 2026 12:16
@ilya-lesikov

Copy link
Copy Markdown
Member

Hi, please, resolve conflicts, but don't force-push anymore, otherwise I need to look at all the commits again.

@ilya-lesikov ilya-lesikov merged commit 6ccf7ec into werf:main Jun 15, 2026
8 checks passed
@ilya-lesikov

Copy link
Copy Markdown
Member

Thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

KEDA ScaledObject is trying to be deployed before deployment

2 participants