Working with AWS can be quite a complex task at times, due to the fact that well composed architectures and solid infrastructures might be troublesome to deploy and maintain in the long run. A main software development goal is to always optimize the development flow by making processes as simple as possible, from the programming language to each and every framework to be used in the project. In AWS it is no different. Even though CloudFormation was already a hugely beneficial tool, the launch of SAM helped even more developers across the world to architect their infrastructures with a smooth efficiency, reducing the time to plan infrastructures and increase productive development time.Last year, AWS took Cloudformation one step further and released CDK (Cloud Development Kit). AWS CDK is one of the most recent releases from Amazon AWS to improve the capability of creating and keeping control of infrastructures with your preferred programming language. Although this technology is quite recent, and may present issues while compared to SAM or even raw CloudFormation, it is undeniable that it eases the whole process of creating and setting up AWS resources. This article will present the advantages as well as some issues you might encounter while using this tool.
Defining AWS CDK
In a nutshell, the AWS Cloud Development Kit is an open-source framework that aims to make an easier and faster way to create AWS Cloud resources that will be transformed into AWS CloudFormation templates. With CDK, the cloud infrastructure development can use all the perks provided by the desired programming languages, such as TypeScript, JavaScript, Python, Java and C#. This can drastically reduce the time spent on architecture, along with solid API reference and a very useful CLI that allows the interaction with CDK applications.
CDK integrations and known issues
One of the benefits that makes using AWS CDK so tempting is that although the tool itself has some complexities, an integration with a SAM project can be easily achieved. But, due to being a new framework, some of the cloud components are not very stable yet, which can be the case for APIs with Lambda functions because it can negatively affect the infrastructure scalability. In those cases, SAM templates, which are rock stable by now, can do just the trick, and those can be homogeneously incorporated into CDK applications. Another common issue is that as the framework is relatively new, updates are constantly being made on the packages, which may result in compatibility issues when installing CDK modules.The ability to overcome issues like those above described, as well as the fact that there are AWS resources that currently lack Constructs, such as Pinpoint and Athena, makes this framework a solid option for development teams facilitating the development of solid cloud architectures. As the tool is improved, it is expected that those issues will be solved, allowing an even faster and consistent development process.
Small learning curve
Besides the programming language that is going to be used to create the cloud resources, which most of the time is already background knowledge, there are a few factors that make the learning curve relatively small. Not having to know all the basics and background information of each construct may be one of the biggest factors. When instantiating a resource, its basic roles and sets are already predefined, allowing the developer to focus only on elements they may need to customize. This allows developers that are starting in the cloud environment to acquire knowledge about the resources while still being productive and delivering projects. There may be times where the basics won't be enough, but by the time the development process is complete, all the time previously saved by using the framework will be available to research in how to architect solutions for those problems.
Faster development process
The development process is a balance of using the frameworks that will make the development process faster while maintaining its quality. Spending time creating enormous CloudFormation templates can be quite hard and time consuming, but it offers solid results and the cloud stacks created with it are solid. When SAM was launched, it made the developer's life much easier, as its templates are quite smaller, while not losing its capabilities as it is transformed into CloudFormation templates. The same can be said for CDK: it brings the comfort of defining components programmatically while still having a compilation that allows the stack to have all the perks provided by CloudFormation, such as rollback in case of failures, safe deployment and drift detection.The usage of CDK constructs allows an acceleration of the development process, as the constructs come with predefined configurations for each AWS cloud resource they create, including its basic roles and properties.As an example of how the creation of cloud resources using CDK can speed up the development of cloud architectures, a definition of a bucket that allows get requests from specific domains is going to be demonstrated in both an AWS CloudFormation template and a AWS CDK application. This policy in a CloudFormation template should look like this:
"westpointBucket": {
"Type": "AWS::S3::Bucket",
"Properties": {
"BucketName": "westpoint-bucket",
"CorsConfiguration": {
"CorsRules": [
{
"AllowedMethods": [
"GET"
],
"AllowedOrigins": [
"//westpoint.io/*"
]
}
]
},
"WebsiteConfiguration": {
"ErrorDocument": "index.html",
"IndexDocument": "index.html"
}
},
"UpdateReplacePolicy": "Delete",
"DeletionPolicy": "Delete"
},
"westpointBucketPolicy": {
"Type": "AWS::S3::BucketPolicy",
"Properties": {
"Bucket": {
"Ref": "westpointBucket"
},
"PolicyDocument": {
"Statement": [
{
"Action": "s3:GetObject",
"Effect": "Allow",
"Principal": "*",
"Resource": {
"Fn::Join": [
"",
[
{
"Fn::GetAtt": [
"westpointBucket",
"Arn"
]
},
"/*"
]
]
}
}
],
"Version": "2012-10-17"
}
}
}
While the same resource can be created using CDK like this:
import * as cdk from '@aws-cdk/core';
import * as s3 from '@aws-cdk/aws-s3';
const cors_rule: [s3.CorsRule] = [{
allowedOrigins: ['//westpoint.io/*'],
allowedMethods: [s3.HttpMethods.GET]
}];
const westpointBucket = new s3.Bucket(this, 'westpoint-bucket', {
bucketName: 'westpoint-bucket',
cors: cors_rule,
publicReadAccess: true,
websiteIndexDocument: "index.html",
websiteErrorDocument: "index.html",
removalPolicy: cdk.RemovalPolicy.DESTROY
});
As demonstrated above, defining this kind of resource on CDK applications is much faster and more compact compared to the same definition in CloudFormation. Although some issues may exist, as pointed out before, it is undeniable that this tool improves the productivity of the development teams, allowing them to focus more on what is important: the product itself.
Constructs: The base for each application
Constructs are the pieces that will come together when creating applications with AWS CDK. They are the representation of cloud components, such as a simple S3 bucket, or a DynamoDB table, as well as composite components, such as an AWS CodePipeline, which will be composed of multiple resources to accomplish its purpose.Defining resources using constructs in a CDK application is a quite simple task compared to what needs to be done on a CloudFormation template.
import * as dynamodb from '@aws-cdk/aws-dynamodb';
const westpointTable = new dynamodb.Table(
this,
'westpoint-table',
{
partitionKey:
{
name: 'id',
type: dynamodb.AttributeType.STRING
},
tableName: 'WestpointTable'
});
The code snippet above represents the definition of an Amazon DynamoDB table using TypeScript. Each AWS resource has its own dependency, allowing the developers to import only what is needed for the application, reducing the size of the application by not importing packages that are not going to be used. As of the table itself, it accepts three attributes: scope, ID and props.
- Scope: defines which construct the new construct is present within. When creating CDK stacks, each construct should be inside another construct, creating a hierarchy of constructs starting from Stacks all the way to smaller resources, such as a DynamoDB table. In almost every case, this is going to be passed as the parameter.
- ID: defines the id of the construct, which must be unique within the scope. It is important to notice that the ID does not represent the resource name, its purpose is to separate each cloud resource within the scope.
- Params: an object that defines all the properties that are going to be passed to customize the cloud resource. They are divided in two types: required and optional. Required params are the sets of properties that the developers must set to create the desired cloud resource, while the optional params are non-mandatory properties that can be passed to better suit the projects needs, usually overwriting predefined settings.
For the previously defined DynamoDB table, which the ID 'westpoint-table' was set, the set of properties passed to it were the partition key, which is a required parameter to the creation of the resource, and the table name, which optionally nominates the table that is going to be created in the AWS infrastructure. Not defining the table name would result in the creation of the resource with the default table name, which is a concatenation of all the constructs present within the current stack.CDK constructs are divided in three types: those being low-level constructs, higher-level constructs, and patterns. They represent multiple complexities of constructs that can be used in the cloud stack definition.Low-level constructs represent the smaller constructs, also called Cfn resources. They are all the resources that are available on CloudFormation templates, and require explicit declaration of all its properties, without any kind of basic resource creation. For its usage, deep knowledge about the AWS service is required, as the developer needs to specify all the models of the resource.Higher-level components also represent AWS services, but as an API that handles most of the configurations. They allow the development of cloud resources without deep knowledge about the resources themselves, as it bootstraps an instance of the service, and only requires basic user configuration to suit their needs.The last type, patterns, represent constructs that allow the simple creation of common tasks that otherwise would require some effort to be put together. They often consist of multiple AWS resources, such as the LambdaRestApi construct, which consists of a simple API Gateway resource that is backed up by a Lambda function.
AWS CDK CLI
Along with what was previously mentioned, AWS CDK has a CLI that is the main tool to interact with CDK applications. It is responsible for commands such as verifying the defined stacks, generating the CloudFormation templates and deploying your application to the AWS infrastructure. These perks allow the developers to validate their stacks much faster than it would be to deploy CloudFormation stacks to the cloud, in which case you would have to wait for the entire process to finish to then realize there was some kind of issue in the templates. As some commands are vital for the usage of CDK, they are going to be presented here to show an overview of what the CLI is capable of.
The basic command to quick start CDK projects. It generates a folder with the necessary files and dependencies to create a CDK application. It comes with options to select the language, list available templates to start your stack and possibility to auto setup a git repository for it.
This command is responsible for generating the CloudFormation stack that will be created when deploying your CDK application. It can be used to verify if the current template definition in your code represents a valid AWS CloudFormation template, reducing the time needed to discover issues. It comes with an option to synthesize only the requested stacks, leaving behind all their dependencies.
This is the most important command present in the CLI. It allows the deployment of your application into the AWS cloud environment. Running this command will result in the creation of the CloudFormation templates for the defined stacks present in the code, and then uploading those templates in the cloud. It comes with multiple options, such as passing parameters to the stack, selecting the output file path, tags that may be added to the stack, and more.
There might be situations where the template created by the deploy command can't be directly uploaded to the cloud due to its size. When this happens, the bootstrap of your application is required. It consists of uploading the generated templates into AWS buckets for them to be deployed again using the previous command. This command comes with many options, such as selecting the bucket the templates will be uploaded to, selecting the AWS KMS master key for encryption, as well as adding tags to the stack, and more.
This command is used to remove deployed CDK stacks. It removes from the cloud all the resources created by your CDK application, besides some special cases. One of those cases is S3 buckets: the destroy command will never delete a bucket that is not empty, which most of the time it will not be, requiring manual deletion after the destroy process is finished. It comes with options to not destroy dependencies and force exclusions, not requiring confirmations afterwards. As we can see, the AWS CDK CLI is one of the biggest friends of the developer when defining cloud resource stacks, having its multiple perks that facilitate the process of creating and deploying AWS infrastructures.
Conclusion
As described in this article, AWS CDK and its CLI facilitate the development of AWS infrastructures, as it allows developers to use programming languages rather than using notation languages such as YAML or JSON. The creation and deployment of each and every stack is a lot easier when making usage of elements such as the synthesize command to validate stacks. Following this article I will write a complimentary article tackling the most common issues of using CDK and how to solve them, allowing a quick understanding of some of the issues that may occur and allowing an even easier and faster development. I hope you found this article useful.Mark AvdiCTO | WestPoint.io | Lover of all things Serverless