What is AWS CDK and How it Works?
Within a short span of time, AWS Cloud Development Kit (CDK) has become an indispensable tool for developers and DevOps teams. Given how this open-source software development framework has become all the rage today, let’s dive into what AWS CDK is, talk in brief about AWS CDK setup, what it is all about and how it works.
So let’s get started!
What is AWS CDK all about?
CDK stands for Cloud development Kit and is a tool from AWS cloud services to write infrastructure as code.
In CDK you import modules for AWS resources such as lambda and s3 bucket / API gateway and using the functions provided, you specify the resources for your application
You don’t have to go to AWS to create resources manually, as all the resources are automatically created once you deploy your infrastructure as code on AWS.
Since it's a code file, you can store it anywhere such as in GitHub repo and deploy it on any AWS account whenever you need to.
How does AWS CDK work
AWS already has a tool called cloudformation template where you write YAML code to define your AWS resources. However, when learning and building with this template, there are various complexities involved.
But with AWS CDK, you can use your existing knowledge of programming languages like javascript/python/java, etc to define your stack.
Once you define your resources and hit the build command, CDK will create a YAML cloudformation template for your stack. This removes the added complexity to learn and implement the cloudformation template.
CDK v1 Vs v2
In CDK version 1 you need to install individual packages for each AWS resource (lambda/ s3 / API gateway, etc). However, with this approach you work with only those libraries required. But it also creates an issue with tracking and managing your resource libraries as different versions of the libraries are not compatible with each other and when a new resource has to be added it has to be of the same version as your previously installed libraries or you need to upgrade them with the latest version.
With CDK version 2, on the other hand, they removed the package-based approach and moved to a single core library and all the constructs are part of it. Here, you can just import from aws-cdk-lib all the required constructs.
CDK CLI installation
To work with AWS CDK, you will first need to install the CDK CLI.
To install, use the
npm install -g aws-cdk or yarn add aws-cdk
To Upgrade to v2 use:
npm update -g aws-cdk or yarn global upgrade aws-cdk
Once installed, you can use cdk –version on command line to verify your cli installation and version
Also make sure the AWS CLI which is separate from CDK CLI is also installed as it will be needed to configure the aws account credentials when we will deploy it on AWS
Setup a new CDK project
To create a new CDK project, create a new folder with the project name.
open the new folder in code editor eg. VS codes and open the integrated terminal.
Make sure you are inside the project folder or use:
cd <folder name > on terminal to go in the project folder
In the terminal, enter the following command
cdk init app --language typescript
This will initialize CDK project with typescript template. You can pass any other supported language as parameters. Currently supported languages are Typescript, javascript, java, python.
You don't need to pass project name explicitly as it will be picked up from the FOLDER name of the project.
Once it is done generating the files and folders required for your project. you can start working on the project.
Following will be the contents of the package.json file. Here you will see all the dependencies for your project.
The aws-cdk-lib, which is present, is the main library that will allow us to import the AWS constructs that are needed in our stack.
Inside the project director, there will be a bin folder that contains demo_project.ts file
This file is the root of your stack. Here, you set AWS settings like the AWS region to deploy to and the account to use.
Below the bin folder, there is a lib folder. Here, you specify your stack , i.e create the AWS services needed.
You need to import the construct required from the aws-cdk-lib library and also specify your resources inside the constructor of the class.
For the purpose of the demo, we will create a simple lambda function connected to API gateway which will receive data and save data in dynamo DB.
For this, we will need the following resources:
aws-cdk-lib/aws-lambda
aws-cdk-lib/aws-dynamodb
aws-cdk-lib/aws-apigateway
Since the stack is parsed from top to bottom, first, let’s create the resources needed by our other resources. Let’s create a DynamoDB table;
// resource name variables
const tableName:string = "DemoTable";
// The code that defines your stack goes here
const table = new DynamoDB.Table(this,"demo-table",{
partitionKey:{name:"PK",type:DynamoDB.AttributeType.STRING},
sortKey:{name:"SK",type:DynamoDB.AttributeType.STRING},
tableName:tableName,
});
The above code are the configurations required to create a dynamoDB table,
The first parameter is the “this” which points to the current object.
The second (“demo-table”) is the logical ID of the resource and is separate from the name of the table. this is used to uniquely identify the resources.
The third is a object with the configurations for the table,
partitionKey : Each table should have a partition key, used to uniquely identify the entries in
table, The partition key object takes two parameter the name of the key to be used
as partition key and the type of the key, to query efficiently on data each table should have a partition key
sortKey :- the sort key is optional. But, if you want to group data with the same partition Key then you can specify the sort key. Sort key determines the order of how data with the same partition key is stored. With this field, you can specify multiple entries with the same partition key which works to efficiently query multiple entries in just one query.
E.g
{ PK: ”test123”, SK: ”TS#123”, emp_name : “test” }
{ PK: ”test123”, SK: ”TS#456” ,”emp_address”: ” Goa, India ” }
{ PK: ”test123”, SK: ”TS#789”,”emp_salary”: 230000 }
tableName : This is also an optional field and specifies the name of the table. If you don’t pass the table name, AWS automatically generate one using the logical id of the resource.
Next, let’s setup an AWS CDK lambda function and write code for the same.
const demoFunction = new Lambda.Function(this,"demo-function",{
functionName:"demo-function",
runtime:Lambda.Runtime.NODEJS_14_X,
code:Lambda.Code.fromAsset(path.join(__dirname,"Lambda","demo-function")),
handler:"index.handler",
environment: {
'demo_table_name': table.tableName,
},
})
We are creating an AWS CDK lambda function using the Lambda construct and then accessing the Function option on it, “demo-function” is the ID of the function.
functionName(optional) :- specifies the name of the function. If not passed, AWS generates one using the logical ID.
runtime (required) :- specifies the environment & version to use to run the code , node.js ,
Python , Java etc.
code (required) :- specifies the folder location of the funcion code / app logic to be used for the
Function.
Handler :- the function name inside the file which will be used to resolve the request ,
Here we have specifies "index.handler" separate by .(dot),
Index :- is the name of the file
handler :- the function inside the file to be used
environment :- environment holds all the environmental variables that the function should have
access to. We are passing the table name to the function so it can be used in
Querying the table.
We can access property like name, arn on the variable where we are storing the construct
With that we can pass the name and the arn of the resources to other functions as required.
Once done we will add the below statement after the function so that function has access to the table. This will generate the basic IAM roles required for the function to have access to the table.
table.grantReadWriteData(demoFunction);
For the logic of the handler, we will keep it simple, just take the data and insert into DB.
let AWS = require("aws-sdk");
const DEMO_TABLE = process.env.demo_table_name
const documentClient = new AWS.DynamoDB.DocumentClient({region:"us-east-2"})
exports.handler = async (event: any, context: any, callback: any) => {
let _body = JSON.parse(event.body);
console.log(_body);
const response:boolean = await saveDataToTable(_body);
if(response){
return {
statusCode: 200,
body: JSON.stringify({"message":"data saved successfully"}),
headers: {
'Content-Type': 'application/json'
}
};
}else{
return {
statusCode: 403,
body: JSON.stringify({"message":"some error occured"}),
headers: {
'Content-Type': 'application/json'
}
};
}
}
const saveDataToTable = async (insertData: any) => {
const params = {
TableName: DEMO_TABLE,
Item: {
...insertData,
created: +Date.now(),
}
};
try {
await documentClient.put(params).promise();
return true;
} catch (e) {
console.log(e);
return false;
}
} //function end
Let’s now set up the AWS CDK API gateway so that we can call the code using URL.
We will use the LambdaRestApi function present on Apigateway,
const api = new Apigateway.LambdaRestApi(this,"demo-api",{
proxy:false,
handler:demoFunction
})
api.root.addMethod("POST");
This function creates a new API link to the lambda function. The parameters for the funcion are logical id and a object containing setting which includes:
proxy :- When false you have to define your models and mappings for the request, response, and integration.
handler:- This takes the variable in which the lambda function you created is stored.
Now that the setup is done, let’s deploy the stack on AWS. For this, you need to create an access key and a secret key from AWS for your account.
Then, you can use AWS configure in the CLI tool to enter the credentials. Also note, you need AWS cli installed for the command to work.
Before deployment, we need to compile the typescript code to js to do this run “ tsc “ in the root of the project.
We will use the CDK list command to list the name of the stack. We need the stack name to pass it when deploying. You can have multiple stacks in the same setup.
Next, we use the cdk synth command to generate the cloud formation template.
Once done, we can deploy it on AWS.
You will require the stack name for deploying on AWS use cdk ls command to list the stack
Next, it shows you the roles that will be created review and enter y at prompt and click enter and wait for it to finish.
Once done it will show you the following output and also show you the API links you have created. You can check the AWS console to check the resources created.
Now, you can call the API with the data.
You should see the data in dynamoDB
Note :- whenever you make changes to the stack, you need to run cdk synth command for CDK to include the changes. You don't need to run the cdk synth command when you change your lambda function code.
You can use the tsc -w to start the typescript compiler to watch for changes in code and build the js versions of the code.
If you don't need the stack and want to delete the roles and function from AWS, you can use
cdk destroy
cdk destroy removes all the resources & roles created but it does not delete resources like s3 and dynamoDB. For this,you need to manually delete them.
Github Repository
https://github.com/SankalpChari52/cdkdemostack
AWS CDK DOC link
https://docs.aws.amazon.com/cdk/api/versions.html
Need help with AWS CDK, have queries about Lambda integration with API gateway or are looking for top-notch AWS Cloud Consulting Services or DevOps as a service? Get in touch with our experts. SJ Innovation is here to help you with all your major and minor AWS infrastructure needs. Contact us for any issues you face regarding the use of infrastructure as code in AWS today!
Also read our blog on How to Build and Deploy a Serverless API Using AWS CDK