Skip to Content
Technical Articles
Author's profile photo Gaurav Abbi

In-cluster eventing in SAP BTP, Kyma runtime

Kyma has recently introduced in-cluster eventing. This implies that you can now implement microservices and serverless functions inside the Kyma runtime that rely on Event-Driven architecture. You can have microservices that can produce events as well as consume events inside Kyma runtime. This enables you to achieve asynchronous flows when required. Earlier it was only possible for connected SAP Solutions such as SAP Commerce Cloud to send events and trigger workloads in Kyma runtime.

As per the Kyma documentation,

In-cluster Eventing allows publishers to send messages and subscribers to receive them without the need for a Kyma Application. This means that instead of the usual event flow where Application Connector publishes events to the Event Publisher Proxy, events can be published from within the cluster directly to the Event Publisher Proxy.

 

 

This is important for business scenarios and use cases where you would like to have asynchronous workflows. Examples include

  • Triggering a long-running background processing based on user actions. This ensures that we reliably execute the processing while at the same time providing a swift response to the user thus providing a better user experience.
  • Doing a fan-out and triggering multiple processes on a single event or action
  • and many others…

Kyma eventing ensures that the event is reliably delivered until the subscriber processes the event successfully.

 

In this blog post, we will walk through a quick tutorial to set up and test the in-cluster eventing in Kyma Runtime.

 

Steps

 

Set up namespace

  • Create namespace¬†in-cluster-events
kubectl create ns in-cluster-events

 

Create a trigger to consume the event

This can be any function or microservice with a Kubernetes Service deployed.
I am using a simple function that just prints the event payload and called it event-subscriber.

It is defined in in-cluster-events namespace.

module.exports = { 
  main: function (event, context) {
    console.log(event.data);
  }
}

 

Create a Subscription to receive events. The subscription custom resource is used to subscribe to events.

cat <<EOF | kubectl -n in-cluster-events apply -f -
apiVersion: eventing.kyma-project.io/v1alpha1
kind: Subscription
metadata:
  name: mysub
spec:
  filter:
    filters:
    - eventSource:
        property: source
        type: exact
        value: ""
      eventType:
        property: type
        type: exact
        value: sap.kyma.custom.nonexistingapp.order.created.v1
  protocol: ""
  protocolsettings: {}
  sink: http://event-subscriber.in-cluster-events.svc.cluster.local #this is the service name and port
EOF

 

This sample Subscription resource subscribes to an event called sap.kyma.custom.nonexistingapp.order.created.v1.

This is defined in the eventType.value property in the Subscription definition.

The sink is the subscriber to which events will be delivered. In this case, it is the function that we have defined earlier. (http://event-subscriber.in-cluster-events.svc.cluster.local)

Now our function is ready to receive any events. Let’s go ahead and send some events

Sending events

 

Create an event producer

Now we need a workload running inside Kyma runtime that can publish events. It can be a microservice or function. The events in Kyma conform to cloudevents specification. You can use various cloudevents SDKs available to produce and consume the events in your preferred technology. To keep this tutorial simple, I will be using curl as my event producer.

Let’s go ahead and launch a pod that has the curl command available and enter the shell.

kubectl -n in-cluster-events run curl --image=radial/busyboxplus:curl -i --tty

After the pod starts, you will be inside the shell of the pod. From there run the curl command to send the event

curl -k -i -X POST \
  "http://eventing-event-publisher-proxy.kyma-system/publish" \
  -H "Content-Type: application/cloudevents+json" \
  --data @- << EOF
  {
        "source": "kyma",
        "specversion": "1.0",
        "eventtypeversion": "v1",
        "data": {"orderCode":"3211213"},
        "datacontenttype": "application/json",
        "id": "759815c3-b142-48f2-bf18-c6502dc0998f",
        "type": "sap.kyma.custom.nonexistingapp.order.created.v1"
  }
EOF

Verify

Check the logs of the function to verify event has been received.

Assigned Tags

      12 Comments
      You must be Logged on to comment or reply to a post.
      Author's profile photo Andrei Vishnevsky
      Andrei Vishnevsky

      Hi Gaurav,

      Thanks a lot for the blog! Very useful and I just implemented in-cluster events to simplify a couple of things in our cluster.

      However, I have a question. In the subscription in the filter for eventSource you have source exact "". And then in the event itself the source is "kyma". Then how is the filter matched? Shouldn't be the filter looks like source exact "kyma" instead? And why does it currently work with the empty value in the filter?

      Author's profile photo Gaurav Abbi
      Gaurav Abbi
      Blog Post Author

      Hi Andrei,

      There are two sources being referred to here.

      one is originating application or event producer and the other is the eventing broker.

      The CRD is best piece of information here https://kyma-project.io/docs/components/eventing/#custom-resource-custom-resource

      Author's profile photo Remi ASTIER
      Remi ASTIER

      The address of the publishing proxy seems to have changed.

      Author's profile photo Gaurav Abbi
      Gaurav Abbi
      Blog Post Author

      I still see the service in my cluster.

      Author's profile photo Remi ASTIER
      Remi ASTIER

      I execute the same curl command in two namespaces, it works only in the namespace with istio enabled.

      kubectl run -n kyma-system --rm -i --tty mypod --image=curlimages/curl --restart=Never -- curl -v -X POST \
      -H "ce-specversion: 1.0" \
      -H "ce-type: sap.kyma.custom.nonexistingapp.rits.offer.v1" \
      -H "ce-source: myapp" \
      -H "ce-eventtypeversion: v1" \
      -H "ce-id: 94064655-7e9e-4795-97a3-81bfd497aac5" \
      -H "content-type: application/json" \
      -d "{\"orderCode\":\"3211213\", \"orderStatus\":\"changed\"}" \
      http://eventing-publisher-proxy.kyma-system.svc.cluster.local/publish

      Is it because I have istio injection disabled? The subscription works fine.

      Author's profile photo Gaurav Abbi
      Gaurav Abbi
      Blog Post Author

      Hi Remi,

      Yes, you need to enable istio.

       

      Best regards,

      Gaurav

      Author's profile photo Remi ASTIER
      Remi ASTIER

      Thanks, what's the messaging pattern? fire and forget or request reply?

      Author's profile photo Gaurav Abbi
      Gaurav Abbi
      Blog Post Author

      Hi Remi,

      It is fire and forget. Essentially, if you want to have asynchronous flows, you can consider using in-cluster eventing.

      Author's profile photo anim basu
      anim basu

      Hi Gaurav,

      Thanks for the awesome blog.

      I am writing python code inside the function. I triggered an event from my Cloud for customer and I am getting 200 Ok status in my C4C system. but in Kyma the function is getting executed.

      I am getting a hold of the event id by doing the following.

      Is it the right way to do it for python.
      Regards,
      Anim Basu

      def main(event, context):
          message = 'Hello World from the Kyma Function '+context['function-name']+' running on '+context['runtime']+ '!';
          event_entity_id = context['data']['root-entity-id']‚Äč
      Author's profile photo Gaurav Abbi
      Gaurav Abbi
      Blog Post Author

      Hi Anim,

      I have not tried in python. In Nodejs the event object contains the data.

      e.g.

      var accountId = event.data["entity-id"];

       

      You can refer to the following example as a reference:

      https://github.com/SAP-samples/kyma-runtime-extension-samples/blob/main/address-completion-c4c/sales-cloud-address-completion-here/function/handler.js#L13

       

      Best regards,

      Gaurav

       

      Author's profile photo Anim Basu
      Anim Basu

      Hi Gaurav,

      I am able to fetch the event ID now. I have one small doubt. When I am triggering the serverless function on create event of a ticket in SAP C4C, I can see in the log that the function is running multiple times even if there is no error.

      Why it shows this behavior?

      Can you guide me how to control this?

      I want my code to be run once on creation of a ticket in SAP C4C.

       

      Regards.

      Anim Basu

      Author's profile photo Gaurav Abbi
      Gaurav Abbi
      Blog Post Author

      Hi Anim,

      In general, the event delivery is atleast-once, so there could also be the possibility that the eventing setup can send the event multiple times. It is always recommended to implement event handling to take care of multiple event deliveries.

      There could be other reasons that you see the event multiple times. e.g. Have you configured the update event too? In that case, if you do some modifications and apply them back, the update event will be triggered.

       

      BR

      Gaurav