AWS CDK simplifies IaC by wrapping CloudFormation into code-driven constructs, allowing greater flexibility and automation. AWS CDK operates differently from Terraform when managing infrastructure updates. While Terraform uses a strict declarative model and state files to manage resources, CDK relies on CloudFormation templates and incremental updates.

When you modify your CDK stack, CDK synthesizes a new CloudFormation template. During deployment, CloudFormation evaluates the changes and determines whether resources can be updated in place or if replacement is required. Only changes to immutable properties, such as the VPC, cluster name, or Kubernetes version, might force a resource replacement.

To safely manage updates, use the cdk diff command. It shows the exact changes that CDK plans to make, allowing you to confirm whether any resource replacements are required before deployment. This approach minimizes surprises and ensures that updates to your infrastructure align with your expectations.

Key CloudFormation Concepts for CDK

  • Stacks: Logical units of deployment, like Terraform workspaces, managing related resources as a group.
  • Templates: JSON/YAML definitions of resources; CDK auto-generates these from your code (cdk synth).
  • ChangeSets: Deployment previews showing proposed changes to existing stacks, akin to terraform plan.
  • Parameters and Outputs:
    • Parameters: Deployment-time inputs (e.g., AMI IDs).
    • Outputs: Deployment-time exports for inter-stack or external use.
    • Prefer CDK constructor arguments for compile-time control; use CfnParameter only for reusability or manual deployments.

Importing Existing Resources in CDK

Use fromXyzAttributes or similar methods in resource constructs to reference existing AWS resources:

existing_bucket = s3.Bucket.from_bucket_arn(self, "ImportedBucket", bucket_arn="arn:aws:s3:::my-bucket")

Tip

Imports are read-only within CDK, ensuring no accidental updates to unmanaged resources.


Gotchas for Terraform Experts

  • State Management: CloudFormation handles state internally. Actions outside CDK (e.g., manual console changes) cause drift, which isn’t reflected in your CDK code unless detected using drift detection.
  • Immutable Resources: Unlike Terraform, some changes (e.g., renaming an S3 bucket) cause the resource to be replaced entirely, possibly leading to downtime or data loss.
  • Cross-Stack Dependencies: Dependencies between stacks require explicit exports and imports, making it less seamless than Terraform’s variable sharing.
  • Resource Replacement Hacks: Tutorials may suggest replacing stack code with no-op code to avoid stack deletion when moving resources out of the stack. This is risky, as it creates gaps in resource tracking and often relies on manual updates, breaking IaC principles.
  • Environment-Specific Resource Constraints: Multi-region or multi-account setups require extra care with environment variables or CDK context, as they aren’t as straightforward as Terraform workspaces.

Best Practices

  • Avoid Resource Replacement Workarounds:
    • Instead of “clearing stack code” to preserve resources, use imports (fromXyzAttributes) and avoid removing critical stacks unless you know the consequences.
  • Inspect ChangeSets:
    • Always review ChangeSets (cdk deploy) for actions like replacements or deletions to avoid unexpected outcomes.
  • Validate Before Deploying:
    • For multi-environment setups, use cdk diff to preview differences before deploying.
  • Use Constructs Over Raw Resources:
    • Prefer high-level constructs (e.g., Bucket, Queue) to simplify logic, and only use low-level CfnResource when necessary.
  • Explicit Outputs for Cross-Stack Communication:
    • Use CfnOutput to make values accessible across stacks, but modularize stacks to minimize dependencies.
  • Separate Critical Resources:
    • Deploy critical resources (e.g., databases, production buckets) in separate stacks to avoid accidental impact during regular updates.