Kontinuierliche Integration und Bereitstellung (CI/CD) mithilfe von CDK Pipelines - AWS Cloud Development Kit (AWS CDK) v2

Dies ist der AWS CDK v2-Entwicklerhandbuch. Die ältere CDK Version 1 wurde am 1. Juni 2022 in die Wartung aufgenommen und der Support wurde am 1. Juni 2023 eingestellt.

Die vorliegende Übersetzung wurde maschinell erstellt. Im Falle eines Konflikts oder eines Widerspruchs zwischen dieser übersetzten Fassung und der englischen Fassung (einschließlich infolge von Verzögerungen bei der Übersetzung) ist die englische Fassung maßgeblich.

Kontinuierliche Integration und Bereitstellung (CI/CD) mithilfe von CDK Pipelines

Verwenden Sie das Modul CDK Pipelines aus der AWS Construct Library, um die kontinuierliche Bereitstellung von AWS CDK Anwendungen zu konfigurieren. Wenn Sie den Quellcode Ihrer CDK-App in AWS CodeCommit, oder AWS CodeStarübertragenGitHub, kann CDK Pipelines Ihre neue Version automatisch erstellen, testen und bereitstellen.

CDK Pipelines aktualisieren sich selbst. Wenn Sie Anwendungsstufen oder Stacks hinzufügen, konfiguriert sich die Pipeline automatisch neu, um diese neuen Stufen oder Stacks bereitzustellen.

Anmerkung

CDK Pipelines unterstützt zwei APIs. Eine davon ist die ursprüngliche API, die in der CDK Pipelines Developer Preview zur Verfügung gestellt wurde. Die andere ist eine moderne API, die das Feedback von CDK-Kunden aus der Vorschauphase berücksichtigt. Die Beispiele in diesem Thema verwenden die moderne API. Einzelheiten zu den Unterschieden zwischen den beiden unterstützten APIs finden Sie unter Original-API von CDK Pipelines im GitHubaws-cdk-Repository.

Bootstrap für Ihre Umgebungen AWS

Bevor Sie CDK Pipelines verwenden können, müssen Sie die AWS Umgebung, in der Sie Ihre Stacks bereitstellen, booten.

Eine CDK-Pipeline umfasst mindestens zwei Umgebungen. In der ersten Umgebung wird die Pipeline bereitgestellt. In der zweiten Umgebung möchten Sie die Stacks oder Stages der Anwendung bereitstellen (Stages sind Gruppen verwandter Stacks). Diese Umgebungen können identisch sein, eine bewährte Methode besteht jedoch darin, die Stufen in verschiedenen Umgebungen voneinander zu isolieren.

Anmerkung

AWS CDK BootstrappingWeitere Informationen zu den Arten von Ressourcen, die durch Bootstrapping erstellt werden, und zur Anpassung des Bootstrap-Stacks finden Sie unter.

Für die kontinuierliche Bereitstellung mit CDK Pipelines muss Folgendes im CDK Toolkit-Stack enthalten sein:

  • Ein Amazon Simple Storage Service (Amazon S3) -Bucket.

  • Ein Amazon ECR-Repository.

  • IAM-Rollen, um den verschiedenen Teilen einer Pipeline die erforderlichen Berechtigungen zu erteilen.

Das CDK Toolkit aktualisiert Ihren vorhandenen Bootstrap-Stack oder erstellt bei Bedarf einen neuen.

Um eine Umgebung zu booten, die eine AWS CDK Pipeline bereitstellen kann, rufen Sie sie cdk bootstrap wie im folgenden Beispiel gezeigt auf. Wenn Sie das AWS CDK Toolkit über den npx Befehl aufrufen, wird es bei Bedarf vorübergehend installiert. Es wird auch die Version des Toolkits verwenden, die im aktuellen Projekt installiert ist, falls eine existiert.

--cloudformation-execution-policiesgibt den ARN einer Richtlinie an, unter der future CDK-Pipeline-Bereitstellungen ausgeführt werden. Die AdministratorAccess Standardrichtlinie stellt sicher, dass Ihre Pipeline jeden Ressourcentyp bereitstellen kann. AWS Wenn Sie diese Richtlinie verwenden, stellen Sie sicher, dass Sie dem gesamten Code und den Abhängigkeiten vertrauen, aus denen Ihre AWS CDK App besteht.

Die meisten Organisationen schreiben strengere Kontrollen darüber vor, welche Ressourcen automatisiert eingesetzt werden können. Erkundigen Sie sich bei der zuständigen Abteilung Ihres Unternehmens nach den Richtlinien, die für Ihre Pipeline gelten sollen.

Sie können die --profile Option weglassen, wenn Ihr AWS Standardprofil die erforderliche Authentifizierungskonfiguration und AWS-Region enthält.

macOS/Linux
npx cdk bootstrap aws://ACCOUNT-NUMBER/REGION --profile ADMIN-PROFILE \ --cloudformation-execution-policies arn:aws:iam::aws:policy/AdministratorAccess
Windows
npx cdk bootstrap aws://ACCOUNT-NUMBER/REGION --profile ADMIN-PROFILE ^ --cloudformation-execution-policies arn:aws:iam::aws:policy/AdministratorAccess

Verwenden Sie stattdessen die folgenden Befehle, um zusätzliche Umgebungen zu starten, in denen AWS CDK Anwendungen über die Pipeline bereitgestellt werden. Die --trust Option gibt an, welches andere Konto über Berechtigungen zum Bereitstellen von AWS CDK Anwendungen in dieser Umgebung verfügen soll. Geben Sie für diese Option die AWS Konto-ID der Pipeline an.

Auch hier können Sie die --profile Option weglassen, wenn Ihr AWS Standardprofil die erforderliche Authentifizierungskonfiguration und AWS-Region enthält.

macOS/Linux
npx cdk bootstrap aws://ACCOUNT-NUMBER/REGION --profile ADMIN-PROFILE \ --cloudformation-execution-policies arn:aws:iam::aws:policy/AdministratorAccess \ --trust PIPELINE-ACCOUNT-NUMBER
Windows
npx cdk bootstrap aws://ACCOUNT-NUMBER/REGION --profile ADMIN-PROFILE ^ --cloudformation-execution-policies arn:aws:iam::aws:policy/AdministratorAccess ^ --trust PIPELINE-ACCOUNT-NUMBER
Tipp

Verwenden Sie Administratoranmeldedaten nur für das Bootstrap und die Bereitstellung der ersten Pipeline. Verwenden Sie anschließend die Pipeline selbst, nicht Ihren lokalen Computer, um Änderungen bereitzustellen.

Wenn Sie eine ältere Bootstrap-Umgebung aktualisieren, ist der vorherige Amazon S3 S3-Bucket verwaist, wenn der neue Bucket erstellt wird. Löschen Sie es manuell mithilfe der Amazon S3 S3-Konsole.

Schützen Sie Ihren Bootstrap-Stack vor dem Löschen

Wenn ein Bootstrap-Stack gelöscht wird, werden die AWS Ressourcen, die ursprünglich in der Umgebung zur Unterstützung von CDK-Bereitstellungen bereitgestellt wurden, ebenfalls gelöscht. Dies führt dazu, dass die Pipeline nicht mehr funktioniert. In diesem Fall gibt es keine allgemeine Lösung für die Wiederherstellung.

Nachdem Ihre Umgebung gebootet wurde, sollten Sie den Bootstrap-Stack der Umgebung nicht löschen und neu erstellen. Versuchen Sie stattdessen, den Bootstrap-Stack auf eine neue Version zu aktualisieren, indem Sie den Befehl erneut ausführen. cdk bootstrap

Zum Schutz vor versehentlichem Löschen Ihres Bootstrap-Stacks empfehlen wir Ihnen, die --termination-protection Option mit dem cdk bootstrap Befehl zum Aktivieren des Kündigungsschutzes bereitzustellen. Sie können den Kündigungsschutz für neue oder bestehende Bootstrap-Stacks aktivieren. Weitere Informationen zu dieser Option finden Sie unter. --termination-protection

Nachdem Sie den Kündigungsschutz aktiviert haben, können Sie die AWS CLI CloudFormation OR-Konsole zur Überprüfung verwenden.

Um den Kündigungsschutz zu aktivieren
  1. Führen Sie den folgenden Befehl aus, um den Kündigungsschutz für einen neuen oder vorhandenen Bootstrap-Stack zu aktivieren:

    $ cdk bootstrap --termination-protection
  2. Verwenden Sie die CloudFormation Konsole AWS CLI oder, um dies zu überprüfen. Im Folgenden finden Sie ein Beispiel unter Verwendung der AWS CLI. Wenn Sie Ihren Bootstrap-Stack-Namen geändert haben, CDKToolkit ersetzen Sie ihn durch Ihren Stack-Namen:

    $ aws cloudformation describe-stacks --stack-name CDKToolkit --query "Stacks[0].EnableTerminationProtection" true

Initialisieren Sie ein Projekt

Erstellen Sie ein neues, leeres GitHub Projekt und klonen Sie es auf Ihre Workstation im my-pipeline Verzeichnis. (Unsere Codebeispiele in diesem Thema verwenden GitHub. Sie können auch AWS CodeStar oder verwenden AWS CodeCommit.)

git clone GITHUB-CLONE-URL my-pipeline cd my-pipeline
Anmerkung

Sie können einen anderen Namen als den Namen my-pipeline für das Hauptverzeichnis Ihrer App verwenden. Wenn Sie dies jedoch tun, müssen Sie die Datei- und Klassennamen später in diesem Thema anpassen. Das liegt daran, dass das AWS CDK Toolkit einige Datei- und Klassennamen auf dem Namen des Hauptverzeichnisses basiert.

Initialisieren Sie das Projekt nach dem Klonen wie gewohnt.

TypeScript
$ cdk init app --language typescript
JavaScript
$ cdk init app --language javascript
Python
$ cdk init app --language python

Nachdem die App erstellt wurde, geben Sie auch die folgenden beiden Befehle ein. Diese aktivieren die virtuelle Python-Umgebung der App und installieren die AWS CDK Kernabhängigkeiten.

$ source .venv/bin/activate # On Windows, run `.\venv\Scripts\activate` instead $ python -m pip install -r requirements.txt
Java
$ cdk init app --language java

Wenn Sie eine IDE verwenden, können Sie das Projekt jetzt öffnen oder importieren. Wählen Sie in Eclipse beispielsweise „Datei“ > „Importieren“ > „Maven“ > „Bestehende Maven-Projekte“. Stellen Sie sicher, dass die Projekteinstellungen so eingestellt sind, dass sie Java 8 (1.8) verwenden.

C#
$ cdk init app --language csharp

Wenn Sie Visual Studio verwenden, öffnen Sie die Lösungsdatei im src Verzeichnis.

Go
$ cdk init app --language go

Geben Sie nach der Erstellung der App auch den folgenden Befehl ein, um die AWS Construct Library-Module zu installieren, die die App benötigt.

$ go get
Wichtig

Stellen Sie sicher, dass Sie Ihre cdk.json cdk.context.json Dateien der Quellcodeverwaltung übergeben. Die Kontextinformationen (wie Feature-Flags und zwischengespeicherte Werte, die aus Ihrem AWS Konto abgerufen wurden) sind Teil des Status Ihres Projekts. Die Werte können in einer anderen Umgebung unterschiedlich sein, was zu unerwarteten Änderungen Ihrer Ergebnisse führen kann. Weitere Informationen finden Sie unter Kontextwerte und AWS CDK.

Definieren Sie eine Pipeline

Ihre CDK Pipelines Pipelines-Anwendung wird mindestens zwei Stacks enthalten: einen, der die Pipeline selbst darstellt, und einen oder mehrere Stacks, die die über sie bereitgestellte Anwendung darstellen. Stacks können auch in Stufen gruppiert werden, mit denen Sie Kopien von Infrastruktur-Stacks in verschiedenen Umgebungen bereitstellen können. Zunächst werden wir uns mit der Pipeline befassen und uns später mit der Anwendung befassen, die sie bereitstellen wird.

Das Konstrukt CodePipelineist das Konstrukt, das eine CDK-Pipeline darstellt, die AWS CodePipeline als Deployment Engine verwendet wird. Wenn Sie CodePipeline in einem Stack instanziieren, definieren Sie den Quellspeicherort für die Pipeline (z. B. ein GitHub Repository). Sie definieren auch die Befehle zum Erstellen der App.

Im Folgenden wird beispielsweise eine Pipeline definiert, deren Quelle in einem GitHub Repository gespeichert ist. Sie beinhaltet auch einen Build-Schritt für eine TypeScript CDK-Anwendung. Geben Sie die Informationen zu Ihrem GitHub Repo an den angegebenen Stellen ein.

Anmerkung

Standardmäßig authentifiziert sich die Pipeline GitHub mit einem persönlichen Zugriffstoken, das in Secrets Manager unter dem Namen github-token gespeichert ist.

Sie müssen auch die Instanziierung des Pipeline-Stacks aktualisieren, um das AWS Konto und die Region anzugeben.

TypeScript

In lib/my-pipeline-stack.ts (kann variieren, wenn Ihr Projektordner nicht benannt my-pipeline ist):

import * as cdk from 'aws-cdk-lib'; import { Construct } from 'constructs'; import { CodePipeline, CodePipelineSource, ShellStep } from 'aws-cdk-lib/pipelines'; export class MyPipelineStack extends cdk.Stack { constructor(scope: Construct, id: string, props?: cdk.StackProps) { super(scope, id, props); const pipeline = new CodePipeline(this, 'Pipeline', { pipelineName: 'MyPipeline', synth: new ShellStep('Synth', { input: CodePipelineSource.gitHub('OWNER/REPO', 'main'), commands: ['npm ci', 'npm run build', 'npx cdk synth'] }) }); } }

In bin/my-pipeline.ts (kann variieren, wenn Ihr Projektordner nicht benannt istmy-pipeline):

#!/usr/bin/env node import * as cdk from 'aws-cdk-lib'; import { MyPipelineStack } from '../lib/my-pipeline-stack'; const app = new cdk.App(); new MyPipelineStack(app, 'MyPipelineStack', { env: { account: '111111111111', region: 'eu-west-1', } }); app.synth();
JavaScript

In lib/my-pipeline-stack.js (kann variieren, wenn Ihr Projektordner nicht benannt istmy-pipeline):

const cdk = require('aws-cdk-lib'); const { CodePipeline, CodePipelineSource, ShellStep } = require('aws-cdk-lib/pipelines'); class MyPipelineStack extends cdk.Stack { constructor(scope, id, props) { super(scope, id, props); const pipeline = new CodePipeline(this, 'Pipeline', { pipelineName: 'MyPipeline', synth: new ShellStep('Synth', { input: CodePipelineSource.gitHub('OWNER/REPO', 'main'), commands: ['npm ci', 'npm run build', 'npx cdk synth'] }) }); } } module.exports = { MyPipelineStack }

In bin/my-pipeline.js (kann variieren, wenn Ihr Projektordner nicht benannt istmy-pipeline):

#!/usr/bin/env node const cdk = require('aws-cdk-lib'); const { MyPipelineStack } = require('../lib/my-pipeline-stack'); const app = new cdk.App(); new MyPipelineStack(app, 'MyPipelineStack', { env: { account: '111111111111', region: 'eu-west-1', } }); app.synth();
Python

In my-pipeline/my-pipeline-stack.py (kann variieren, wenn Ihr Projektordner nicht benannt istmy-pipeline):

import aws_cdk as cdk from constructs import Construct from aws_cdk.pipelines import CodePipeline, CodePipelineSource, ShellStep class MyPipelineStack(cdk.Stack): def __init__(self, scope: Construct, construct_id: str, **kwargs) -> None: super().__init__(scope, construct_id, **kwargs) pipeline = CodePipeline(self, "Pipeline", pipeline_name="MyPipeline", synth=ShellStep("Synth", input=CodePipelineSource.git_hub("OWNER/REPO", "main"), commands=["npm install -g aws-cdk", "python -m pip install -r requirements.txt", "cdk synth"] ) )

In app.py:

#!/usr/bin/env python3 import aws_cdk as cdk from my_pipeline.my_pipeline_stack import MyPipelineStack app = cdk.App() MyPipelineStack(app, "MyPipelineStack", env=cdk.Environment(account="111111111111", region="eu-west-1") ) app.synth()
Java

In src/main/java/com/myorg/MyPipelineStack.java (kann variieren, wenn Ihr Projektordner nicht benannt istmy-pipeline):

package com.myorg; import java.util.Arrays; import software.constructs.Construct; import software.amazon.awscdk.Stack; import software.amazon.awscdk.StackProps; import software.amazon.awscdk.pipelines.CodePipeline; import software.amazon.awscdk.pipelines.CodePipelineSource; import software.amazon.awscdk.pipelines.ShellStep; public class MyPipelineStack extends Stack { public MyPipelineStack(final Construct scope, final String id) { this(scope, id, null); } public MyPipelineStack(final Construct scope, final String id, final StackProps props) { super(scope, id, props); CodePipeline pipeline = CodePipeline.Builder.create(this, "pipeline") .pipelineName("MyPipeline") .synth(ShellStep.Builder.create("Synth") .input(CodePipelineSource.gitHub("OWNER/REPO", "main")) .commands(Arrays.asList("npm install -g aws-cdk", "cdk synth")) .build()) .build(); } }

In src/main/java/com/myorg/MyPipelineApp.java (kann variieren, wenn Ihr Projektordner nicht benannt istmy-pipeline):

package com.myorg; import software.amazon.awscdk.App; import software.amazon.awscdk.Environment; import software.amazon.awscdk.StackProps; public class MyPipelineApp { public static void main(final String[] args) { App app = new App(); new MyPipelineStack(app, "PipelineStack", StackProps.builder() .env(Environment.builder() .account("111111111111") .region("eu-west-1") .build()) .build()); app.synth(); } }
C#

In src/MyPipeline/MyPipelineStack.cs (kann variieren, wenn Ihr Projektordner nicht benannt istmy-pipeline):

using Amazon.CDK; using Amazon.CDK.Pipelines; namespace MyPipeline { public class MyPipelineStack : Stack { internal MyPipelineStack(Construct scope, string id, IStackProps props = null) : base(scope, id, props) { var pipeline = new CodePipeline(this, "pipeline", new CodePipelineProps { PipelineName = "MyPipeline", Synth = new ShellStep("Synth", new ShellStepProps { Input = CodePipelineSource.GitHub("OWNER/REPO", "main"), Commands = new string[] { "npm install -g aws-cdk", "cdk synth" } }) }); } } }

In src/MyPipeline/Program.cs (kann variieren, wenn Ihr Projektordner nicht benannt istmy-pipeline):

using Amazon.CDK; namespace MyPipeline { sealed class Program { public static void Main(string[] args) { var app = new App(); new MyPipelineStack(app, "MyPipelineStack", new StackProps { Env = new Amazon.CDK.Environment { Account = "111111111111", Region = "eu-west-1" } }); app.Synth(); } } }
Go
package main import ( "github.com/aws/aws-cdk-go/awscdk/v2" codebuild "github.com/aws/aws-cdk-go/awscdk/v2/awscodebuild" ssm "github.com/aws/aws-cdk-go/awscdk/v2/awsssm" pipeline "github.com/aws/aws-cdk-go/awscdk/v2/pipelines" "github.com/aws/constructs-go/constructs/v10" "github.com/aws/jsii-runtime-go" "os" ) // my CDK Stack with resources func NewCdkStack(scope constructs.Construct, id *string, props *awscdk.StackProps) awscdk.Stack { stack := awscdk.NewStack(scope, id, props) // create an example ssm parameter _ = ssm.NewStringParameter(stack, jsii.String("ssm-test-param"), &ssm.StringParameterProps{ ParameterName: jsii.String("/testparam"), Description: jsii.String("ssm parameter for demo"), StringValue: jsii.String("my test param"), }) return stack } // my CDK Application func NewCdkApplication(scope constructs.Construct, id *string, props *awscdk.StageProps) awscdk.Stage { stage := awscdk.NewStage(scope, id, props) _ = NewCdkStack(stage, jsii.String("cdk-stack"), &awscdk.StackProps{Env: props.Env}) return stage } // my CDK Pipeline func NewCdkPipeline(scope constructs.Construct, id *string, props *awscdk.StackProps) awscdk.Stack { stack := awscdk.NewStack(scope, id, props) // GitHub repo with owner and repository name githubRepo := pipeline.CodePipelineSource_GitHub(jsii.String("owner/repo"), jsii.String("main"), &pipeline.GitHubSourceOptions{ Authentication: awscdk.SecretValue_SecretsManager(jsii.String("my-github-token"), nil), }) // self mutating pipeline myPipeline := pipeline.NewCodePipeline(stack, jsii.String("cdkPipeline"), &pipeline.CodePipelineProps{ PipelineName: jsii.String("CdkPipeline"), // self mutation true - pipeline changes itself before application deployment SelfMutation: jsii.Bool(true), CodeBuildDefaults: &pipeline.CodeBuildOptions{ BuildEnvironment: &codebuild.BuildEnvironment{ // image version 6.0 recommended for newer go version BuildImage: codebuild.LinuxBuildImage_FromCodeBuildImageId(jsii.String("aws/codebuild/standard:6.0")), }, }, Synth: pipeline.NewCodeBuildStep(jsii.String("Synth"), &pipeline.CodeBuildStepProps{ Input: githubRepo, Commands: &[]*string{ jsii.String("npm install -g aws-cdk"), jsii.String("cdk synth"), }, }), }) // deployment of actual CDK application myPipeline.AddStage(NewCdkApplication(stack, jsii.String("MyApplication"), &awscdk.StageProps{ Env: targetAccountEnv(), }), &pipeline.AddStageOpts{ Post: &[]pipeline.Step{ pipeline.NewCodeBuildStep(jsii.String("Manual Steps"), &pipeline.CodeBuildStepProps{ Commands: &[]*string{ jsii.String("echo \"My CDK App deployed, manual steps go here ... \""), }, }), }, }) return stack } // main app func main() { defer jsii.Close() app := awscdk.NewApp(nil) // call CDK Pipeline NewCdkPipeline(app, jsii.String("CdkPipelineStack"), &awscdk.StackProps{ Env: pipelineEnv(), }) app.Synth(nil) } // env determines the AWS environment (account+region) in which our stack is to // be deployed. For more information see: https://docs.aws.amazon.com/cdk/latest/guide/environments.html func pipelineEnv() *awscdk.Environment { return &awscdk.Environment{ Account: jsii.String(os.Getenv("CDK_DEFAULT_ACCOUNT")), Region: jsii.String(os.Getenv("CDK_DEFAULT_REGION")), } } func targetAccountEnv() *awscdk.Environment { return &awscdk.Environment{ Account: jsii.String(os.Getenv("CDK_DEFAULT_ACCOUNT")), Region: jsii.String(os.Getenv("CDK_DEFAULT_REGION")), } }

Sie müssen eine Pipeline einmal manuell bereitstellen. Danach hält sich die Pipeline aus dem Quellcode-Repository auf dem neuesten Stand. Stellen Sie also sicher, dass der Code im Repo der Code ist, den Sie bereitstellen möchten. Checken Sie Ihre Änderungen ein GitHub, klicken Sie auf und stellen Sie sie dann bereit:

git add --all git commit -m "initial commit" git push cdk deploy
Tipp

Nachdem Sie die erste Bereitstellung abgeschlossen haben, benötigt Ihr lokales AWS Konto keinen Administratorzugriff mehr. Dies liegt daran, dass alle Änderungen an Ihrer App über die Pipeline bereitgestellt werden. Sie müssen lediglich in der Lage sein, darauf zu drücken GitHub.

Phasen der Bewerbung

Um eine AWS Multi-Stack-Anwendung zu definieren, die der Pipeline auf einmal hinzugefügt werden kann, definieren Sie eine Unterklasse von. Stage (Dies unterscheidet sich von CdkStage dem Modul CDK Pipelines.)

Die Phase enthält die Stapel, aus denen Ihre Anwendung besteht. Wenn zwischen den Stacks Abhängigkeiten bestehen, werden die Stacks automatisch in der richtigen Reihenfolge zur Pipeline hinzugefügt. Stacks, die nicht voneinander abhängen, werden parallel bereitgestellt. Sie können eine Abhängigkeitsbeziehung zwischen Stacks hinzufügen, indem Sie aufrufen. stack1.addDependency(stack2)

Stufen akzeptieren ein env Standardargument, das zur Standardumgebung für die darin enthaltenen Stacks wird. (Für Stacks kann immer noch eine eigene Umgebung angegeben werden.).

Eine Anwendung wird der Pipeline hinzugefügt, indem sie addStage() mit Instanzen von Stageaufgerufen wird. Eine Phase kann mehrmals instanziiert und der Pipeline hinzugefügt werden, um verschiedene Phasen Ihrer DTAP- oder Multi-Region-Anwendungspipeline zu definieren.

Wir werden einen Stack erstellen, der eine einfache Lambda-Funktion enthält, und diesen Stack in einer Phase platzieren. Dann fügen wir die Phase der Pipeline hinzu, damit sie bereitgestellt werden kann.

TypeScript

Erstellen Sie die neue Dateilib/my-pipeline-lambda-stack.ts, die unseren Anwendungsstapel enthält, der eine Lambda-Funktion enthält.

import * as cdk from 'aws-cdk-lib'; import { Construct } from 'constructs'; import { Function, InlineCode, Runtime } from 'aws-cdk-lib/aws-lambda'; export class MyLambdaStack extends cdk.Stack { constructor(scope: Construct, id: string, props?: cdk.StackProps) { super(scope, id, props); new Function(this, 'LambdaFunction', { runtime: Runtime.NODEJS_18_X, handler: 'index.handler', code: new InlineCode('exports.handler = _ => "Hello, CDK";') }); } }

Erstellen Sie die neue Datei lib/my-pipeline-app-stage.ts für unsere Bühne.

import * as cdk from 'aws-cdk-lib'; import { Construct } from "constructs"; import { MyLambdaStack } from './my-pipeline-lambda-stack'; export class MyPipelineAppStage extends cdk.Stage { constructor(scope: Construct, id: string, props?: cdk.StageProps) { super(scope, id, props); const lambdaStack = new MyLambdaStack(this, 'LambdaStack'); } }

Bearbeitenlib/my-pipeline-stack.ts, um die Phase zu unserer Pipeline hinzuzufügen.

import * as cdk from 'aws-cdk-lib'; import { Construct } from 'constructs'; import { CodePipeline, CodePipelineSource, ShellStep } from 'aws-cdk-lib/pipelines'; import { MyPipelineAppStage } from './my-pipeline-app-stage'; export class MyPipelineStack extends cdk.Stack { constructor(scope: Construct, id: string, props?: cdk.StackProps) { super(scope, id, props); const pipeline = new CodePipeline(this, 'Pipeline', { pipelineName: 'MyPipeline', synth: new ShellStep('Synth', { input: CodePipelineSource.gitHub('OWNER/REPO', 'main'), commands: ['npm ci', 'npm run build', 'npx cdk synth'] }) }); pipeline.addStage(new MyPipelineAppStage(this, "test", { env: { account: "111111111111", region: "eu-west-1" } })); } }
JavaScript

Erstellen Sie die neue Dateilib/my-pipeline-lambda-stack.js, die unseren Anwendungsstapel enthält, der eine Lambda-Funktion enthält.

const cdk = require('aws-cdk-lib'); const { Function, InlineCode, Runtime } = require('aws-cdk-lib/aws-lambda'); class MyLambdaStack extends cdk.Stack { constructor(scope, id, props) { super(scope, id, props); new Function(this, 'LambdaFunction', { runtime: Runtime.NODEJS_18_X, handler: 'index.handler', code: new InlineCode('exports.handler = _ => "Hello, CDK";') }); } } module.exports = { MyLambdaStack }

Erstellen Sie die neue Datei lib/my-pipeline-app-stage.js für unsere Bühne.

const cdk = require('aws-cdk-lib'); const { MyLambdaStack } = require('./my-pipeline-lambda-stack'); class MyPipelineAppStage extends cdk.Stage { constructor(scope, id, props) { super(scope, id, props); const lambdaStack = new MyLambdaStack(this, 'LambdaStack'); } } module.exports = { MyPipelineAppStage };

Bearbeitenlib/my-pipeline-stack.ts, um die Phase zu unserer Pipeline hinzuzufügen.

const cdk = require('aws-cdk-lib'); const { CodePipeline, CodePipelineSource, ShellStep } = require('aws-cdk-lib/pipelines'); const { MyPipelineAppStage } = require('./my-pipeline-app-stage'); class MyPipelineStack extends cdk.Stack { constructor(scope, id, props) { super(scope, id, props); const pipeline = new CodePipeline(this, 'Pipeline', { pipelineName: 'MyPipeline', synth: new ShellStep('Synth', { input: CodePipelineSource.gitHub('OWNER/REPO', 'main'), commands: ['npm ci', 'npm run build', 'npx cdk synth'] }) }); pipeline.addStage(new MyPipelineAppStage(this, "test", { env: { account: "111111111111", region: "eu-west-1" } })); } } module.exports = { MyPipelineStack }
Python

Erstellen Sie die neue Dateimy_pipeline/my_pipeline_lambda_stack.py, die unseren Anwendungsstapel enthält, der eine Lambda-Funktion enthält.

import aws_cdk as cdk from constructs import Construct from aws_cdk.aws_lambda import Function, InlineCode, Runtime class MyLambdaStack(cdk.Stack): def __init__(self, scope: Construct, construct_id: str, **kwargs) -> None: super().__init__(scope, construct_id, **kwargs) Function(self, "LambdaFunction", runtime=Runtime.NODEJS_18_X, handler="index.handler", code=InlineCode("exports.handler = _ => 'Hello, CDK';") )

Erstellen Sie die neue Datei my_pipeline/my_pipeline_app_stage.py für unsere Bühne.

import aws_cdk as cdk from constructs import Construct from my_pipeline.my_pipeline_lambda_stack import MyLambdaStack class MyPipelineAppStage(cdk.Stage): def __init__(self, scope: Construct, construct_id: str, **kwargs) -> None: super().__init__(scope, construct_id, **kwargs) lambdaStack = MyLambdaStack(self, "LambdaStack")

Bearbeitenmy_pipeline/my-pipeline-stack.py, um die Phase zu unserer Pipeline hinzuzufügen.

import aws_cdk as cdk from constructs import Construct from aws_cdk.pipelines import CodePipeline, CodePipelineSource, ShellStep from my_pipeline.my_pipeline_app_stage import MyPipelineAppStage class MyPipelineStack(cdk.Stack): def __init__(self, scope: Construct, construct_id: str, **kwargs) -> None: super().__init__(scope, construct_id, **kwargs) pipeline = CodePipeline(self, "Pipeline", pipeline_name="MyPipeline", synth=ShellStep("Synth", input=CodePipelineSource.git_hub("OWNER/REPO", "main"), commands=["npm install -g aws-cdk", "python -m pip install -r requirements.txt", "cdk synth"])) pipeline.add_stage(MyPipelineAppStage(self, "test", env=cdk.Environment(account="111111111111", region="eu-west-1")))
Java

Erstellen Sie die neue Dateisrc/main/java/com.myorg/MyPipelineLambdaStack.java, die unseren Anwendungsstapel enthält, der eine Lambda-Funktion enthält.

package com.myorg; import software.constructs.Construct; import software.amazon.awscdk.Stack; import software.amazon.awscdk.StackProps; import software.amazon.awscdk.services.lambda.Function; import software.amazon.awscdk.services.lambda.Runtime; import software.amazon.awscdk.services.lambda.InlineCode; public class MyPipelineLambdaStack extends Stack { public MyPipelineLambdaStack(final Construct scope, final String id) { this(scope, id, null); } public MyPipelineLambdaStack(final Construct scope, final String id, final StackProps props) { super(scope, id, props); Function.Builder.create(this, "LambdaFunction") .runtime(Runtime.NODEJS_18_X) .handler("index.handler") .code(new InlineCode("exports.handler = _ => 'Hello, CDK';")) .build(); } }

Erstellen Sie die neue Datei src/main/java/com.myorg/MyPipelineAppStage.java für unsere Bühne.

package com.myorg; import software.constructs.Construct; import software.amazon.awscdk.Stack; import software.amazon.awscdk.Stage; import software.amazon.awscdk.StageProps; public class MyPipelineAppStage extends Stage { public MyPipelineAppStage(final Construct scope, final String id) { this(scope, id, null); } public MyPipelineAppStage(final Construct scope, final String id, final StageProps props) { super(scope, id, props); Stack lambdaStack = new MyPipelineLambdaStack(this, "LambdaStack"); } }

Bearbeitensrc/main/java/com.myorg/MyPipelineStack.java, um die Phase zu unserer Pipeline hinzuzufügen.

package com.myorg; import java.util.Arrays; import software.constructs.Construct; import software.amazon.awscdk.Environment; import software.amazon.awscdk.Stack; import software.amazon.awscdk.StackProps; import software.amazon.awscdk.StageProps; import software.amazon.awscdk.pipelines.CodePipeline; import software.amazon.awscdk.pipelines.CodePipelineSource; import software.amazon.awscdk.pipelines.ShellStep; public class MyPipelineStack extends Stack { public MyPipelineStack(final Construct scope, final String id) { this(scope, id, null); } public MyPipelineStack(final Construct scope, final String id, final StackProps props) { super(scope, id, props); final CodePipeline pipeline = CodePipeline.Builder.create(this, "pipeline") .pipelineName("MyPipeline") .synth(ShellStep.Builder.create("Synth") .input(CodePipelineSource.gitHub("OWNER/REPO", "main")) .commands(Arrays.asList("npm install -g aws-cdk", "cdk synth")) .build()) .build(); pipeline.addStage(new MyPipelineAppStage(this, "test", StageProps.builder() .env(Environment.builder() .account("111111111111") .region("eu-west-1") .build()) .build())); } }
C#

Erstellen Sie die neue Dateisrc/MyPipeline/MyPipelineLambdaStack.cs, die unseren Anwendungsstapel enthält, der eine Lambda-Funktion enthält.

using Amazon.CDK; using Constructs; using Amazon.CDK.AWS.Lambda; namespace MyPipeline { class MyPipelineLambdaStack : Stack { public MyPipelineLambdaStack(Construct scope, string id, StackProps props=null) : base(scope, id, props) { new Function(this, "LambdaFunction", new FunctionProps { Runtime = Runtime.NODEJS_18_X, Handler = "index.handler", Code = new InlineCode("exports.handler = _ => 'Hello, CDK';") }); } } }

Erstellen Sie die neue Datei src/MyPipeline/MyPipelineAppStage.cs für unsere Bühne.

using Amazon.CDK; using Constructs; namespace MyPipeline { class MyPipelineAppStage : Stage { public MyPipelineAppStage(Construct scope, string id, StageProps props=null) : base(scope, id, props) { Stack lambdaStack = new MyPipelineLambdaStack(this, "LambdaStack"); } } }

Bearbeitensrc/MyPipeline/MyPipelineStack.cs, um die Phase zu unserer Pipeline hinzuzufügen.

using Amazon.CDK; using Constructs; using Amazon.CDK.Pipelines; namespace MyPipeline { public class MyPipelineStack : Stack { internal MyPipelineStack(Construct scope, string id, IStackProps props = null) : base(scope, id, props) { var pipeline = new CodePipeline(this, "pipeline", new CodePipelineProps { PipelineName = "MyPipeline", Synth = new ShellStep("Synth", new ShellStepProps { Input = CodePipelineSource.GitHub("OWNER/REPO", "main"), Commands = new string[] { "npm install -g aws-cdk", "cdk synth" } }) }); pipeline.AddStage(new MyPipelineAppStage(this, "test", new StageProps { Env = new Environment { Account = "111111111111", Region = "eu-west-1" } })); } } }

Jede von hinzugefügte Anwendungsphase addStage() führt zum Hinzufügen einer entsprechenden Pipeline-Phase, die durch eine vom addStage() Aufruf zurückgegebene StageDeploymentInstanz repräsentiert wird. Sie können der Phase Aktionen vor oder nach der Bereitstellung hinzufügen, indem Sie die Methode addPre() or addPost() aufrufen.

TypeScript
// import { ManualApprovalStep } from 'aws-cdk-lib/pipelines'; const testingStage = pipeline.addStage(new MyPipelineAppStage(this, 'testing', { env: { account: '111111111111', region: 'eu-west-1' } })); testingStage.addPost(new ManualApprovalStep('approval'));
JavaScript
// const { ManualApprovalStep } = require('aws-cdk-lib/pipelines'); const testingStage = pipeline.addStage(new MyPipelineAppStage(this, 'testing', { env: { account: '111111111111', region: 'eu-west-1' } })); testingStage.addPost(new ManualApprovalStep('approval'));
Python
# from aws_cdk.pipelines import ManualApprovalStep testing_stage = pipeline.add_stage(MyPipelineAppStage(self, "testing", env=cdk.Environment(account="111111111111", region="eu-west-1"))) testing_stage.add_post(ManualApprovalStep('approval'))
Java
// import software.amazon.awscdk.pipelines.StageDeployment; // import software.amazon.awscdk.pipelines.ManualApprovalStep; StageDeployment testingStage = pipeline.addStage(new MyPipelineAppStage(this, "test", StageProps.builder() .env(Environment.builder() .account("111111111111") .region("eu-west-1") .build()) .build())); testingStage.addPost(new ManualApprovalStep("approval"));
C#
var testingStage = pipeline.AddStage(new MyPipelineAppStage(this, "test", new StageProps { Env = new Environment { Account = "111111111111", Region = "eu-west-1" } })); testingStage.AddPost(new ManualApprovalStep("approval"));

Sie können Stufen zu einer Wave hinzufügen, um sie parallel bereitzustellen, z. B. wenn Sie eine Phase für mehrere Konten oder Regionen bereitstellen.

TypeScript
const wave = pipeline.addWave('wave'); wave.addStage(new MyApplicationStage(this, 'MyAppEU', { env: { account: '111111111111', region: 'eu-west-1' } })); wave.addStage(new MyApplicationStage(this, 'MyAppUS', { env: { account: '111111111111', region: 'us-west-1' } }));
JavaScript
const wave = pipeline.addWave('wave'); wave.addStage(new MyApplicationStage(this, 'MyAppEU', { env: { account: '111111111111', region: 'eu-west-1' } })); wave.addStage(new MyApplicationStage(this, 'MyAppUS', { env: { account: '111111111111', region: 'us-west-1' } }));
Python
wave = pipeline.add_wave("wave") wave.add_stage(MyApplicationStage(self, "MyAppEU", env=cdk.Environment(account="111111111111", region="eu-west-1"))) wave.add_stage(MyApplicationStage(self, "MyAppUS", env=cdk.Environment(account="111111111111", region="us-west-1")))
Java
// import software.amazon.awscdk.pipelines.Wave; final Wave wave = pipeline.addWave("wave"); wave.addStage(new MyPipelineAppStage(this, "MyAppEU", StageProps.builder() .env(Environment.builder() .account("111111111111") .region("eu-west-1") .build()) .build())); wave.addStage(new MyPipelineAppStage(this, "MyAppUS", StageProps.builder() .env(Environment.builder() .account("111111111111") .region("us-west-1") .build()) .build()));
C#
var wave = pipeline.AddWave("wave"); wave.AddStage(new MyPipelineAppStage(this, "MyAppEU", new StageProps { Env = new Environment { Account = "111111111111", Region = "eu-west-1" } })); wave.AddStage(new MyPipelineAppStage(this, "MyAppUS", new StageProps { Env = new Environment { Account = "111111111111", Region = "us-west-1" } }));

Bereitstellungen testen

Sie können einer CDK-Pipeline Schritte hinzufügen, um die von Ihnen durchgeführten Bereitstellungen zu validieren. Sie können beispielsweise die CDK-Pipeline-Bibliotheken verwendenShellStep, um Aufgaben wie die folgenden auszuführen:

  • Es wird versucht, auf ein neu bereitgestelltes Amazon API Gateway zuzugreifen, das von einer Lambda-Funktion unterstützt wird

  • Überprüfung einer Einstellung einer bereitgestellten Ressource durch Ausgabe eines Befehls AWS CLI

In seiner einfachsten Form sieht das Hinzufügen von Validierungsaktionen wie folgt aus:

TypeScript
// stage was returned by pipeline.addStage stage.addPost(new ShellStep("validate", { commands: ['../tests/validate.sh'], }));
JavaScript
// stage was returned by pipeline.addStage stage.addPost(new ShellStep("validate", { commands: ['../tests/validate.sh'], }));
Python
# stage was returned by pipeline.add_stage stage.add_post(ShellStep("validate", commands=[''../tests/validate.sh''] ))
Java
// stage was returned by pipeline.addStage stage.addPost(ShellStep.Builder.create("validate") .commands(Arrays.asList("'../tests/validate.sh'")) .build());
C#
// stage was returned by pipeline.addStage stage.AddPost(new ShellStep("validate", new ShellStepProps { Commands = new string[] { "'../tests/validate.sh'" } }));

Viele AWS CloudFormation Bereitstellungen führen zur Generierung von Ressourcen mit unvorhersehbaren Namen. Aus diesem Grund bieten CDK Pipelines die Möglichkeit, AWS CloudFormation Ausgaben nach einer Bereitstellung zu lesen. Dadurch ist es möglich, (zum Beispiel) die generierte URL eines Load Balancers an eine Testaktion zu übergeben.

Um Ausgaben zu verwenden, machen Sie das CfnOutput Objekt verfügbar, an dem Sie interessiert sind. Übergeben Sie es dann in der envFromCfnOutputs Eigenschaft eines Schritts, um es als Umgebungsvariable innerhalb dieses Schritts verfügbar zu machen.

TypeScript
// given a stack lbStack that exposes a load balancer construct as loadBalancer this.loadBalancerAddress = new cdk.CfnOutput(lbStack, 'LbAddress', { value: `https://${lbStack.loadBalancer.loadBalancerDnsName}/` }); // pass the load balancer address to a shell step stage.addPost(new ShellStep("lbaddr", { envFromCfnOutputs: {lb_addr: lbStack.loadBalancerAddress}, commands: ['echo $lb_addr'] }));
JavaScript
// given a stack lbStack that exposes a load balancer construct as loadBalancer this.loadBalancerAddress = new cdk.CfnOutput(lbStack, 'LbAddress', { value: `https://${lbStack.loadBalancer.loadBalancerDnsName}/` }); // pass the load balancer address to a shell step stage.addPost(new ShellStep("lbaddr", { envFromCfnOutputs: {lb_addr: lbStack.loadBalancerAddress}, commands: ['echo $lb_addr'] }));
Python
# given a stack lb_stack that exposes a load balancer construct as load_balancer self.load_balancer_address = cdk.CfnOutput(lb_stack, "LbAddress", value=f"https://{lb_stack.load_balancer.load_balancer_dns_name}/") # pass the load balancer address to a shell step stage.add_post(ShellStep("lbaddr", env_from_cfn_outputs={"lb_addr": lb_stack.load_balancer_address} commands=["echo $lb_addr"]))
Java
// given a stack lbStack that exposes a load balancer construct as loadBalancer loadBalancerAddress = CfnOutput.Builder.create(lbStack, "LbAddress") .value(String.format("https://%s/", lbStack.loadBalancer.loadBalancerDnsName)) .build(); stage.addPost(ShellStep.Builder.create("lbaddr") .envFromCfnOutputs( // Map.of requires Java 9 or later java.util.Map.of("lbAddr", loadBalancerAddress)) .commands(Arrays.asList("echo $lbAddr")) .build());
C#
// given a stack lbStack that exposes a load balancer construct as loadBalancer loadBalancerAddress = new CfnOutput(lbStack, "LbAddress", new CfnOutputProps { Value = string.Format("https://{0}/", lbStack.loadBalancer.LoadBalancerDnsName) }); stage.AddPost(new ShellStep("lbaddr", new ShellStepProps { EnvFromCfnOutputs = new Dictionary<string, CfnOutput> { { "lbAddr", loadBalancerAddress } }, Commands = new string[] { "echo $lbAddr" } }));

Sie können einfache Validierungstests direkt in das schreibenShellStep, aber dieser Ansatz wird unhandlich, wenn der Test mehr als ein paar Zeilen umfasst. Für komplexere Tests können Sie zusätzliche Dateien (z. B. vollständige Shell-Skripte oder Programme in anderen Sprachen) ShellStep über die inputs Eigenschaft hinzufügen. Bei den Eingaben kann es sich um jeden Schritt handeln, der eine Ausgabe hat, einschließlich einer Quelle (z. B. eines GitHub Repositorys) oder einer anderenShellStep.

Das Importieren von Dateien aus dem Quell-Repository ist angemessen, wenn die Dateien direkt im Test verwendet werden können (z. B. wenn sie selbst ausführbar sind). In diesem Beispiel deklarieren wir unser GitHub Repo als source (anstatt es inline als Teil von zu instanziieren). CodePipeline Dann übergeben wir diesen Dateisatz sowohl an die Pipeline als auch an den Validierungstest.

TypeScript
const source = CodePipelineSource.gitHub('OWNER/REPO', 'main'); const pipeline = new CodePipeline(this, 'Pipeline', { pipelineName: 'MyPipeline', synth: new ShellStep('Synth', { input: source, commands: ['npm ci', 'npm run build', 'npx cdk synth'] }) }); const stage = pipeline.addStage(new MyPipelineAppStage(this, 'test', { env: { account: '111111111111', region: 'eu-west-1' } })); stage.addPost(new ShellStep('validate', { input: source, commands: ['sh ../tests/validate.sh'] }));
JavaScript
const source = CodePipelineSource.gitHub('OWNER/REPO', 'main'); const pipeline = new CodePipeline(this, 'Pipeline', { pipelineName: 'MyPipeline', synth: new ShellStep('Synth', { input: source, commands: ['npm ci', 'npm run build', 'npx cdk synth'] }) }); const stage = pipeline.addStage(new MyPipelineAppStage(this, 'test', { env: { account: '111111111111', region: 'eu-west-1' } })); stage.addPost(new ShellStep('validate', { input: source, commands: ['sh ../tests/validate.sh'] }));
Python
source = CodePipelineSource.git_hub("OWNER/REPO", "main") pipeline = CodePipeline(self, "Pipeline", pipeline_name="MyPipeline", synth=ShellStep("Synth", input=source, commands=["npm install -g aws-cdk", "python -m pip install -r requirements.txt", "cdk synth"])) stage = pipeline.add_stage(MyApplicationStage(self, "test", env=cdk.Environment(account="111111111111", region="eu-west-1"))) stage.add_post(ShellStep("validate", input=source, commands=["sh ../tests/validate.sh"], ))
Java
final CodePipelineSource source = CodePipelineSource.gitHub("OWNER/REPO", "main"); final CodePipeline pipeline = CodePipeline.Builder.create(this, "pipeline") .pipelineName("MyPipeline") .synth(ShellStep.Builder.create("Synth") .input(source) .commands(Arrays.asList("npm install -g aws-cdk", "cdk synth")) .build()) .build(); final StageDeployment stage = pipeline.addStage(new MyPipelineAppStage(this, "test", StageProps.builder() .env(Environment.builder() .account("111111111111") .region("eu-west-1") .build()) .build())); stage.addPost(ShellStep.Builder.create("validate") .input(source) .commands(Arrays.asList("sh ../tests/validate.sh")) .build());
C#
var source = CodePipelineSource.GitHub("OWNER/REPO", "main"); var pipeline = new CodePipeline(this, "pipeline", new CodePipelineProps { PipelineName = "MyPipeline", Synth = new ShellStep("Synth", new ShellStepProps { Input = source, Commands = new string[] { "npm install -g aws-cdk", "cdk synth" } }) }); var stage = pipeline.AddStage(new MyPipelineAppStage(this, "test", new StageProps { Env = new Environment { Account = "111111111111", Region = "eu-west-1" } })); stage.AddPost(new ShellStep("validate", new ShellStepProps { Input = source, Commands = new string[] { "sh ../tests/validate.sh" } }));

Das Abrufen der zusätzlichen Dateien aus dem Synth-Schritt ist angemessen, wenn Ihre Tests kompiliert werden müssen, was im Rahmen der Synthese erfolgt.

TypeScript
const synthStep = new ShellStep('Synth', { input: CodePipelineSource.gitHub('OWNER/REPO', 'main'), commands: ['npm ci', 'npm run build', 'npx cdk synth'], }); const pipeline = new CodePipeline(this, 'Pipeline', { pipelineName: 'MyPipeline', synth: synthStep }); const stage = pipeline.addStage(new MyPipelineAppStage(this, 'test', { env: { account: '111111111111', region: 'eu-west-1' } })); // run a script that was transpiled from TypeScript during synthesis stage.addPost(new ShellStep('validate', { input: synthStep, commands: ['node tests/validate.js'] }));
JavaScript
const synthStep = new ShellStep('Synth', { input: CodePipelineSource.gitHub('OWNER/REPO', 'main'), commands: ['npm ci', 'npm run build', 'npx cdk synth'], }); const pipeline = new CodePipeline(this, 'Pipeline', { pipelineName: 'MyPipeline', synth: synthStep }); const stage = pipeline.addStage(new MyPipelineAppStage(this, "test", { env: { account: "111111111111", region: "eu-west-1" } })); // run a script that was transpiled from TypeScript during synthesis stage.addPost(new ShellStep('validate', { input: synthStep, commands: ['node tests/validate.js'] }));
Python
synth_step = ShellStep("Synth", input=CodePipelineSource.git_hub("OWNER/REPO", "main"), commands=["npm install -g aws-cdk", "python -m pip install -r requirements.txt", "cdk synth"]) pipeline = CodePipeline(self, "Pipeline", pipeline_name="MyPipeline", synth=synth_step) stage = pipeline.add_stage(MyApplicationStage(self, "test", env=cdk.Environment(account="111111111111", region="eu-west-1"))) # run a script that was compiled during synthesis stage.add_post(ShellStep("validate", input=synth_step, commands=["node test/validate.js"], ))
Java
final ShellStep synth = ShellStep.Builder.create("Synth") .input(CodePipelineSource.gitHub("OWNER/REPO", "main")) .commands(Arrays.asList("npm install -g aws-cdk", "cdk synth")) .build(); final CodePipeline pipeline = CodePipeline.Builder.create(this, "pipeline") .pipelineName("MyPipeline") .synth(synth) .build(); final StageDeployment stage = pipeline.addStage(new MyPipelineAppStage(this, "test", StageProps.builder() .env(Environment.builder() .account("111111111111") .region("eu-west-1") .build()) .build())); stage.addPost(ShellStep.Builder.create("validate") .input(synth) .commands(Arrays.asList("node ./tests/validate.js")) .build());
C#
var synth = new ShellStep("Synth", new ShellStepProps { Input = CodePipelineSource.GitHub("OWNER/REPO", "main"), Commands = new string[] { "npm install -g aws-cdk", "cdk synth" } }); var pipeline = new CodePipeline(this, "pipeline", new CodePipelineProps { PipelineName = "MyPipeline", Synth = synth }); var stage = pipeline.AddStage(new MyPipelineAppStage(this, "test", new StageProps { Env = new Environment { Account = "111111111111", Region = "eu-west-1" } })); stage.AddPost(new ShellStep("validate", new ShellStepProps { Input = synth, Commands = new string[] { "node ./tests/validate.js" } }));

Sicherheitshinweise

Jede Form von Continuous Delivery birgt inhärente Sicherheitsrisiken. Im Rahmen des Modells der AWS gemeinsamen Verantwortung sind Sie für die Sicherheit Ihrer Informationen in der AWS Cloud verantwortlich. Die CDK-Pipelines-Bibliothek verschafft Ihnen einen Vorsprung, indem sie sichere Standardeinstellungen und bewährte Modellierungsmethoden integriert.

Es liegt jedoch in der Natur der Sache, dass eine Bibliothek, die ein hohes Maß an Zugriff benötigt, um ihren beabsichtigten Zweck zu erfüllen, keine vollständige Sicherheit gewährleisten kann. Es gibt viele Angriffsvektoren außerhalb AWS und Ihres Unternehmens.

Beachten Sie insbesondere Folgendes:

  • Achten Sie auf die Software, auf die Sie angewiesen sind. Prüfen Sie alle Drittanbieter-Software, die Sie in Ihrer Pipeline ausführen, da sie die bereitgestellte Infrastruktur verändern kann.

  • Verwenden Sie das Sperren von Abhängigkeiten, um versehentliche Upgrades zu verhindern. CDK Pipelines respektiert package-lock.json und stellt yarn.lock sicher, dass Ihre Abhängigkeiten die sind, die Sie erwarten.

  • CDK Pipelines läuft auf Ressourcen, die in Ihrem eigenen Konto erstellt wurden, und die Konfiguration dieser Ressourcen wird von Entwicklern gesteuert, die Code über die Pipeline einreichen. Daher können CDK Pipelines allein nicht vor böswilligen Entwicklern schützen, die versuchen, Konformitätsprüfungen zu umgehen. Wenn Ihr Bedrohungsmodell Entwickler beinhaltet, die CDK-Code schreiben, sollten Sie externe Compliance-Mechanismen wie AWS CloudFormation Hooks (präventiv) oder AWS Config (reaktiv) einrichten, zu deren Deaktivierung die AWS CloudFormation Ausführungsrolle nicht berechtigt ist.

  • Anmeldeinformationen für Produktionsumgebungen sollten kurzlebig sein. Nach dem Bootstrapping und der ersten Bereitstellung benötigen Entwickler überhaupt keine Kontoanmeldeinformationen mehr. Änderungen können über die Pipeline bereitgestellt werden. Reduzieren Sie die Wahrscheinlichkeit, dass Anmeldeinformationen durchsickern, indem Sie sie gar nicht erst benötigen.

Fehlerbehebung

Die folgenden Probleme treten häufig bei den ersten Schritten mit CDK Pipelines auf.

Pipeline: Interner Fehler
CREATE_FAILED  | AWS::CodePipeline::Pipeline | Pipeline/Pipeline
Internal Failure

Überprüfen Sie Ihr GitHub Zugriffstoken. Es fehlt möglicherweise oder verfügt nicht über die erforderlichen Berechtigungen für den Zugriff auf das Repository.

Schlüssel: Die Richtlinie enthält eine Anweisung mit einem oder mehreren ungültigen Prinzipalen
CREATE_FAILED | AWS::KMS::Key | Pipeline/Pipeline/ArtifactsBucketEncryptionKey
Policy contains a statement with one or more invalid principals.

Eine der Zielumgebungen wurde nicht mit dem neuen Bootstrap-Stack gebootet. Stellen Sie sicher, dass alle Ihre Zielumgebungen bootstrapped sind.

Der Stack befindet sich im Status ROLLBACK_COMPLETE und kann nicht aktualisiert werden.
Stack STACK_NAME is in ROLLBACK_COMPLETE state and can not be updated. (Service:
AmazonCloudFormation; Status Code: 400; Error Code: ValidationError; Request
ID: ...)

Der Stack ist bei der vorherigen Bereitstellung fehlgeschlagen und befindet sich in einem Zustand, der nicht erneut versucht werden kann. Löschen Sie den Stack von der AWS CloudFormation Konsole und wiederholen Sie die Bereitstellung.