keda icon indicating copy to clipboard operation
keda copied to clipboard

Add support for templating in `spec.triggers.metadata.query`

Open aryan9600 opened this issue 2 years ago • 9 comments

Proposal

It'd be great if Keda allowed users to use templates instead of hardcoding the target deployment name in the query when using a scaler like Prometheus. Something along the lines of:

triggers:
  - type: prometheus
    metadata:
      serverAddress: http://<prometheus-host>:9090
      metricName: http_requests_total
      threshold: '100'
      query: sum(rate(http_requests_total{deployment="{{ target-deployment }}"}[2m]))

Keda could then refer to .spec.scaleTargetRef to get the actual value and insert it into the query before running the query. This would enable other operators to interact with ScaledObjects in a cleaner manner.

Use-Case

This would help a controller in creating a ScaledObject for a deployment based on an existing user provided ScaledObject for a different deployment. Right now, copying over the spec of the existing ScaledObject (and inherently the query for the scaler) would lead to the new ScaledObject to scale based on the query meant for the other deployment. This would force some kind of a best effort attempt at modifying the query suitable for the new ScaledObject, which is error prone. Adding support for templates, makes it easier for controllers by letting them just copy pasting the spec and eliminates the need for any hacky query modification.

Anything else?

No response

aryan9600 avatar Mar 14 '22 11:03 aryan9600

I am not a big fan of this. .spec.scaleTargetRef of the ScaledObject need to be specified anyway. You can automate generation of ScaledObjects, so if you are specifying .spec.scaleTargetRef then it is not so problematic to specify the same value anywhere in the metadata.

zroubalik avatar Mar 16 '22 14:03 zroubalik

Specifying .spce.scaleTargetRef in the to be generated ScaledObject is rather simple, you just use the name of the deployment you want to target. Since right now we have to hard code the deployment name in the query, figuring out the right query for the to be generated ScaledObject on the other hand could be a much more complex task, as it would involve parsing the original query, doing some regex on it and making a guess about where to modify the deployment name in the query, which is error prone and could lead to potentially unexpected behavior.

aryan9600 avatar Mar 16 '22 17:03 aryan9600

The point is that AFAIR, right now that information is not passed to the scalers, so we have to pass extra information to all the scalers that is only needed in 1 edge case inside one of them. TBH, I don't like a lot of this because it opens the door to pass other internal information that scalers shouldn't have. I mean, why not the min and max replicas? Or in your same case, why not the API version also apart from the name?

I agree with @zroubalik here, if you have an automatism to add .spec.scaleTargetRef, the same variable could be used to replace it in the metadata.

JorTurFer avatar Mar 24 '22 08:03 JorTurFer

I kinda prefer what ArgoRollout did with AnalysisTemplate

apiVersion: argoproj.io/v1alpha1
kind: AnalysisTemplate
metadata:
  name: success-rate
spec:
  args:
  - name: application-name
  metrics:
  - name: success-rate
    successCondition: result.successRate >= 0.95
    provider:
      newRelic:
        profile: my-newrelic-secret  # optional, defaults to 'newrelic'
        query: |
          FROM Transaction SELECT percentage(count(*), WHERE httpResponseCode != 500) as successRate where appName = '{{ args.application-name }}'

^ spec.args seems like something that could workout anywhere for any query or type.

pragmaticivan avatar May 06 '22 20:05 pragmaticivan

Perhaps key/value with defaults would work well enough here?

- name: application-name
  value: myapp

pragmaticivan avatar May 06 '22 20:05 pragmaticivan

Not sure how far it could get, but here's what I think would be ideal to have args support:

apiVersion: keda.sh/v1alpha1
kind: ScaledObject
metadata:
  name: nr-rollouts-demo
spec:
  maxReplicaCount: 15
  args:
    - name: app-name
       value: 'myapp'
    - name: canary-pod-hash
       value: 'hash'
    - name: since
       value: '30 seconds'
  scaleTargetRef:
    name: rollouts-demo
  triggers:
  - type: new-relic
    metadata:
      account: 'accnum'
      nrql: "SELECT rate(count(apm.service.transaction.duration), 1 second) as 'Web throughput' FROM Metric WHERE (appName = '{{ args.app-name }}') AND (host like '{{ args.app-name }}-{{ args.canary-pod-hash }}-%') AND (transactionType = 'Web')  SINCE {{ args.since }} UNTIL NOW"
      noDataError: "true"
      threshold: '10'
    authenticationRef:
      name: keda-trigger-auth-new-relic

A Rollout/Canary system could inject args to be used/replaced in the query above.

pragmaticivan avatar May 08 '22 03:05 pragmaticivan

Interesting, is this something you are willing to contribute?

zroubalik avatar May 30 '22 12:05 zroubalik

This issue has been automatically marked as stale because it has not had recent activity. It will be closed in 7 days if no further activity occurs. Thank you for your contributions.

stale[bot] avatar Jul 29 '22 20:07 stale[bot]

This issue has been automatically closed due to inactivity.

stale[bot] avatar Aug 08 '22 07:08 stale[bot]