Use Cases

Claude Code × AWS CloudFormation/CDK Komplettanleitung | Infrastruktur automatisch als Code generieren

AWS-Infrastruktur als Code mit Claude Code beschleunigen. Funktionierender Code für CloudFormation-Templates, CDK TypeScript-Stacks und Multi-Stack-Design — aus Masas echter Produktionserfahrung.

„Ich hasse es, jedes Mal durch die AWS-Konsole zu klicken, um Infrastruktur einzurichten” — wer hat das nicht schon gedacht? CloudFormation und CDK machen Infrastruktur durch Code reproduzierbar, aber das Schreiben dieser Templates kostet Zeit.

Ich verwalte die Infrastruktur dieser Website (Cloudflare Pages + Workers + D1) mit Claude Code, und für AWS-Geschäftsinfrastruktur lasse ich Claude Code ebenfalls CloudFormation/CDK-Templates generieren. Templates, die früher Stunden dauerten, sind jetzt in 1/5 der Zeit fertig.


CloudFormation vs CDK: Was soll man wählen?

CloudFormation: AWS-nativer Service, der Infrastruktur in JSON/YAML beschreibt
CDK (Cloud Development Kit): Framework, das Infrastruktur in TypeScript/Python beschreibt
                              und zu CloudFormation synthetisiert
VergleichCloudFormationCDK
SpracheJSON / YAMLTypeScript, Python, Java usw.
TypsicherheitKeineAusgezeichnet (vollständig typsicher mit TypeScript)
WiederverwendbarkeitGering (Copy-Paste)Hoch (abstrahiert mit Klassen & Funktionen)
LernkurveNiedrigMittel
Claude Code-KompatibilitätAusgezeichnetHervorragend

Für neue Projekte wird CDK TypeScript dringend empfohlen. Die Kompatibilität mit Claude Code ist hervorragend, und kombiniert mit Typvervollständigung entsteht qualitativ hochwertiger Code.


Schritt 1: Bestehende AWS-Ressourcen in CloudFormation umwandeln

Ein Muster für den Fall, dass Sie eine bestehende AWS-Umgebung nachträglich kodifizieren möchten.

claude -p "
Wandle folgende AWS-Konfiguration in ein CloudFormation-Template (YAML) um.

[Aktuelle Konfiguration]
- VPC: 10.0.0.0/16, 2 öffentliche Subnetze, 2 private Subnetze
- EC2: t3.medium, Amazon Linux 2023, im öffentlichen Subnetz
- RDS: MySQL 8.0, db.t3.micro, im privaten Subnetz
- ALB: HTTPS (ACM-Zertifikat), Weiterleitung zu EC2
- Sicherheitsgruppen: Erlaube 443 vom ALB, erlaube 3306 von EC2 zu RDS

[Anforderungen]
- Umgebung (dev/staging/prod) per Parameter umschaltbar
- Ressourcennamen mit Umgebungsname als Präfix versehen
- ALB-DNS-Name in CloudFormation Outputs ausgeben
"

Generiertes CloudFormation-Template (Auszug):

AWSTemplateFormatVersion: "2010-09-09"
Description: "Web Application Infrastructure"

Parameters:
  Environment:
    Type: String
    AllowedValues: [dev, staging, prod]
    Default: dev
  DBPassword:
    Type: String
    NoEcho: true  # Passwort maskieren

Resources:
  VPC:
    Type: AWS::EC2::VPC
    Properties:
      CidrBlock: 10.0.0.0/16
      EnableDnsHostnames: true
      Tags:
        - Key: Name
          Value: !Sub "${Environment}-vpc"

  PublicSubnet1:
    Type: AWS::EC2::Subnet
    Properties:
      VpcId: !Ref VPC
      CidrBlock: 10.0.1.0/24
      AvailabilityZone: !Select [0, !GetAZs ""]
      MapPublicIpOnLaunch: true
      Tags:
        - Key: Name
          Value: !Sub "${Environment}-public-1"

  # ALB-Sicherheitsgruppe
  ALBSecurityGroup:
    Type: AWS::EC2::SecurityGroup
    Properties:
      GroupDescription: ALB Security Group
      VpcId: !Ref VPC
      SecurityGroupIngress:
        - IpProtocol: tcp
          FromPort: 443
          ToPort: 443
          CidrIp: 0.0.0.0/0

Outputs:
  ALBDnsName:
    Value: !GetAtt ApplicationLoadBalancer.DNSName
    Export:
      Name: !Sub "${Environment}-alb-dns"

Schritt 2: Serverless-Stack mit CDK aufbauen

Mit CDK schreibt man in TypeScript, was die Wiederverwendung von Logik vereinfacht.

# CDK-Projekt initialisieren
mkdir my-infra && cd my-infra
npx cdk init app --language typescript

claude -p "
Implementiere folgende Serverless-Konfiguration in CDK TypeScript in lib/my-infra-stack.ts.

[Konfiguration]
- API Gateway (REST API) + Lambda (Node.js 20)
- DynamoDB-Tabelle (PAY_PER_REQUEST)
- S3-Bucket (privat, Versionierung aktiviert)
- CloudFront (S3-Ursprung, benutzerdefinierte Domain)
- DynamoDB-Tabellenname und S3-Bucket-Name als Lambda-Umgebungsvariablen übergeben
- Minimale IAM-Rolle automatisch an Lambda anhängen

Alle Ressourcen angemessen taggen,
in Produktion (NODE_ENV=production) Löschschutz aktivieren.
"

Generierter CDK-Code:

// lib/my-infra-stack.ts
import * as cdk from "aws-cdk-lib";
import * as lambda from "aws-cdk-lib/aws-lambda";
import * as apigateway from "aws-cdk-lib/aws-apigateway";
import * as dynamodb from "aws-cdk-lib/aws-dynamodb";
import * as s3 from "aws-cdk-lib/aws-s3";
import * as cloudfront from "aws-cdk-lib/aws-cloudfront";
import * as origins from "aws-cdk-lib/aws-cloudfront-origins";

export class MyInfraStack extends cdk.Stack {
  constructor(scope: cdk.App, id: string, props?: cdk.StackProps) {
    super(scope, id, props);

    const isProd = process.env.NODE_ENV === "production";

    // DynamoDB-Tabelle
    const table = new dynamodb.Table(this, "AppTable", {
      partitionKey: { name: "PK", type: dynamodb.AttributeType.STRING },
      sortKey: { name: "SK", type: dynamodb.AttributeType.STRING },
      billingMode: dynamodb.BillingMode.PAY_PER_REQUEST,
      pointInTimeRecovery: true,
      deletionProtection: isProd,
      removalPolicy: isProd ? cdk.RemovalPolicy.RETAIN : cdk.RemovalPolicy.DESTROY,
    });

    // S3-Bucket
    const bucket = new s3.Bucket(this, "AssetsBucket", {
      versioned: true,
      blockPublicAccess: s3.BlockPublicAccess.BLOCK_ALL,
      encryption: s3.BucketEncryption.S3_MANAGED,
      deletionProtection: isProd,
      removalPolicy: isProd ? cdk.RemovalPolicy.RETAIN : cdk.RemovalPolicy.DESTROY,
    });

    // Lambda-Funktion
    const apiLambda = new lambda.Function(this, "ApiLambda", {
      runtime: lambda.Runtime.NODEJS_20_X,
      handler: "index.handler",
      code: lambda.Code.fromAsset("src/lambda"),
      environment: {
        TABLE_NAME: table.tableName,
        BUCKET_NAME: bucket.bucketName,
        NODE_ENV: process.env.NODE_ENV ?? "development",
      },
      timeout: cdk.Duration.seconds(30),
      memorySize: 512,
    });

    // Minimale Berechtigungen an Lambda vergeben
    table.grantReadWriteData(apiLambda);
    bucket.grantReadWrite(apiLambda);

    // API Gateway
    const api = new apigateway.RestApi(this, "AppApi", {
      restApiName: "MyApp API",
      defaultCorsPreflightOptions: {
        allowOrigins: apigateway.Cors.ALL_ORIGINS,
        allowMethods: apigateway.Cors.ALL_METHODS,
      },
    });

    api.root.addProxy({
      defaultIntegration: new apigateway.LambdaIntegration(apiLambda),
    });

    // CloudFront
    const distribution = new cloudfront.Distribution(this, "Distribution", {
      defaultBehavior: {
        origin: new origins.S3Origin(bucket),
        viewerProtocolPolicy: cloudfront.ViewerProtocolPolicy.REDIRECT_TO_HTTPS,
      },
    });

    // Ausgabe
    new cdk.CfnOutput(this, "ApiUrl", { value: api.url });
    new cdk.CfnOutput(this, "CloudFrontUrl", { value: distribution.distributionDomainName });
  }
}

Schritt 3: Bestehende Stacks aktualisieren und Unterschiede prüfen

# Unterschiede vor dem Deployment prüfen
npx cdk diff

# Claude Code die Unterschiede erklären lassen
claude -p "
Lies diese cdk diff-Ausgabe und erkläre auf Deutsch, was sich geändert hat.
Gehe besonders auf Änderungen an Sicherheitsgruppen und IAM-Richtlinien ein.

$(npx cdk diff 2>&1)
"

Schritt 4: Multi-Stack-Architektur entwerfen

Infrastruktur in Produktionsgröße wird durch Aufteilen in mehrere Stacks verwaltet.

claude -p "
Entwirf folgende Multi-Stack-Konfiguration in CDK TypeScript.

[Stack-Aufteilung]
- NetworkStack: VPC, Subnetze, Sicherheitsgruppen
- DatabaseStack: RDS, ElastiCache (abhängig von NetworkStack)
- ApplicationStack: ECS, ALB, AutoScaling (abhängig von NetworkStack, DatabaseStack)
- MonitoringStack: CloudWatch-Dashboards, Alarme, SNS-Benachrichtigungen

Stack-Abhängigkeiten und Verwendung von CfnOutput / Fn.importValue einbeziehen.
"
// bin/app.ts
import * as cdk from "aws-cdk-lib";
import { NetworkStack } from "../lib/network-stack";
import { DatabaseStack } from "../lib/database-stack";
import { ApplicationStack } from "../lib/application-stack";
import { MonitoringStack } from "../lib/monitoring-stack";

const app = new cdk.App();
const env = { account: process.env.CDK_ACCOUNT, region: "eu-central-1" };

const network = new NetworkStack(app, "NetworkStack", { env });
const database = new DatabaseStack(app, "DatabaseStack", { env, vpc: network.vpc });
const application = new ApplicationStack(app, "ApplicationStack", {
  env,
  vpc: network.vpc,
  database: database.cluster,
});
new MonitoringStack(app, "MonitoringStack", {
  env,
  alb: application.alb,
  database: database.cluster,
});

Schritt 5: CloudFormation/CDK-Debugging an Claude Code delegieren

Bei Deployment-Fehlern kann Claude Code auch bei der Lösung helfen.

claude -p "
CDK deploy schlägt mit folgendem Fehler fehl.
Erkläre Ursache und Lösung:

$(npx cdk deploy 2>&1 | tail -30)
"

Häufige Fehlermuster:

  • ROLLBACK_COMPLETE: Vorheriges Deployment fehlgeschlagen, Stack beschädigt → cdk destroy ausführen, dann neu deployen
  • UPDATE_ROLLBACK_FAILED: Konflikt mit manuellen Änderungen → manuell in der AWS-Konsole beheben
  • Resource already exists: Namenskollision mit bestehender Ressource → Ressourcennamen ändern oder importieren

4 häufige Fallstricke

1. Löschschutz mit cdk destroy umgehen

In Entwicklungsumgebungen bleiben Ressourcen nach cdk destroy bestehen, wenn man removalPolicy: DESTROY nicht setzt. In Produktion RETAIN verwenden, um versehentliches Löschen zu verhindern.

2. CloudFormation-Drift-Erkennung ignorieren

Wenn Sie Ressourcen manuell in der AWS-Konsole ändern, weicht CloudFormation von der Realität ab (Drift). Führen Sie monatlich eine Drift-Erkennung in der CloudFormation-Konsole durch.

3. Geheimnisse direkt in Templates schreiben

# Schlecht: Passwort bleibt im Template
DBPassword: "mysecretpassword"

# Gut: Aus Secrets Manager oder Parameter Store abrufen
DBPassword: !Sub "{{resolve:secretsmanager:prod/db-password}}"

4. CDK-Versionsfixierung vernachlässigen

Wenn CDK-Versionen im Team nicht in package.json abgeglichen sind, entstehen Unterschiede. package-lock.json committen, um eine einheitliche Version sicherzustellen.


Zusammenfassung

AufgabeClaude Codes Beitrag
CloudFormation-GenerierungVollständiges YAML nur durch Beschreibung der Anforderungen
CDK-ImplementierungTypsicherer Infrastrukturcode in TypeScript
Stack-DesignMulti-Stack-Abhängigkeitsarchitektur
Diff-Erklärungcdk diff-Ausgabe auf Deutsch erklärt
DebuggingUrsache und Lösung aus Fehlerprotokollen

Infrastruktur als Code ist etwas, das wir alle wissen, dass wir es tun sollten, aber immer wieder aufschieben. Mit Claude Code beschreiben Sie einfach „die AWS-Konfiguration, die ich brauche” und das Template ist fertig — die Hürde zur IaC-Einführung sinkt dramatisch.

Verwandte Artikel

Referenzen

#claude-code #aws #cloudformation #cdk #iac #typescript

Bring deinen Claude-Code-Workflow aufs nächste Level

50 in der Praxis erprobte Prompt-Vorlagen zum direkten Copy-and-paste in Claude Code.

Kostenlos

Kostenloses PDF: Claude-Code-Spickzettel in 5 Minuten

Trag einfach deine E-Mail-Adresse ein – wir senden dir den A4-Spickzettel als PDF sofort zu.

Wir behandeln deine Daten sorgfältig und senden niemals Spam.

Masa

Über den Autor

Masa

Ingenieur, der Claude Code intensiv nutzt. Betreibt claudecode-lab.com, ein Tech-Medium in 10 Sprachen mit über 2.000 Seiten.