Although a user can use the CloudEvent PipelineResource to emit events during a TaskRun or PipelineRun, some folks may want this to happen by default, for significant events such as:
The CloudEvent PipelineResource is the only option for this right now, but even that needs #1684 before it can be relied on (see #2053)
/kind feature
@bobcatfish I've been thinking about this for a bit, and I think it would be great to have the ability to specify a sink in the Task|PipelineRun so that cloud events could be sent by a task without the need of altering the task to add the pipeline resource. This would greatly improve the re-usability of tasks, e.g. when using Tasks as CI Jobs.
It gets a bit more complicated than just a sink though, since we might need to:
A lot of those might be avoided when using tekton triggers by using a single EventListener with multiple triggers and CEL filters to select the right thing to select.
This is highly related to the notification work too, as I think the basic infrastructure required in the controller to make this happen is the same as that needed for notifications.
/assign
As a starting point, I think it's a fair assumption to let receivers / channels filter events, and err on the side of sending too many events, in favour of a lean syntax on Tekton side.
In practice this means that a PipelineRun and a TaskRun will get a new field that allows specifying a list of sinks. If sinks are specified, a cloud event will be sent for all events to all sinks.
Options for the field name: sinks, cloudEvents, cloudEventSinks, notify
apiVersion: tekton.dev/v1beta1
kind: PipelineRun
metadata:
name: pipeline-with-sinks
spec:
serviceAccountName: bot
cloudEvents:
- http://my-event-listener
- https://another-event-listener
- https://some-external-service
pipelineRef:
name: my-pipeline
params:
- name: p1
value: v1
resources:
- name: source
resourceRef:
name: git-resource
Similar syntax for TaskRuns. When set on PipelineRun level, all siniks would apply to all TaskRuns.
This might just be an implementation detail, but one option to consider is have the pipeline controller only "generate" Tekton lifecycle Kubernetes events and then leave the decision on CloudEvents or http endpoints up to a sub-project with a controller that listens for the Tekton events and distributes them.
We actually need the Kubernetes events in our service's "agent" already so this would simplify our implementation.
This might just be an implementation detail, but one option to consider is have the pipeline controller only "generate" Tekton lifecycle Kubernetes events and then leave the decision on CloudEvents or http endpoints up to a sub-project with a controller that listens for the Tekton events and distributes them.
We actually need the Kubernetes events in our service's "agent" already so this would simplify our implementation.
I think we can do both, aka : by default sending k8s events, and if cloudEvents field is specified send them there too :wink:
I really like the ease-of-use of the proposed syntax, and pushing the responsibility of filtering the events to the receiver rather than Tekton.
Per discussion in the WG just now, I wanted to put forward a use case that might affect the design a little bit:
A team authors their organization's Tasks and Pipelines. That team wants to ensure that every Run emits cloudEvents to a specific set of endpoints for monitoring / data collection / regulatory requirements. With the current design each developer team, who mostly write Runs, has to remember to include the cloudEvents end points in those Runs. So I wonder if there is a way to set the "default" set of endpoints that every Run receives. Three options we talked about on the call:
cloudEvents that get added to any Run using them.cloudEvents section (like our "defaults" ConfigMap).cloudEvents "slots" which _must_ be bound by Run authors.After thinking about it a little bit I like number 2 the best so far. I can also see that there are different levels of granularity here: 1 is Pipeline / Task specific, 2 is global, 3 is Run-specific but with stricter validation that endpoints were included.
Another wrinkle: Do we merge the cloudEvents lists if they're specified in both a global location and a Run? Or replace them with those specified in the Run? My hunch is we should merge.
Thank you @sbwsg for your feedback and for capturing the WG discussion here.
We're going to emit k8s events for all lifecycle events, which partly covers the monitoring use case. Nonetheless, I think it would make sense to support sending cloud events for all pipeline/taskruns.
My favourite option would be (2), i.e. use sinks from a global configmap, and send cloud events for all lifecycle events for all tasks/pipelines. Other options are not necessarily orthogonal, so we could also add them as we need in future.
The way I would go about implementing this is:
How does this sound?
Cheers @afrittoli Sounds like a really solid approach to me!
I will also address https://github.com/tektoncd/pipeline/issues/2328 as part of this work
Note: priorities for this issue are emitting events at end of Pipeline and Task execution, https://github.com/tektoncd/pipeline/issues/742 additionally adds after step execution
Is this the intended replacement for CloudEvent PipelineResources in the future, since PipelineResources are more-or-less deprecated in the latest release of Tekton?
This will provide more than we can achieve with CloudEventPipelineResource, since it will include k8s and CloudEvents for every life cycle event of both tasks and pipelines.
Resources are not officially deprecated, but likely they will either reworked or replaced. In either case the cloud event resource might go away since it doesn't really fit the same pattern as other pipeline resource, its functionality is not executed in injected steps but in the controller.
There is also Eventrouter that can forward Kubernetes Event to a Sink. We use this today to forward "platform"-events to e.g. Kafka and Dashboards.
The reason why I'd like to emit cloud events directly, either from the main controller or from a dedicated one, is that k8s events have a fixed structure and afaik do not allow storing the whole source object in the event.
Hi @afrittoli , I am genuinely staggered by your hard work. Thanks so much for doing this!
I got one question:
What is the expectation if the third party component registers to monitor every events generated by any Run? In order to monitor every events, I am imagining the situation of injecting sinkURI from third party controller into the ConfigMap, but I want to make sure that no breakage occur in Tekton ecosystem.
Hi @afrittoli , I am genuinely staggered by your hard work. Thanks so much for doing this!
I got one question:
What is the expectation if the third party component registers to monitor every events generated by any Run? In order to monitor every events, I am imagining the situation of injecting sinkURI from third party controller into the ConfigMap, but I want to make sure that no breakage occur in Tekton ecosystem.
Hi @tom24d, thank you for your interest in this topic. The way I imagined this is that the administrator of a Tekton deployment would configure the target URL for cloud events.
The config map can also be edited by a third party controller as you mentioned, as long as it has the rights to edit a configmap in the namespace where Tekton is deployed.
Your question makes me wonder if we should support a list of sinkURI instead of a single one?
In https://github.com/tektoncd/pipeline/pull/2837 I introduced the configuration option as a single string, but it should be possible to change that to a list if needed.
Once https://github.com/tektoncd/pipeline/pull/2837 is finished I will add a similar PR for pipelineruns, and later I plan to enabled configuring a sinkURI at taskrun and pipelinerun level, to allow for better granularity.
@afrittoli
In 2837 I introduced the configuration option as a single string, but it should be possible to change that to a list if needed.
If there is no problem for that idea, I think that gonna make the basic way for third party actor! 😀
The reason is, I was wondering if there is a general registration mechanism to receive every events from Tekton. As long as regarding the discussion here, it seems like injecting sinkURI to the ConfigMap is the simplest way for me.
Thanks!
@afrittoli
In 2837 I introduced the configuration option as a single string, but it should be possible to change that to a list if needed.
If there is no problem for that idea, I think that gonna make the basic way for third party actor! 😀
The reason is, I was wondering if there is a general registration mechanism to receive every events from Tekton. As long as regarding the discussion here, it seems like injecting sinkURI to the ConfigMap is the simplest way for me.Thanks!
Yes, with #2837 you will be able to set the sinkURI in the config map to receive cloud events.
Tekton also publishes kubernetes events to the cluster, so you could intercept those too, but you'd need an app running on the same cluster with access to those events.
Your question makes me wonder if we should support a list of sinkURI instead of a single one?
In #2837 I introduced the configuration option as a single string, but it should be possible to change that to a list if needed.
I would think it would make sense to support more than one sink indead :upside_down_face:
As per discussion during the API WG on 13/07/20 we will not support for now any option beyond the single sink in the platform wide configuration.
The following use cases:
One concern with this approach is the volume of events sent. Right now it's all or nothing, and in case of tasks and pipelines running in different namespaces, they would have to report events to a central broker, which may raise concerns in terms of traffic separation.
If Tekton users will start using cloud events, they may report on missing features and those will be addressed via dedicated TEPs / PRs.
Most helpful comment
As a starting point, I think it's a fair assumption to let receivers / channels filter events, and err on the side of sending too many events, in favour of a lean syntax on Tekton side.
In practice this means that a
PipelineRunand aTaskRunwill get a new field that allows specifying a list of sinks. If sinks are specified, a cloud event will be sent for all events to all sinks.Options for the field name:
sinks,cloudEvents,cloudEventSinks,notifySimilar syntax for
TaskRuns. When set onPipelineRunlevel, all siniks would apply to allTaskRuns.