I used both in depth. CDK as it is now is a wrapper around CloudFormation and therefore suffers from same limitations: AWS only, 'static' templates.
Pulimi on the other hand is closer to terraform, except you can write in a language which actually doesn't stand in your way and allows you to programmatically access values available during execution only. With CDK you can only reference them in CF template (lets say instance ID which you just created), but these are never "lifted" to your code. Also CDK misses native 'datasources' and offers limited mechanism for lookups.
Pulumi also has a killer Automatioin featre, where you can code infrastructure migrations, not unlike you'd do it for SQL. Neither TF nor CDK allows you to do that, and you'd need to code infrastructure state transitions in error prone bash wrappers.
As a developer, I quite liked Pulumi resource model, documentation and team responsiveness on Github and slack channel. I am working with CDK now, because of costs and I'd prefer Pulumi if there was a choice.
The migration as code feature sounds the most promising from your comment. I use terraform heavily, and while its good to capture infra state, there's no good mechanism to automate infrastructure migration from one state to another in code. I think this would be incredibly valuable to capture that.
I must admit that I'm skeptical on how well this would actually work though. Infrastructure API's tend to be flaky, and I'm not sure how reusable the migration code would actually be. If its too flaky, people will just not use it.
The migration style changes sound really interesting.
CDK indeed is just another layer of abstraction on top of CloudFormation, itself already a leaky complex abstraction, and it bites you in a lot of ways.
Same could be sad for Pulumi though, couldn't it? It's a leaky abstraction on top of Terraform which is a leaky abstraction on top of $YourProvider's API.
I'm still much happier using CDK vs CF or Pulumi vs HCL though.
the problem isn't necessarily in the abstraction. It's in the language design. Terraform (HCL) started off as a declarative language. Then people wanted string concatenation. Then conditionals. Then modules. You end up with this kludge of a language that benefits from none of the foresight of having been designed as a general purpose programming language from the outset -- no unit testing, poor control structures, etc.
When i looked the SDK was only available in certain languages which was a issue for me at the time. I just checked and they have python and csharp. Pulumi has potential to reduce the verbosity of infrastructure configuration and enable engineers to tailor it more to the application on demand. Adding a new queue can be done as part of a app release and not handled in a separate pipeline. It isn’t fun to wrangle infrastructure pipelines and when necessary orchestrate changes.
CDK is just a different way of writing cloudformation essentially, its code that is transformed into cloudformation templates, so inherits all its problems.
Pulumi is more like Terraform but without HCL. So imagine instead of having to find-the-HCL-way-to-do-things and work within those constraints to make terraform work, you can use one of a few languages to build up resources (similar to you would in HCL) and have pulumi provision/act on them for you including managing their state.
Quite different to CDK/CloudFormation and much more like Terraform without the handcuffs of HCL. (sometimes handcuffs are useful tho..)
In addition to what others have said, it is important to point out that the CDK is AWS specific. Your "infrastructure" is rarely just "AWS" even if you're not multi-cloud. Terraform and Pulumi can operate on things outside of AWS like Github, Okta, Cloudflare, Datadog, Hashicorp Vault, etc.
It is nice to have one system or even repo for managing all of that.
> In addition to what others have said, it is important to point out that the CDK is AWS specific.
As mentioned in other comments here, CDK for Terraform is another option and it's not AWS specific - it should work with any Terraform provider and there are heaps available.
All those frameworks have their own DSL/config languages that lack expressiveness and inevitably become a really bad scripting language to support everything people want to do.
Pulumi started with actual programming languages instead which gives you full expressiveness, IDE integration, and more, without learning yet another new language. And since infrastructure is just represented as objects in the language, creating and combining them in complex ways is much more natural than wiring up configs.
I migrated from Terraform to AWS CDK and I'm very happy.
The good:
- Tooling for any major language (Typescript, Python)… is lightyears ahead of anything you will find for Terraform / HCL.
- You can write your code as declaratively as possible (like you would do using TF), but you always have the escape hatch of using all libs available to your language of choice.
- AWS CDK uses CloudFormation under the hood, so you get cool stuff like automatic rollbacks in case of failure.
- You have access to much more mature testing frameworks, compared to what is available to TF. Because AWS CDK synthetize CF templates, you can also snapshot those for regression testing. Applying good software engineering practices is overall much easier. Most languages are much easier to extend than HCL.
- AWS is constantly releasing higher level libraries so you don't need to fiddle with low level API details. When using Terraform, you generally must understand your cloud provider API at a very fine level to implement IaC.
The bad:
- AWS CDK is written in Typescript and automatically translated to other languages. Even though you can use Python, C#, etc... Most examples and tutorials exist in Typescript. Also, you always must install npm + cdk + the libraries in the language you are using, so using any language other than Typescript means supporting two toolchains, which is a pain in the ass. I started with AWS CDK in Python and now I'm migrating to Typescript.
- Some modules only exist for Typescript.
- Since CF is used under the hood, it only supports resources supported by CF. Sometimes CF support takes a while. Since TF is just a wrapper for a Cloud Provider API, it generally implements new resources much quicker.
- It has its own vocabulary and and ways to do stuff (L1/L2 Construct? Stack? Retention Policy?)... even if you've used a lot of TF and know AWS very well, there's a learning curve.
- Same guy shows how to contribute to AWS CDK. I've found that looking at their source code is a great way to learn about good practices and patterns: https://www.youtube.com/watch?v=OXQSSibrt-A
CDK maintains the state with AWS itself, Pulumi operates their own state service (with option of self management). I have never used CDK, but I've heard that it's hard to recover from state corruption in CDK.
While this is true, the reason is not called out: CDK simply generates a CloudFormation Template, and thus uses CloudFormation for state management, rather than using the cloud APIs directly.
IME this is one of the best features of CDK, coming from someone who uses both Terraform and Cloudformation for development/production.
I never have to worry about losing the state or ending with the incomplete state, and no matter what, I can always just delete the whole CF stack (in rare cases, you might have to retry deletion, but it never loses resources.)
I just saw (5 mins ago) a CloudFormation stack lose resources - it happens all the time if one is not careful to prevent all modification outside of the tool (the same as other infrastructure provisioning tools). DELETE_FAILED is not a fun state to be in, nor is it one that can easily be reasoned about.
That said, I don’t think that “generates CloudFormation JSON” is a bad attribute of CDK, but it is a major difference between Pulumi and CDK. In particular it means arbitrary values cannot be used for control flow at run time with CDK, since the template has a static generation step. However, it also does not require an additional tool at runtime, which has value in some cases.
Perhaps I'm misunderstanding your point but doesn't Cloudformation use the cloud APIs directly? I'm curious why the extra level of indirection is important.
CloudFormation does quite a bit of work to manage and calculate state differences. It's not CDK itself managing it (to my knowledge).
This is noteworthy because many times CDK's constraints match CloudFormation's constraints.
I've noticed a few issues in the CDK github repo that a feature is incomplete because they are waiting for a change or feature to land in CloudFormation first.
I am using Terraform 100% now, but sometimes wish I had more than the HCL (hashicorp configuration language) syntax available to use in my code.