Sample App Tutorial Page Compilation (#6007)
* feat: add the first three pages of the sample app tutorial * Apply suggestions from code review Co-authored-by: Pierangelo Di Pilato <pierangelodipilato@gmail.com> * fix: fix the review comments in pg0 and pg1 * feat: add blog post 2 * feat: adding the images for page 2 * add: add more pages * add: adding the rest of the pages * add: modify the nav * add: finishing polishing * fix: update the iframe embedded video link * fix: fix the video embedding dimension and the access * fix: link minor error fix * fix: hide the setup script section * Apply suggestions from code review Co-authored-by: Christoph Stäbler <cstabler@redhat.com> * Update docs/bookstore/page-0/page-0-intro.md Co-authored-by: Christoph Stäbler <cstabler@redhat.com> * Update docs/bookstore/page-0.5/pg0.5-env-setup.md Co-authored-by: Christoph Stäbler <cstabler@redhat.com> * fix: fix christoph's comment * fix: Remove all the extra new lines * fix: update kubernetes to Kubernetes * Apply suggestions from code review Co-authored-by: Pierangelo Di Pilato <pierangelodipilato@gmail.com> Co-authored-by: Christoph Stäbler <cstabler@redhat.com> * fix: fix the wrong indentation in the yaml files * Update docs/bookstore/page-2/pg2-sentiment-svc.md Co-authored-by: Christoph Stäbler <cstabler@redhat.com> * fix: fix review comments * fix: change the console output to text - pg0.5 * fix: replace the console output pic with plaintextg for pg1 * fix: replace the console output pic with plaintext for pg 2&3 * fix: replace the console output pic with plaintext for pg 4 * fix: replace the console output pic with plaintext for pg 5 * fix: replace the console output pic with plaintext for pg 6 * fix: replace the console output pic with plaintext for pg 7 * fix: fix christoph's comments * Apply suggestions from code review Co-authored-by: Christoph Stäbler <cstabler@redhat.com> * fix: applying christoph's comments fix * fix: fix christoph's nit comments + open the link in new tab * fix: make sure all the command have the same root which is /start * fix: make all the links open in the new tab * fix: fix small errors * fix: remove default namespace * Update docs/bookstore/page-1/pg1-review-svc-1.md Co-authored-by: Christoph Stäbler <cstabler@redhat.com> * Apply suggestions from code review Co-authored-by: Christoph Stäbler <cstabler@redhat.com> * fix: update the wording to follow the Knative's branding guideline * fix: update the wording to follow the Knative's branding guideline * fix: update the naming of the pages * fix: fixing the wrong link in the tutorial.md page * Apply the patch from Christoph Co-authored-by: Christoph Stäbler <cstabler@redhat.com> * Apply suggestions from code review Co-authored-by: Christoph Stäbler <cstabler@redhat.com> * Update docs/bookstore/page-1/send-review-comment-to-broker.md Co-authored-by: Pierangelo Di Pilato <pierangelodipilato@gmail.com> --------- Co-authored-by: Pierangelo Di Pilato <pierangelodipilato@gmail.com> Co-authored-by: Christoph Stäbler <cstabler@redhat.com>
|
@ -20,10 +20,10 @@ The function's output will be only from
|
|||
---
|
||||
|
||||
### Prerequisite 1: Install Knative `func` CLI
|
||||
Knative Function enables you to easily create, build, and deploy stateless, event-driven functions as [Knative Services](https://knative.dev/docs/serving/services/#:~:text=Knative%20Services%20are%20used%20to,the%20Service%20to%20be%20configured) by using the func CLI.
|
||||
Knative Function enables you to easily create, build, and deploy stateless, event-driven functions as [Knative Services](https://knative.dev/docs/serving/services/#:~:text=Knative%20Services%20are%20used%20to,the%20Service%20to%20be%20configured){:target="_blank"} by using the func CLI.
|
||||
|
||||
In order to do so, you need to install the `func` CLI.
|
||||
You can follow the [official documentation](https://knative.dev/docs/getting-started/install-func/) to install the `func` CLI.
|
||||
You can follow the [official documentation](https://knative.dev/docs/getting-started/install-func/){:target="_blank"} to install the `func` CLI.
|
||||
|
||||
Running `func version` in your terminal to verify the installation, and you should see the version of the `func` CLI you installed.
|
||||
|
||||
|
@ -55,7 +55,7 @@ func create -l python sentiment-analysis
|
|||
|
||||
This command will create a new directory with the name `sentiment-analysis` and a bunch of files in it. The `func` CLI will generate a basic function template for you to start with.
|
||||
|
||||
You can find all the supported languages templates [here](https://knative.dev/docs/functions/).
|
||||
You can find all the supported languages templates [here](https://knative.dev/docs/functions/){:target="_blank"}.
|
||||
|
||||
The file tree will look like this:
|
||||
```bash
|
||||
|
@ -175,7 +175,7 @@ setup(
|
|||
|
||||
### Step 5: Try to build and run your Knative Function on your local machine
|
||||
|
||||
In knative function, there are two ways to build: using the [pack build](https://github.com/knative/func/blob/8f3f718a5a036aa6b6eaa9f70c03aeea740015b9/docs/reference/func_build.md?plain=1#L46) or using the [source-to-image (s2i) build](https://github.com/knative/func/blob/4f48549c8ad4dad34bf750db243d81d503f0090f/docs/reference/func_build.md?plain=1#L43).
|
||||
In knative function, there are two ways to build: using the [pack build](https://github.com/knative/func/blob/8f3f718a5a036aa6b6eaa9f70c03aeea740015b9/docs/reference/func_build.md?plain=1#L46){:target="_blank"} or using the [source-to-image (s2i) build](https://github.com/knative/func/blob/4f48549c8ad4dad34bf750db243d81d503f0090f/docs/reference/func_build.md?plain=1#L43){:target="_blank"}.
|
||||
|
||||
Currently. only the **s2i** build is supported if you need to run setup.py. When building with s2i, the `setup.py` file will be executed automatically after the dependencies have been installed.
|
||||
|
||||
|
@ -255,7 +255,7 @@ Knative function also have an easy way to simulate the CloudEvent, you can use t
|
|||
func invoke -f=cloudevent --data='{"input": "I love Knative so much"}' --content-type=application/json --type="new-comment" -v
|
||||
```
|
||||
where the `-f` flag indicates the type of the data, is either `HTTP` or `cloudevent`, and the `--data` flag is the input text.
|
||||
You can read more about `func invoke` [here](https://github.com/knative/func/blob/main/docs/reference/func_invoke.md).
|
||||
You can read more about `func invoke` [here](https://github.com/knative/func/blob/main/docs/reference/func_invoke.md){:target="_blank"}.
|
||||
|
||||
In this case, you will get the full CloudEvent response:
|
||||
|
||||
|
@ -302,7 +302,7 @@ NAMESPACE NAME URL
|
|||
default sentiment-analysis-app http://sentiment-analysis-app.default.10.99.46.8.sslip.io sentiment-analysis-app-00002 sentiment-analysis-app-00002 True
|
||||
```
|
||||
|
||||
Please note: if your URL ends with .svc.cluster.local, that means you can only access the function from within the cluster. You probably forget to configure the network or [start the tunnel](https://knative.dev/docs/getting-started/quickstart-install/#__tabbed_3_2) if you are using minikube.
|
||||
Please note: if your URL ends with .svc.cluster.local, that means you can only access the function from within the cluster. You probably forget to configure the network or [start the tunnel](https://knative.dev/docs/getting-started/quickstart-install/#__tabbed_3_2){:target="_blank"} if you are using minikube.
|
||||
|
||||
### Step 7: Verify the Deployment
|
||||
After deployment, the `func` CLI provides a URL to access your function. You can verify the function's operation by sending a request with a sample review comment.
|
||||
|
@ -340,8 +340,8 @@ Recall note box: you can get the URL to the function by running the following co
|
|||
kubectl get kservice -A
|
||||
```
|
||||
---
|
||||
Another option is to use curl to send a CloudEvent to the function.
|
||||
Using curl command to send a CloudEvent to the broker:
|
||||
Another option is to use curl to send a CloudEvents to the function.
|
||||
Using curl command to send a CloudEvents to the Broker:
|
||||
```bash
|
||||
[root@curler:/]$ curl -v "http://sentiment-analysis-app.default.10.99.46.8.sslip.io" \
|
||||
-X POST \
|
||||
|
|
|
@ -4,12 +4,12 @@
|
|||
|
||||
To create a Slack workspace, follow these steps:
|
||||
|
||||
- Visit [https://slack.com/get-started#/createnew](https://slack.com/get-started#/createnew).
|
||||
- Visit [https://slack.com/get-started#/createnew](https://slack.com/get-started#/createnew){:target="_blank"}.
|
||||
- Enter your email address and click Continue, or continue with Apple or Google.
|
||||
- Check your email for a confirmation code.
|
||||
- Enter the code on the Slack website.
|
||||
- Click "Create a Workspace" and follow the prompts.
|
||||
- For detailed instructions for androids and , refer to [Create a workspace](https://slack.com/help/articles/206845317-Create-a-Slack-workspace).
|
||||
- For detailed instructions how to create a workspace via the Desktop App, on Android or iOS, refer to [Create a Slack workspace](https://slack.com/help/articles/206845317-Create-a-Slack-workspace){:target="_blank"}.
|
||||
|
||||
## Adding Channels to Your Workspace
|
||||
|
||||
|
@ -17,13 +17,13 @@ After creating your Slack workspace, you can add channels by following these ste
|
|||
|
||||
- Click the '+' icon next to 'Channels' on the sidebar of your Slack workspace.
|
||||
- Choose "Create a channel" and specify the channel name and purpose.
|
||||
- For enterprise grid organizations, refer to [Slack's help article](https://slack.com/help/articles/115001399587-Add-a-channel-to-multiple-workspaces-in-your-Enterprise-Grid-organization) for instructions.
|
||||
- For enterprise grid organizations, refer to [Slack's help article](https://slack.com/help/articles/115001399587-Add-a-channel-to-multiple-workspaces-in-your-Enterprise-Grid-organization){:target="_blank"} for instructions.
|
||||
|
||||
## Setting Up a Webhook for Notifications
|
||||
|
||||
To set up a webhook for sending notifications to your Slack workspace:
|
||||
|
||||
- Create a [Slack app](https://api.slack.com/apps/new), following the instructions by signing in, adding name and workspace to put the app in.
|
||||
- Create a [Slack app](https://api.slack.com/apps/new){:target="_blank"}, following the instructions by signing in, adding name and workspace to put the app in.
|
||||
- After this, you'll be redirected to the setting pages of your new app. Choose **Incoming Webhook** and toggle **Activate Webhook**.
|
||||
- Scroll down to click the option **Add New Webhook to Workspace**.
|
||||

|
||||
|
@ -33,4 +33,4 @@ To set up a webhook for sending notifications to your Slack workspace:
|
|||

|
||||
- Afterwards, the text channel should have a new message
|
||||

|
||||
- Go to [Slack's webhook documentation](https://api.slack.com/messaging/webhooks) to learn more about setting up webhooks.
|
||||
- Go to [Slack's webhook documentation](https://api.slack.com/messaging/webhooks){:target="_blank"} to learn more about setting up webhooks.
|
||||
|
|
|
@ -89,20 +89,20 @@ If the output lists the `BookReviews` table as follows, your database has been c
|
|||
## Question & Discussion
|
||||
1. Why did we choose to deploy our PostgreSQL database using a StatefulSet instead of a Knative Service?
|
||||
|
||||
We use [StatefulSet](https://kubernetes.io/docs/concepts/workloads/controllers/statefulset/) for databases instead of Knative Service mainly because databases need to remember data (like a notebook that keeps your notes). StatefulSets are good at remembering things because they can save data and have a special name and place where they live. This is very important for databases.
|
||||
We use [StatefulSet](https://kubernetes.io/docs/concepts/workloads/controllers/statefulset/){:target="_blank"} for databases instead of Knative Service mainly because databases need to remember data (like a notebook that keeps your notes). StatefulSets are good at remembering things because they can save data and have a special name and place where they live. This is very important for databases.
|
||||
|
||||
Knative Services are more like notebooks that you use and then throw away when you're done. They're great for tasks that don't need to keep data for a long time. You can make them go away when you don't need them and come back when you do. But databases need to always remember information, so they can't just disappear and come back.
|
||||
|
||||
Also, databases often talk in their own special language, not the usual web language (HTTP) that Knative Services are really good at understanding. Because of this, Knative Services aren't the best choice for databases. That's why we choose StatefulSet for databases in Kubernetes.
|
||||
|
||||
---
|
||||
Note box: However, Knative Service supports Volumes and Persistent Volumes, which can be used to store data. You can read more [here](https://knative.dev/docs/serving/services/storage/) about how to use Volumes and Persistent Volumes with Knative Services specially for your use case.
|
||||
Note box: However, Knative Service supports Volumes and Persistent Volumes, which can be used to store data. You can read more [here](https://knative.dev/docs/serving/services/storage/){:target="_blank"} about how to use Volumes and Persistent Volumes with Knative Services specially for your use case.
|
||||
|
||||
---
|
||||
|
||||
2. When should I use Knative Service, and what would be the best use case for it?
|
||||
|
||||
You can read more about the best use cases for Knative Service [here](https://knative.dev/docs/serving/samples/)!
|
||||
You can read more about the best use cases for Knative Service [here](https://knative.dev/docs/serving/samples/){:target="_blank"}!
|
||||
|
||||
## Conclusion
|
||||
By following this guide, you have successfully deployed a PostgreSQL server on a Kubernetes cluster, set up persistent storage, and initialized your database using a Kubernetes job. Congratulations! Your bookstore now has the database service.
|
|
@ -18,7 +18,7 @@ pnpm dev
|
|||
bun dev
|
||||
```
|
||||
|
||||
Open [http://localhost:3000](http://localhost:3000) with your browser to see the result.
|
||||
Open [http://localhost:3000](http://localhost:3000){:target="_blank"} with your browser to see the result.
|
||||
|
||||
# Project Structures
|
||||
|
||||
|
@ -33,7 +33,7 @@ This repository contains a Next.js application that utilizes next-themes and Tai
|
|||
|
||||
## Prerequisites
|
||||
|
||||
- Docker installed on your machine. You can download and install Docker from [here](https://www.docker.com/get-started).
|
||||
- Docker installed on your machine. You can download and install Docker from [here](https://www.docker.com/get-started){:target="_blank"}.
|
||||
|
||||
## Dockerization Steps
|
||||
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
|
|
|
@ -10,7 +10,7 @@ spec:
|
|||
selector:
|
||||
matchLabels:
|
||||
app: node-server
|
||||
sink: # In this case, the sink is our broker, which is the eventing service that will receive the events
|
||||
sink: # In this case, the sink is our Broker, which is the eventing service that will receive the events
|
||||
ref:
|
||||
apiVersion: eventing.knative.dev/v1
|
||||
kind: Broker
|
||||
|
|
|
@ -98,7 +98,7 @@ app.post('/add', async (req, res) => {
|
|||
const brokerURI = process.env.K_SINK;
|
||||
|
||||
if (receivedEvent.type === 'new-review-comment') {
|
||||
// Forward the event to the broker with the necessary CloudEvent headers
|
||||
// Forward the event to the Broker with the necessary CloudEvent headers
|
||||
const response = await fetch(brokerURI, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
|
|
|
@ -15,7 +15,7 @@ spec:
|
|||
apiVersion: serving.knative.dev/v1
|
||||
kind: Service
|
||||
name: sentiment-analysis-app
|
||||
reply: # This is the last step of the sequence, it will send the event back to the broker as reply
|
||||
reply: # This is the last step of the sequence, it will send the event back to the Broker as reply
|
||||
ref:
|
||||
kind: Broker
|
||||
apiVersion: eventing.knative.dev/v1
|
||||
|
|
|
@ -21,10 +21,10 @@ kubectl apply -f https://github.com/knative/eventing/releases/download/knative-v
|
|||
kubectl apply -f https://github.com/knative/eventing/releases/download/knative-v1.14.0/eventing-core.yaml
|
||||
echo "Knative Eventing installed successfully."
|
||||
|
||||
# Install Knative imc broker
|
||||
# Install Knative imc Broker
|
||||
kubectl apply -f https://github.com/knative/eventing/releases/download/knative-v1.14.0/in-memory-channel.yaml
|
||||
kubectl apply -f https://github.com/knative/eventing/releases/download/knative-v1.14.0/mt-channel-broker.yaml
|
||||
echo "Knative in-memory channel and broker installed successfully."
|
||||
echo "Knative in-memory Channel and Broker installed successfully."
|
||||
|
||||
# Detect whether the user has knative function "func" installed
|
||||
if ! command -v func &> /dev/null
|
||||
|
|
|
@ -11,7 +11,7 @@ When a CloudEvent with the type `new-review-comment` is sent to the Knative Even
|
|||
## Install prerequisites
|
||||
|
||||
### Prerequisite 1: Install Camel CLI
|
||||
Install the Camel K CLI (`kamel`) on your local machine. You can find the installation instructions [here](https://camel.apache.org/camel-k/2.2.x/cli/cli.html).
|
||||
Install the Camel K CLI (`kamel`) on your local machine. You can find the installation instructions [here](https://camel.apache.org/camel-k/2.2.x/cli/cli.html){:target="_blank"}.
|
||||
|
||||
**Troubleshot**: 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.
|
||||
|
||||
|
@ -29,7 +29,7 @@ $ kamel install --registry docker.io --organization <your-organization> --regist
|
|||
|
||||
Replace the placeholders with your actual Docker registry information.
|
||||
|
||||
If you are using other container registries, you may need to read more [here](https://camel.apache.org/camel-k/2.2.x/installation/registry/registry.html) for the installation.
|
||||
If you are using other container registries, you may need to read more [here](https://camel.apache.org/camel-k/2.2.x/installation/registry/registry.html){:target="_blank"} for the installation.
|
||||
|
||||
You will see this message if the installation is successful:
|
||||
|
||||
|
@ -43,19 +43,19 @@ Follow the instruction here on how to create the slack workspace and generate an
|
|||
## Implementation
|
||||
### Step 1: Create the Broker
|
||||
|
||||
This broker is created solely for testing purposes and is intended for temporary use during this part of the tutorial only.
|
||||
This Broker is created solely for testing purposes and is intended for temporary use during this part of the tutorial only.
|
||||
|
||||
**Method 1**: Initialize a broker within your Kubernetes cluster using the Knative CLI:
|
||||
**Method 1**: Initialize a Broker within your Kubernetes cluster using the Knative CLI:
|
||||
|
||||
```bash
|
||||
$ kn broker create book-review-broker
|
||||
```
|
||||
You will see this message if the broker is created successfully:
|
||||
You will see this message if the Broker is created successfully:
|
||||
|
||||
```
|
||||
Broker ‘book-review-broker’ successfully created in namespace ‘default’.
|
||||
Broker 'book-review-broker' successfully created in namespace 'default'.
|
||||
```
|
||||
**Method 2**: You can create a new YAML file to create the broker:
|
||||
**Method 2**: You can create a new YAML file to create the Broker:
|
||||
|
||||
*new-knative-broker.yaml*
|
||||
```yaml
|
||||
|
@ -70,7 +70,7 @@ After you saved the file, you can apply the configuration to your Kubernetes clu
|
|||
```bash
|
||||
$ kubectl apply -f new-knative-broker.yaml
|
||||
```
|
||||
You will see this message if the broker is created successfully:
|
||||
You will see this message if the Broker is created successfully:
|
||||
|
||||
```
|
||||
broker.eventing.knative.dev/book-review-broker created
|
||||
|
@ -139,9 +139,9 @@ slack-sink-pipe Ready 1
|
|||
|
||||
To trigger notifications, you'll need to simulate an event that matches the criteria set in your Slack sink configuration. For example, submitting a book review could be an event of type `new-review-comment`.
|
||||
|
||||
Directly sending CloudEvents to a broker using curl from an external machine (like your local computer) is typically **constrained** due to the networking and security configurations of Kubernetes clusters.
|
||||
Directly sending CloudEvents to a Broker using curl from an external machine (like your local computer) is typically **constrained** due to the networking and security configurations of Kubernetes clusters.
|
||||
|
||||
Therefore, you need to create a new pod in your Kubernetes cluster to send a CloudEvent to the broker. You can use the following command to create a new pod:
|
||||
Therefore, you need to create a new pod in your Kubernetes cluster to send a CloudEvent to the Broker. You can use the following command to create a new pod:
|
||||
|
||||
```bash
|
||||
$ kubectl run curler --image=radial/busyboxplus:curl -it --restart=Never
|
||||
|
@ -154,9 +154,9 @@ If you don't see a command prompt, try pressing enter.
|
|||
```
|
||||
|
||||
|
||||
Using curl command to send a CloudEvent to the broker:
|
||||
Using curl command to send a CloudEvent to the Broker:
|
||||
```bash
|
||||
[root@curler:/]$ curl -v "<The URI to your broker>" \
|
||||
[root@curler:/]$ curl -v "<The URI to your Broker>" \
|
||||
-X POST \
|
||||
-H "Ce-Id: review1" \
|
||||
-H "Ce-Specversion: 1.0" \
|
||||
|
@ -166,7 +166,7 @@ Using curl command to send a CloudEvent to the broker:
|
|||
-d 'Hello from Knative!'
|
||||
```
|
||||
|
||||
You can find the URI to your broker by running the following command:
|
||||
You can find the URI to your Broker by running the following command:
|
||||
|
||||
```bash
|
||||
$ kubectl get broker book-review-broker
|
||||
|
|
|
@ -89,20 +89,20 @@ If the output lists the `BookReviews` table as follows, your database has been c
|
|||
## Question & Discussion
|
||||
1. Why did we choose to deploy our PostgreSQL database using a StatefulSet instead of a Knative Service?
|
||||
|
||||
We use [StatefulSet](https://kubernetes.io/docs/concepts/workloads/controllers/statefulset/) for databases instead of Knative Service mainly because databases need to remember data (like a notebook that keeps your notes). StatefulSets are good at remembering things because they can save data and have a special name and place where they live. This is very important for databases.
|
||||
We use [StatefulSet](https://kubernetes.io/docs/concepts/workloads/controllers/statefulset/){:target="_blank"} for databases instead of Knative Service mainly because databases need to remember data (like a notebook that keeps your notes). StatefulSets are good at remembering things because they can save data and have a special name and place where they live. This is very important for databases.
|
||||
|
||||
Knative Services are more like notebooks that you use and then throw away when you're done. They're great for tasks that don't need to keep data for a long time. You can make them go away when you don't need them and come back when you do. But databases need to always remember information, so they can't just disappear and come back.
|
||||
|
||||
Also, databases often talk in their own special language, not the usual web language (HTTP) that Knative Services are really good at understanding. Because of this, Knative Services aren't the best choice for databases. That's why we choose StatefulSet for databases in Kubernetes.
|
||||
|
||||
---
|
||||
Note box: However, Knative Service supports Volumes and Persistent Volumes, which can be used to store data. You can read more [here](https://knative.dev/docs/serving/services/storage/) about how to use Volumes and Persistent Volumes with Knative Services specially for your use case.
|
||||
Note box: However, Knative Service supports Volumes and Persistent Volumes, which can be used to store data. You can read more [here](https://knative.dev/docs/serving/services/storage/){:target="_blank"} about how to use Volumes and Persistent Volumes with Knative Services specially for your use case.
|
||||
|
||||
---
|
||||
|
||||
2. When should I use Knative Service, and what would be the best use case for it?
|
||||
|
||||
You can read more about the best use cases for Knative Service [here](https://knative.dev/docs/serving/samples/)!
|
||||
You can read more about the best use cases for Knative Service [here](https://knative.dev/docs/serving/samples/{:target="_blank"}!
|
||||
|
||||
## Conclusion
|
||||
By following this guide, you have successfully deployed a PostgreSQL server on a Kubernetes cluster, set up persistent storage, and initialized your database using a Kubernetes job. Congratulations! Your bookstore now has the database service.
|
|
@ -18,7 +18,7 @@ pnpm dev
|
|||
bun dev
|
||||
```
|
||||
|
||||
Open [http://localhost:3000](http://localhost:3000) with your browser to see the result.
|
||||
Open [http://localhost:3000](http://localhost:3000){:target="_blank"} with your browser to see the result.
|
||||
|
||||
# Project Structures
|
||||
|
||||
|
@ -33,7 +33,7 @@ This repository contains a Next.js application that utilizes next-themes and Tai
|
|||
|
||||
## Prerequisites
|
||||
|
||||
- Docker installed on your machine. You can download and install Docker from [here](https://www.docker.com/get-started).
|
||||
- Docker installed on your machine. You can download and install Docker from [here](https://www.docker.com/get-started){:target="_blank"}.
|
||||
|
||||
## Dockerization Steps
|
||||
|
||||
|
|
|
@ -98,7 +98,7 @@ app.post('/add', async (req, res) => {
|
|||
const brokerURI = process.env.K_SINK;
|
||||
|
||||
if (receivedEvent.type === 'new-review-comment') {
|
||||
// Forward the event to the broker with the necessary CloudEvent headers
|
||||
// Forward the event to the Broker with the necessary CloudEvent headers
|
||||
const response = await fetch(brokerURI, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
|
|
|
@ -21,10 +21,10 @@ kubectl apply -f https://github.com/knative/eventing/releases/download/knative-v
|
|||
kubectl apply -f https://github.com/knative/eventing/releases/download/knative-v1.14.0/eventing-core.yaml
|
||||
echo "Knative Eventing installed successfully."
|
||||
|
||||
# Install Knative imc broker
|
||||
# Install Knative imc Broker
|
||||
kubectl apply -f https://github.com/knative/eventing/releases/download/knative-v1.14.0/in-memory-channel.yaml
|
||||
kubectl apply -f https://github.com/knative/eventing/releases/download/knative-v1.14.0/mt-channel-broker.yaml
|
||||
echo "Knative in-memory channel and broker installed successfully."
|
||||
echo "Knative in-memory Channel and Broker installed successfully."
|
||||
|
||||
# Detect whether the user has knative function "func" installed
|
||||
if ! command -v func &> /dev/null
|
||||
|
|
|
@ -11,7 +11,7 @@ When a CloudEvent with the type `new-review-comment` is sent to the Knative Even
|
|||
## Install prerequisites
|
||||
|
||||
### Prerequisite 1: Install Camel CLI
|
||||
Install the Camel K CLI (`kamel`) on your local machine. You can find the installation instructions [here](https://camel.apache.org/camel-k/2.2.x/cli/cli.html).
|
||||
Install the Camel K CLI (`kamel`) on your local machine. You can find the installation instructions [here](https://camel.apache.org/camel-k/2.2.x/cli/cli.html){:target="_blank"}.
|
||||
|
||||
**Troubleshot**: 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.
|
||||
|
||||
|
@ -29,7 +29,7 @@ $ kamel install --registry docker.io --organization <your-organization> --regist
|
|||
|
||||
Replace the placeholders with your actual Docker registry information.
|
||||
|
||||
If you are using other container registries, you may need to read more [here](https://camel.apache.org/camel-k/2.2.x/installation/registry/registry.html) for the installation.
|
||||
If you are using other container registries, you may need to read more [here](https://camel.apache.org/camel-k/2.2.x/installation/registry/registry.html){:target="_blank"} for the installation.
|
||||
|
||||
You will see this message if the installation is successful:
|
||||
|
||||
|
@ -43,19 +43,19 @@ Follow the instruction here on how to create the slack workspace and generate an
|
|||
## Implementation
|
||||
### Step 1: Create the Broker
|
||||
|
||||
This broker is created solely for testing purposes and is intended for temporary use during this part of the tutorial only.
|
||||
This Broker is created solely for testing purposes and is intended for temporary use during this part of the tutorial only.
|
||||
|
||||
**Method 1**: Initialize a broker within your Kubernetes cluster using the Knative CLI:
|
||||
**Method 1**: Initialize a Broker within your Kubernetes cluster using the Knative CLI:
|
||||
|
||||
```bash
|
||||
$ kn broker create book-review-broker
|
||||
```
|
||||
You will see this message if the broker is created successfully:
|
||||
You will see this message if the Broker is created successfully:
|
||||
|
||||
```
|
||||
Broker ‘book-review-broker’ successfully created in namespace ‘default’.
|
||||
Broker 'book-review-broker' successfully created in namespace 'default'.
|
||||
```
|
||||
**Method 2**: You can create a new YAML file to create the broker:
|
||||
**Method 2**: You can create a new YAML file to create the Broker:
|
||||
|
||||
*new-knative-broker.yaml*
|
||||
```yaml
|
||||
|
@ -70,7 +70,7 @@ After you saved the file, you can apply the configuration to your Kubernetes clu
|
|||
```bash
|
||||
$ kubectl apply -f new-knative-broker.yaml
|
||||
```
|
||||
You will see this message if the broker is created successfully:
|
||||
You will see this message if the Broker is created successfully:
|
||||
|
||||
```
|
||||
broker.eventing.knative.dev/book-review-broker created
|
||||
|
@ -79,7 +79,7 @@ broker.eventing.knative.dev/book-review-broker created
|
|||
|
||||
### Step 2: Configure the Slack Sink
|
||||
|
||||
We use a feature called "Pipe" in Camel K to link event sources and destinations. Specifically, the Pipe connects events from a Broker, our source, to a Slack channel through a Slack sink Kamelet, our destination. This setup automatically sends notifications to Slack whenever new events occur, streamlining the flow of information.
|
||||
We use a feature called "Pipe" in Apache Camel K to link event sources and destinations. Specifically, the Pipe connects events from a Broker, our source, to a Slack channel through a Slack sink Kamelet, our destination. This setup automatically sends notifications to Slack whenever new events occur, streamlining the flow of information.
|
||||
|
||||
|
||||
1. Create a Slack app and generate an incoming webhook URL for your designated channel where notifications will be sent. Refer to Slack documentation for how to do this.
|
||||
|
@ -139,9 +139,9 @@ slack-sink-pipe Ready 1
|
|||
|
||||
To trigger notifications, you'll need to simulate an event that matches the criteria set in your Slack sink configuration. For example, submitting a book review could be an event of type `new-review-comment`.
|
||||
|
||||
Directly sending CloudEvents to a broker using curl from an external machine (like your local computer) is typically **constrained** due to the networking and security configurations of Kubernetes clusters.
|
||||
Directly sending CloudEvents to a Broker using curl from an external machine (like your local computer) is typically **constrained** due to the networking and security configurations of Kubernetes clusters.
|
||||
|
||||
Therefore, you need to create a new pod in your Kubernetes cluster to send a CloudEvent to the broker. You can use the following command to create a new pod:
|
||||
Therefore, you need to create a new pod in your Kubernetes cluster to send a CloudEvent to the Broker. You can use the following command to create a new pod:
|
||||
|
||||
```bash
|
||||
$ kubectl run curler --image=radial/busyboxplus:curl -it --restart=Never
|
||||
|
@ -154,7 +154,7 @@ If you don't see a command prompt, try pressing enter.
|
|||
```
|
||||
|
||||
|
||||
Using curl command to send a CloudEvent to the broker:
|
||||
Using curl command to send a CloudEvents to the Broker:
|
||||
```bash
|
||||
[root@curler:/]$ curl -v "<The URI to your broker>" \
|
||||
-X POST \
|
||||
|
@ -166,7 +166,7 @@ Using curl command to send a CloudEvent to the broker:
|
|||
-d 'Hello from Knative!'
|
||||
```
|
||||
|
||||
You can find the URI to your broker by running the following command:
|
||||
You can find the URI to your Broker by running the following command:
|
||||
|
||||
```bash
|
||||
$ kubectl get broker book-review-broker
|
||||
|
|
|
@ -16,4 +16,4 @@
|
|||
#
|
||||
|
||||
slack.channel=#bookstore-owner
|
||||
slack.webhook.url=
|
||||
slack.webhook.url=https://hooks.slack.com/services/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
|
|
@ -4,12 +4,12 @@
|
|||
|
||||
To create a Slack workspace, follow these steps:
|
||||
|
||||
- Visit [https://slack.com/get-started#/createnew](https://slack.com/get-started#/createnew).
|
||||
- Visit [https://slack.com/get-started#/createnew](https://slack.com/get-started#/createnew){:target="_blank"}.
|
||||
- Enter your email address and click Continue, or continue with Apple or Google.
|
||||
- Check your email for a confirmation code.
|
||||
- Enter the code on the Slack website.
|
||||
- Click "Create a Workspace" and follow the prompts.
|
||||
- For detailed instructions for androids and , refer to [Create a workspace](https://slack.com/help/articles/206845317-Create-a-Slack-workspace).
|
||||
- For detailed instructions for androids and , refer to [Create a workspace](https://slack.com/help/articles/206845317-Create-a-Slack-workspace){:target="_blank"}.
|
||||
|
||||
## Adding Channels to Your Workspace
|
||||
|
||||
|
@ -17,13 +17,13 @@ After creating your Slack workspace, you can add channels by following these ste
|
|||
|
||||
- Click the '+' icon next to 'Channels' on the sidebar of your Slack workspace.
|
||||
- Choose "Create a channel" and specify the channel name and purpose.
|
||||
- For enterprise grid organizations, refer to [Slack's help article](https://slack.com/help/articles/115001399587-Add-a-channel-to-multiple-workspaces-in-your-Enterprise-Grid-organization) for instructions.
|
||||
- For enterprise grid organizations, refer to [Slack's help article](https://slack.com/help/articles/115001399587-Add-a-channel-to-multiple-workspaces-in-your-Enterprise-Grid-organization){:target="_blank"} for instructions.
|
||||
|
||||
## Setting Up a Webhook for Notifications
|
||||
|
||||
To set up a webhook for sending notifications to your Slack workspace:
|
||||
|
||||
- Create a [Slack app](https://api.slack.com/apps/new), following the instructions by signing in, adding name and workspace to put the app in.
|
||||
- Create a [Slack app](https://api.slack.com/apps/new){:target="_blank"}, following the instructions by signing in, adding name and workspace to put the app in.
|
||||
- After this, you'll be redirected to the setting pages of your new app. Choose **Incoming Webhook** and toggle **Activate Webhook**.
|
||||
- Scroll down to click the option **Add New Webhook to Workspace**.
|
||||

|
||||
|
|
|
@ -20,24 +20,38 @@ nav:
|
|||
# Getting started
|
||||
###############################################################################
|
||||
- Tutorial:
|
||||
- Tutorial introduction: getting-started/README.md
|
||||
- Install Knative using quickstart: getting-started/quickstart-install.md
|
||||
- Knative Functions:
|
||||
- About Knative Functions: getting-started/about-knative-functions.md
|
||||
- Installing Knative Functions: getting-started/install-func.md
|
||||
- Creating a function: getting-started/create-a-function.md
|
||||
- Building, running, or deploying a function: getting-started/build-run-deploy-func.md
|
||||
- Knative Serving:
|
||||
- Deploying a Knative Service: getting-started/first-service.md
|
||||
- Autoscaling: getting-started/first-autoscale.md
|
||||
- Traffic splitting: getting-started/first-traffic-split.md
|
||||
- Knative Eventing:
|
||||
- About Knative Eventing: getting-started/getting-started-eventing.md
|
||||
- Sources, Brokers, and Triggers: getting-started/first-broker.md
|
||||
- Using a Knative Service as a source: getting-started/first-source.md
|
||||
- Using Triggers and sinks: getting-started/first-trigger.md
|
||||
- What's Next?: getting-started/next-steps.md
|
||||
- Clean Up: getting-started/clean-up.md
|
||||
- Overview: getting-started/tutorial.md
|
||||
- Quickstart:
|
||||
- Tutorial introduction: getting-started/README.md
|
||||
- Install Knative using quickstart: getting-started/quickstart-install.md
|
||||
- Knative Functions:
|
||||
- About Knative Functions: getting-started/about-knative-functions.md
|
||||
- Installing Knative Functions: getting-started/install-func.md
|
||||
- Creating a function: getting-started/create-a-function.md
|
||||
- Building, running, or deploying a function: getting-started/build-run-deploy-func.md
|
||||
- Knative Serving:
|
||||
- Deploying a Knative Service: getting-started/first-service.md
|
||||
- Autoscaling: getting-started/first-autoscale.md
|
||||
- Traffic splitting: getting-started/first-traffic-split.md
|
||||
- Knative Eventing:
|
||||
- About Knative Eventing: getting-started/getting-started-eventing.md
|
||||
- Sources, Brokers, and Triggers: getting-started/first-broker.md
|
||||
- Using a Knative Service as a source: getting-started/first-source.md
|
||||
- Using Triggers and sinks: getting-started/first-trigger.md
|
||||
- What's Next?: getting-started/next-steps.md
|
||||
- Clean Up: getting-started/clean-up.md
|
||||
- "E2E tutorial: Knative Bookstore":
|
||||
- Overview: bookstore/page-0/welcome-knative-bookstore-tutorial.md
|
||||
- Disclaimer: bookstore/disclaimer/README.md
|
||||
- Environment Setup: bookstore/page-0.5/environment-setup.md
|
||||
- 1 - Send Comments to Broker: bookstore/page-1/send-review-comment-to-broker.md
|
||||
- 2 - Create Sentiment Service: bookstore/page-2/sentiment-analysis-service-for-bookstore-reviews.md
|
||||
- 3 - Create Bad Word Service: bookstore/page-3/create-bad-word-filter-service.md
|
||||
- 4 - Create Sequence: bookstore/page-4/create-sequence-to-streamline-ML-workflows.md
|
||||
- 5 - Create DB service: bookstore/page-5/deploy-database-service.md
|
||||
- 6 - Advanced event filtering: bookstore/page-6/advanced-event-filtering.md
|
||||
- 7 - Connect Slack via Camel-K: bookstore/page-7/slack-sink-learning-knative-eventing-and-apache-camel-K-integration.md
|
||||
- 8 - Extra Challenges: bookstore/extra-challenge/README.md
|
||||
###############################################################################
|
||||
# Installing
|
||||
###############################################################################
|
||||
|
|
|
@ -0,0 +1,46 @@
|
|||
# Creating a Slack Workspace
|
||||
|
||||

|
||||
|
||||
To create a Slack workspace, follow these steps:
|
||||
|
||||
1. Visit [https://slack.com/get-started#/createnew](https://slack.com/get-started#/createnew){:target="_blank"}.
|
||||
2. Enter your email address and click Continue, or continue with Apple or Google.
|
||||
3. Check your email for a confirmation code.
|
||||
4. Enter the code on the Slack website.
|
||||
5. Click "Create a Workspace" and follow the prompts.
|
||||
6. For detailed instructions how to create a workspace via the Desktop App, Android or iOS, refer to [Create a Slack workspace](https://slack.com/help/articles/206845317-Create-a-Slack-workspace){:target="_blank"}.
|
||||
|
||||
## **Adding Channels to Your Workspace**
|
||||
|
||||
After creating your Slack workspace, you can add channels by following these steps:
|
||||
|
||||
1. Click the '+' icon next to 'Channels' on the sidebar of your Slack workspace.
|
||||
2. Choose "Create a channel" and specify the channel name and purpose.
|
||||
3. For enterprise grid organizations, refer to [Slack's help article](https://slack.com/help/articles/115001399587-Add-a-channel-to-multiple-workspaces-in-your-Enterprise-Grid-organization){:target="_blank"} for instructions.
|
||||
|
||||
## **Setting Up a Webhook for Notifications**
|
||||
|
||||
To set up a webhook for sending notifications to your Slack workspace:
|
||||
|
||||
- 1: Create a [Slack app](https://api.slack.com/apps/new){:target="_blank"}, following the instructions by signing in, adding name and workspace to put the app in.
|
||||
|
||||
- 2: After this, you'll be redirected to the setting pages of your new app. Choose Incoming Webhook and toggle Activate Webhook.
|
||||
|
||||
- 3: Scroll down to click the option Add New Webhook to Workspace.
|
||||
|
||||

|
||||
|
||||
- 4: The page will give you a link associated with the app you created. This link will be where API requests are sent to send messages to your Slack workspace.
|
||||
|
||||

|
||||
|
||||
- 5: To test if the webhook works as needed, you can try sending an API request to this link to see if the message goes through. I used Postman to test this. Remember that this is an `application/json` file.
|
||||
|
||||

|
||||
|
||||
- 6: Afterwards, the text channel should have a new message.
|
||||
|
||||

|
||||
|
||||
- 7: Go to [Slack's webhook documentation](https://api.slack.com/messaging/webhooks){:target="_blank"} to learn more about setting up webhooks.
|
After Width: | Height: | Size: 289 KiB |
After Width: | Height: | Size: 149 KiB |
After Width: | Height: | Size: 112 KiB |
After Width: | Height: | Size: 141 KiB |
After Width: | Height: | Size: 72 KiB |
|
@ -0,0 +1,57 @@
|
|||
# **Disclaimer**
|
||||
|
||||

|
||||
|
||||
Hello dear Knative Learners,
|
||||
|
||||
Before you begin this tutorial, **please take note of the following disclaimer**. In the spirit of open source, we strive for transparency. This tutorial incorporates many other open source projects, and we are grateful to all the incredible contributors. Your amazing work has made this tutorial possible.
|
||||
|
||||
If you're interested in getting started with open source, check out our guide: Get Started with Open Source at Knative.
|
||||
|
||||
Thank you, and happy learning!
|
||||
|
||||
### **Open Source Libraries Used**
|
||||
|
||||
This tutorial makes use of several open source libraries to build the bookstore application. Below are the libraries used along with their respective documentation and project links:
|
||||
|
||||
- [Profanity Check](https://pypi.org/project/profanity-check/)
|
||||
- [Flask](https://flask.palletsprojects.com/en/3.0.x/)
|
||||
- [CloudEvents](https://cloudevents.io/)
|
||||
- [TextBlob](https://textblob.readthedocs.io/en/dev/)
|
||||
- [Node.js](https://nodejs.org/en)
|
||||
- [Next.js](https://nextjs.org/)
|
||||
- [PostgreSQL](https://www.postgresql.org/)
|
||||
- [Apache Camel](https://camel.apache.org/)
|
||||
|
||||
### **Music Used in the Demo Video**
|
||||
|
||||
The music used in the demo video is sourced from Uppbeat, which provides free music for creators:
|
||||
|
||||
- Music: [Trendsetter](https://uppbeat.io/t/mood-maze/trendsetter) by Mood Maze
|
||||
- License Code: JHDMCOJT3ZC4EVUB
|
||||
|
||||
### **Graphic Creation License**
|
||||
|
||||
Graphics used in this tutorial were created using Canva:
|
||||
|
||||
- Canva License: [Content License Agreement](https://www.canva.com/policies/content-license-agreement)
|
||||
|
||||
### **Results of ML Services in This Tutorial**
|
||||
|
||||
The results of the sentiment analysis and inappropriate language filter (a.k.a bad word filter) are generated using the open source libraries mentioned above. Knative **is not responsible** for the accuracy or reliability of the output generated by these libraries.
|
||||
|
||||
### **General Disclaimer**
|
||||
|
||||
This tutorial is provided for educational purposes only. While every effort has been made to ensure the accuracy and reliability of the information provided, the authors and contributors of this tutorial make no guarantees, representations, or warranties of any kind, express or implied, about the completeness, accuracy, reliability, suitability, or availability of the information contained within the tutorial for any purpose.
|
||||
|
||||
By using this tutorial, you acknowledge that:
|
||||
|
||||
- You are responsible for verifying the information and results obtained from the tutorial.
|
||||
- The tutorial may contain links to external websites and resources; the authors and contributors of this tutorial are not responsible for the content, privacy policies, or practices of these external websites and resources.
|
||||
- The open source libraries used in this tutorial are third-party products; the authors and contributors of this tutorial are not responsible for the performance, accuracy, or reliability of these libraries.
|
||||
|
||||
### **Contact**
|
||||
|
||||

|
||||
|
||||
If you have any questions or concerns regarding this disclaimer or the tutorial, please feel free to reach out to the Knative community via the Cloud Native Computing Foundation (CNCF) Slack, particularly the [#knative](https://cloud-native.slack.com/archives/C04LGHDR9K7){:target="_blank"} channel.
|
After Width: | Height: | Size: 268 KiB |
After Width: | Height: | Size: 108 KiB |
|
@ -0,0 +1,130 @@
|
|||
# **Extra Challenges**
|
||||
|
||||

|
||||
|
||||
Congratulations on completing the bookstore tutorial! Kubernetes and Knative have a high learning curve due to their complexity, but you did it! You should be proud of your accomplishment.
|
||||
|
||||
Now it's time to test your mastery of the skills you've learned with Kuack. We've prepared a few extra challenges for you to explore. Take a look and have fun!
|
||||
|
||||
## **Challenge 1: Integrate with Another Notification Service as Sink (Telegram)**
|
||||
|
||||

|
||||
|
||||
**Description**
|
||||
|
||||
Add Telegram notifications for new comments using Apache Camel K.
|
||||
|
||||
**Objective**
|
||||
|
||||
Send Telegram notifications for new comments.
|
||||
|
||||
**Steps**
|
||||
|
||||
1. Create a new event type or filter attribute for Telegram notifications.
|
||||
2. Set up a Trigger to route these events to a Camel K integration service.
|
||||
3. Use Apache Camel K to send messages to a Telegram chat by setting up the telegram-sink.
|
||||
|
||||
**What You Will Learn**
|
||||
|
||||
- Integrating with external notification services using Apache Camel K.
|
||||
- Using Triggers to route specific events.
|
||||
- Working with the Telegram API.
|
||||
|
||||
**Estimated Time**
|
||||
|
||||
0.5-1 hours
|
||||
|
||||
## **Challenge 2: Implement Comment Deletion**
|
||||
|
||||

|
||||
|
||||
**Description**
|
||||
|
||||
Add functionality to delete comments from the database using an event-driven approach.
|
||||
|
||||
**Objective**
|
||||
|
||||
Allow users to delete the selected comment.
|
||||
|
||||
**Steps**
|
||||
|
||||
1. Create a new event type for comment deletion.
|
||||
2. Set up a Trigger to listen for deletion events.
|
||||
3. Implement a function in the node-server to handle the deletion and update the database.
|
||||
|
||||
**What You will Learn:**
|
||||
|
||||
- Creating and handling new event types.
|
||||
- Setting up Triggers for specific events.
|
||||
- Performing database operations based on events.
|
||||
|
||||
**Estimated Time**
|
||||
|
||||
1-2 hours
|
||||
|
||||
## **Challenge 3: Format the Output for the Sink**
|
||||
|
||||

|
||||
|
||||
**Description**
|
||||
|
||||
Learn how to create an event consumer app that formats event data before sending it to a sink.
|
||||
|
||||
**Objective**
|
||||
|
||||
Transform event data and send it to the appropriate sink.
|
||||
|
||||
**Steps**
|
||||
|
||||
1. Create a new function in node-server to consume and transform events.
|
||||
2. Set up a Trigger to route events (Event X - unformatted) to this transformation service.
|
||||
3. Implement the transformation logic to convert Event X into Event Y - formatted.
|
||||
4. Configure the service to send the transformed event (Event Y) to the Slack sink.
|
||||
5. Ensure the function replies with the transformed event.
|
||||
|
||||
**What You Will Learn**
|
||||
|
||||
- Creating an event consumer app.
|
||||
- Adding a new step in a Sequence to process events.
|
||||
- Transforming events within a service and routing the transformed events to a sink.
|
||||
- Using Triggers and functions with replies in an event-driven architecture.
|
||||
|
||||
**Estimated Time**
|
||||
|
||||
1-2 hours
|
||||
|
||||
## **Challenge 4: Submit Comments via Telegram**
|
||||
|
||||

|
||||
|
||||
**Description**
|
||||
|
||||
Enable users to submit new comments through a Telegram bot using Apache Camel K.
|
||||
|
||||
**Objective**
|
||||
|
||||
Allow users to send comments via Telegram.
|
||||
|
||||
**Steps**
|
||||
|
||||
1. Create a Telegram bot and obtain the bot token.
|
||||
2. Set up an [Apache Camel K Telegram source](https://camel.apache.org/camel-kamelets/4.4.x/telegram-source.html){:target="_blank"} to listen for messages from the Telegram bot.
|
||||
3. Create a new event type for comments received via Telegram.
|
||||
4. Set up a Trigger to process these events and route them to the comment handling service.
|
||||
5. Implement a function in the node-server to handle the new comments and update the database.
|
||||
|
||||
**What You Will Learn**
|
||||
|
||||
- Creating and configuring a Telegram bot.
|
||||
- Using Apache Camel K to integrate Telegram as an event source with your application.
|
||||
- Handling new event types and processing user input from external sources.
|
||||
|
||||
**Estimated Time**
|
||||
|
||||
2-3 hours
|
||||
|
||||
## **Help**
|
||||
|
||||

|
||||
|
||||
Join the supportive Knative community via the Cloud Native Computing Foundation (CNCF) Slack, particularly the [#knative](https://cloud-native.slack.com/archives/C04LGHDR9K7){:target="_blank"} channel. Before posting your questions, please search to see if they've already been answered. Your feedback on this tutorial is invaluable, so don't hesitate to reach out with suggestions or questions.
|
After Width: | Height: | Size: 88 KiB |
After Width: | Height: | Size: 268 KiB |
After Width: | Height: | Size: 97 KiB |
After Width: | Height: | Size: 135 KiB |
After Width: | Height: | Size: 141 KiB |
After Width: | Height: | Size: 94 KiB |
|
@ -0,0 +1,306 @@
|
|||
# Environment Setup
|
||||
|
||||

|
||||
|
||||
In this page, we will be discussing how to set up your environment, and make sure to run up the UI front end and the Book Review Service’s node server.
|
||||
|
||||
## **What does the final deliverable for this section look like?**
|
||||
|
||||
- You have a running Kubernetes (k8s) cluster on your local machine, with Knative installed.
|
||||
- You have your front end application deployed as Kubernetes deployment with port-forwarding to localhost:3000
|
||||
- You have your Node.js application deployed as Kubernetes deployment with port-forwarding to localhost:8080
|
||||
|
||||
We will be fulfilling each requirement with the order above.
|
||||
|
||||
## **Clone the Repository**
|
||||

|
||||
|
||||
```sh
|
||||
git clone https://github.com/knative/docs.git
|
||||
```
|
||||
???+ bug "Troubleshooting"
|
||||
Having issue with cloning your repo? Check [here](https://docs.github.com/en/repositories/creating-and-managing-repositories/troubleshooting-cloning-errors){:target="_blank"} for help.
|
||||
|
||||
!!! warning
|
||||
|
||||
**IMPORTANT**: Please take some time to read the [Disclaimer](../disclaimer/README.md){:target="_blank"} before moving to the next page.
|
||||
|
||||
|
||||
## **File Structure**
|
||||
|
||||

|
||||
|
||||
The code for the sample app is in `docs/code-samples/eventing/bookstore-sample-app`
|
||||
|
||||
Under `bookstore-sample-app` folder, there are 2 folders:
|
||||
|
||||
* **/solution**: this folder contains all the yaml files, and the code you needed. Check it when you got stuck.
|
||||
|
||||
* **/start**: this folder contains the necessary files for you to get started. Save there all the configuration files yourself following the tutorial!
|
||||
|
||||

|
||||
|
||||
!!! tip
|
||||
Kuack suggests you to start from **/start**, write all the configuration files as you go over the tutorial, and check solutions when you got stuck.
|
||||
|
||||

|
||||
|
||||
Always `cd` back to the root directory, which is `/start`, before running any commands.
|
||||
|
||||
All the commands in the tutorial are written **assuming you are in the `/start` directory**.
|
||||
|
||||
|
||||
## **Shortcut**
|
||||
|
||||

|
||||
|
||||
Running `docs/code-samples/eventing/bookstore-sample-app/start/setup.sh` will automatically complete all tasks in this section.
|
||||
|
||||
!!! warning
|
||||
|
||||
However, if you are not familiar with the process, we recommend reviewing the steps below.
|
||||
|
||||
## **Instructions**
|
||||
|
||||
### **Task 1: Set Up a Running Kubernetes Cluster with Knative Installed**
|
||||
|
||||

|
||||
|
||||
Please follow the instructions [here](https://knative.dev/docs/install/){:target="_blank"} to spin up your cluster with Knative installed!
|
||||
|
||||
???+ success "Verify"
|
||||
|
||||
You should see the pods in the `knative-eventing` and `knative-serving` namespaces running before proceeding.
|
||||
|
||||
```
|
||||
NAMESPACE NAME READY STATUS RESTARTS AGE
|
||||
knative-eventing eventing-controller-7576f555d5-7c2p2 1/1 Running 0 4m50s
|
||||
knative-eventing eventing-webhook-5874bb8445-cqcn9 1/1 Running 0 4m50s
|
||||
knative-eventing imc-controller-8c5d5ddb5-m249l 1/1 Running 0 4m49s
|
||||
knative-eventing imc-dispatcher-76d9f7464b-dphd6 1/1 Running 0 4m49s
|
||||
knative-eventing mt-broker-controller-8d8f8d48f-rvlcv 1/1 Running 0 4m48s
|
||||
knative-eventing mt-broker-filter-85c457f879-dvhnj 1/1 Running 0 4m48s
|
||||
knative-eventing mt-broker-ingress-5688f4cd68-nm8cc 1/1 Running 0 4m48s
|
||||
knative-serving activator-55d856fccd-g5qpw 1/1 Running 0 4m53s
|
||||
knative-serving autoscaler-5fb49c64c7-hrjng 1/1 Running 0 4m53s
|
||||
knative-serving controller-ddbb9d4f-khttq 1/1 Running 0 4m53s
|
||||
knative-serving net-kourier-controller-68d89f78d5-hw8r6 1/1 Running 0 4m52s
|
||||
knative-serving webhook-85b9744fc5-6w9sg 1/1 Running 0 4m53s
|
||||
kourier-system 3scale-kourier-gateway-dbc5b88f5-7g29n 1/1 Running 0 4m52s
|
||||
kube-system coredns-5dd5756b68-49xsj 1/1 Running 0 12m
|
||||
kube-system etcd-minikube 1/1 Running 0 12m
|
||||
kube-system kube-apiserver-minikube 1/1 Running 0 12m
|
||||
kube-system kube-controller-manager-minikube 1/1 Running 0 12m
|
||||
kube-system kube-proxy-tqcvx 1/1 Running 0 12m
|
||||
kube-system kube-scheduler-minikube 1/1 Running 0 12m
|
||||
kube-system storage-provisioner 1/1 Running 0 12m
|
||||
```
|
||||
|
||||
#### **Extra Step for Minikube Users:**
|
||||
|
||||

|
||||
|
||||
Attention! In case you're not using the Knative Quick Start, set up the tunnel manually to connect to services of type `LoadBalancer`:
|
||||
|
||||
Run the following command and keep the terminal open:
|
||||
|
||||
```shell
|
||||
minikube tunnel
|
||||
```
|
||||
|
||||
???+ success "Verify"
|
||||
If there aren't any error messages, it means you have set up the tunnel successfully.
|
||||
|
||||
### **Task 2: Running the Bookstore Web App**
|
||||
|
||||

|
||||
|
||||
The Next.js frontend app is located in the `docs/code-samples/eventing/bookstore-sample-app/start/frontend` folder.
|
||||
|
||||
Ensure that port 3000 on your local machine is not being used by another application.
|
||||
|
||||
#### **Deploy the Frontend App**
|
||||
|
||||
You can either [build the image locally](https://docs.docker.com/get-started/02_our_app/){:target="_blank"} or use our pre-built image. If you are using the pre-built image, you can proceed to the next step.
|
||||
|
||||
When ready, run the following command to deploy the frontend app:
|
||||
|
||||
```shell
|
||||
kubectl apply -f frontend/config/100-front-end-deployment.yaml
|
||||
```
|
||||
|
||||
This will create the Deployment and expose it with a Service of type LoadBalancer to receive external traffic:
|
||||
|
||||
```
|
||||
deployment.apps/bookstore-frontend created
|
||||
service/bookstore-frontend-svc created
|
||||
```
|
||||
|
||||
???+ success "Verify"
|
||||
Run the following command to check if the pod is running:
|
||||
|
||||
```shell
|
||||
kubectl get pods
|
||||
```
|
||||
|
||||
You will see that your front end pod is running.
|
||||
|
||||
```
|
||||
NAME READY STATUS RESTARTS AGE
|
||||
bookstore-frontend-7b879ffb78-9bln6 1/1 Running 0 4m37s
|
||||
```
|
||||
|
||||
|
||||
|
||||
#### **Port Forwarding (Optional under condition)**
|
||||
|
||||

|
||||
|
||||
You might need to set up port forwarding to access the app from your local machine.
|
||||
|
||||
Check if port forwarding is necessary by running:
|
||||
|
||||
```shell
|
||||
kubectl get services
|
||||
```
|
||||
|
||||
And you will see the following console output:
|
||||
```
|
||||
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
|
||||
bookstore-frontend-svc LoadBalancer 10.99.187.173 <pending> 3000:31600/TCP 27m
|
||||
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 39m
|
||||
```
|
||||
|
||||
|
||||
|
||||
!!! note
|
||||
If the `EXTERNAL-IP` for your frontend service is `127.0.0.1`, port forwarding is not needed.
|
||||
|
||||
If port forwarding is required, run the following command:
|
||||
|
||||
```shell
|
||||
kubectl port-forward svc/bookstore-frontend-svc 3000:3000
|
||||
```
|
||||
|
||||
You should see the following output:
|
||||
|
||||
```
|
||||
Forwarding from 127.0.0.1:3000 -> 3000
|
||||
Forwarding from [::1]:3000 -> 3000
|
||||
```
|
||||
|
||||
|
||||
**Don't close the terminal when port-forwarding is established.** Start a new terminal to run the next command.
|
||||
|
||||
???+ success "Verify"
|
||||
|
||||
Visit [http://localhost:3000](http://localhost:3000){:target="_blank"} in your browser. The UI page should appear!
|
||||
|
||||

|
||||
|
||||
### **Task 3: Running the Book Review Service**
|
||||
|
||||

|
||||
|
||||
The Node.js server is located in the `node-server` folder.
|
||||
|
||||
!!! warning
|
||||
|
||||
Ensure that port 8080 on your local machine is not being used by another application.
|
||||
|
||||
#### **Deploy the Book Review Service: Node.js Server**
|
||||
|
||||
You can either [build the image locally](https://docs.docker.com/get-started/02_our_app/){:target="_blank"} or use our pre-built image. If you are using the pre-built image, you can proceed to the next step.
|
||||
|
||||
When ready, run the following command to deploy the Node.js server:
|
||||
|
||||
```shell
|
||||
kubectl apply -f node-server/config/100-deployment.yaml
|
||||
```
|
||||
|
||||
This command will pull the image and deploy it to your cluster as a Deployment. It will also expose it as a LoadBalancer to receive external traffic.
|
||||
|
||||
```
|
||||
deployment.apps/node-server created
|
||||
service/node-server-svc created
|
||||
```
|
||||
|
||||
???+ success "Verify"
|
||||
|
||||
Run the following command to check if the pod is running:
|
||||
|
||||
```shell
|
||||
kubectl get pods
|
||||
```
|
||||
|
||||
You will see that your Node.js server (node-server) pod is running.
|
||||
```
|
||||
NAME READY STATUS RESTARTS AGE
|
||||
bookstore-frontend-7b879ffb78-9bln6 1/1 Running 0 39m
|
||||
node-server-68bf98cdf4-skjmh 1/1 Running 0 38m
|
||||
```
|
||||
|
||||
|
||||
#### **Port Forwarding (optional under condition)**
|
||||
|
||||

|
||||
|
||||
You might need to set up port forwarding to access the app from your local machine.
|
||||
|
||||
Check if port forwarding is necessary by running:
|
||||
|
||||
```shell
|
||||
kubectl get services
|
||||
```
|
||||
And you will see the following console output:
|
||||
```
|
||||
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
|
||||
bookstore-frontend-svc LoadBalancer 10.99.187.173 <pending> 3000:31600/TCP 73m
|
||||
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 85m
|
||||
node-server-svc LoadBalancer 10.101.90.35 <pending> 80:31792/TCP 73m
|
||||
```
|
||||
|
||||
!!! note
|
||||
If the `EXTERNAL-IP` for your Node.js service is `127.0.0.1`, port forwarding is not needed. If you failed to visit the page `localhost:8080`, you can try to set up port forwarding.
|
||||
|
||||
If port forwarding is required, open a new terminal and run:
|
||||
|
||||
```shell
|
||||
kubectl port-forward svc/node-server-svc 8080:80
|
||||
```
|
||||
You should see the following output:
|
||||
|
||||
```
|
||||
Forwarding from 127.0.0.1:8080 > 8000
|
||||
Forwarding from [::1]:8080 > 8000
|
||||
```
|
||||
|
||||
**Don't close the terminal when port-forwarding is established.** Start a new terminal to run the next command.
|
||||
|
||||
|
||||
???+ success "Verify"
|
||||
|
||||
Visit [http://localhost:8080](http://localhost:8080){:target="_blank"} in your browser. The Node.js service should be up and running.
|
||||
|
||||
And in your front end page, you should see the status turns green and say "Connected to node server".
|
||||
|
||||

|
||||
|
||||
## **Troubleshooting**
|
||||
If you encounter any issues during the setup process, refer to the troubleshooting section in the documentation or check the logs of your Kubernetes pods for more details.
|
||||
???+ bug "Troubleshooting"
|
||||
|
||||
To check the logs, use the following command:
|
||||
|
||||
```shell
|
||||
kubectl logs <pod-name>
|
||||
```
|
||||
|
||||
Replace `<pod-name>` with the name of the pod you want to check.
|
||||
|
||||
## **Next Step**
|
||||

|
||||
|
||||
You have successfully set up the cluster with Knative installed, and running your front end app and node server. You are all set to start learning. Your journey begins from here.
|
||||
|
||||
[Go to Lesson 1 - Send Review Comment to Broker :fontawesome-solid-paper-plane:](../page-1/send-review-comment-to-broker.md){ .md-button .md-button--primary }
|
After Width: | Height: | Size: 160 KiB |
After Width: | Height: | Size: 152 KiB |
After Width: | Height: | Size: 149 KiB |
After Width: | Height: | Size: 90 KiB |
After Width: | Height: | Size: 141 KiB |
After Width: | Height: | Size: 15 KiB |
After Width: | Height: | Size: 254 KiB |
After Width: | Height: | Size: 62 KiB |
After Width: | Height: | Size: 163 KiB |
After Width: | Height: | Size: 83 KiB |
After Width: | Height: | Size: 165 KiB |
After Width: | Height: | Size: 266 KiB |
After Width: | Height: | Size: 149 KiB |
After Width: | Height: | Size: 125 KiB |
After Width: | Height: | Size: 243 KiB |
After Width: | Height: | Size: 108 KiB |
After Width: | Height: | Size: 440 KiB |
After Width: | Height: | Size: 200 KiB |
After Width: | Height: | Size: 95 KiB |
After Width: | Height: | Size: 94 KiB |
After Width: | Height: | Size: 137 KiB |
After Width: | Height: | Size: 55 KiB |
After Width: | Height: | Size: 58 KiB |
After Width: | Height: | Size: 281 KiB |
After Width: | Height: | Size: 54 KiB |
After Width: | Height: | Size: 410 KiB |
|
@ -0,0 +1,139 @@
|
|||
# Welcome: Knative Bookstore Tutorial
|
||||
|
||||

|
||||
|
||||
**Welcome to Knative's End-to-End Sample Application Tutorial!**
|
||||
|
||||
- Are you completely new to Knative and unsure where to start?
|
||||
- Are you considering converting your application to an event-driven architecture but don't know how?
|
||||
- Are you curious to see what Knative can do in real life?
|
||||
- Are you new to the cloud computing world and looking to get started with open source?
|
||||
|
||||
!!! success "You found the right place"
|
||||
|
||||
If any of these resonate with you, you've found the perfect starting point.
|
||||
|
||||
In this tutorial, we will construct an online bookstore application. This interactive guide, suitable for beginners and experienced engineers alike, will take you through the steps of building, deploying, and monitoring an application using Knative's powerful features. For those familiar with the process, concise graphics are available to streamline your learning experience.
|
||||
|
||||
## **What are we building?**
|
||||
|
||||

|
||||
|
||||
Our App is an online bookstore that sells a single book. Customers can post comments about the book anonymously, with each comment displayed alongside an emoji reflecting the sentiment of the comment. Comments with inappropriate content are automatically filtered out, discarded, and logged in the backend.
|
||||
|
||||
As the bookstore owner, you'll receive notifications via Slack each time if a comment containing a "bad word" is submitted.
|
||||
|
||||
## **Learning Goal**
|
||||
|
||||

|
||||
|
||||
You will learn Event-Driven Architecture (EDA) and how it contrasts with traditional application designs that use microservices and REST APIs. You'll learn:
|
||||
|
||||
- **The Fundamentals of EDA**: Explore the core principles of event-driven architecture and how it enhances responsiveness and scalability in applications.
|
||||
- **Comparative Insights**: Understand the differences between EDA and traditional architectures, highlighting the benefits and use cases of each.
|
||||
- **Practical Application**: Discover how to transition your existing applications to an event-driven model, utilizing the powerful features of Knative Eventing.
|
||||
|
||||

|
||||
|
||||
Knative is a powerful framework that operates on top of Kubernetes. This tutorial will guide you through:
|
||||
|
||||
- **Setting Up Your Cluster**: You'll start by spinning up your own Kubernetes cluster, which is the foundation for deploying and managing containers.
|
||||
- **Exploring Knative**: Gain hands-on experience with key Knative concepts and components.
|
||||
- **Some example use cases of Knative**.
|
||||
|
||||
By the end of this tutorial, you will not only understand these concepts but also feel comfortable implementing them, empowering you to build robust, scalable event-driven applications with Knative.
|
||||
|
||||
## **Bookstore Architecture**
|
||||
|
||||

|
||||
|
||||
The bookstore application consists of the following components:
|
||||
|
||||
### User Interface
|
||||
|
||||
A frontend Next.js application that interacts with these services. It is a web page where users can select a book to view its details, ratings and reviews.
|
||||
|
||||
### Database Service
|
||||
|
||||
An in-memory PostgreSQL instance on Kubernetes, storing all user comments.
|
||||
|
||||
### Book Reviews Service
|
||||
|
||||
A Node.js web server that will perform the event forwarding, database operation, and handling the websocket connection.
|
||||
|
||||
### Notification Service
|
||||
|
||||
An Apache Camel K pipe that connects our event-driven architecture with a third-party webhook: Slack. It receives the CloudEvent and sends it as a message to a Slack Workspace.
|
||||
|
||||
### ML Models Service
|
||||
|
||||
There are 2 Machine learning workflows that can conduct sentiment analysis on user's review comment and hateful word sanity check. You will be using a [Knative Sequence](https://knative.dev/docs/eventing/flows/sequence/){:target="_blank"} to make sure they are executed in order.
|
||||
|
||||
### Book Store Broker
|
||||
|
||||
It acts as the central brain of our event-driven architecture. It connects all the microservices together, receives the event, and makes sure all the events are safely delivered to the correct destination.
|
||||
|
||||
### Bad Word Broker
|
||||
|
||||
It acts as the bridge between the book store Broker and the Slack Sink, so we can send notification to your Slack when a comment containing "bad word" is submitted.
|
||||
|
||||
## **Tutorial Page Structure**
|
||||
|
||||
|
||||
We will be building the sample app in this order:
|
||||
|
||||
0. [**Environment Setup**](../page-0.5/environment-setup.md){:target="_blank"}: Set up the environment for the tutorial. This includes installing the cluster, the frontend and the backend.
|
||||
|
||||
1. [**Send comments to the Broker**](../page-1/send-review-comment-to-broker.md){:target="_blank"}: Pass reviews from the frontend to event-display via the Broker. This involves learning about Broker, SinkBinding and CloudEvents event types.
|
||||
|
||||
2. [**Deploy Sentiment Analysis Service**](../page-2/sentiment-analysis-service-for-bookstore-reviews.md){:target="_blank"}: Gain knowledge on deploying a sentiment analysis service using Knative Function.
|
||||
|
||||
3. [**Deploy Bad Word Filter Service**](../page-3/create-bad-word-filter-service.md){:target="_blank"}: Implement a bad word filter service using Knative Function yourself.
|
||||
|
||||
4. [**Use a Sequence to Run the ML Workflows in order**](../page-4/create-sequence-to-streamline-ML-workflows.md){:target="_blank"}: Learn how to utilize a Knative Sequence to ensure your ML workflows executes in order.
|
||||
|
||||
5. [**Database Deployment**](../page-5//deploy-database-service.md){:target="_blank"}: Understand the deployment of an in-memory PostgreSQL instance using a plain Kubernetes deployment.
|
||||
|
||||
6. [**Advanced event filtering**](../page-6/advanced-event-filtering.md){:target="_blank"}: Integrate all components by receiving "analyzed reviews" via Broker (using a Trigger) and storing them into the database. This includes learning about Triggers and Filters.
|
||||
|
||||
7. [**Connect with External Services/API**](../page-7/slack-sink-learning-knative-eventing-and-apache-camel-K-integration.md){:target="_blank"}: Learn how to connect your application with external services and APIs using Knative Eventing and Apache Camel K integrations.
|
||||
|
||||
8. [**Extra Challenges**](../extra-challenge/README.md){:target="_blank"}: Additional challenges to test your understanding of the concepts learned in the tutorial.
|
||||
|
||||
## **How to properly learn?**
|
||||
|
||||
### Preview the Final Bookstore: 1-Minute Demo Video
|
||||
|
||||
To help you visualize what you'll be creating, we've prepared a brief demo video. This two-minute preview showcases the final bookstore application, providing a clearer understanding of what you can expect to build.
|
||||
|
||||
<iframe width="1924" height="500" src="https://www.youtube.com/embed/5D8pTcQSacw" title="Knative E2E Bookstore Tutorial - 1-min Demo" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>
|
||||
|
||||
???+ bug "Video not working above?"
|
||||
If the video is not working, you can watch it [here](https://www.youtube.com/watch?v=5D8pTcQSacw&ab_channel=Knative){:target="_blank"}.
|
||||
|
||||
### Step-by-Step Guidance for Beginners
|
||||
|
||||

|
||||
|
||||
This tutorial is meticulously structured to be beginner-friendly, featuring detailed, step-by-step instructions for building the sample app. Simply follow the sequence we've laid out: each section builds upon the previous, guiding you through the construction of the application. Should you encounter any hurdles, the Knative community is a fantastic resource for support. Don't hesitate to ask questions and seek advice. Check the [Help](#help) section below!
|
||||
|
||||
### Accelerated Learning Path for Advanced Users
|
||||
|
||||

|
||||
|
||||
If you find the tutorial too basic, or if it covers familiar territory, feel free to adjust your learning approach. Each section of the tutorial is accompanied by concise graphics that summarize key concepts. Advanced learners can choose to focus on these graphics to grasp the essentials faster, streamlining the learning experience without sacrificing depth or understanding.
|
||||
|
||||
## **Help**
|
||||
|
||||

|
||||
|
||||
Join the supportive Knative community via the Cloud Native Computing Foundation (CNCF) Slack, particularly the [#knative](https://cloud-native.slack.com/archives/C04LGHDR9K7){:target="_blank"} channel. Before posting your questions, please search to see if they've already been answered. Your feedback on this tutorial is invaluable, so don't hesitate to reach out with suggestions or questions.
|
||||
|
||||
## **Next Step**
|
||||
|
||||
|
||||

|
||||
|
||||
Let's set up the environment first.
|
||||
|
||||
[Go to Environment Setup :fontawesome-solid-paper-plane:](../page-0.5/environment-setup.md){ .md-button .md-button--primary }
|
After Width: | Height: | Size: 122 KiB |
After Width: | Height: | Size: 118 KiB |
After Width: | Height: | Size: 84 KiB |
After Width: | Height: | Size: 226 KiB |
After Width: | Height: | Size: 116 KiB |
After Width: | Height: | Size: 116 KiB |
After Width: | Height: | Size: 155 KiB |
After Width: | Height: | Size: 133 KiB |
After Width: | Height: | Size: 50 KiB |
After Width: | Height: | Size: 128 KiB |
After Width: | Height: | Size: 68 KiB |
After Width: | Height: | Size: 45 KiB |
After Width: | Height: | Size: 110 KiB |
After Width: | Height: | Size: 71 KiB |
After Width: | Height: | Size: 127 KiB |
After Width: | Height: | Size: 69 KiB |
|
@ -0,0 +1,423 @@
|
|||
# Send Review Comment to Broker
|
||||
|
||||

|
||||
|
||||
The main dashboard of our bookstore features a comment section where readers can view comments from others and submit their own through a text input area. While the process appears straightforward - click a button, and the comment is posted - the underlying mechanism is powered by a robust event-driven architecture.
|
||||
|
||||
## **What Knative features will we learn about?**
|
||||
|
||||
- Knative Eventing Broker
|
||||
- Knative Eventing Sink
|
||||
- Knative SinkBinding
|
||||
|
||||
## **What does the deliverable look like?**
|
||||
|
||||

|
||||
|
||||
In simple words: after the user clicks on the submit button in the frontend, the comment will show up in the event-display service.
|
||||
|
||||
## **Implementation**
|
||||
|
||||
### **Step 0: Know the basics**
|
||||
|
||||

|
||||
|
||||
In the world of microservices and REST APIs, we often refer to requests as the primary method of communication between services. However, in an event-driven architecture, the smallest unit is an event. Knative Eventing adheres to the CloudEvents specification, making it essential to understand this concept before moving forward. Learn more about CloudEvents [here](https://cloudevents.io/){:target="_blank"} before proceeding!
|
||||
|
||||
### **Step 1: Understand Book Review Service**
|
||||
|
||||

|
||||
|
||||
The book review service is our Node.js API server, playing a crucial role in our event-driven architecture. It's essential to understand how it operates, as it receives events and processes them appropriately.
|
||||
|
||||

|
||||
|
||||
**Key Concepts: Broker and SinkBinding**
|
||||
|
||||
Before we dive into the code, let's clarify two important concepts:
|
||||
|
||||
- **Broker**: Acts as the central point in the event-driven architecture, routing events to the correct destinations.
|
||||
- **SinkBinding**: This Knative Eventing component automatically injects the Broker's address into the environment variable `K_SINK`, ensuring that the Node.js server always has the correct address without manual updates.
|
||||
|
||||
You will get a deeper understanding along the way.
|
||||
|
||||

|
||||
|
||||
Let's examine the `node-server/index.js` file, starting with the `/add` function. When a user submits a comment through the frontend, it is first received by this endpoint.
|
||||
|
||||
```javascript
|
||||
app.post('/add', async (req, res) => {
|
||||
try {
|
||||
const receivedEvent = HTTP.toEvent({headers: req.headers, body: req.body});
|
||||
const brokerURI = process.env.K_SINK;
|
||||
|
||||
if (receivedEvent.type === 'new-review-comment') {
|
||||
const response = await fetch(brokerURI, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/cloudevents+json',
|
||||
'ce-specversion': receivedEvent.specversion,
|
||||
'ce-type': receivedEvent.type,
|
||||
'ce-source': receivedEvent.source,
|
||||
'ce-id': receivedEvent.id,
|
||||
},
|
||||
body: JSON.stringify(receivedEvent.data),
|
||||
});
|
||||
}
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
**Receiving Events**: The `/add` endpoint receives events from the frontend. It uses CloudEvents' SDK to convert the incoming request into a CloudEvent object:
|
||||
|
||||
```javascript
|
||||
const receivedEvent = HTTP.toEvent({headers: req.headers, body: req.body});
|
||||
```
|
||||
|
||||
**Determining Broker Address**: The Broker's address is dynamically assigned in the cluster. The Node.js server retrieves this address from the environment variable `K_SINK`:
|
||||
|
||||
```javascript
|
||||
const brokerURI = process.env.K_SINK;
|
||||
```
|
||||
|
||||
You may wonder who told the environment variable about the address? That’s Knative SinkBinding.
|
||||
|
||||
**Event Filtering**: The service checks the event type. If it's a `new-review-comment`, it forwards the event to the Broker:
|
||||
|
||||
```javascript
|
||||
if (receivedEvent.type === 'new-review-comment') {
|
||||
// logic that forwards the event, see below
|
||||
}
|
||||
```
|
||||
|
||||
**Forwarding Events Logic**: The event is forwarded to the Broker with the appropriate CloudEvent headers:
|
||||
|
||||
```javascript
|
||||
const response = await fetch(brokerURI, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/cloudevents+json',
|
||||
'ce-specversion': receivedEvent.specversion,
|
||||
'ce-type': receivedEvent.type,
|
||||
'ce-source': receivedEvent.source,
|
||||
'ce-id': receivedEvent.id,
|
||||
},
|
||||
body: JSON.stringify(receivedEvent.data),
|
||||
});
|
||||
```
|
||||
|
||||

|
||||
|
||||
**Exploring Other Functions**
|
||||
|
||||
The Node.js server contains other functions that follow a similar pattern, with detailed comments explaining their functionality:
|
||||
|
||||
- `/insert`: Receives CloudEvents and inserts the payload into the PostgreSQL database.
|
||||
- `/comment`: Creates a WebSocket connection with the frontend to transport comments from the database.
|
||||
|
||||
### **Step 2: Create Broker**
|
||||
|
||||

|
||||
|
||||
The Broker acts as a router in your event-driven application, receiving events and routing them to the correct destination.
|
||||
|
||||
|
||||
|
||||
- 1: Create a new YAML file named `node-server/config/200-broker.yaml` and add the following content:
|
||||
|
||||
???+ abstract "_node-server/config/200-broker.yaml_"
|
||||
```yaml
|
||||
apiVersion: eventing.knative.dev/v1
|
||||
kind: Broker
|
||||
metadata:
|
||||
name: bookstore-broker
|
||||
```
|
||||
|
||||
- 2: Apply the YAML file:
|
||||
|
||||
```bash
|
||||
kubectl apply -f node-server/config/200-broker.yaml
|
||||
```
|
||||
|
||||
You will see the following output:
|
||||
```
|
||||
broker.eventing.knative.dev/bookstore-broker created
|
||||
```
|
||||
|
||||
Alternatively, use the [Knative CLI `kn`](https://knative.dev/docs/client/#kn){:target="_blank"} to create the Broker:
|
||||
|
||||
```bash
|
||||
kn broker create bookstore-broker
|
||||
```
|
||||
|
||||
You will see the following output:
|
||||
```
|
||||
Broker 'bookstore-broker' successfully created in namespace 'default'.
|
||||
```
|
||||
|
||||
???+ success "Verify"
|
||||
Running the following command to list the Brokers:
|
||||
```bash
|
||||
kubectl get brokers
|
||||
```
|
||||
|
||||
|
||||
You should see the Broker `bookstore-broker` with `READY` status as `True`.
|
||||
|
||||
```
|
||||
NAME URL AGE READY REASON
|
||||
bookstore-broker http://broker-ingress.knative-eventing.svc.cluster.local/default/bookstore-broker 7m30s True
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
???+ bug "Troubleshooting"
|
||||
|
||||
If there are issues, use the following command to diagnose:
|
||||
|
||||
```bash
|
||||
kubectl describe broker bookstore-broker
|
||||
```
|
||||
|
||||
### **Step 3: Create a SinkBinding between the Node.js server and Broker**
|
||||
|
||||

|
||||
|
||||
Hardcoding URLs to connect with Kubernetes services in your application can be limiting and inflexible. A SinkBinding dynamically injects the URL of the Kubernetes service into your application.
|
||||
|
||||
Learn more about SinkBinding [here](https://knative.dev/docs/eventing/custom-event-source/sinkbinding/){:target="_blank"} and the [spec schema](https://knative.dev/docs/eventing/custom-event-source/sinkbinding/reference/){:target="_blank"}!
|
||||
|
||||
**Create a SinkBinding:**
|
||||
|
||||
- 1: Create a new YAML file named `300-sinkbinding.yaml` in the `node-server/config` folder and add the following content:
|
||||
|
||||
???+ abstract "_node-server/config/300-sinkbinding.yaml_"
|
||||
```yaml
|
||||
apiVersion: sources.knative.dev/v1
|
||||
kind: SinkBinding
|
||||
metadata:
|
||||
name: node-sinkbinding
|
||||
spec:
|
||||
subject:
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
selector:
|
||||
matchLabels:
|
||||
app: node-server
|
||||
sink: # In this case, the sink is our Broker, which is the eventing service that will receive the events
|
||||
ref:
|
||||
apiVersion: eventing.knative.dev/v1
|
||||
kind: Broker
|
||||
name: bookstore-broker
|
||||
|
||||
```
|
||||
|
||||
- 2: Apply the YAML file:
|
||||
|
||||
```bash
|
||||
kubectl apply -f node-server/config/300-sinkbinding.yaml
|
||||
```
|
||||
|
||||
You will see the following output:
|
||||
```
|
||||
sinkbinding.sources.knative.dev/node-sinkbinding created
|
||||
```
|
||||
|
||||
???+ success "Verify"
|
||||
Running the following command to list the sinkbindings:
|
||||
```bash
|
||||
kubectl get sinkbindings
|
||||
|
||||
```
|
||||
You should see the sinkbinding `node-sinkbinding` with `READY` status as `True`.
|
||||
|
||||
```
|
||||
NAME SINK AGE READY REASON
|
||||
node-sinkbinding http://broker-ingress.knative-eventing.svc.cluster.local/default/bookstore-broker 2m43s True
|
||||
|
||||
```
|
||||
|
||||
|
||||
### **Step 4: Create event-display service**
|
||||
|
||||

|
||||
|
||||
Event display is a debugging tool in Knative Eventing that allows you to use it as a temporary destination (a.k.a sink) for your event to go.
|
||||
|
||||
**Create an Event Display Service:**
|
||||
|
||||
- 1: Create a new YAML file named `100-event-display.yaml` in the `node-server/config` folder and add the following content:
|
||||
|
||||
???+ abstract "_node-server/config/100-event-display.yaml_"
|
||||
|
||||
```yaml
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: event-display
|
||||
spec:
|
||||
replicas: 1
|
||||
selector:
|
||||
matchLabels:
|
||||
app: event-display
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: event-display
|
||||
spec:
|
||||
containers:
|
||||
- name: event-display
|
||||
image: gcr.io/knative-releases/knative.dev/eventing-contrib/cmd/event_display
|
||||
ports:
|
||||
- containerPort: 8080
|
||||
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: event-display
|
||||
spec:
|
||||
selector:
|
||||
app: event-display
|
||||
ports:
|
||||
- protocol: TCP
|
||||
port: 80
|
||||
targetPort: 8080
|
||||
type: ClusterIP
|
||||
|
||||
```
|
||||
|
||||
- 2: Apply the YAML file:
|
||||
|
||||
```bash
|
||||
kubectl apply -f node-server/config/100-event-display.yaml
|
||||
```
|
||||
|
||||
You will see the following output:
|
||||
```
|
||||
deployment.apps/event-display created
|
||||
service/event-display created
|
||||
```
|
||||
|
||||
???+ success "Verify"
|
||||
Running the following command to list the pods:
|
||||
```bash
|
||||
kubectl get pods
|
||||
```
|
||||
|
||||
You should see the pod `event-display-XXXXXXX-XXXXX` in "Running" status.
|
||||
|
||||
```
|
||||
NAME READY STATUS RESTARTS AGE
|
||||
bookstore-frontend-7b879ffb78-9bln6 1/1 Running 0 91m
|
||||
event-display-55967c745d-bxrgh 1/1 Running 0 4m44s
|
||||
node-server-644795d698-r9zlr 1/1 Running 0 4m43s
|
||||
```
|
||||
|
||||
|
||||
|
||||
### **Step 5: Create a Trigger that connects the Broker and event display**
|
||||
|
||||

|
||||
|
||||
A Trigger is able to forward the event to the correct destination based on the [CloudEvent's attributes](https://knative.dev/docs/eventing/#:~:text=Knative%20Eventing%20uses%20standard%20HTTP%20POST%20requests%20to%20send%20and%20receive%20events%20between%20event%20producers%20and%20sinks.%20These%20events%20conform%20to%20the%20CloudEvents%20specifications%2C%20which%20enables%20creating%2C%20parsing%2C%20sending%2C%20and%20receiving%20events%20in%20any%20programming%20language.){:target="_blank"}. It is the connector between the Broker and the event destination.
|
||||
|
||||
A Filter in the Trigger will **filter the events based on the filter condition**. You will specify your filter condition in the Trigger’s YAML file. **If no filter is specified, the Trigger will forward all the events that the Broker received.**
|
||||
|
||||

|
||||
|
||||
There is also a concept called [Channel](https://knative.dev/docs/eventing/channels/){:target="_blank"} in Knative, and generally speaking, you can treat Broker & Trigger without filter the same as Channel & Subscription.
|
||||
|
||||
Learn more about Broker & Trigger [here](https://knative.dev/docs/eventing/brokers/){:target="_blank"}!
|
||||
|
||||
**Create a Trigger:**
|
||||
|
||||

|
||||
|
||||
Here we are creating a Trigger that will send all the events to event-display.
|
||||
|
||||

|
||||
|
||||
- 1: Create a new YAML file named `200-log-trigger.yaml` and add the following content:
|
||||
|
||||
???+ abstract "_node-server/config/200-log-trigger.yaml_"
|
||||
```yaml
|
||||
# This Trigger subscribes to the Broker and will forward all the events that it received to event-display.
|
||||
apiVersion: eventing.knative.dev/v1
|
||||
kind: Trigger
|
||||
metadata:
|
||||
name: log-trigger
|
||||
spec:
|
||||
broker: bookstore-broker
|
||||
subscriber:
|
||||
ref:
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
name: event-display
|
||||
```
|
||||
|
||||
- 2: Apply the YAML file:
|
||||
|
||||
```bash
|
||||
kubectl apply -f node-server/config/200-log-trigger.yaml
|
||||
```
|
||||
|
||||
You will see the following output:
|
||||
```
|
||||
trigger.eventing.knative.dev/log-trigger created
|
||||
```
|
||||
|
||||
???+ success "Verify"
|
||||
Running the following command to list the Triggers:
|
||||
```bash
|
||||
kubectl get triggers
|
||||
```
|
||||
The Trigger `log-trigger` should have `READY` status as `True`.
|
||||
|
||||
|
||||
```
|
||||
NAME BROKER SUBSCRIBER_URI AGE READY REASON
|
||||
log-trigger bookstore-broker http://event-display.default.svc.cluster.local 6m2s True
|
||||
```
|
||||
|
||||
|
||||
### **Validate**
|
||||
|
||||

|
||||
|
||||
Open the logs of the event-display with the following command:
|
||||
|
||||
```bash
|
||||
kubectl logs -l=app=event-display -f
|
||||
```
|
||||
|
||||
???+ success "Verify"
|
||||
Type something in the comment box in the UI and click the submit button. The comment should appear in the event-display service with the following output:
|
||||
|
||||
```plaintext
|
||||
☁️ cloudevents.Event
|
||||
Validation: valid
|
||||
Context Attributes,
|
||||
specversion: 1.0
|
||||
type: new-review-comment
|
||||
source: bookstore-eda
|
||||
id: unique-comment-id
|
||||
datacontenttype: application/json
|
||||
Extensions,
|
||||
knativearrivaltime: 2024-05-19T05:27:36.232562628Z
|
||||
Data,
|
||||
{
|
||||
"reviewText": "test"
|
||||
}
|
||||
```
|
||||
|
||||
### **Next Step**
|
||||
|
||||

|
||||
|
||||
Please make sure you pass the Validate test before proceeding.
|
||||
|
||||
[Go to Deploy ML workflow: Sentiment Analysis :fontawesome-solid-paper-plane:](../page-2/sentiment-analysis-service-for-bookstore-reviews.md){ .md-button .md-button--primary }
|
After Width: | Height: | Size: 83 KiB |
After Width: | Height: | Size: 79 KiB |
After Width: | Height: | Size: 75 KiB |
After Width: | Height: | Size: 58 KiB |
After Width: | Height: | Size: 97 KiB |
After Width: | Height: | Size: 93 KiB |
After Width: | Height: | Size: 160 KiB |
After Width: | Height: | Size: 102 KiB |
After Width: | Height: | Size: 128 KiB |
After Width: | Height: | Size: 86 KiB |
After Width: | Height: | Size: 104 KiB |
After Width: | Height: | Size: 113 KiB |
After Width: | Height: | Size: 98 KiB |
After Width: | Height: | Size: 64 KiB |
|
@ -0,0 +1,414 @@
|
|||
# Sentiment Analysis Service for Bookstore Reviews
|
||||
|
||||

|
||||
|
||||
As a bookstore owner, you aim to receive instant notifications in a Slack channel whenever a customer submits a new negative review comment. By leveraging Knative Function, you can set up a serverless function that contains a simple sentiment analysis service to categorize review comments by sentiment.
|
||||
|
||||
## **Which Knative features will we learn about?**
|
||||
|
||||
The ease to use **Knative Function** to deploy your service, and make it be managed by Knative Serving, which gives you the ability to **auto-scale your service to zero**, and scale up to handle the demand.
|
||||
|
||||
## **What does the final deliverable look like?**
|
||||
|
||||

|
||||
|
||||
A running serverless Knative Function that contains a python application that receives the new review comments as CloudEvent and returns the sentiment classification of the input text as CloudEvent.
|
||||
|
||||
The function's output will be only from:
|
||||
|
||||
- Positive
|
||||
|
||||
- Neutral
|
||||
|
||||
- Negative
|
||||
|
||||
## **Install Prerequisites**
|
||||
|
||||
### **Prerequisite 1: Install Knative func CLI**
|
||||
|
||||

|
||||
|
||||
Knative Function enables you to easily create, build, and deploy stateless, event-driven functions as [Knative Services](https://knative.dev/docs/serving/services/#:~:text=Knative%20Services%20are%20used%20to,the%20Service%20to%20be%20configured){:target="_blank"} by using the func CLI.
|
||||
|
||||
In order to do so, you need to install the func CLI. You can follow the [official documentation](https://knative.dev/docs/getting-started/install-func/){:target="_blank"} to install the func CLI.
|
||||
|
||||
???+ success "Verify"
|
||||
Running `func version` in your terminal to verify the installation, and you should see the version of the func CLI you installed.
|
||||
|
||||
???+ bug "Troubleshooting"
|
||||
If you see `command not found`, you may need to add the func CLI to your PATH.
|
||||
|
||||
## **Implementation**
|
||||
|
||||

|
||||
|
||||
The process is straightforward:
|
||||
|
||||
1. Begin by utilizing the `func create` command to generate your code template.
|
||||
|
||||
2. Next, incorporate your unique code into this template.
|
||||
|
||||
3. Finally, execute `func deploy` to deploy your application seamlessly to the Kubernetes cluster.
|
||||
|
||||
This workflow ensures a smooth transition from development to deployment within the Knative Functions ecosystem.
|
||||
|
||||
### **Step 1: Create a Knative Function template**
|
||||
|
||||

|
||||
|
||||
Create a new function using the func CLI:
|
||||
|
||||
```
|
||||
func create -l <language> <function-name>
|
||||
```
|
||||
|
||||
In this case, we are creating a Python function, so the command will be:
|
||||
|
||||
```
|
||||
func create -l python sentiment-analysis-app
|
||||
```
|
||||
|
||||
This command will create a new directory with the name `sentiment-analysis-app` and a bunch of files in it. The func CLI will generate a basic function template for you to start with.
|
||||
|
||||
You can find all the supported language templates [here](https://knative.dev/docs/functions/){:target="_blank"}.
|
||||
|
||||
???+ success "Verify"
|
||||
|
||||
The file tree will look like this:
|
||||
|
||||
```
|
||||
start/sentiment-analysis-app
|
||||
├── func.yaml
|
||||
├── .funcignore
|
||||
├── .gitignore
|
||||
├── requirements.txt
|
||||
├── app.sh
|
||||
├── test_func.py
|
||||
├── README.md
|
||||
├── Procfile
|
||||
└── func.py
|
||||
```
|
||||
|
||||
### **Step 2: Replace the generated code with the sentiment analysis logic**
|
||||
|
||||

|
||||
|
||||
`func.py` is the file that contains the code for the function. You can replace the generated code with the sentiment analysis logic. You can use the following code as a starting point:
|
||||
|
||||
???+ abstract "_sentiment-analysis-app/func.py_"
|
||||
|
||||
```python
|
||||
from parliament import Context
|
||||
from flask import Request, request, jsonify
|
||||
import json
|
||||
from textblob import TextBlob
|
||||
from time import sleep
|
||||
from cloudevents.http import CloudEvent, to_structured
|
||||
|
||||
# The function to convert the sentiment analysis result into a CloudEvent
|
||||
def create_cloud_event(inputText, badWordResult, data):
|
||||
attributes = {
|
||||
"type": "moderated-comment",
|
||||
"source": "sentiment-analysis",
|
||||
"datacontenttype": "application/json",
|
||||
"sentimentResult": data,
|
||||
"badwordfilter": badWordResult,
|
||||
}
|
||||
|
||||
# Put the sentiment analysis result into a dictionary
|
||||
data = {
|
||||
"reviewText": inputText,
|
||||
"badWordResult": badWordResult,
|
||||
"sentimentResult": data,
|
||||
}
|
||||
|
||||
# Create a CloudEvent object
|
||||
event = CloudEvent(attributes, data)
|
||||
return event
|
||||
|
||||
def analyze_sentiment(text):
|
||||
analysis = TextBlob(text["reviewText"])
|
||||
sentiment = "neutral"
|
||||
|
||||
if analysis.sentiment.polarity > 0:
|
||||
sentiment = "positive"
|
||||
elif analysis.sentiment.polarity < 0:
|
||||
sentiment = "negative"
|
||||
|
||||
badWordResult = ""
|
||||
try:
|
||||
badWordResult = text["badWordResult"]
|
||||
except:
|
||||
pass
|
||||
|
||||
# Convert the sentiment into a CloudEvent
|
||||
sentiment = create_cloud_event(text["reviewText"], badWordResult, sentiment)
|
||||
return sentiment
|
||||
|
||||
def main(context: Context):
|
||||
"""
|
||||
Function template
|
||||
The context parameter contains the Flask request object and any
|
||||
CloudEvent received with the request.
|
||||
"""
|
||||
|
||||
print("Sentiment Analysis Received CloudEvent: ", context.cloud_event)
|
||||
|
||||
# Add your business logic here
|
||||
return analyze_sentiment(context.cloud_event.data)
|
||||
```
|
||||
|
||||
### **Step 3: Configure the dependencies**
|
||||
|
||||

|
||||
|
||||
The `requirements.txt` file contains the dependencies for the function. You can add the following dependencies to the `requirements.txt` file:
|
||||
???+ abstract "_sentiment-analysis-app/requirements.txt_"
|
||||
|
||||
```
|
||||
Flask==3.0.2
|
||||
textblob==0.18.0.post0
|
||||
parliament-functions==0.1.0
|
||||
cloudevents==1.10.1
|
||||
```
|
||||
|
||||
Knative Function will automatically install the dependencies listed here when you build the function.
|
||||
|
||||
### **Step 4: Configure the pre-built environment**
|
||||
|
||||

|
||||
|
||||
In order to properly use the `textblob` library, you need to download the corpora, which is a large collection of text data that is used to train the sentiment analysis model. You can do this by creating a new file called `setup.py`, Knative Function will ensure that the `setup.py` file is executed after the dependencies have been installed.
|
||||
|
||||
The `setup.py` file should contain the following code for your bookstore:
|
||||
|
||||
???+ abstract "_sentiment-analysis-app/setup.py_"
|
||||
```python
|
||||
from setuptools import setup, find_packages
|
||||
from setuptools.command.install import install
|
||||
import subprocess
|
||||
|
||||
class PostInstallCommand(install):
|
||||
"""Post-installation for installation mode."""
|
||||
def run(self):
|
||||
# Call the superclass run method
|
||||
install.run(self)
|
||||
# Run the command to download the TextBlob corpora
|
||||
subprocess.call(['python', '-m', 'textblob.download_corpora', 'lite'])
|
||||
|
||||
setup(
|
||||
name="download_corpora",
|
||||
version="1.0",
|
||||
packages=find_packages(),
|
||||
cmdclass={
|
||||
'install': PostInstallCommand,
|
||||
}
|
||||
)
|
||||
```
|
||||
|
||||
### **Step 5: Build and run your Knative Function locally (Optional)**
|
||||
??? info "Click here to expand"
|
||||
|
||||
|
||||

|
||||
|
||||
In Knative Function, there are two ways to build: using the [pack build](https://github.com/knative/func/blob/8f3f718a5a036aa6b6eaa9f70c03aeea740015b9/docs/reference/func_build.md?plain=1#L46){:target="_blank"} or using the [source-to-image (s2i) build](https://github.com/knative/func/blob/4f48549c8ad4dad34bf750db243d81d503f0090f/docs/reference/func_build.md?plain=1#L43){:target="_blank"}.
|
||||
|
||||
Currently only the s2i build is supported if you need to run `setup.py`. When building with s2i, the `setup.py` file will be executed automatically after the dependencies have been installed.
|
||||
|
||||
Before we get started, configure the container registry to push the image to the container registry. You can use the following command to configure the container registry:
|
||||
|
||||
```
|
||||
export FUNC_REGISTRY=<your-container-registry>
|
||||
```
|
||||
|
||||
In this case, we will use the s2i build by adding the flag `-b=s2i`, and `-v` to see the verbose output.
|
||||
|
||||
```
|
||||
func build -b=s2i -v
|
||||
```
|
||||
|
||||
When the build is complete, you will see the following output:
|
||||
|
||||
```
|
||||
🙌 Function built: <Your container registry username>/sentiment-analysis-app:latest
|
||||
```
|
||||
|
||||
This command will build the function and push the image to the container registry. After the build is complete, you can run the function using the following command:
|
||||
|
||||
---
|
||||
|
||||
**Troubleshooting**
|
||||
|
||||
`❗Error: '/home/Kuack/Documents/knative/docs/code-samples' does not contain an initialized function`
|
||||
|
||||
**Solution: You may want to check whether you are in the correct directory. You can use the following command to check the current directory. If you are in the right directory, and the error still occurs, try to check your `func.yaml`, as it has to contain the field `created` and the right timestamp to be treated as a valid Knative Function.**
|
||||
|
||||
---
|
||||
|
||||
```
|
||||
func run -b=s2i -v
|
||||
```
|
||||
|
||||
In the future, you can skip the step of `func build`, because `func run` will automatically build the function for you.
|
||||
|
||||
You will see the following output if the function is running successfully:
|
||||
|
||||
```
|
||||
❗function up-to-date. Force rebuild with --build
|
||||
Running
|
||||
|
||||
on host port 8080
|
||||
---> Running application from script (app.sh) ...
|
||||
```
|
||||
|
||||
Knative Function has an easy way to simulate the CloudEvent, you can use the following command to simulate the CloudEvent and test your function out:
|
||||
|
||||
```
|
||||
func invoke -f=cloudevent --data='{"reviewText": "I love Knative so much"}' --content-type=application/json --type="new-review-comment" -v
|
||||
```
|
||||
|
||||
where the `-f` flag indicates the type of the data, is either `HTTP` or `cloudevent`, and the `--data` flag is the input text. You can read more about `func invoke` [here](https://github.com/knative/func/blob/main/docs/reference/func_invoke.md){:target="_blank"}.
|
||||
|
||||
In this case, you will get the full CloudEvent response:
|
||||
|
||||
```
|
||||
Context Attributes,
|
||||
specversion: 1.0
|
||||
type: new-review-comment
|
||||
source: book-review-broker
|
||||
id: ebbcd761-3a78-4c44-92e3-de575d1f2d38
|
||||
time: 2024-05-27T04:44:07.549303Z
|
||||
datacontenttype: application/json
|
||||
Extensions,
|
||||
badwordfilter: good
|
||||
Data,
|
||||
{
|
||||
"reviewText": "I love Knative so much",
|
||||
"badWordResult": "",
|
||||
"sentimentResult": "positive"
|
||||
}
|
||||
```
|
||||
|
||||
### **Step 6: Deploy the function to the cluster**
|
||||
|
||||

|
||||
|
||||
!!! note
|
||||
Please enter `/sentiment-analysis-app` when you are executing the following commands.
|
||||
|
||||
After you have finished the code, you can deploy the function to the cluster using the following command:
|
||||
|
||||
```bash
|
||||
func deploy -b=s2i -v
|
||||
```
|
||||
???+ success "Verify"
|
||||
|
||||
When the deployment is complete, you will see the following output:
|
||||
|
||||
```
|
||||
Function deployed in namespace "default" and exposed at URL:
|
||||
http://sentiment-analysis-app.default.svc.cluster.local
|
||||
```
|
||||
|
||||
!!! tip
|
||||
You can find the URL of the Knative Function (Knative Service) by running the following command:
|
||||
|
||||
```bash
|
||||
kubectl get kservice
|
||||
```
|
||||
|
||||
You will see the URL in the output:
|
||||
|
||||
```
|
||||
NAME URL LATESTCREATED LATESTREADY READY REASON
|
||||
sentiment-analysis-app http://sentiment-analysis-app.default.svc.cluster.local sentiment-analysis-app-00001 sentiment-analysis-app-00001 True
|
||||
```
|
||||
|
||||
|
||||
|
||||
## **Knative Serving: scale down to zero**
|
||||
|
||||

|
||||
|
||||
If you use the following command to query all the pods in the cluster, you will see that the pod is running:
|
||||
|
||||
```bash
|
||||
kubectl get pods
|
||||
```
|
||||
|
||||
where `-A` is the flag to query all the pods in all namespaces.
|
||||
|
||||
And you will find that your sentiment analysis app is running:
|
||||
|
||||
```
|
||||
NAMESPACE NAME READY STATUS RESTARTS AGE
|
||||
default sentiment-analysis-app-00002-deployment 2/2 Running 0 2m
|
||||
```
|
||||
|
||||
But if you wait for a while without sending any CloudEvent to your function, and query the pods again, you will find that the pod that has your sentiment analysis app **disappeared**!
|
||||
|
||||
This is because Knative Serving's autoscaler will **automatically scale down to zero** if there is no request to the function! Learn more at [Knative Autoscaling](https://knative.dev/docs/serving/autoscaling/){:target="_blank"}.
|
||||
|
||||
---
|
||||
|
||||
## **Verify**
|
||||
|
||||

|
||||
|
||||
After deployment, the `func` CLI provides a URL to access your function. You can verify the function's operation by sending a request with a sample review comment.
|
||||
|
||||
Simply use Knative Function's command `func invoke` to directly send a CloudEvent to the function on your cluster:
|
||||
|
||||
```bash
|
||||
func invoke -f=cloudevent --data='{"reviewText":"I love Knative so much"}' -v
|
||||
```
|
||||
|
||||
- `-f` flag indicates the type of the data, is either `HTTP` or `cloudevent`
|
||||
- `--data` flag is the input text
|
||||
- `-t` flag is the URI to the Knative Function.
|
||||
|
||||
???+ success "Verify"
|
||||
|
||||
If you see the response, it means that the function is running successfully.
|
||||
|
||||
```
|
||||
Context Attributes,
|
||||
specversion: 1.0
|
||||
type: moderated-comment
|
||||
source: sentiment-analysis
|
||||
id: 0c2d0659-a30e-4efd-bcce-803f15ff5cc5
|
||||
time: 2024-06-11T15:12:43.795405Z
|
||||
datacontenttype: application/json
|
||||
Extensions,
|
||||
badwordfilter:
|
||||
sentimentresult: positive
|
||||
Data,
|
||||
{
|
||||
"reviewText": "I love Knative so much",
|
||||
"badWordResult": "",
|
||||
"sentimentResult": "positive"
|
||||
}
|
||||
```
|
||||
|
||||

|
||||
|
||||
In this tutorial, you learned how to create a serverless function for a simple sentiment analysis service with Knative.
|
||||
|
||||
## **Next Step**
|
||||
|
||||

|
||||
|
||||
Next, we'll deploy another ML service following the same procedure. We encourage you to try it yourself!
|
||||
|
||||
!!! tip
|
||||
Don't forget to `cd` into the root directory `/start` before proceeding.
|
||||
|
||||
|
||||
If you feel comfortable deploying the other ML service yourself, follow this **simplified guide**:
|
||||
|
||||
[Go to Deploy ML workflow: Bad word filter :fontawesome-solid-paper-plane:](../page-3/create-bad-word-filter-service.md){ .md-button .md-button--primary }
|
||||
|
||||
If you encounter any issues, don't worry—we have a detailed tutorial ready for you.
|
||||
|
||||
[Solution - Go to Deploy ML workflow: Bad word filter :fontawesome-solid-paper-plane:](../page-3/solution-create-bad-word-filter-service.md){ .md-button .md-button--primary }
|
|
@ -0,0 +1,178 @@
|
|||
# Create Bad Word Filter Service
|
||||
|
||||

|
||||
|
||||
As a bookstore owner, you aim to receive instant notifications in a Slack channel whenever a customer submits a new negative review comment. By leveraging Knative Function, you can set up a serverless function that contains a simple bad word filter service to tell whether the text contains any hateful/insultive speech.
|
||||
|
||||
If you ever get stuck, check the solution here.
|
||||
|
||||
[Solution - Go to Deploy ML workflow: Bad word filter :fontawesome-solid-paper-plane:](../page-3/solution-create-bad-word-filter-service.md){ .md-button .md-button--primary }
|
||||
|
||||
## **What Knative features will we learn about?**
|
||||
|
||||
- The easiness to use Knative Function to deploy your service, and make it be managed by Knative Serving, which gives you the ability to auto-scale your service to zero, and scale up to handle the demand.
|
||||
|
||||
## **What does the final deliverable look like?**
|
||||
|
||||

|
||||
|
||||
A running serverless Knative Function that contains a python application that receives the new review comments as CloudEvent and returns the result that tells your input text contains any inappropriate languages or not. The result is sent back as CloudEvent.
|
||||
|
||||
!!! info
|
||||
We are using the `profanity_check` library to detect the bad words in the text. It is a open source library. Please see the disclaimer here. The result may not be 100% accurate.
|
||||
|
||||
The function's output will be only from:
|
||||
|
||||
- good
|
||||
- bad
|
||||
|
||||
## **Implementation**
|
||||
|
||||

|
||||
|
||||
The process is straightforward:
|
||||
|
||||
1. Begin by utilizing the `func create` command to generate your code template.
|
||||
2. Next, incorporate your unique code into this template.
|
||||
3. Finally, execute `func deploy` to deploy your application seamlessly to the Kubernetes cluster.
|
||||
|
||||
This workflow ensures a smooth transition from development to deployment within the Knative Functions ecosystem.
|
||||
|
||||
---
|
||||
|
||||
### **Step 1: Create a Knative Function template**
|
||||
|
||||

|
||||
|
||||
???+ success "Verify"
|
||||
|
||||
The file tree will look like this:
|
||||
|
||||
```
|
||||
/start/bad-word-filter
|
||||
├── func.yaml
|
||||
├── .funcignore
|
||||
├── .gitignore
|
||||
├── requirements.txt
|
||||
├── app.sh
|
||||
├── test_func.py
|
||||
├── README.md
|
||||
└── Procfile
|
||||
└── func.py
|
||||
```
|
||||
|
||||
### **Step 2: Replace the generated code with the bad word filter logic**
|
||||
|
||||

|
||||
|
||||
`func.py` is the file that contains the code for the function. You can replace the generated code with the bad word filter logic. You can use the following code as a starting point:
|
||||
|
||||
???+ abstract "_bad-word-filter/func.py_"
|
||||
```python
|
||||
from parliament import Context
|
||||
from profanity_check import predict
|
||||
from cloudevents.http import CloudEvent
|
||||
|
||||
# The function to convert the bad word filter result into a CloudEvent
|
||||
def create_cloud_event(inputText, data):
|
||||
attributes = {
|
||||
"type": "new-review-comment",
|
||||
"source": "book-review-broker",
|
||||
"datacontenttype": "application/json",
|
||||
"badwordfilter": data,
|
||||
}
|
||||
|
||||
# Put the bad word filter result into a dictionary
|
||||
data = {"reviewText": inputText, "badWordResult": data}
|
||||
|
||||
# Create a CloudEvent object
|
||||
event = CloudEvent(attributes, data)
|
||||
return event
|
||||
|
||||
def inappropriate_language_filter(text):
|
||||
profanity_result = predict([text["reviewText"]])
|
||||
result = "good"
|
||||
if profanity_result[0] == 1:
|
||||
result = "bad"
|
||||
|
||||
profanity_event = create_cloud_event(text["reviewText"], result)
|
||||
return profanity_event
|
||||
|
||||
def main(context: Context):
|
||||
"""
|
||||
Function template
|
||||
The context parameter contains the Flask request object and any
|
||||
CloudEvent received with the request.
|
||||
"""
|
||||
print("Received CloudEvent: ", context.cloud_event)
|
||||
|
||||
# Add your business logic here
|
||||
return inappropriate_language_filter(context.cloud_event.data)
|
||||
```
|
||||
|
||||
### **Step 3: Configure the dependencies**
|
||||
|
||||

|
||||
|
||||
???+ abstract "_bad-word-filter/requirements.txt_"
|
||||
```plaintext
|
||||
parliament-functions==0.1.0
|
||||
alt-profanity-check==1.4.1.post1
|
||||
cloudevents==1.10.1
|
||||
```
|
||||
|
||||
### **Step 4: Deploy the function to the cluster**
|
||||
|
||||

|
||||
!!! note
|
||||
Please enter `/bad-word-filter` when you are executing the following commands.
|
||||
|
||||
```plaintext
|
||||
func deploy -b=s2i -v
|
||||
```
|
||||
???+ success "Verify"
|
||||
Expect to see the following message:
|
||||
```
|
||||
Function deployed in namespace "default" and exposed at URL:
|
||||
http://bad-word-filter.default.svc.cluster.local
|
||||
```
|
||||
|
||||
## **Verify**
|
||||
|
||||

|
||||
|
||||
```plaintext
|
||||
func invoke -f=cloudevent --data='{"reviewText":"I love Knative so much"}' -v
|
||||
```
|
||||
|
||||
???+ success "Verify"
|
||||
Expect to receive a CloudEvent response:
|
||||
|
||||
```plaintext
|
||||
Context Attributes,
|
||||
specversion: 1.0
|
||||
type: new-review-comment
|
||||
source: book-review-broker
|
||||
id: ebbcd761-3a78-4c44-92e3-de575d1f2d38
|
||||
time: 2024-05-27T04:44:07.549303Z
|
||||
datacontenttype: application/json
|
||||
Extensions,
|
||||
badwordfilter: good
|
||||
Data,
|
||||
{
|
||||
"reviewText": "I love Knative so much",
|
||||
"badWordResult": "good"
|
||||
}
|
||||
```
|
||||
|
||||
If you see the response, it means that the function is running successfully.
|
||||
|
||||
## **Next Step**
|
||||
|
||||

|
||||
|
||||
In this tutorial, you learned how to create a serverless function for a simple service that can detect inappropriate languages in text with Knative.
|
||||
|
||||
Next, we'll be learning how to use Knative Sequence to connect the 2 ML workflows and make sure they are executed in the order you want.
|
||||
|
||||
[Go to Create Knative Sequence :fontawesome-solid-paper-plane:](../page-4/create-sequence-to-streamline-ML-workflows.md){ .md-button .md-button--primary }
|
After Width: | Height: | Size: 79 KiB |
After Width: | Height: | Size: 86 KiB |
After Width: | Height: | Size: 89 KiB |
After Width: | Height: | Size: 137 KiB |
After Width: | Height: | Size: 94 KiB |