Introduction to AWS CDK And Building A Simple Serverless App Using AWS CDK In Java
A framework to provision amd maintain your AWS Infrastructure programmatically.
Introduction
AWS Cloud Development Kit(AWS CDK) is a framework to define cloud infrastructure using code and provision resources through CloudFormation. Developers can use supported programming languages to build reusable cloud components easily. It is very common to use JSON/YAML configuration files to provision resources but they lack the potential of an actual programming language. The AWS CDK supports TypeScript, JavaScript, Python, Java, and C#/.Net. So developers can now comfortably deal with Infrastructure provisioning using their favorite programming language.
Some Key Concepts
Constructs
Construct is a basic building block of the AWS CDK App and represents a cloud component. A Construct can either be a single resource or a component consisting of multiple resources. AWS CDK has the AWS Construct Library that includes constructs for various AWS resources.
For example lambda.Function represents a lambda function, dynamodb.Table represents a DynamoDB table, etc.
Stacks
A stack is the unit of deployment in AWS CDK. All resources defined within the scope of a stack are provisioned as a single unit. All constructs that represent AWS resources must be in the scope of a Stack. These resources are provisioned through CloudFormation, thus have the same limitations as that of CloudFormation. One CDK app can contain multiple stacks. The following code declares a stack -
public class CdkDemoStack extends Stack {
public CdkDemoStack(final Construct scope, final String id) {
this(scope, id, null);
}
public CdkDemoStack(final Construct scope, final String id, final StackProps props) {
super(scope, id, props);
// The code that defines your stack goes here
}
}
Apps
App is at the root of the construct tree. All the stacks defined must be in the scope of the App construct. Following example defines an app that initiates the CdkDemoStack stack and produces a CloudFormation template.
App app = new App();
new CdkDemoStack(app, "CdkDemoStack");
app.synth();
Resources
A resource is one of the constructs of AWS CDK construct Library that represents an AWS resource. You can create an instance of the construct class with required arguments and configurations to create a resource.
The following example defines a Lambda Function -
final Function hello = Function.Builder.create(this, "HelloHandler")
.runtime(Runtime.NODEJS_10_X) // execution environment
.code(Code.fromAsset("lambda")) // code loaded from the "lambda" directory
.handler("hello.handler") // file is "hello", function is "handler"
.build();
Assets
Assets represent all the artifacts the AWS CDK app need to operate. It can include local files, directories, Docker images, etc. For example, in this tutorial, I have created a directory to keep handler code for AWS Lambda.
Permissions
AWS IAM modules provide various access and permissions constructs that allow AWS resource to communicate with each other.
For example, if bucket is an Amazon S3 bucket, and function is a Lambda function, the code below grants the function read access to the bucket.
bucket.grantRead(function);
Working of AWS CDK Application
Image Source: What is AWS CDK?
A developer builds an app that contains stacks and respective AWS resources. AWS CDK automatically compiles your code but its recommended to do it manually as well to check for errors and run tests. In case of Java, you can perform below actions -
mvn package
cdk synth
cdk deploy
cdk synth command synthesizes a AWS CloudFormation template from one or more of the stacks in your AWS CDK app
cdk deploy command deploys the resources defined by one or more of the stacks in your AWS CDK app to AWS.
Build a Serverless App with API Gateway and Lambda
In this tutorial, I have built an API Gateway in front of a Lambda Function. The API Gateway exposes a public HTTP endpoint that triggers the lambda and returns a simple hello string. Complete code on Github.
Prerequisites
AWS Account
You need to set up the profile with an active access key and secret. The regions you specify will be used by AWS CDK to deploy the resources
- Install AWS CDK
npm install -g aws-cdk
- Java
Create Project
- Create a directory
mkdir cdk-demo && cd cdk-demo
- Create a Java CDK project
cdk init app --language java
It creates a Maven project with the same name as the directory you created. The project structrue looks like -
- Lambda handler code
Create a directory where you will keep your lambda code. In this tutorial, I have created a directory called lambda and placed a simple lambda function code written in Javascript that returns a string -
var AWS = require("aws-sdk");
exports.handler = async function(event) {
console.log("request:", JSON.stringify(event, undefined, 2));
return {
statusCode: 200,
headers: { "Content-Type": "text/plain" },
body: `Hello, it's me CloudController!`
};
};
- Add required Constructs as maven dependencies
As we will be using Lambda and API Gateway, only those dependencies are added in pom.xml.
<dependency>
<groupId>software.amazon.awscdk</groupId>
<artifactId>lambda</artifactId>
<version>${cdk.version}</version>
</dependency>
<dependency>
<groupId>software.amazon.awscdk</groupId>
<artifactId>apigateway</artifactId>
<version>${cdk.version}</version>
</dependency>
- Add Resources using AWS Construct Library
Add a lambda function and an API Gateway to your stack.
public class CdkDemoStack extends Stack {
public CdkDemoStack(final Construct scope, final String id) {
this(scope, id, null);
}
public CdkDemoStack(final Construct scope, final String id, final StackProps props) {
super(scope, id, props);
// The code that defines your stack goes here
final Function hello = Function.Builder.create(this, "HelloHandler")
.runtime(Runtime.NODEJS_10_X) // execution environment
.code(Code.fromAsset("lambda")) // code loaded from the "lambda" directory
.handler("hello.handler") // file is "hello", function is "handler"
.build();
// Defines an API Gateway REST API resource backed by our "hello" function
LambdaRestApi.Builder.create(this, "Endpoint")
.handler(hello)
.build();
}
}
- Synthesize a template
cdk synth
It outputs a CloudFormation template representing the resources you defined in your stack -
- Bootstrapping an Environment
If you are using AWS CDK for the first time, you will need to bootstrap an environment. It basically creates an S3 Bucket for storing files and IAM roles that grant permissions needed to perform deployments.
cdk bootstrap
After successful bootstrapping you can see a stack named CDKToolkit created in AWS CloudFormation Console.
- Package & Deploy
mvn package
cdk deploy
cdk deploy deploys the Stack and create resources in your configured region and outputs an API Gateway endpoint.
- Test your App
You can either test the endpoint in the terminal with the curl command or directly in a browser.
- Check Differences
If you add more resources to your code and want to check the differences between your code and existing stack, use cdk diff command.
cdk diff
Here it shows, there is the addition of a DynamoDB table. Once confirmed you can package and deploy your code again for changes to reflected in the actual stack.
CleanUp
It is important to delete all resources to avoid billing. In case of AWS CDK, You can use a simple command to delete a stack -
cdk destroy
It will ask for confirmation, once confirmed the stack along with all resources will be deleted. After emptying the S3 Bucket, you can manually delete the bootstrapped stack either through AWS CLI or CloudFormation Console.
Conclusion
AWS CDK is a powerful framework that allows developers to use their favorite programming language to define and provision AWS resources. This significantly reduces the efforts required to write longer CloudFormation templates. Developers can use Object-Oriented principles and logic to build small re-usable modules to design their architecture. Thus helping developers to maintain their infrastructure as they maintain their application code.