This tutorial will show an example of running Dapr with a Kubernetes events input binding. You'll be deploying the Node application and will require a component definition with a Kubernetes event binding component.
Attribute | Details |
---|---|
Dapr runtime version | v0.10.0 |
Language | Node.js |
Environment | Local or Kubernetes |
This sample requires you to have the following installed on your machine:
Also, unless you have already done so, clone the repository with the samples and cd
into the right directory:
git clone https://github.com/dapr/samples.git
cd samples/read-kubernetes-events
The first thing you need is an RBAC enabled Kubernetes cluster. This could be running on your machine using Minikube, or it could be a fully-fledged cluser in Azure using AKS.
Once you have that make sure you get a positive response from the following kubectl command
kubectl get pods
This should either have output as No resources found in default namespace.
or should list the pods running the default
namesapce.
- Setup Dapr
Follow instructions to download and install the Dapr CLI and initialize Dapr.
- Understand the code
Now that Dapr is set up locally, navigate to the Read Kubernetes Events sample:
cd node
In the app.js
you'll find a simple express
application, which exposes a single route and handler. First, take a look at the top of the file:
const express = require('express');
const bodyParser = require('body-parser');
require('isomorphic-fetch');
const app = express();
app.use(bodyParser.json());
const port = 3000;
The port defined here is the default port the node app runs on.
Next, take a look at the kube-events
handler:
app.post('/kube-events', (req, res) => {
console.log("Hello from Kube Events!");
console.log(req.body);
res.status(200).send();
});
This simple gets the request, prints a log line and the request body in the console.
- Understand the component definition:
cd ../deploy/
The kubernetes.yaml
file defines the component that Dapr has to register with the particular configuration. The binding spec can be seen here.
apiVersion: dapr.io/v1alpha1
kind: Component
metadata:
name: kube-events
namespace: kube-events
spec:
type: bindings.kubernetes
version: v1
metadata:
- name: namespace
value: kube-events
- name: resyncPreiodInSec
value: "5"
This registers a bindings.kubernetes
component with the name kube-events
(which is also the route for the post request) and defines the namespace to watch kube-events
and the period to resync with the server 5
s.
- Run the code locally
The sample uses default kubectl config from the local machine and does not need Dapr or the application to be deployed in Kubernetes. This is simply to illustrate that functionality of the Kubernetes events input binding.
- Navigate to Node subscriber directory in your CLI:
cd ./node
- Install dependencies:
npm install
- Run Node sample app with Dapr:
dapr run --app-id bindings-kevents-nodeapp --app-port 3000 node app.js --components-path ../deploy
You should see the output:
ℹ️ Updating metadata for app command: node app.js
✅ You're up and running! Both Dapr and your app logs will appear here.
- Create a few Kubernetes Events to view through the application
The application is watching the namespace kube-events
. If it is already present in your kubernetes cluster you might be seeing some events already. If not follow the steps below.
- Create namespace
kube-events
if not present:
kubectl create ns kube-events
- Deploy a quick Kubernetes hello-world application in the created namespace:
kubectl create deployment hello-node -n kube-events --image=k8s.gcr.io/echoserver:1.4
Output logs from the node application should be of the form:
== APP == Hello from Kube Events!
== APP == {
== APP == event: 'add',
== APP == oldVal: {
== APP == metadata: { creationTimestamp: null },
== APP == involvedObject: {},
...
== APP == },
== APP == newVal: {
== APP == metadata: {
== APP == name: 'hello-node.162c269e7cedc889',
== APP == namespace: 'kube-events',
== APP == selfLink: '/api/v1/namespaces/kube-events/events/hello-node.162c269e7cedc889',
...
== APP == }
== APP == }
Note that the event is categorized as an
add
event. There are three types of events that the binding monitorsadd
,delete
andupdate
events.
- Delete the deployment just created:
kubectl delete deployment hello-node -n kube-events
Output should be
== APP == Hello from Kube Events!
== APP == {
== APP == event: 'delete',
== APP == oldVal: {
== APP == metadata: {
== APP == name: 'hello-node.162c2661c524d095',
== APP == namespace: 'kube-events',
== APP == selfLink: '/api/v1/namespaces/kube-events/events/hello-node.162c2661c524d095',
...
== APP == }
== APP == }
Note that the event is categorized as a
delete
event.
- Delete namepace (if it was created for this sample):
kubectl delete ns kube-events
Apart from the previous requisites the following are needed.
-
Need a shell capable of running make for building and pushing container to Docker Hub repo.
-
makefile
also usessed
command for editing file on the fly. -
Docker Hub account.
-
You will be using the same app that was used in Step 2 to test locally. For running the application in Kubernetes, a container is needed.
-
Once the repo has been cloned, change to the read-kubernetes-events directory
cd read-kubernetes-events
- Set the environment variable DOCKER_REPO to your docker hub username
export DOCKER_REPO=<REPO>
- Build the application container
make build
The output should be of the form
docker build -f node/Dockerfile node/. -t docker.io/<REPO>/k8s-events-node:edge
...
Successfully built 908b65d9d01f
Successfully tagged <REPO>/k8s-events-node:edge
- Push the container to your docker hub repository
make push
Note: you might need to login to your docker hub repo. Docker Hub quickstart
- Create namespace
kube-events
if not present:
kubectl create ns kube-events
- Apply the kubernetes configuration to your cluster using the kubectl command.
apiVersion: dapr.io/v1alpha1
kind: Component
metadata:
name: kube-events
namespace: kube-events
spec:
type: bindings.kubernetes
version: v1
metadata:
- name: namespace
value: kube-events
- name: resyncPreiodInSec
value: "5"
kubectl apply -f ./deploy/kubernetes.yaml
- View the
./deploy/node.yaml
file. It does the following
- Creates a role called
events-reader
with permission toget, list and watch
events
resource. More details can be found here. - Creates a role binding called
read-events
which binds default ServiceAccount inkube-events
namespace to the Role previously created. - Create a service called
events-nodeapp
. - Creates a deployment called
events-nodeapp
with reference to be container created and pushed in steps 4 and 5.
The container referred to is
image: DOCKER_REPO/k8s-events-node:edge # When applying using make, the DOCKER_REPO is replaced with the environment variable
The DOCKER_REPO name needs to be replaced with the name of your DOCKER_REPO for which an environment variable was created. The process is encapsulated in a make command.
- To apply the
node.yaml
configuration to kubernetes cluster, make sure you are within the folderread-kubernetes-events
and run
make apply-node-app-k8s
The output will be of the form
sed -e s"/DOCKER_REPO/<REPO>/g" ./deploy/node.yaml | kubectl apply -f -
role.rbac.authorization.k8s.io/events-reader created
rolebinding.rbac.authorization.k8s.io/read-events created
service/events-nodeapp created
deployment.apps/events-nodeapp created
- You can now observe the logs
kubectl get pods -n kube-events
Output will be of the form:
NAME READY STATUS RESTARTS AGE
events-nodeapp-69cdb56c6d-m7qd8 2/2 Running 0 3m56s
Run:
kubectl -n kube-events logs -f events-nodeapp-69cdb56c6d-m7qd8 node
Output should be of the form
Hello from Kube Events!
{ event: 'add',
oldVal:
{ metadata: { creationTimestamp: null },
involvedObject: {},
source: {},
...},
newVal:
{ metadata:
{ name: 'events-nodeapp.162cd2271581f9dc',
namespace: 'kube-events',
selfLink: '/api/v1/namespaces/kube-events/events/events-nodeapp.162cd2271581f9dc',
...
reportingComponent: '',
reportingInstance: '' } }
- Cleanup
- Delete the applied configuration
node.yaml
make delete-node-app-k8s
Output should be of the form:
sed -e s"/DOCKER_REPO/<REPO>/g" ./deploy/node.yaml | kubectl delete -f -
role.rbac.authorization.k8s.io "events-reader" deleted
rolebinding.rbac.authorization.k8s.io "read-events" deleted
service "events-nodeapp" deleted
deployment.apps "events-nodeapp" deleted
- Delete the applied configuration
kubernetes.yaml
kubectl delete -f ./deploy/kubernetes.yaml
- Delete namepace (if it was created for this sample):
kubectl delete ns kube-events