AWS Open Source Blog

Expedite Production Ready Distributed Application Development with Dapr on AWS

Distributed applications are software systems that consist of multiple components or modules running on different infrastructure within a network. These components work together to achieve a common goal or provide a service, communicating and coordinating their actions across the network.

Most organizations build distributed applications for two main reasons. First, they have multiple development teams that need to work independently while contributing to a larger system. Second, they require a solution where components built using different programming languages can interact with each other.

Developing distributed applications is challenging because numerous components need to work cohesively. Developers must consider resiliency, observability, security, and scalability across multiple services and runtimes. Furthermore, distributed applications typically don’t operate in isolation; they interact with message brokers, data stores, and external services. Integrating with these resources requires knowledge of specific APIs and SDKs which increases the complexity to build such systems.

In this post, we will review how open source Dapr can help developers build reliable and secure distributed applications with in-built best practices and patterns. We will also describe common Dapr use cases on AWS.

About Dapr

Dapr (Distributed Application Runtime) is an open source project aiming to make secure and reliable microservices development easier, regardless of the programming language or framework. Dapr was accepted by the Cloud Native Computing Foundation (CNCF) with Incubating maturity level in November 2021. It is managed by a growing open source community and is trusted by large organizations.

Dapr provides building block APIs for communication, state, and workflow. Dapr runs in a separate process next to your application using a sidecar pattern. It offers best practices and patterns to develop distributed applications with built-in security, resiliency and observability. This helps you to focus on business logic rather than implementing boilerplate code.

Dapr diagram

The Dapr APIs are decoupled from the underlying resources, making Dapr a flexible solution. It can use various message brokers, state stores, secret stores, and other resources across AWS, open source solutions, and other cloud providers.

Dapr APIs and Components

Dapr’s modular architecture and pluggable components allow you to choose the APIs and components that best suit your application requirements, making it a flexible and extensible platform for building modern, cloud-native applications.

Depending on your business needs, you can choose APIs such as State Management, Publish/Subscribe, Workflow, Actors, Secrets and more. This diagram describes the APIs available in Dapr with some of the supported AWS and open source components.

Dapr components diagram

You configure the underlying resources by adding Dapr component YAML files that describe the component type and include metadata on how to connect to the components.

There are over 100 components across all the Dapr APIs. Developers can benefit from the decoupling of APIs and components by using local components for development on their local machines, and switching to AWS based components for further development, testing, and production workloads in the cloud.

Dapr API Examples

When you build distributed applications with Dapr, you leverage Dapr building block APIs to quickly integrate with internal or external resources. This diagram shows how services use the Dapr APIs to communicate with each other and with configuration stores, secret stores, message brokers, state stores, and other services using bindings.

The application code that uses the Dapr APIs has no reference to specific client SDKs for the underlying resources. It remains the same when replacing one component for another of the same type. The resource-specific connection is abstracted away and is the responsibility of the Dapr sidecar.

The Dapr APIs are exposed via HTTP/gRPC and the APIs can be used with any programming language that can interact with these protocols. Client SDKs support is available for Python, NodeJS, .NET, Java, Go, Rust, C++ and PHP.

This example Python code snippet shows saving an order detail into an Amazon DynamoDB state store. The table specific details such as table, partition key, and time to live (TTL) are configured in the statestore.yaml file. By changing the statestore.yaml file, you can change the backend state store to another supported solution such as Amazon ElastiCache without changing application code.

Example Python Code Snippet:

from dapr.clients import DaprClient

DAPR_STORE_NAME = "mystatestore"

with DaprClient() as client:
    orderId = 'order1'
    order = { 'orderId': orderId, 'name': 'laptop', 'quantity': 1 }
    client.save_state(DAPR_STORE_NAME, orderId, str(order))

Example statestore.yaml for DynamoDB:

apiVersion: dapr.io/v1alpha1
kind: Component
metadata:
  name: mystatestore
spec:
  type: state.aws.dynamodb
  version: v1
  metadata:
  - name: table
    value: "Orders"
  - name: accessKey
    secretKeyRef:
      name: dynamodb-secrets
      key: accessKey
  - name: secretKey
    secretKeyRef:
      name: dynamodb-secrets
      key: secretKey
  - name: endpoint
    value: "http://localhost:8080" # Optional
  - name: region
    value: "us-west-2" # Optional
  - name: sessionToken
    value: "myTOKEN" # Optional
  - name: ttlAttributeName
    value: "expiresAt" # Optional
  - name: partitionKey
    value: "CustomerID" # Optional
auth:
  secretStore: mysecretstore

Common Dapr use cases on AWS

Dapr APIs integrate with various AWS services to fulfill use cases around communication, state, and workflow management. This integration allows developers to leverage the capabilities of Dapr while taking advantage of the scalability, reliability, and security features provided by AWS.

Service Communication

In distributed systems, you need to establish service communication across multiple microservices considering security, service discovery, error handling, and observability.

Using Dapr’s Service Invocation API with Amazon Elastic Kubernetes Service (Amazon EKS), developers can easily communicate between different microservices with a standard set of APIs and in-built encryption, metrics, tracing, retries, and backoff handling.

The following diagram shows how Dapr Service Invocation works for two microservices hosted as different Amazon EKS applications.

Dapr service invocation diagram

  1. Application A hosted in an Amazon EKS pod calls its local Dapr sidecar (source) via http or gRPC.
  2. Source Dapr sidecar performs service discovery to understand the target application to invoke.
  3. After discovering the target service, source Dapr sidecar forwards the request to target Dapr sidecar. Invocation between Dapr sidecars is always through gRPC.
  4. The target Dapr sidecar invokes the Application B.
  5. The service response flows through the same way in the opposite direction.

Publish and Subscribe

For event-driven architectures, publish and subscribe (pub/sub) is a commonly used asynchronous communication pattern. Publishers are the components that generate messages to a message broker whereas subscribers are components that subscribe to one or more topics or channels.

This diagram shows an example of how multiple microservices applications communicate asynchronously with Dapr’s Pub/Sub API using Amazon EKS, Amazon Simple Notification Service (Amazon SNS) and Amazon Simple Queue Service (Amazon SQS).

Dapr’s Pub/Sub API diagram

By using Dapr’s Pub/Sub API, you can change the message broker backend by updating the pubsub.yaml component file without changing the application code. This makes it simple to switch to Amazon Managed Streaming for Apache Kafka (Amazon MSK) if you discover that it is a better fit for your use-case than AWS SMS and Amazon SQS. As the Dapr Pub/Sub API abstracts the messages that are produced and subscribed in the message broker, the producer and subscriber applications are not impacted by switching to Amazon MSK in this particular use-case.

If only some of your applications use Dapr, partial adoption of Dapr’s Pub/Sub API can also bring flexibility in architecture by leveraging different producer or subscriber applications. For example, Dapr sidecar proxies can be integrated with Amazon SNS and Amazon SQS for Amazon EKS based applications whereas other consumers such as AWS Fargate can directly poll the Amazon SQS queue for message processing.

Workflow Engine

Microservices orchestration is the process of managing and coordinating the interactions between multiple microservices in a distributed application architecture. Workflow orchestration involves coordinating the communication, data flow, and execution of various services to ensure that they work together seamlessly. One of the most important features of a workflow system is that the workflow execution is reliable. A workflow should always run to completion even if the workflow engine is temporarily not available.

Dapr Workflow offers durable execution of long running workflows where developers author these workflows as code. A large benefit of authoring workflows as code is that they can be unit tested, resulting in a well-documented and maintainable code base. Dapr Workflow can be combined with many AWS services to build stateful and fault-tolerant applications. Developers can benefit from the scale, performance, and cost efficiency of the AWS services as well as eliminating the need for managing the underlying infrastructure. As Dapr Workflow integrates with other Dapr APIs such as Service Invocation, Pub/Sub, State Management and so on, developers have the flexibility to choose different AWS services to design different communication and integration patterns across the application workflow.

Dapr workflow example diagram

Dapr Workflow provides workflow patterns developers can use to build reliable workflows such as task chaining, fan-out/fan-in, waiting for external events, and asynchronous HTTP response handling. Using these patterns with different AWS services within your applications can help design and implement production ready stateful and long running applications quickly with minimum effort. For example, if you are designing an e-commerce application where you want to process orders, store order data and state in a database, and send notifications to customers and fulfillment teams, you can use Dapr workflows to define the workflow using AWS services. A Dapr state store component can be configured to interact with DynamoDB to save order state. A Dapr Pub/Sub component can be configured to publish messages to an Amazon SNS topic for customer and fulfillment notifications. You define the tasks to be executed in a particular order and Dapr Workflow engine takes care of scheduling and execution of the tasks.

State Management

With Dapr’s State Management API building block, you can integrate different state stores on AWS such as DynamoDB or ElastiCache to design and manage your stateful applications. Without writing any boilerplate code for consistency and concurrency requirements for your state store, you can define the respective values within your statestore.yaml component file.

This diagram illustrates an example of how Dapr is integrated with DynamoDB to handle state management for an application.

State management example for Dapr

Another benefit of using Dapr’s State Management API with AWS services is that it allows you to replace the state store with an alternative service depending on your business needs without changing the application code. By changing the component yaml file, users can easily move from Amazon DynamoDB to Amazon ElastiCache or vice versa to choose the developer experience that is right for them.

Getting Started with Dapr on Amazon EKS

Before you can run Dapr applications on an Amazon EKS cluster, you need to configure the following prerequisites:

  • An AWS Identity and Access Management (IAM) user or role with required permissions
  • A running Amazon EKS cluster
  • The kubectl command line tool installed on your device or AWS CloudShell.
  • The Dapr CLI for running Dapr related tasks, like running an application with a Dapr sidecar locally, or reviewing sidecar logs.

Once all the prerequisites are configured and installed, the next step is to install Dapr on your EKS cluster. To get the current context, run kubectl config current-context command.

sh-5.2$ kubectl config current-context
admin@eks-cluster2.us-west-2.eksctl.io

You can deploy Dapr on a different Amazon EKS cluster by updating the context. For example:

sh-5.2$ kubectl config use-context admin@eks-cluster1.us-west-2.eksctl.io
Switched to context "admin@eks-cluster1.us-west-2.eksctl.io".

To initialize Dapr on your cluster, run the following command.

sh-5.2$ dapr init -k
 
⌛  Making the jump to hyperspace...
ℹ️  Note: To install Dapr using Helm, see here: https://docs.dapr.io/getting-started/install-dapr-kubernetes/#install-with-helm-advanced
 
ℹ️  Container images will be pulled from Docker Hub
✅  Deploying the Dapr control plane with latest version to your cluster...
✅  Deploying the Dapr dashboard with latest version to your cluster...
✅  Success! Dapr has been installed to namespace dapr-system. To verify, run `dapr status -k' in your terminal.

To check the Dapr installation on “dapr-system” namespace, run the following command.

sh-5.2$ dapr status -k
  NAME                   NAMESPACE    HEALTHY  STATUS   REPLICAS  VERSION  AGE  CREATED
  dapr-dashboard         dapr-system  True     Running  1         0.14.0   7m   2024-07-16 23:21.04
  dapr-placement-server  dapr-system  True     Running  1         1.13.5   7m   2024-07-16 23:21.02
  dapr-sentry            dapr-system  True     Running  1         1.13.5   7m   2024-07-16 23:21.02
  dapr-operator          dapr-system  True     Running  1         1.13.5   7m   2024-07-16 23:21.02
  dapr-sidecar-injector  dapr-system  True     Running  1         1.13.5   7m   2024-07-16 23:21.02

You should see that dapr-dashboard, dapr-placement-server, dapr-sentry, dapr-operator and dapr-sidecar-injector are in “Running” state.

At this point, Dapr is deployed in your Amazon EKS cluster. You can follow Dapr Tutorials from the Dapr Docs, such as the Hello World Kubernetes tutorial or the Distributed Calculator to deploy Dapr sample applications to your Amazon EKS cluster.

Clean Up

To uninstall Dapr from the EKS cluster you can run the following command.

dapr uninstall -k

To delete the EKS cluster, you can run the “eksctl delete” command by specifying the cluster name. You can replace the your_cluster_name with your own cluster name.

eksctl delete cluster --name your_cluster_name

Conclusion

In this blog post, we provided an introduction to Dapr, an open source project to expedite distributed application development by providing integrated APIs for communication, state, and workflow. We looked at Dapr’s modular architecture which provides a swappable component model, standardized APIs, and built-in best-practices and patterns for distributed application development, allowing developers to be more efficient building microservices. After diving into Dapr features, we explained the common Dapr use cases on AWS for service invocation, pub/sub communication, workflow, and state management. You can start building applications with Dapr on Amazon EKS by following the Getting Started section and with quick starts available in Dapr documentation.

Please consider joining the Dapr Discord where thousands of developers get together and share their experiences. If you want to stay up to date with the latest Dapr developments and learn how customers use Dapr in production, join the bi-weekly Dapr Community Call live-stream.

Mustafa Duzok

Mustafa Duzok

Mustafa is a Senior Startup Solutions Architect at AWS where he helps Startups customers build and deliver successful products on the cloud. He has a special interest in Analytics especially on streaming and search solutions. In his spare time, Mustafa likes to hike, watch soccer and movies.

Marc Duiker

Marc Duiker

Marc is a Sr developer advocate at Diagrid with a strong focus on event-driven architectures. He is one of the Dapr community managers and co-host of the Dapr community calls. He loves helping developers to achieve more every day. In his spare time, Marc likes to give attention to the creative part of his brain. He likes creating pixel art, coding visuals and music, and writing and designing retro games.