Should You Start Using CDK?

If you’re still creating your AWS infrastructure by clicking around in the console or using annoying CloudFormation template files, then you should really consider using CDK. CDK stands for Cloud Development kit, and its a much better way to create all of your AWS resources. In this article, I’ll tell you about the pros and cons of using CDK to help you decide if its the right choice for your new projects.

Benefits of Using CDK

Create your infrastructure with code

CDK’s main benefit is that it allows you create all of your AWS infrastructure using a programming language. Today, it supports most popular languages including Python, Typescript, Javascript, Ruby, C++, Golang, Java, and more.

Using a programming language to create your infrastructure is more than just a convenience—it makes defining your infrastructure faster, more flexible, and dynamic. For example, imagine you have a RDS Postgres database with a test and production environment. In production, you want to use a large instance to handle high traffic, while in test its fine to use a less powerful instance to save on cost. Using CDK, you can create a single function that dynamically decides what type of instance to create based on the environment. Your code might look a little something like this.

from aws_cdk import aws_rds as rds

def createRDSInstance(environment: str) -> DatabaseInstance:
instanceType = ""
storage = 0

if environment is "production":
instanceType = "db.m7g.4xlarge"
storage = 500
else:
instanceType = "db.t2.medium"
storage = 20

return rds.DatabaseInstance(self, "MyDatabase",
instance_identifier="my-db-instance",
instance_type=ec2.InstanceType(instanceType), # <---- notice the dynamically passed in instance type
engine=rds.DatabaseInstanceEngine.postgres(version=rds.PostgresEngineVersion.VER_13_3),
allocated_storage=storage # notice the dynamically passed in storage
)

# Runner
environment = ... # <--- environment is dynamically set based on CDK input context
instance = createRdsInstance(environment)

Autocomplete is another notable feature that sets CDK apart. When working on your project, your IDE will automatically give syntax hinting as you type. This means you can spend less time looking through documentation and more time developing. The image below shows autocomplete in action.

CDK Autocomplete in action using Python and a S3 bucket.

Re-use common infrastructure with constructs

Ontop of this, you can define re-usable components called CDK constructs. Constructs are pre-defined objects you can use to create on more AWS resources. Constructs can be easily shared between projects using a centralized Github repository. In fact, this is how we internally at Amazon share helpful CDK patterns with one another. For example, one common pattern internally at Amazon is an API Gateway with a Lambda Function that uses a proprietary technology to handle requests. One engineer implemented this pattern in a common Git repository that then got shared with dozens of tech teams. This increased the speed of getting infrastructure set up so that we can focus more on our actual application logic.

Alternatively, you can leverage many of the existing constructs offered by AWS via the Construct Library. AWS offers different types of constructs at varying levels of abstraction. This includes L1 constructs which are low-level and allow you to completely control the resource you’re creating, L2 constructs that are higher level abstractions over the previous with sensible defaults out of the box, and L3 constructs are patterns that combine multiple L2 constructs to create ready to use AWS architectures.

Unit Test your constructs to ensure functionality

CDK also supports the ability to unit test your application before you commit it to source control. For those of you that aren’t as familiar with unit tests, they are automated tests that verify the correctness of individual functions or methods. They help catch bugs early, ensure code behaves as expected, and make refactoring safer by providing a safety net.

By unit testing your CDK code, you can be 100% sure it is behaving as expected. This isn’t as much of a problem for solo projects, but in teams with multiple developers committing changes to one project, having robust unit tests is an effective way to prevent bugs from being introduced into a system.

Want to get more hands-on CDK experience? Check out my project-oriented course: Web Scraping on AWS

As an example of CDK unit tests, below is an example that tests the RDS Postgres instance we created in the above section’s code snippet.

import unittest
from aws_cdk import core, assertions
from aws_cdk import aws_rds as rds, aws_ec2 as ec2

class RdsInstanceTestStack(core.Stack):
    def __init__(self, scope: core.Construct, id: str, environment: str, **kwargs):
        super().__init__(scope, id, **kwargs)
        self.database = createRDSInstance(self, environment)

class TestRdsInstance(unittest.TestCase):
    def setUp(self):
        self.app = core.App()

    def test_rds_instance_production(self):
        """Test RDS instance properties in production environment."""
        stack = RdsInstanceTestStack(self.app, "TestStack", environment="production")
        template = assertions.Template.from_stack(stack)

        template.has_resource_properties("AWS::RDS::DBInstance", {
            "DBInstanceClass": "db.m7g.4xlarge",
            "AllocatedStorage": "500"
        })

    def test_rds_instance_non_production(self):
        """Test RDS instance properties in non-production environment."""
        stack = RdsInstanceTestStack(self.app, "TestStack", environment="staging")
        template = assertions.Template.from_stack(stack)

        template.has_resource_properties("AWS::RDS::DBInstance", {
            "DBInstanceClass": "db.t2.medium",
            "AllocatedStorage": "20"
        })

if __name__ == '__main__':
    unittest.main()

These test cases work by examining CDK’s generated CloudFormation file to ensure it contains the resources and properties that we specified in our CDK code. We acquire the template using a handy built-in method with the code template = assertions.Template.from_stack(stack) and ensure it has the correct settings using template.has_resource_properties(...) .

To ensure you don’t accidentally introduce breaking changes, these tests can be automatically run as part of a CI / CD pipeline or optionally during development before you push your infrastructure changes into AWS.

Abstraction lets you generate entire AWS applications quickly

Previously, creating applications requiring multiple different AWS components (like a S3 Bucket + SNS Notification) required configuring each separate component before finally linking them together with glue code. But with CDK, this becomes tremendously easier. Using CDK’s L3 constructs (also known as Patterns) you can generate entire application architectures in just a couple lines of code. The types of constructs available vary in complexity from simple onces like an API Gateway Endpoint + a Lambda Function, to massive architectures that contain a VPC with multiple subnets, RDS Databases, Compute Infrastructure, Load Balancers, and more. This level of abstraction (albeit opinionated in terms of what you can customize) allows you to quickly create complex AWS architectures leveraging AWS best practices without having to understand every single setting underneath the hood.

First class support

Finally, when choosing an infrastructure as code provider, one needs to be aware of support levels the technology provides. Thankfully, CDK is developed, maintained, and updated by AWS itself. This means that there is a certain quality standard you may not see if competitor products like Terraform or Pulumi — AWS literally has their reputation on the line here.

This isn’t to say that bugs don’t get introduced from time to time — a quick glance at the CDK team’s Github Issues page will tell you otherwise. But rest assured that impactful bugs are few and far between, and if they are introduced, they are resolved quickly by AWS’ extensive team of developers.

Now I’ve given you a broad overview of the benefits CDK has to offer. But CDK isn’t perfect and has a number of drawbacks you should be aware of before considering it for your next project.

Drawbacks of using CDK

Slow updates for new service features

As we noted above, AWS develops, maintains, and updates CDK. However, there are hundreds of independent teams within AWS that all work on different services. These teams are primarily concerned with developing and releasing either new features or new services altogether — they primary concern is not to keep CDK up to date. This means that at times, AWS service teams will release brand new features that folks are eager to use, but these features/settings are not yet available in CDK. This presents a problem, since if you drank the CDK kool-aid and rely on it for all of your infrastructure, you are effectively blocked from using new features until AWS release the corresponding feature in CDK code. There are certain workarounds for this, but this requires manipulating CDK L1 constructs to pass in custom variables — this option is not for the faint of heart. Instead, most folks simply wait a couple weeks or months until the corresponding CDK feature is released. This highly upvoted topic on reddit highlights community frustration with the issue.

Total
0
Shares
Leave a Reply

Your email address will not be published. Required fields are marked *

Related Posts