Dapr helloworld
Based on https://github.com/dapr/quickstarts/tree/master/tutorials/hello-kubernetes
This tutorial will get you up and running with Dapr in a Kubernetes cluster. The Python App generates messages and the Node app consumes and persists them. Applications source code and their Dokerfile can be found in src folder.
Step 1 - Create and configure a state store
Dapr can use a number of different state stores (Redis, CosmosDB, DynamoDB, Cassandra, etc) to persist and retrieve state. This demo will use Redis.
kubectl apply -f ./deploy/redis.yaml
Step 2 - Deploy the Node.js app with the Dapr sidecar
kubectl apply -f ./deploy/node.yaml
Kubernetes deployments are asyncronous. This means you'll need to wait for the deployment to complete before moving on to the next steps. You can do so with the following command:
kubectl rollout status deploy/nodeapp
This will deploy the Node.js app to Kubernetes. The Dapr control plane will automatically inject the Dapr sidecar to the Pod. If you take a look at the node.yaml
file, you will see how Dapr is enabled for that deployment:
dapr.io/enabled: true
- this tells the Dapr control plane to inject a sidecar to this deployment.
dapr.io/app-id: nodeapp
- this assigns a unique id or name to the Dapr application, so it can be sent messages to and communicated with by other Dapr apps.
dapr.io/enable-api-logging: "true"
- this is added to node.yaml file by default to see the API logs.
You'll also see the container image that you're deploying. If you want to update the code and deploy a new image, see Next Steps section.
There are several different ways to access a Kubernetes service depending on which platform you are using. Port forwarding is one consistent way to access a service, whether it is hosted locally or on a cloud Kubernetes provider like AKS.
kubectl port-forward service/nodeapp 8080:80
This will make your service available on http://localhost:8080.
Step 3 - Verify Service
To call the service that you set up port forwarding to, from a command prompt run:
curl http://localhost:8080/ports
Expected output:
{"DAPR_HTTP_PORT":"3500","DAPR_GRPC_PORT":"50001"}
Next submit an order to the app
curl --request POST --data "@sample.json" --header Content-Type:application/json http://localhost:8080/neworder
Expected output: Empty reply from server
Confirm the order was persisted by requesting it from the app
curl http://localhost:8080/order
Expected output:
{ "orderId": "42" }
Step 4 - Deploy the Python app with the Dapr sidecar
At a quick glance, this is a basic Python app that posts JSON messages to localhost:3500
, which is the default listening port for Dapr. You can invoke the Node.js application's neworder
endpoint by posting to v1.0/invoke/nodeapp/method/neworder
. The message contains some data
with an orderId that increments once per second:
n = 0
while True:
n += 1
message = {"data": {"orderId": n}}
try:
response = requests.post(dapr_url, json=message)
except Exception as e:
print(e)
time.sleep(1)
Deploy the Python app to your Kubernetes cluster:
kubectl apply -f ./deploy/python.yaml
As with above, the following command will wait for the deployment to complete:
kubectl rollout status deploy/pythonapp
Step 5 - Observe messages
Now that the Node.js and Python applications are deployed, watch messages come through:
Get the logs of the Node.js app:
kubectl logs --selector=app=node -c node --tail=-1
If all went well, you should see logs like this:
Got a new order! Order ID: 1
Successfully persisted state for Order ID: 1
Got a new order! Order ID: 2
Successfully persisted state for Order ID: 2
Got a new order! Order ID: 3
Successfully persisted state for Order ID: 3
Step 6 - Observe API call logs
Now that the Node.js and Python applications are deployed, watch API call logs come through:
Get the API call logs of the node app:
kubectl logs --selector=app=node -c daprd --tail=-1
When save state API calls are made, you should see logs similar to this:
time="2022-04-25T22:46:09.82121774Z" level=info method="POST /v1.0/state/statestore" app_id=nodeapp instance=nodeapp-7dd6648dd4-7hpmh scope=dapr.runtime.http-info type=log ver=1.7.2
time="2022-04-25T22:46:10.828764787Z" level=info method="POST /v1.0/state/statestore" app_id=nodeapp instance=nodeapp-7dd6648dd4-7hpmh scope=dapr.runtime.http-info type=log ver=1.7.2
Get the API call logs of the Python app:
kubectl logs --selector=app=python -c daprd --tail=-1
time="2022-04-27T02:47:49.972688145Z" level=info method="POST /neworder" app_id=pythonapp instance=pythonapp-545df48d55-jvj52 scope=dapr.runtime.http-info type=log ver=1.7.2
time="2022-04-27T02:47:50.984994545Z" level=info method="POST /neworder" app_id=pythonapp instance=pythonapp-545df48d55-jvj52 scope=dapr.runtime.http-info type=log ver=1.7.2
Step 7 - Confirm successful persistence
Call the Node.js app's order endpoint to get the latest order. Grab the external IP address that you saved before and, append "/order" and perform a GET request against it (enter it into your browser, use Postman, or curl it!):
curl $NODE_APP/order
{"orderID":"42"}
You should see the latest JSON in response!
Step 8 - Cleanup
Once you're done, you can spin down your Kubernetes resources by navigating to the ./deploy
directory and running:
kubectl delete -f .
This will spin down each resource defined by the .yaml
files in the deploy
directory, including the state component.
Note: This will also delete the redis DB and its state store component.