Skip to content

Commit 0951926

Browse files
authoredDec 2, 2024··
Draft pulumi-cdk 1.0 blog (#13434)
Announcement blog for Pulumi CDK version 1.0
1 parent 75aefb6 commit 0951926

File tree

2 files changed

+273
-0
lines changed

2 files changed

+273
-0
lines changed
 
+273
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,273 @@
1+
---
2+
title: "Anouncing the 1.0 release of AWS CDK on Pulumi"
3+
date: 2024-12-02T08:00:00-07:00
4+
meta_desc: "Enhanced support of AWS CDK constructs from within Pulumi. Combine Pulumi and AWS CDK
5+
resources amd use Pulumi Cloud Platform to manage CDK"
6+
meta_image: meta.png
7+
authors:
8+
- matt-jeffryes
9+
- cory-hall
10+
- florian-stadler
11+
- anton-tayanovskyy
12+
tags:
13+
- aws-cdk
14+
---
15+
16+
At Pulumi, we're committed to delivering the widest range of cloud infrastructure building blocks for use in your cloud engineering projects.
17+
In 2022, we introduced [preview](https://www.pulumi.com/blog/aws-cdk-on-pulumi/) support for integrating AWS CDK constructs into Pulumi programs
18+
and today we're happy to announce the 1.0 release of our pulumi-cdk library for typescript. This first stable version completes support for common CDK features
19+
enabling you to deploy almost any CDK construct with Pulumi.
20+
21+
<!--more-->
22+
23+
The pulumi-cdk library provides access to the many high-level libraries ('constructs') built by service teams at AWS and by the AWS CDK community. However, there were some limitations in the preview version of the library that prevented using some constructs and complicating migration of existing CDK stacks. Uncertainty about which constructs were supported has limited adoption of this rich ecosystem by Pulumi users.
24+
25+
With the new 1.0 release, pulumi-cdk has greatly expanded compatibility with all CDK features. Users can now confidently use Pulumi to deploy constructs they have written themselves or any of the 1600+ constructs in AWS's [construct hub](https://constructs.dev/search?cdk=aws-cdk&sort=downloadsDesc&offset=0). We're excited to bring Pulumi users access to all the high level interfaces curated by AWS and the CDK community.
26+
27+
Additionally, existing AWS CDK users now have an easier path to transition from CloudFormation to Pulumi, unlocking faster deployments, integration with Pulumi's vast provider ecosystem and all of the features of Pulumi's Cloud Engineering Platform (like [Policy as Code](https://www.pulumi.com/docs/using-pulumi/crossguard/), [Audit Logs](https://www.pulumi.com/docs/pulumi-cloud/audit-logs/), [Drift detection](https://www.pulumi.com/docs/pulumi-cloud/deployments/drift/), [Secrets](https://www.pulumi.com/docs/esc/get-started/), and much more).
28+
29+
## Deploying CDK Constructs with Pulumi
30+
31+
To deploy existing AWS CDK Constructs using Pulumi:
32+
33+
1. Create a class that derives from `pulumicdk.Stack` (which itself is derived from `awscdk.Stack`).
34+
2. In the constructor, use any AWS CDK constructs from existing libraries such as [`aws-cdk-lib`](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib-readme.html)
35+
3. Create a `pulumicdk.App` instance that constructs an instance of your stack.
36+
37+
For example, the following program deploys an AWS Apprunner CDK Construct using Pulumi:
38+
39+
```typescript
40+
import * as pulumi from '@pulumi/pulumi';
41+
import * as pulumicdk from '@pulumi/cdk';
42+
import { Service, Source } from '@aws-cdk/aws-apprunner-alpha';
43+
44+
class AppRunnerStack extends pulumicdk.Stack {
45+
url: pulumi.Output<string>;
46+
47+
constructor(id: string, options?: pulumicdk.StackOptions) {
48+
super(id, options);
49+
50+
const service = new Service(this, 'service', {
51+
source: Source.fromEcrPublic({
52+
imageConfiguration: { port: 8000 },
53+
imageIdentifier: 'public.ecr.aws/aws-containers/hello-app-runner:latest',
54+
}),
55+
});
56+
57+
this.url = this.asOutput(service.serviceUrl);
58+
}
59+
}
60+
61+
const app = new pulumicdk.App('app', (scope: pulumicdk.App): pulumicdk.AppOutputs => {
62+
const stack = new AppRunnerStack('teststack');
63+
return {
64+
url: stack.url,
65+
};
66+
});
67+
export const url = app.outputs['url'];
68+
```
69+
70+
Deploy with a `pulumi up`:
71+
72+
```console
73+
> pulumi up
74+
75+
Updating (dev)
76+
77+
View Live: https://app.pulumi.com/lukehoban/pulumi-cdk-apprunner/dev/updates/1
78+
79+
Type Name Status
80+
+ pulumi:pulumi:Stack pulumi-cdk-apprunner-dev created
81+
+ └─ cdk:index:StackComponent teststack created
82+
+ └─ cdk:construct:Service teststack/adapter/service created
83+
+ └─ aws-native:apprunner:Service service6D174F83 created
84+
85+
Outputs:
86+
url: "2ez3iazupm.us-west-2.awsapprunner.com"
87+
88+
Resources:
89+
+ 4 created
90+
```
91+
92+
And curl the endpoint:
93+
94+
```console
95+
> curl https://$(pulumi stack output url)
96+
97+
______ __ __ __ _ __
98+
/ ____/___ ____ ____ __________ _/ /___ __/ /___ _/ /_(_)___ ____ _____/ /
99+
/ / / __ \/ __ \/ __ `/ ___/ __ `/ __/ / / / / __ `/ __/ / __ \/ __ \/ ___/ /
100+
/ /___/ /_/ / / / / /_/ / / / /_/ / /_/ /_/ / / /_/ / /_/ / /_/ / / / (__ )_/
101+
\____/\____/_/ /_/\__, /_/ \__,_/\__/\__,_/_/\__,_/\__/_/\____/_/ /_/____(_)
102+
/____/
103+
104+
Congratulations, your service has successfully deployed on AWS App Runner.
105+
106+
Open it in your browser at https://2ez3iazupm.us-west-2.awsapprunner.com/
107+
108+
Try the workshop at https://apprunnerworkshop.com
109+
Read the docs at https://docs.aws.amazon.com/apprunner
110+
```
111+
112+
## Pulumi takes CDK apps to the next level
113+
114+
Combine CDK constructs with any of the features of Pulumi programs to deploy faster, easier and to any cloud. Use Pulumi functions and stack references to connect to pre-existing infrastructure and mix in resources from any provider to bring *all* of your infrastructure under management.
115+
116+
For example, we can use CDK's `ecs_patterns` to quickly create a loadbalanced Fargate service, but route traffic to it with a record in an exisiting CloudFlare DNS zone.
117+
118+
```typescript
119+
import * as path from 'path';
120+
import * as acm from 'aws-cdk-lib/aws-certificatemanager';
121+
import * as aws from '@pulumi/aws';
122+
import * as pulumi from '@pulumi/pulumi';
123+
import * as pulumicdk from '@pulumi/cdk';
124+
import * as cloudflare from '@pulumi/cloudflare';
125+
import * as ecs from 'aws-cdk-lib/aws-ecs';
126+
import * as ecsPatterns from 'aws-cdk-lib/aws-ecs-patterns';
127+
128+
let config = new pulumi.Config();
129+
let accountId = config.requireSecret("cloudflare_account_id");
130+
let zoneName = config.require("cloudflare_zone_name");
131+
let certificateId = config.require("certificate_id");
132+
let certificateKey = config.requireSecret("certificate_key");
133+
134+
class CloudFlareStack extends pulumicdk.Stack {
135+
constructor(app: pulumicdk.App, id: string) {
136+
super(app, id);
137+
138+
// First Load the zone and certificate from CloudFlare
139+
///////////////////////////////////////////////////////
140+
141+
// Read the CloudFlare zone for the domain
142+
const zone = cloudflare.getZoneOutput({
143+
accountId,
144+
name: zoneName,
145+
});
146+
147+
// read the certificate from CloudFlare
148+
const caCertificate = cloudflare.getOriginCaCertificateOutput({
149+
id: certificateId,
150+
});
151+
152+
// Import the certificate in ACM
153+
const cert = new aws.acm.Certificate('import', {
154+
privateKey: certificateKey,
155+
certificateBody: caCertificate.certificate,
156+
});
157+
158+
// Create a L2 reference from the cert arn
159+
const acmCert = acm.Certificate.fromCertificateArn(this, 'cert', pulumicdk.asString(cert.arn));
160+
161+
// Next, use ECS Patterns to create a loadbalanced fargate service with the correct certificate
162+
///////////////////////////////////////////////////////////////////////////////////////////////
163+
164+
const loadBalancedFargateService = new ecsPatterns.ApplicationLoadBalancedFargateService(this, 'Service', {
165+
certificate: acmCert,
166+
redirectHTTP: true,
167+
taskImageOptions: {
168+
image: ecs.ContainerImage.fromRegistry("amazon/amazon-ecs-sample"),
169+
},
170+
});
171+
172+
const alb = loadBalancedFargateService.loadBalancer;
173+
174+
// Finally, Create a record in CloudFlare that directs to the service's loadbalancer
175+
////////////////////////////////////////////////////////////////////////////////////
176+
177+
new cloudflare.Record('alb', {
178+
name: 'cdk-alb',
179+
type: 'CNAME',
180+
zoneId: zone.zoneId,
181+
content: this.asOutput(alb.loadBalancerDnsName),
182+
proxied: true,
183+
});
184+
}
185+
}
186+
187+
class MyApp extends pulumicdk.App {
188+
constructor() {
189+
super('app', (scope: pulumicdk.App) => {
190+
new CloudFlareStack(scope, 'cloudflare');
191+
});
192+
}
193+
}
194+
195+
new MyApp();
196+
```
197+
198+
Pulumi let's you read and create any resource type across thousands of different cloud service providers and integrate them with your CDK stacks. Building CDK apps on Pulumi brings a host of other benefits too, including:
199+
200+
- Customize [resource options](https://www.pulumi.com/docs/iac/concepts/options/) (eg. to protect a database against accidental deletion or deploy to multiple regions in the same program)
201+
- [Detect and manage drift](https://www.pulumi.com/docs/pulumi-cloud/deployments/drift/) with Pulumi deployments
202+
- Track and store user actions and change history with [Audit Logs](https://www.pulumi.com/docs/pulumi-cloud/audit-logs/)
203+
- And a host of other benefits from [Pulumi Cloud](https://www.pulumi.com/product/pulumi-cloud/)
204+
205+
## Expanded Features in pulumi-cdk 1.0
206+
207+
The 1.0 version of pulumi-cdk adds support for key CDK features such as: assets, custom resources, nested stacks, and aspects, so most existing CDK constructs will work with Pulumi without any modification. We've also eliminated the need to call `cdk bootstrap` before running `pulumi up` by integrating a custom Pulumi Synthesizer.
208+
209+
### Using CDK Aspects
210+
211+
Pulumi CDK now supports CDK aspects. For example, you can add the [cdk-nag](https://github.com/cdklabs/cdk-nag) aspect to your stack to enforce best practices:
212+
213+
```ts
214+
import * as pulumicdk from '@pulumi/cdk';
215+
import * as s3 from 'aws-cdk-lib/aws-s3';
216+
import { AwsSolutionsChecks } from 'cdk-nag';
217+
218+
const app = new pulumicdk.App('app', (scope: pulumicdk.App): pulumicdk.AppOutputs => {
219+
const stack = new pulumicdk.Stack('example-stack');
220+
Aspects.of(stack).add(new AwsSolutionsChecks({ verbose: true }));
221+
222+
new s3.Bucket(this, 'bucket');
223+
});
224+
```
225+
226+
#### Example Output
227+
228+
```console
229+
[Error at /test-stack/bucket/Resource] AwsSolutions-S1: The S3 Bucket has server access logs disabled. The bucket should have server access logging enabled to provide detailed records for the requests that are made to the bucket.
230+
[Error at /test-stack/bucket/Resource] AwsSolutions-S10: The S3 Bucket or bucket policy does not require requests to use SSL. You can use HTTPS (TLS) to help prevent potential attackers from eavesdropping on or manipulating network traffic using person-in-the-middle or similar attacks. You should allow only encrypted connections over HTTPS (TLS) using the aws:SecureTransport condition on Amazon S3 bucket policies.
231+
```
232+
233+
### CDK assets
234+
235+
CDK's assets make it easy to bundle code and other files your application needs into an S3 bucket or a Docker container, eliminating extra steps from your build pipeline. For example you can use Docker container asset to deploy a Fargate service from local directory. CDK will build the container image and push to ECR on `pulumi up`.
236+
237+
```ts
238+
import * as pulumicdk from '@pulumi/cdk';
239+
import * as aws from '@pulumi/aws';
240+
import * as ec2 from 'aws-cdk-lib/aws-ec2';
241+
import * as ecs from 'aws-cdk-lib/aws-ecs';
242+
import * as ecs_patterns from 'aws-cdk-lib/aws-ecs-patterns';
243+
244+
const app = new pulumicdk.App('app', (scope: pulumicdk.App) => {
245+
const stack = new pulumicdk.Stack('example-stack');
246+
247+
const vpc = new ec2.Vpc(stack, 'MyVpc');
248+
const cluster = new ecs.Cluster(stack, 'fargate-service-autoscaling', { vpc });
249+
250+
// Create Fargate Service
251+
const fargateService = new ecs_patterns.NetworkLoadBalancedFargateService(this, 'sample-app', {
252+
cluster,
253+
taskImageOptions: {
254+
image: ecs.ContainerImage.fromAsset(path.join(__dirname, './'), {
255+
// assetName is required and is used in the name of the ecr repository that is created
256+
assetName: 'cdk-fargate-example',
257+
}),
258+
},
259+
});
260+
});
261+
```
262+
263+
## Future direction
264+
265+
Currently AWS CDK on Pulumi is supported only for TypeScript users, but we're eager to bring the benefits of the CDK ecosystem to all Pulumi languages in the future. You can comment and upvote on [this tracking issue](https://github.com/pulumi/pulumi-cdk/issues/49), to let us know this is important to you.
266+
267+
We're also exploring options for importing state from CDK applications that are already deployed with CloudFormation to enable seamless migration for existing CDK users. Please let us know on [this tracking issue pulumi-cdk/271](https://github.com/pulumi/pulumi-cdk/issues/271) you would be interested in testing this with us.
268+
269+
## Summary
270+
271+
The 1.0 release of AWS CDK support for Pulumi marks a significant expansion of opportunities to interoperate between the AWS CDK and Pulumi ecosystems. Existing AWS CDK users can now more easily adopt the full power, speed and flexibility of the Pulumi Cloud Platform and its diverse ecosystem. And existing Pulumi users can benefit from the many expert curated constructs and libraries in the CDK community. We're excited to see what you'll build with these two great cloud technologies together.
272+
273+
The AWS CDK on Pulumi project is open source at [https://github.com/pulumi/pulumi-cdk](https://github.com/pulumi/pulumi-cdk) and on NPM at [https://www.npmjs.com/package/@pulumi/cdk](https://www.npmjs.com/package/@pulumi/cdk). Get started today\!
707 KB
Loading

0 commit comments

Comments
 (0)
Please sign in to comment.