Slack sink - Learning Knative Eventing and the Apache Camel K integration

image

As a bookstore owner, you aim to receive instant notifications in a Slack channel whenever a customer submits a new review comment. By leveraging Knative Eventing and Apache Camel K, you can set up an event-driven service that automates these notifications, ensuring you’re always informed.

What Knative features will we learn about?

  • Knative’s ability to connect with third-party services, such as Slack, through event-driven integration using Apache Camel K.

What does the final deliverable look like?

When a CloudEvent with the type moderated-comment and with ce-bad-word-filter set to bad is sent, it triggers a message to be sent in a designated Slack channel.

Install prerequisites

Prerequisite 1: Install Apache Camel CLI

image

Install the Apache Camel K CLI (kamel) on your local machine. You can find the installation instructions here.

Troubleshooting

If after installation you run kamel version and you get an error message, you may need to add the kamel binary to your system’s PATH. You can do this by moving the kamel binary to a directory that is already in your PATH, or by adding the directory where kamel is located to your PATH.

  1. $ export PATH=$PATH:<path-to-kamel-binary>

Prerequisite 2: Install Apache Camel-Kamelets

image

Next, install Apache Camel K on your cluster using the Apache Camel K CLI:

  1. $ kamel install --registry docker.io --organization <your-organization> --registry-auth-username <your-username> --registry-auth-password <your-password>

Replace the placeholders with your actual Docker registry information.

If you are using other container registries, you may need to read more here for the installation.

Verify

You will see this message if the installation is successful:

  1. 📦 OLM is not available in the cluster. Fallback to regular installation.
  2. 🐪 Camel K installed in namespace default

Prerequisite 3: Create a Slack App and Generate an Incoming Webhook URL

image

Follow the instructions here on how to create the Slack workspace and generate an incoming webhook URL for your designated channel where notifications will be sent to.

Verify

You should have a webhook URL that looks like this:

  1. https://hooks.slack.com/services/T00000000/B00000000/XXXXXXXXXXXXXXXXXXXXXXXX

Save this URL as you will need it later.

Prerequisite 4: Create a Secret that stores your Slack Credentials

image

We are storing the webhook URL as a secret. Copy and paste your webhook URL into the file slack-sink/application.properties

/slack-sink/application.properties

  1. slack.channel=#bookstore-owner
  2. slack.webhook.url=https://hooks.slack.com/services/T00000000/B00000000/XXXXXXXXXXXXXXXXXXXXXXXX

Then run the following command to create the secret in the /slack-sink directory:

  1. kubectl create secret generic slack-credentials --from-file=application.properties

Verify

You should see this message if the secret is created successfully:

  1. secret/slack-credentials created

Implementation

Step 0: Learn about Pipe

image

We use a feature called “Pipe” (a.k.a KameletBinding) in Apache Camel K to link event sources and destinations. Specifically, the Pipe connects events from our Broker, our source, to the Slack channel through a Slack sink Kamelet, our destination.

image

From the sample YAML below, you can see we are telling the pipe to filter on the events that have type “moderated-comment”. Pipe will create a Trigger under the hood and route your event to slack-sink.

  1. apiVersion: camel.apache.org/v1
  2. kind: Pipe
  3. metadata:
  4. name: pipe
  5. spec:
  6. source:
  7. ref:
  8. kind: Broker
  9. apiVersion: eventing.knative.dev/v1
  10. name: badword-broker
  11. properties:
  12. type: moderated-comment
  13. sink:
  14. ...

If you hope to learn more about it, check out the article Event Sourcing with Apache Camel K and Knative Eventing by Matthias Weßendorf!

Step 1: Create the Broker that can route “bad word” comments to Slack

image

In the current implementation using Apache Camel K, we can only filter based on the CloudEvent’s type, such as moderated-comment. Filtering based on event extensions, such as badwordfilter: good, is not yet supported. This feature will be available in a future update of Apache Camel K. But we can still use an alternative way to achieve this!

image

Here, we will be connecting book-review-broker with a new Broker called badword-broker. And we will be creating a Trigger that helps us perform the filtering with the extension badwordfilter: good.

  • 1: Append the following content to your node-server/config/200-broker.yaml:

node-server/config/200-broker.yaml

  1. ---
  2. apiVersion: eventing.knative.dev/v1
  3. kind: Broker
  4. metadata:
  5. name: badword-broker
  • 2: Apply the YAML file:

    1. kubectl apply -f 200-broker.yaml

You should see this message if the Broker is created successfully:

  1. broker.eventing.knative.dev/badword-broker created

Alternatively, use the Knative CLI kn to create the broker:

  1. kn broker create badword-broker

You should see this message if the Broker is created successfully:

  1. Broker 'badword-broker' successfully created in namespace 'default'.

Verify

Run the following command to list the Brokers:

  1. kubectl get brokers

You should see the badword-broker listed.

  1. NAME URL AGE READY REASON
  2. badword-broker http://broker-ingress.knative-eventing.svc.cluster.local/default/badword-broker 3s True
  3. bookstore-broker http://broker-ingress.knative-eventing.svc.cluster.local/default/bookstore-broker 5h38m True
  4. ``` Troubleshooting
  5. If there are issues, use the following command to diagnose:

kubectl describe broker badword-broker

  1. ### **Step 2: Create Trigger that filters for bad word comments to badword-broker**
  2. ![image](/projects/knative-1.15-en/49a4b1f1d1f593ade980d29371db5eed.png)
  3. We are creating the Trigger to process the events that have type moderated-comment, and the extension `badwordfilter: bad` and route them to badword-broker.
  4. **Create a Trigger:**
  5. ![image](/projects/knative-1.15-en/298542259dc779d9e70513f94bc45800.png)
  6. - 1: Create a new YAML file named `node-server/config/badword-noti-trigger.yaml` and add the following content:
  7. _node-server/config/badword-noti-trigger.yaml_

apiVersion: eventing.knative.dev/v1 kind: Trigger metadata: name: badword-noti-trigger spec: broker: bookstore-broker filter: attributes: # Trigger will filter events based on BOTH the type and badwordfilter attribute type: moderated-comment # This is the filter that will be applied to the event, only events with the ce-type moderated-comment will be processed badwordfilter: bad # This is the filter that will be applied to the event, only events with the ce-extension badwordfilter: bad will be processed subscriber: ref: apiVersion: eventing.knative.dev/v1 kind: Broker name: badword-broker

  1. - 2: Apply the YAML file:
  1. kubectl apply -f node-server/config/badword-noti-trigger.yaml
  2. ```
  3. You should see this message if the Trigger is created successfully:
  4. ```
  5. trigger.eventing.knative.dev/badword-noti-trigger created
  6. ```

Verify

  1. kubectl get triggers

The Trigger badword-noti-trigger should have READY status as True.

  1. NAME BROKER SUBSCRIBER_URI AGE READY REASON
  2. db-insert-trigger bookstore-broker http://node-server-svc.default.svc.cluster.local/insert 5h41m True
  3. seq-reply-trigger bookstore-broker http://event-display.default.svc.cluster.local 5h39m True
  4. sequence-trigger bookstore-broker http://sequence-kn-sequence-0-kn-channel.default.svc.cluster.local 5h39m True
  5. log-trigger bookstore-broker http://event-display.default.svc.cluster.local 5h41m True
  6. badword-noti-triggerbookstore-broker http://broker-ingress.knative-eventing.svc.cluster.local/default/badword-broker 5h41m True

Step 3: Build the Pipe

This setup automatically sends notifications to Slack whenever a new comment that contains “bad word” occur, streamlining the flow of information.

  • 1: Make sure you have your k8s secret that contains your Slack webhook Url ready. If not, refer to the Prerequisite 3 section.

  • 2: Prepare the YAML configuration for the Slack sink, which will forward events to your Slack channel:

image

Create a new file named slack-sink/config/slack-sink.yaml and add the following content:

slack-sink/config/slack-sink.yaml

  1. apiVersion: camel.apache.org/v1
  2. kind: Pipe
  3. metadata:
  4. name: pipe
  5. annotations:
  6. trait.camel.apache.org/mount.configs: "secret:slack-credentials"
  7. spec:
  8. source:
  9. ref:
  10. kind: Broker
  11. apiVersion: eventing.knative.dev/v1
  12. name: bad-word-broker
  13. properties:
  14. type: moderated-comment
  15. sink:
  16. ref:
  17. kind: Kamelet
  18. apiVersion: camel.apache.org/v1
  19. name: slack-sink
  20. properties:
  21. channel: ${slack.channel}
  22. webhookUrl: ${slack.webhook.url}
  1. Apply the configuration to your Kubernetes cluster:
  1. $ kubectl apply -f slack-sink/slack-sink.yaml

Verify

You will see this message if the configuration is created successfully:

  1. pipe.camel.apache.org/slack-sink-pipe created

But this process will take a few seconds to complete. You can check the status of the pipe by running the following command:

  1. $ kubectl get pipe slack-sink-pipe
  1. NAME PHASE REPLICAS
  2. slack-sink-pipe Ready 1

Step 4: Modify the Knative Services to disable scale to zero

image

In this step, we’ll configure the notification delivery service to prevent it from scaling down to zero, ensuring timely notifications.

Note

ksvc stands for Knative Service.

  1. Check Existing Knative Services:
  1. $ kubectl get ksvc

You should see a service named pipe listed:

  1. NAME URL LATESTCREATED LATESTREADY READY REASON
  2. pipe http://pipe.default.svc.cluster.local pipe-00002 pipe-00002 True
  1. Edit the Knative Service:

To prevent the notification service from scaling down to zero, set the minimum number of pods to keep running.

  1. $ kubectl edit ksvc pipe

Add the following annotation:

  1. spec:
  2. template:
  3. metadata:
  4. annotations:
  5. autoscaling.knative.dev/min-scale: "1"

This configuration ensures that Knative will always maintain at least one instance of the service running.

Verify

  1. $ kubectl get pods

Periodically check the status of the pipe-deployment pods, and see whether they will disappear! If they stay there, then we are good!

Verification

image

Now, you have completed building the sample app. When you submit a comment, you should always receive a notification in your test Slack workspace, achieving the same result as shown in the demo video.

Conclusion

In this tutorial, you learned how to set up an event-driven service that automates notifications to a Slack channel using Knative Eventing and Apache Camel K. By leveraging these technologies, you can seamlessly connect your applications to third-party services and facilitate real-time information exchange between them.

Next Step

image

Congratulations on successfully completing the bookstore sample app tutorial! If you want to deepen your understanding of Knative, open your bookstore front end, the demo book we used is a great starting point! Check the book “Building Serverless Applications on Knative” by Evan Anderson.

image

We’ve prepared additional challenges that build on top of the existing bookstore app for you to tackle. Some solutions are provided, while others are left open to encourage you to explore your own solutions.

Go to Extra Challenges 7 - Connect Slack via Camel-K - 图15