Présentation des AWS CDK piles - AWS Cloud Development Kit (AWS CDK) v2

Ceci est le guide du AWS CDK développeur de la version 2. L'ancienne CDK version 1 est entrée en maintenance le 1er juin 2022 et a pris fin le 1er juin 2023.

Les traductions sont fournies par des outils de traduction automatique. En cas de conflit entre le contenu d'une traduction et celui de la version originale en anglais, la version anglaise prévaudra.

Présentation des AWS CDK piles

Une AWS CDK pile est la plus petite unité de déploiement. Il représente un ensemble de AWS ressources que vous définissez à l'aide de CDK constructions. Lorsque vous déployez CDK des applications, les ressources d'une CDK pile sont déployées ensemble sous forme de AWS CloudFormation pile. Pour en savoir plus sur les AWS CloudFormation piles, consultez la section Gestion des AWS ressources en tant qu'unité unique avec des AWS CloudFormation piles dans le Guide de l'AWS CloudFormation utilisateur.

Vous définissez une pile en étendant ou en héritant de la Stack construction. L'exemple suivant est un modèle courant pour définir une CDK pile dans un fichier distinct, appelé fichier de pile. Ici, nous étendons ou héritons de la Stack classe et définissons un constructeur qui accepte scopeid, et. props Ensuite, nous invoquons le constructeur de la Stack classe de base en utilisant super avec le reçu scopeid, et props :

TypeScript
import * as cdk from 'aws-cdk-lib'; import { Construct } from 'constructs'; export class MyCdkStack extends cdk.Stack { constructor(scope: Construct, id: string, props?: cdk.StackProps) { super(scope, id, props); // Define your constructs here } }
JavaScript
const { Stack } = require('aws-cdk-lib'); class MyCdkStack extends Stack { constructor(scope, id, props) { super(scope, id, props); // Define your constructs here } } module.exports = { MyCdkStack }
Python
from aws_cdk import ( Stack, ) from constructs import Construct class MyCdkStack(Stack): def __init__(self, scope: Construct, construct_id: str, **kwargs) -> None: super().__init__(scope, construct_id, **kwargs) # Define your constructs here
Java
package com.myorg; import software.constructs.Construct; import software.amazon.awscdk.Stack; import software.amazon.awscdk.StackProps; public class MyCdkStack extends Stack { public MyCdkStack(final Construct scope, final String id) { this(scope, id, null); } public MyCdkStack(final Construct scope, final String id, final StackProps props) { super(scope, id, props); // Define your constructs here } }
C#
using Amazon.CDK; using Constructs; namespace MyCdk { public class MyCdkStack : Stack { internal MyCdkStack(Construct scope, string id, IStackProps props = null) : base(scope, id, props) { // Define your constructs here } } }
Go
package main import ( "github.com/aws/aws-cdk-go/awscdk/v2" "github.com/aws/constructs-go/constructs/v10" "github.com/aws/jsii-runtime-go" ) type CdkDemoAppStackProps struct { awscdk.StackProps } func NewCdkDemoAppStack(scope constructs.Construct, id string, props *CdkDemoAppStackProps) awscdk.Stack { var sprops awscdk.StackProps if props != nil { sprops = props.StackProps } stack := awscdk.NewStack(scope, &id, &sprops) // The code that defines your stack goes here return stack } func main() { defer jsii.Close() app := awscdk.NewApp(nil) NewCdkDemoAppStack(app, "CdkDemoAppStack", &CdkDemoAppStackProps{ awscdk.StackProps{ Env: env(), }, }) app.Synth(nil) } //...

L'exemple précédent a uniquement défini une pile. Pour créer la pile, celle-ci doit être instanciée dans le contexte de votre CDK application. Un modèle courant consiste à définir votre CDK application et à initialiser votre pile dans un fichier distinct, appelé fichier d'application.

Voici un exemple de création d'une CDK pile nomméeMyCdkStack. Ici, l'CDKapplication est créée et MyCdkStack instanciée dans le contexte de l'application :

TypeScript
#!/usr/bin/env node import 'source-map-support/register'; import * as cdk from 'aws-cdk-lib'; import { MyCdkStack } from '../lib/my-cdk-stack'; const app = new cdk.App(); new MyCdkStack(app, 'MyCdkStack', { });
JavaScript
#!/usr/bin/env node const cdk = require('aws-cdk-lib'); const { MyCdkStack } = require('../lib/my-cdk-stack'); const app = new cdk.App(); new MyCdkStack(app, 'MyCdkStack', { });
Python

Situé dans app.py :

#!/usr/bin/env python3 import os import aws_cdk as cdk from my_cdk.my_cdk_stack import MyCdkStack app = cdk.App() MyCdkStack(app, "MyCdkStack",) app.synth()
Java
package com.myorg; import software.amazon.awscdk.App; import software.amazon.awscdk.Environment; import software.amazon.awscdk.StackProps; import java.util.Arrays; public class MyCdkApp { public static void main(final String[] args) { App app = new App(); new MyCdkStack(app, "MyCdkStack", StackProps.builder() .build()); app.synth(); } }
C#
using Amazon.CDK; using System; using System.Collections.Generic; using System.Linq; namespace MyCdk { sealed class Program { public static void Main(string[] args) { var app = new App(); new MyCdkStack(app, "MyCdkStack", new StackProps {}); app.Synth(); } } }
Go
package main import ( "github.com/aws/aws-cdk-go/awscdk/v2" "github.com/aws/constructs-go/constructs/v10" "github.com/aws/jsii-runtime-go" ) // ... func main() { defer jsii.Close() app := awscdk.NewApp(nil) NewMyCdkStack(app, "MyCdkStack", &MyCdkStackProps{ awscdk.StackProps{ Env: env(), }, }) app.Synth(nil) } // ...

L'exemple suivant crée une CDK application contenant deux piles :

TypeScript
const app = new App(); new MyFirstStack(app, 'stack1'); new MySecondStack(app, 'stack2'); app.synth();
JavaScript
const app = new App(); new MyFirstStack(app, 'stack1'); new MySecondStack(app, 'stack2'); app.synth();
Python
app = App() MyFirstStack(app, 'stack1') MySecondStack(app, 'stack2') app.synth()
Java
App app = new App(); new MyFirstStack(app, "stack1"); new MySecondStack(app, "stack2"); app.synth();
C#
var app = new App(); new MyFirstStack(app, "stack1"); new MySecondStack(app, "stack2"); app.Synth();
Go
package main import ( "github.com/aws/aws-cdk-go/awscdk/v2" "github.com/aws/constructs-go/constructs/v10" "github.com/aws/jsii-runtime-go" ) type MyFirstStackProps struct { awscdk.StackProps } func NewMyFirstStack(scope constructs.Construct, id string, props *MyFirstStackProps) awscdk.Stack { var sprops awscdk.StackProps if props != nil { sprops = props.StackProps } myFirstStack := awscdk.NewStack(scope, &id, &sprops) // The code that defines your stack goes here return myFirstStack } type MySecondStackProps struct { awscdk.StackProps } func NewMySecondStack(scope constructs.Construct, id string, props *MySecondStackProps) awscdk.Stack { var sprops awscdk.StackProps if props != nil { sprops = props.StackProps } mySecondStack := awscdk.NewStack(scope, &id, &sprops) // The code that defines your stack goes here return mySecondStack } func main() { defer jsii.Close() app := awscdk.NewApp(nil) NewMyFirstStack(app, "MyFirstStack", &MyFirstStackProps{ awscdk.StackProps{ Env: env(), }, }) NewMySecondStack(app, "MySecondStack", &MySecondStackProps{ awscdk.StackProps{ Env: env(), }, }) app.Synth(nil) } // ...

À propos de la pile API

L'Stackobjet fournit un richeAPI, notamment les éléments suivants :

  • Stack.of(construct)— Méthode statique qui renvoie la pile dans laquelle une construction est définie. Ceci est utile si vous devez interagir avec une pile à partir d'une construction réutilisable. L'appel échoue si aucune pile n'est trouvée dans la portée.

  • stack.stackName(Python :stack_name) — Renvoie le nom physique de la pile. Comme mentionné précédemment, toutes les AWS CDK piles ont un nom physique qu'elles AWS CDK peuvent résoudre lors de la synthèse.

  • stack.regionet stack.account — Renvoie la AWS région et le compte, respectivement, dans lesquels cette pile sera déployée. Ces propriétés renvoient l'une des valeurs suivantes :

    • Le compte ou la région explicitement spécifié lors de la définition de la pile

    • Un jeton codé par chaîne qui résout les AWS CloudFormation pseudo-paramètres du compte et de la région pour indiquer que cette pile est indépendante de l'environnement

    Pour plus d'informations sur la manière dont les environnements sont déterminés pour les piles, consultezEnvironnements pour AWS CDK.

  • stack.addDependency(stack)(Python : stack.add_dependency(stack) — Peut être utilisé pour définir explicitement l'ordre de dépendance entre deux piles. Cet ordre est respecté par la cdk deploy commande lors du déploiement de plusieurs piles à la fois.

  • stack.tags— Renvoie un TagManagerque vous pouvez utiliser pour ajouter ou supprimer des balises au niveau de la pile. Ce gestionnaire de balises balise toutes les ressources de la pile et balise également la pile elle-même lorsqu'elle est créée AWS CloudFormation.

  • stack.partition, stack.urlSuffix (Python :url_suffix), stack.stackId (Python :stack_id) et stack.notificationArn (Python :notification_arn) — Renvoie des jetons qui se résolvent en AWS CloudFormation pseudo-paramètres respectifs, tels que{ "Ref": "AWS::Partition" }. Ces jetons sont associés à l'objet de pile spécifique afin que le AWS CDK framework puisse identifier les références entre piles.

  • stack.availabilityZones(Python :availability_zones) — Renvoie l'ensemble des zones de disponibilité disponibles dans l'environnement dans lequel cette pile est déployée. Pour les piles indépendantes de l'environnement, cela renvoie toujours une baie avec deux zones de disponibilité. Pour les piles spécifiques à un environnement, le AWS CDK interroge l'environnement et renvoie l'ensemble exact de zones de disponibilité disponibles dans la région que vous avez spécifiée.

  • stack.parseArn(arn)and stack.formatArn(comps) (Python :parse_arn,format_arn) — Peut être utilisé pour travailler avec Amazon Resource Names (ARNs).

  • stack.toJsonString(obj)(Python :to_json_string) — Peut être utilisé pour formater un objet arbitraire sous forme de JSON chaîne pouvant être incorporée dans un AWS CloudFormation modèle. L'objet peut inclure des jetons, des attributs et des références, qui ne sont résolus que lors du déploiement.

  • stack.templateOptions(Python :template_options) — À utiliser pour spécifier les options du AWS CloudFormation modèle, telles que Transform, Description et Metadata, pour votre pile.

Utilisation des piles

Les piles sont déployées sous forme de AWS CloudFormation pile dans un AWS environnement. L'environnement couvre un domaine spécifique Compte AWS et Région AWS.

Lorsque vous exécutez la cdk synth commande pour une application comportant plusieurs piles, l'assemblage cloud inclut un modèle distinct pour chaque instance de pile. Même si les deux piles sont des instances de la même classe, elles sont émises AWS CDK sous forme de deux modèles individuels.

Vous pouvez synthétiser chaque modèle en spécifiant le nom de la pile dans la cdk synth commande. L'exemple suivant synthétise le modèle pour stack1 :

$ cdk synth stack1

Cette approche est conceptuellement différente de la façon dont les AWS CloudFormation modèles sont normalement utilisés, où un modèle peut être déployé plusieurs fois et paramétré par le biais de paramètres.AWS CloudFormation Bien que AWS CloudFormation les paramètres puissent être définis dans le AWS CDK, ils sont généralement déconseillés car AWS CloudFormation les paramètres ne sont résolus que lors du déploiement. Cela signifie que vous ne pouvez pas déterminer leur valeur dans votre code.

Par exemple, pour inclure de manière conditionnelle une ressource dans votre application en fonction d'une valeur de paramètre, vous devez définir une AWS CloudFormation condition et l'associer à la ressource. AWS CDK Il adopte une approche dans laquelle les modèles concrets sont résolus au moment de la synthèse. Par conséquent, vous pouvez utiliser une if instruction pour vérifier la valeur afin de déterminer si une ressource doit être définie ou si un comportement doit être appliqué.

Note

AWS CDK Il fournit autant de résolution que possible pendant le temps de synthèse afin de permettre une utilisation idiomatique et naturelle de votre langage de programmation.

Comme toute autre construction, les piles peuvent être composées en groupes. Le code suivant montre un exemple de service composé de trois piles : un plan de contrôle, un plan de données et des piles de surveillance. La structure du service est définie deux fois : une fois pour l'environnement bêta et une fois pour l'environnement de production.

TypeScript
import { App, Stack } from 'aws-cdk-lib'; import { Construct } from 'constructs'; interface EnvProps { prod: boolean; } // imagine these stacks declare a bunch of related resources class ControlPlane extends Stack {} class DataPlane extends Stack {} class Monitoring extends Stack {} class MyService extends Construct { constructor(scope: Construct, id: string, props?: EnvProps) { super(scope, id); // we might use the prod argument to change how the service is configured new ControlPlane(this, "cp"); new DataPlane(this, "data"); new Monitoring(this, "mon"); } } const app = new App(); new MyService(app, "beta"); new MyService(app, "prod", { prod: true }); app.synth();
JavaScript
const { App, Stack } = require('aws-cdk-lib'); const { Construct } = require('constructs'); // imagine these stacks declare a bunch of related resources class ControlPlane extends Stack {} class DataPlane extends Stack {} class Monitoring extends Stack {} class MyService extends Construct { constructor(scope, id, props) { super(scope, id); // we might use the prod argument to change how the service is configured new ControlPlane(this, "cp"); new DataPlane(this, "data"); new Monitoring(this, "mon"); } } const app = new App(); new MyService(app, "beta"); new MyService(app, "prod", { prod: true }); app.synth();
Python
from aws_cdk import App, Stack from constructs import Construct # imagine these stacks declare a bunch of related resources class ControlPlane(Stack): pass class DataPlane(Stack): pass class Monitoring(Stack): pass class MyService(Construct): def __init__(self, scope: Construct, id: str, *, prod=False): super().__init__(scope, id) # we might use the prod argument to change how the service is configured ControlPlane(self, "cp") DataPlane(self, "data") Monitoring(self, "mon") app = App(); MyService(app, "beta") MyService(app, "prod", prod=True) app.synth()
Java
package com.myorg; import software.amazon.awscdk.App; import software.amazon.awscdk.Stack; import software.constructs.Construct; public class MyApp { // imagine these stacks declare a bunch of related resources static class ControlPlane extends Stack { ControlPlane(Construct scope, String id) { super(scope, id); } } static class DataPlane extends Stack { DataPlane(Construct scope, String id) { super(scope, id); } } static class Monitoring extends Stack { Monitoring(Construct scope, String id) { super(scope, id); } } static class MyService extends Construct { MyService(Construct scope, String id) { this(scope, id, false); } MyService(Construct scope, String id, boolean prod) { super(scope, id); // we might use the prod argument to change how the service is configured new ControlPlane(this, "cp"); new DataPlane(this, "data"); new Monitoring(this, "mon"); } } public static void main(final String argv[]) { App app = new App(); new MyService(app, "beta"); new MyService(app, "prod", true); app.synth(); } }
C#
using Amazon.CDK; using Constructs; // imagine these stacks declare a bunch of related resources public class ControlPlane : Stack { public ControlPlane(Construct scope, string id=null) : base(scope, id) { } } public class DataPlane : Stack { public DataPlane(Construct scope, string id=null) : base(scope, id) { } } public class Monitoring : Stack { public Monitoring(Construct scope, string id=null) : base(scope, id) { } } public class MyService : Construct { public MyService(Construct scope, string id, Boolean prod=false) : base(scope, id) { // we might use the prod argument to change how the service is configured new ControlPlane(this, "cp"); new DataPlane(this, "data"); new Monitoring(this, "mon"); } } class Program { static void Main(string[] args) { var app = new App(); new MyService(app, "beta"); new MyService(app, "prod", prod: true); app.Synth(); } }
Go
package main import ( "github.com/aws/aws-cdk-go/awscdk/v2" "github.com/aws/constructs-go/constructs/v10" "github.com/aws/jsii-runtime-go" ) type ControlPlaneStackProps struct { awscdk.StackProps } func NewControlPlaneStack(scope constructs.Construct, id string, props *ControlPlaneStackProps) awscdk.Stack { var sprops awscdk.StackProps if props != nil { sprops = props.StackProps } ControlPlaneStack := awscdk.NewStack(scope, jsii.String(id), &sprops) // The code that defines your stack goes here return ControlPlaneStack } type DataPlaneStackProps struct { awscdk.StackProps } func NewDataPlaneStack(scope constructs.Construct, id string, props *DataPlaneStackProps) awscdk.Stack { var sprops awscdk.StackProps if props != nil { sprops = props.StackProps } DataPlaneStack := awscdk.NewStack(scope, jsii.String(id), &sprops) // The code that defines your stack goes here return DataPlaneStack } type MonitoringStackProps struct { awscdk.StackProps } func NewMonitoringStack(scope constructs.Construct, id string, props *MonitoringStackProps) awscdk.Stack { var sprops awscdk.StackProps if props != nil { sprops = props.StackProps } MonitoringStack := awscdk.NewStack(scope, jsii.String(id), &sprops) // The code that defines your stack goes here return MonitoringStack } type MyServiceStackProps struct { awscdk.StackProps Prod bool } func NewMyServiceStack(scope constructs.Construct, id string, props *MyServiceStackProps) awscdk.Stack { var sprops awscdk.StackProps if props != nil { sprops = props.StackProps } MyServiceStack := awscdk.NewStack(scope, jsii.String(id), &sprops) NewControlPlaneStack(MyServiceStack, "cp", &ControlPlaneStackProps{ StackProps: sprops, }) NewDataPlaneStack(MyServiceStack, "data", &DataPlaneStackProps{ StackProps: sprops, }) NewMonitoringStack(MyServiceStack, "mon", &MonitoringStackProps{ StackProps: sprops, }) return MyServiceStack } func main() { defer jsii.Close() app := awscdk.NewApp(nil) betaProps := MyServiceStackProps{ StackProps: awscdk.StackProps{ Env: env(), }, Prod: false, } NewMyServiceStack(app, "beta", &betaProps) prodProps := MyServiceStackProps{ StackProps: awscdk.StackProps{ Env: env(), }, Prod: true, } NewMyServiceStack(app, "prod", &prodProps) app.Synth(nil) } // ...

Cette AWS CDK application se compose finalement de six piles, trois pour chaque environnement :

$ cdk ls betacpDA8372D3 betadataE23DB2BA betamon632BD457 prodcp187264CE proddataF7378CE5 prodmon631A1083

Les noms physiques des AWS CloudFormation piles sont automatiquement déterminés en AWS CDK fonction du chemin de construction de la pile dans l'arbre. Par défaut, le nom d'une pile est dérivé de l'ID de construction de l'Stackobjet. Cependant, vous pouvez spécifier un nom explicite en utilisant l'stackNameaccessoire (en Pythonstack_name), comme suit.

TypeScript
new MyStack(this, 'not:a:stack:name', { stackName: 'this-is-stack-name' });
JavaScript
new MyStack(this, 'not:a:stack:name', { stackName: 'this-is-stack-name' });
Python
MyStack(self, "not:a:stack:name", stack_name="this-is-stack-name")
Java
new MyStack(this, "not:a:stack:name", StackProps.builder() .StackName("this-is-stack-name").build());
C#
new MyStack(this, "not:a:stack:name", new StackProps { StackName = "this-is-stack-name" });

Utilisation des piles imbriquées

Une pile imbriquée est une CDK pile que vous créez à l'intérieur d'une autre pile, connue sous le nom de pile parent. Vous créez des piles imbriquées à l'aide de cette construction. NestedStack

En utilisant des piles imbriquées, vous pouvez organiser les ressources sur plusieurs piles. Les piles imbriquées permettent également de contourner la limite de AWS CloudFormation 500 ressources pour les piles. Une pile imbriquée est considérée comme une seule ressource dans la pile qui la contient. Cependant, il peut contenir jusqu'à 500 ressources, y compris des piles imbriquées supplémentaires.

La portée d'une pile imbriquée doit être une NestedStack construction Stack or. La pile imbriquée n'a pas besoin d'être déclarée de manière lexicale dans sa pile parent. Il suffit de passer la pile parent comme premier paramètre (scope) lors de l'instanciation de la pile imbriquée. Hormis cette restriction, la définition des constructions dans une pile imbriquée fonctionne exactement de la même manière que dans une pile ordinaire.

Au moment de la synthèse, la pile imbriquée est synthétisée dans son propre AWS CloudFormation modèle, qui est téléchargé dans le compartiment AWS CDK intermédiaire lors du déploiement. Les piles imbriquées sont liées à leur pile parent et ne sont pas traitées comme des artefacts de déploiement indépendants. Ils ne sont pas répertoriés par cdk list et ne peuvent pas être déployés parcdk deploy.

Les références entre les piles parentes et les piles imbriquées sont automatiquement traduites en paramètres de pile et en sorties dans les AWS CloudFormation modèles générés, comme pour toute référence entre piles.

Avertissement

Les modifications apportées à la posture de sécurité ne sont pas affichées avant le déploiement pour les piles imbriquées. Ces informations ne sont affichées que pour les piles de niveau supérieur.