Salta ai contenuti

Infrastruttura CDK

AWS CDK è un framework per definire l’infrastruttura cloud nel codice e fornirla tramite AWS CloudFormation.

Il generatore di infrastruttura TypeScript crea un’applicazione di infrastruttura AWS CDK scritta in TypeScript. L’applicazione generata include le best practice di sicurezza tramite controlli di sicurezza Checkov.

Puoi generare un nuovo progetto di infrastruttura in due modi:

Terminal window
pnpm nx g @aws/nx-plugin:ts#infra
Puoi anche eseguire una prova per vedere quali file verrebbero modificati
Terminal window
pnpm nx g @aws/nx-plugin:ts#infra --dry-run
ParametroTipoPredefinitoDescrizione
name Obbligatoriostring-Il nome dell'applicazione.
directory stringpackagesLa directory della nuova applicazione.
subDirectory string-La sottodirectory in cui viene posizionato il progetto. Per impostazione predefinita corrisponde al nome del progetto.
stageConfig booleanAbilita la configurazione centralizzata degli stage (credenziali, account, regione) per deployment CDK multi-ambiente.
preferInstallDependencies booleantrueSe preferire l'installazione delle dipendenze dopo l'esecuzione del generatore. Impostare su false per rimandare l'installazione quando si eseguono più generatori in batch (l'installazione viene comunque eseguita se necessaria affinché i generatori successivi possano calcolare il grafo dei progetti Nx); installare una volta alla fine.

Il generatore creerà la seguente struttura di progetto nella directory <directory>/<name>:

  • Directorysrc
    • main.ts Application entry point instantiating CDK stages to deploy
    • Directorystages CDK Stage definitions
      • application-stage.ts Defines a collection of stacks to deploy in a stage
    • Directorystacks CDK Stack definitions
      • application-stack.ts Main application stack
  • cdk.json CDK configuration
  • package.json Project manifest defining the project’s package name and dependencies
  • project.json Project configuration and build targets
  • checkov.yml Checkov configuration file

Se imposti l’opzione stageConfig, il generatore crea anche due pacchetti condivisi per la gestione centralizzata delle credenziali (se non esistono già):

  • Directorypackages/common
    • Directoryinfra-config Stage configuration types and credential mappings
      • Directorysrc
        • stages.types.ts Type definitions for stage credentials and config
        • stages.config.ts Your stage-to-credential mappings (edit this)
        • index.ts Re-exports for importing from other packages
    • Directoryscripts Centralized deploy/destroy scripts
      • Directorysrc
        • infra-deploy.ts Deploy bin script
        • infra-destroy.ts Destroy bin script
        • Directorystage-credentials/ Shared logic (credential lookup, CDK command building)

Puoi iniziare a scrivere la tua infrastruttura CDK all’interno di src/stacks/application-stack.ts, ad esempio:

src/stacks/application-stack.ts
import { Stack, StackProps } from 'aws-cdk-lib';
import { Bucket } from 'aws-cdk-lib/aws-s3'
import { Construct } from 'constructs';
export class ApplicationStack extends Stack {
constructor(scope: Construct, id: string, props?: StackProps) {
super(scope, id, props);
// Declare your infrastructure here
new Bucket(this, 'MyBucket');
}
}

CDK utilizza gli Stage per raggruppare gli stack che dovrebbero essere distribuiti insieme in un ambiente specifico. Il file src/main.ts generato crea uno stage sandbox per il tuo sviluppo e test personale:

src/main.ts
new ApplicationStage(app, 'my-app-sandbox', {
env: {
account: process.env.CDK_DEFAULT_ACCOUNT,
region: process.env.CDK_DEFAULT_REGION,
},
});
// Define other instances of stages, such as beta and prod, below

La proprietà env indica a CDK in quale account AWS e regione distribuire. CDK_DEFAULT_ACCOUNT e CDK_DEFAULT_REGION vengono risolti automaticamente dalla CLI CDK dalle tue credenziali AWS attive. Consulta la documentazione sugli ambienti CDK per maggiori dettagli.

Lo stage sandbox è quello che il target deploy-sandbox distribuisce.

Se hai generato con stageConfig, il file main.ts legge l’account e la regione da un file di configurazione centralizzato, ricorrendo alle variabili d’ambiente quando non è impostata alcuna configurazione:

src/main.ts (with stageConfig)
import { resolveStage } from '@my-scope/common-infra-config';
// Looks up the stage under this project (packages/infra), falling back to
// shared stages. Returns undefined when no config exists for the stage.
const sandboxConfig = resolveStage('packages/infra', 'my-app-sandbox');
new ApplicationStage(app, 'my-app-sandbox', {
env: {
account: sandboxConfig?.account ?? process.env.CDK_DEFAULT_ACCOUNT,
region: sandboxConfig?.region ?? process.env.CDK_DEFAULT_REGION,
},
});

Puoi aggiungere più stage per distribuire in ambienti diversi. Ad esempio, stage beta e prod che puntano ad account AWS separati:

src/main.ts
new ApplicationStage(app, 'project-beta', {
env: {
account: '123456789012',
region: 'us-west-2',
},
});
new ApplicationStage(app, 'project-prod', {
env: {
account: '098765432109',
region: 'us-west-2',
},
});

Uno Stage raggruppa uno o più stack. Puoi aggiungere tutti gli stack di cui hai bisogno all’interno di uno stage:

src/stages/application-stage.ts
import { Stage, StageProps } from 'aws-cdk-lib';
import { Construct } from 'constructs';
import { BackendStack } from '../stacks/backend-stack.js';
import { FrontendStack } from '../stacks/frontend-stack.js';
export class ApplicationStage extends Stage {
constructor(scope: Construct, id: string, props?: StageProps) {
super(scope, id, props);
new BackendStack(this, 'Backend', {
crossRegionReferences: true,
})
new FrontendStack(this, 'Frontend', {
crossRegionReferences: true,
});
}
}

Quando hai più stage che puntano a diversi account AWS, gestire le credenziali manualmente può essere soggetto a errori, specialmente man mano che il numero di stage cresce.

L’opzione stageConfig risolve questo problema generando due pacchetti condivisi:

  • packages/common/infra-config — Un singolo file di configurazione in cui mappi ogni stage alle sue credenziali AWS, account e regione. Questo è importabile da qualsiasi pacchetto nel tuo workspace, quindi il tuo main.ts CDK può leggere account e regione dalla stessa fonte di verità.
  • packages/common/scripts — Comandi infra-deploy e infra-destroy che avvolgono CDK con risoluzione automatica delle credenziali. Quando esegui deploy, lo script legge la configurazione, imposta le variabili d’ambiente AWS corrette per il processo figlio CDK ed esegue cdk deploy. Il tuo ambiente shell non viene mai modificato.

Modifica packages/common/infra-config/src/stages.config.ts per mappare i tuoi stage alle credenziali AWS:

packages/common/infra-config/src/stages.config.ts
import type { StagesConfig } from './stages.types.js';
const config: StagesConfig = {
projects: {
// The key is the project path relative to the workspace root.
// This matches the path in project.json and in deploy commands.
'packages/infra': {
stages: {
// Stage names must match the CDK stage identifiers in main.ts
// (the first argument to `new ApplicationStage(app, 'my-app-dev', ...)`).
'my-app-dev': {
credentials: { type: 'profile', profile: 'dev-account' },
region: 'us-east-1',
},
'my-app-prod': {
credentials: {
type: 'assumeRole',
assumeRole: 'arn:aws:iam::123456789012:role/DeployRole',
},
region: 'us-west-2',
account: '123456789012',
},
},
},
},
shared: {
// Shared stages are available to all infra projects.
// Project-specific entries take priority over shared ones.
stages: {
sandbox: {
credentials: { type: 'profile', profile: 'personal-sandbox' },
region: 'us-east-1',
},
},
},
};
export default config;

Quando distribuisci, ad esempio:

Terminal window
pnpm nx deploy infra my-app-dev/*

Lo script di distribuzione:

  1. Estrae il nome dello stage my-app-dev dagli argomenti del comando
  2. Cerca le credenziali nella configurazione: prima sotto projects['packages/infra'], poi sotto shared
  3. Se trovate, imposta AWS_PROFILE (o assume il ruolo IAM) solo per il processo figlio CDK
  4. Se non trovate, ricorre a qualsiasi credenziale AWS presente nel tuo ambiente

Ciò significa che i flussi di lavoro esistenti senza alcuna configurazione continuano a funzionare — lo script applica le credenziali solo quando trova una voce corrispondente.

Sono supportate due strategie di credenziali:

  • profile — Utilizza un profilo AWS CLI nominato da ~/.aws/config. Lo script imposta AWS_PROFILE per il processo CDK.
  • assumeRole — Chiama STS AssumeRole con l’ARN del ruolo specificato e passa le credenziali temporanee a CDK. Puoi opzionalmente specificare un profile come credenziali di origine per la chiamata AssumeRole, un externalId per le policy di trust cross-account e una sessionDuration in secondi.

Ogni configurazione di stage include una region obbligatoria e un account opzionale:

  • region (obbligatorio) — La regione AWS in cui distribuire (ad esempio, us-east-1, eu-west-2).
  • account (opzionale) — L’ID dell’account AWS. Se omesso, CDK lo deduce dalle credenziali attive al momento della distribuzione. Consulta la documentazione sugli ambienti CDK per come CDK risolve account e regione.

Il file main.ts generato legge questi valori dalla configurazione in modo che la sintesi e la distribuzione CDK utilizzino le stesse impostazioni di ambiente:

src/main.ts
const sandboxConfig = resolveStage('packages/infra', 'my-app-sandbox');
new ApplicationStage(app, 'my-app-sandbox', {
env: {
account: sandboxConfig?.account ?? process.env.CDK_DEFAULT_ACCOUNT,
region: sandboxConfig?.region ?? process.env.CDK_DEFAULT_REGION,
},
});

Gli stage condivisi (sotto shared.stages) si applicano a qualsiasi progetto di infrastruttura nel workspace. Questo è utile quando più progetti distribuiscono nello stesso account sandbox — definisci le credenziali una volta invece di ripeterle per ogni progetto.

Gli stage specifici del progetto (sotto projects['packages/infra'].stages) si applicano solo a quel progetto. Quando entrambi esistono per lo stesso nome di stage, la voce specifica del progetto ha la priorità.

Se hai utilizzato i generatori tRPC API o FastAPI per creare API, noterai che hai già alcuni construct disponibili in packages/common/constructs per distribuirli.

Se, ad esempio, hai creato un’API tRPC chiamata my-api, puoi semplicemente importare e istanziare il construct per aggiungere tutta l’infrastruttura necessaria per distribuirla:

src/stacks/application-stack.ts
import { Stack, StackProps } from 'aws-cdk-lib';
import { Construct } from 'constructs';
import { MyApi } from '@my-scope/common-constructs';
export class ApplicationStack extends Stack {
constructor(scope: Construct, id: string, props?: StackProps) {
super(scope, id, props);
// Add infrastructure for your API
new MyApi(this, 'MyApi', {
integrations: MyApi.defaultIntegrations(this).build(),
});
}
}

Se hai utilizzato il generatore React Website, noterai che hai già un construct in packages/common/constructs per distribuirlo. Ad esempio:

src/stacks/application-stack.ts
import { Stack, StackProps } from 'aws-cdk-lib';
import { Construct } from 'constructs';
import { MyWebsite } from '@my-scope/common-constructs';
export class ApplicationStack extends Stack {
constructor(scope: Construct, id: string, props?: StackProps) {
super(scope, id, props);
// Add infrastructure for your website
new MyWebsite(this, 'MyWebsite');
}
}

Come parte del tuo target build, oltre all’esecuzione dei target predefiniti di compilazione, lint e test, il tuo progetto di infrastruttura viene sintetizzato in CloudFormation. Questo può anche essere eseguito in modo autonomo, eseguendo il target synth:

Terminal window
pnpm nx synth <my-infra>

Troverai il tuo cloud assembly sintetizzato nella cartella dist principale, sotto dist/packages/<my-infra-project>/cdk.out.

Un target checkov viene aggiunto al tuo progetto che esegue controlli di sicurezza sulla tua infrastruttura utilizzando Checkov.

Terminal window
pnpm nx checkov <my-infra>

Troverai i risultati dei test di sicurezza nella cartella dist principale, sotto dist/packages/<my-infra-project>/checkov.

Potrebbero esserci casi in cui desideri sopprimere determinate regole su risorse. Puoi farlo in due modi:

import { suppressRules } from '@my-scope/common-constructs';
// suppresses the CKV_AWS_XXX for the given construct.
suppressRules(construct, ['CKV_AWS_XXX'], 'Reason');
import { suppressRules } from '@my-scope/common-constructs';
// Supresses the CKV_AWS_XXX for the construct or any of its descendants if it is an instance of Bucket
suppressRules(construct, ['CKV_AWS_XXX'], 'Reason', (construct) => construct instanceof Bucket);

Se stai distribuendo un’applicazione CDK in un account AWS per la prima volta, dovrà essere sottoposto a bootstrap. Il bootstrap crea le risorse di cui CDK ha bisogno per gestire le distribuzioni (un bucket S3 per gli asset, ruoli IAM, ecc.).

Innanzitutto, assicurati di aver configurato le credenziali per il tuo account AWS.

Successivamente, esegui il comando bootstrap per ogni account e regione in cui prevedi di distribuire:

Terminal window
npx cdk bootstrap aws://<account-id>/<region>

Per maggiori dettagli, consulta la documentazione sul bootstrap CDK.

Il tuo progetto ha tre target di distribuzione, ciascuno adatto a una situazione diversa:

TargetUsalo per
deploy-sandboxDistribuire il tuo stage sandbox personale durante lo sviluppo. Non è necessario un argomento stage.
deployDistribuire qualsiasi stage, nominando lo stage o gli stack che desideri.
deploy-ciDistribuire da una pipeline CI/CD, utilizzando un cloud assembly pre-sintetizzato.

Innanzitutto, assicurati di aver configurato le credenziali AWS. Se hai generato con stageConfig e hai configurato le credenziali degli stage in packages/common/infra-config/src/stages.config.ts, il comando deploy risolverà e applicherà automaticamente le credenziali corrette per lo stage di destinazione. Altrimenti, assicurati che le tue credenziali AWS siano impostate nel tuo ambiente (ad esempio, tramite AWS_PROFILE o variabili d’ambiente). Consulta la documentazione sulle credenziali AWS per le opzioni disponibili.

Il target deploy-sandbox distribuisce lo stage sandbox che main.ts dichiara, quindi non devi ricordare il suo nome di stage:

Terminal window
pnpm nx deploy-sandbox <my-infra>

Questo è il modo più rapido per ottenere la tua copia dell’applicazione in esecuzione su AWS mentre sviluppi.

Il target deploy distribuisce qualsiasi stage o stack tu nomini. Usalo per stage diversi dal tuo sandbox, o per distribuire un singolo stack:

Terminal window
pnpm nx deploy <my-infra> <my-infra>-sandbox/*

Puoi specificare qualsiasi stage purché sia definito in main.ts. Per distribuire un singolo stack, fornisci il nome completo dello stack:

Terminal window
pnpm nx deploy <my-infra> <my-infra>-sandbox/Application

Usa il target deploy-ci se stai distribuendo su AWS come parte di una pipeline CI/CD.

Terminal window
pnpm nx deploy-ci <my-infra> my-stage/*

Questo target differisce leggermente dal target deploy normale in quanto distribuisce un cloud assembly pre-sintetizzato piuttosto che sintetizzare al volo. Questo evita potenziali non-determinismi da cambiamenti di versione dei pacchetti, assicurando che ogni fase della pipeline distribuisca utilizzando lo stesso cloud assembly.

Usa il target destroy per smantellare le tue risorse:

Terminal window
pnpm nx destroy <my-infra> <my-infra>-sandbox/*

Per ulteriori informazioni su CDK, consulta la Guida per sviluppatori CDK e il Riferimento API.