Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Possibility to bring in pluggable and shareable trait configuration #4271

Closed
mertdotcc opened this issue Apr 25, 2023 · 9 comments
Closed

Possibility to bring in pluggable and shareable trait configuration #4271

mertdotcc opened this issue Apr 25, 2023 · 9 comments
Assignees
Labels

Comments

@mertdotcc
Copy link
Contributor

mertdotcc commented Apr 25, 2023

The title might not be 100% on point so you guys feel free to change it.

Consider the following kamel run command:

kamel run \
--config configmap:my-configmap/platform.baseUrl \
--config secret:my-secret/platform.auth-token \
--open-api file:./resources/platform-openapi.yaml \
--resource file:./resources/platform-template-response.json \
--resource file:./resources/sample-error-response.json \
--dependency mvn:org.mapstruct:mapstruct:1.5.2.Final \
--dependency mvn:com.fasterxml.jackson.datatype:jackson-datatype-jsr310:2.14.2 \
--dependency camel:jackson
--source ./sources/PlatformBean.java \
--trait container.enabled=true \
--trait container.request-cpu="100m" \
--trait container.request-memory="128Mi" \
--trait container.limit-cpu="250m" \
--trait container.limit-memory="256Mi" \
--trait container.port=8443 \
--trait health.enabled=true \
--trait health.liveness-probe-enabled=true \
--trait health.liveness-scheme="HTTP" \
--trait health.liveness-initial-delay=0 \
--trait health.liveness-timeout=10 \
--trait health.liveness-period=15 \
--trait health.liveness-success-threshold=1 \
--trait health.liveness-failure-threshold=3 \
--trait health.readiness-probe-enabled=true \
--trait health.readiness-scheme="HTTP" \
--trait health.readiness-initial-delay=0 \
--trait health.readiness-timeout=10 \
--trait health.readiness-period=15 \
--trait health.readiness-success-threshold=1 \
--trait health.readiness-failure-threshold=3 \
--trait knative-service.enabled=true \
--trait knative-service.autoscaling-class="kpa.autoscaling.knative.dev" \
--trait knative-service.autoscaling-metric="rps" \
--trait knative-service.autoscaling-target=100 \
--trait knative-service.min-scale=0 \
--trait knative-service.max-scale=20 \
--trait prometheus.enabled=true \
--trait prometheus.pod-monitor=true \
--trait prometheus.pod-monitor-labels="release=kube-prometheus-stack" \
--trait quarkus.enabled=true \
--trait quarkus.package-type=native \
Integration.java

This is quite a long kamel run command. We usually keep these in a run.sh file for each integration and let the CI/CD pipeline run these shell files. The thing is, the content of our run.sh files share a lot of code between them, resulting in unnecessary duplication. Also, we have some developers with Java background writing these integrations, and they are not (and should not) be too bothered with all these trait configurations. We have dedicated people with decent Kubernetes, Knative, Istio, etc experience that usually prepares these platform-specific trait customizations and audits them.

The idea I have is roughly the following:

  • I would like to create a TraitProfile (?) named Knative-Enabled-100-RPS-Min-Scale-0 with the following content:
    --trait knative-service.enabled=true
    --trait knative-service.autoscaling-class="kpa.autoscaling.knative.dev"
    --trait knative-service.autoscaling-metric="rps"
    --trait knative-service.autoscaling-target=100
    --trait knative-service.min-scale=0
    --trait knative-service.max-scale=20
    
  • Another TraitProfile named Quarkus-Native with the following content:
    --trait quarkus.enabled=true
    --trait quarkus.package-type=native
    
  • Another TraitProfile named Default-Health-Config with the following content:
    --trait health.enabled=true
    --trait health.liveness-probe-enabled=true
    --trait health.liveness-scheme="HTTP"
    --trait health.liveness-initial-delay=0
    --trait health.liveness-timeout=10
    --trait health.liveness-period=15
    --trait health.liveness-success-threshold=1
    --trait health.liveness-failure-threshold=3
    --trait health.readiness-probe-enabled=true
    --trait health.readiness-scheme="HTTP"
    --trait health.readiness-initial-delay=0
    --trait health.readiness-timeout=10
    --trait health.readiness-period=15
    --trait health.readiness-success-threshold=1
    --trait health.readiness-failure-threshold=3
    
  • And finally, another TraitProfile named Container-Limit-250m-256Mi:
    --trait container.enabled=true
    --trait container.request-cpu="100m"
    --trait container.request-memory="128Mi"
    --trait container.limit-cpu="250m"
    --trait container.limit-memory="256Mi"
    --trait container.port=8443
    
  • And re-use these profiles in my kamel run command as such:
    kamel run \
    --config configmap:my-configmap/platform.baseUrl \
    --config secret:my-secret/platform.auth-token \
    --open-api file:./resources/platform-openapi.yaml \
    --resource file:./resources/platform-template-response.json \
    --resource file:./resources/sample-error-response.json \
    --dependency mvn:org.mapstruct:mapstruct:1.5.2.Final \
    --dependency mvn:com.fasterxml.jackson.datatype:jackson-datatype-jsr310:2.14.2 \
    --dependency camel:jackson
    --source ./sources/PlatformBean.java \
    --trait-profile Knative-Enabled-100-RPS-Min-Scale-0 \
    --trait-profile Quarkus-Native \
    --trait-profile Default-Health-Config \
    --trait-profile Container-Limit-250m-256Mi \
    

This, IMHO, would be a great addition to Camel-K as it is something we would use everywhere. These profiles would be installed onto the Kubernetes platform, just like Kamelets, and the developers would be able to browse through them. A developer whose focus is to write integrations wouldn't be worried about these configurations. A platform engineer who is well-versed in Knative, Istio, etc but not aware of the kamel CLI syntax would just write these TraitProfile customizations in a YAML and kubectl apply them as CRDs. Same platform engineer would be able to replace Knative-Enabled-100-RPS-Min-Scale-0 with Knative-Enabled-250-RPS-Min-Scale-1 for example; resulting in fast iterations.

Something roughly like this:

apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
  labels:
    app: camel-k
  name: traitprofiles.camel.apache.org
spec:
  group: camel.apache.org
  names:
    kind: TraitProfile
    listKind: TraitProfileList
    plural: traitprofiles
    shortNames:
    - tp
    singular: traitprofile
...

And the actual TraitProfile YAML spec would look something like this:

apiVersion: camel.apache.org/v1beta1
kind: TraitProfile
metadata:
  name: Knative-Enabled-100-RPS-Min-Scale-0
spec: 
  traits:
    knative-service:
      autoscalingMetric: rps
      autoscalingTarget: 100
      class: kpa.autoscaling.knative.dev
      enabled: true
      maxScale: 20
      minScale: 1
...

What do you guys think? I am aware of we already have something called "Trait Profiles" as per this but I see no usage/showcase of that besides the Knative, Kubernetes, and Openshift profiles. And these three are rather pre-defined profiles that the platform uses. So I am under the impression that the existing "Trait Profiles" are not exactly for what I am proposing here. Please correct me if I am wrong. I got confused by this so I created this issue.

@squakez
Copy link
Contributor

squakez commented Apr 25, 2023

I think this was already required in #934 - in the while, you can use IntegrationPlatform and provide there the definition of traits you want to use. Then, any Integration built from that platform will share them.

@mertdotcc
Copy link
Contributor Author

My understanding is that any trait configuration I set up directly in the IntegrationPlatform will be applied to all integrations, no? This is not quite what I want.

@squakez
Copy link
Contributor

squakez commented Apr 25, 2023

My understanding is that any trait configuration I set up directly in the IntegrationPlatform will be applied to all integrations, no? This is not quite what I want.

Yes, that's correct, it is kind of possible workaround for the time being.

@mertdotcc
Copy link
Contributor Author

I see. I don't think that it is a suitable workaround for my needs though as I would like to control these traits on the integration level, rather than the integration platform level.

I've read @lburgazzoli's issue and I think we both envision the same feature. I am assuming that you guys are open to having/building such a feature since #934 is still open and marked as never-stale. Would you like to entertain the idea of introducing a new CRD to tackle this? Would this be the right approach?

@squakez
Copy link
Contributor

squakez commented Apr 26, 2023

Could be an idea. As always it's a matter of priorities. And as always, anyone is very welcome to contribute to the feature :)

@mertdotcc
Copy link
Contributor Author

Yeah, I get your point. :) Would like to work on this actually. Do you think this makes sense as a CRD though?

@squakez
Copy link
Contributor

squakez commented Apr 26, 2023

I don't have preferences tbh. Probably a CRD would fit better and can be typed against any other format such as a simple configmap and could be easily extended with more configuration in the future. Let me know if you're going to work on it so I can assign this issue to you.

@mertdotcc
Copy link
Contributor Author

Yeah, go ahead and assign the issue to me. CRD it is!

@github-actions
Copy link
Contributor

github-actions bot commented Aug 2, 2023

This issue has been automatically marked as stale due to 90 days of inactivity.
It will be closed if no further activity occurs within 15 days.
If you think that’s incorrect or the issue should never stale, please simply write any comment.
Thanks for your contributions!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants