翻訳は機械翻訳により提供されています。提供された翻訳内容と英語版の間で齟齬、不一致または矛盾がある場合、英語版が優先します。
レイヤー 3 コンストラクト
L1 コンストラクトが CloudFormation リソースをプログラムコードにリテラル変換し、L2 コンストラクトが詳細な CloudFormation 構文の多くをヘルパーメソッドとカスタムロジックに置き換える場合、L3 コンストラクトは何をしますか? その答えは、想像力によってのみ制限されます。特定のユースケースに合わせてレイヤー 3 を作成できます。プロジェクトに特定のプロパティのサブセットを持つリソースが必要な場合は、そのニーズを満たすために再利用可能な L3 コンストラクトを作成できます。
L3 コンストラクトは、 内のパターンと呼ばれます AWS CDK。パターンは、 のConstructクラスを拡張する AWS CDK (またはクラスを拡張するConstruct クラスを拡張する) オブジェクトで、レイヤー 2 を超えて抽象化されたロジックを実行します。 AWS CDK CLI を使用して cdk init を実行して新しい AWS CDK プロジェクトを開始する場合は、app、、 libの 3 つの AWS CDK アプリケーションタイプから選択する必要がありますsample-app。
app と sample-appはどちらも、CloudFormation スタックを構築して AWS 環境にデプロイする従来の AWS CDK アプリケーションを表します。を選択するとlib、まったく新しい L3 コンストラクトの構築が選択されます。 appと sample-appでは、 が AWS CDK サポートする任意の言語を選択できますが、 では TypeScript しか選択できませんlib。これは、 AWS CDK が TypeScript でネイティブに記述され、JSiilibを開始する場合は、 の拡張機能を構築することを選択します AWS CDK。
Construct クラスを拡張するクラスは L3 コンストラクトにすることができますが、レイヤー 3 の最も一般的なユースケースは、リソースインタラクション、リソース拡張、カスタムリソースです。ほとんどの L3 コンストラクトは、機能を拡張 AWS CDK するために、これら 3 つのケースのうち 1 つ以上を使用します。
リソースインタラクション
ソリューションは通常、連携する複数の AWS サービスを使用します。例えば、Amazon CloudFront ディストリビューションでは、S3 バケットをオリジンとして使用し、一般的なエクスプロイトから保護 AWS WAF することがよくあります。 AWS AppSync Amazon API Gateway では、APIs のデータソースとして Amazon DynamoDB テーブルがよく使用されます。のパイプラインでは、Amazon S3 をソースとして使用し、ビルドステージ AWS CodeBuild に使用する AWS CodePipeline ことがよくあります。このような場合、2 つ以上の相互接続された L2 コンストラクトのプロビジョニングを処理する単一の L3 コンストラクトを作成すると便利です。 L2
CloudFront ディストリビューションを SL3 オリジン、その前に配置 AWS WAF する 、Amazon Route 53 レコード、転送中の暗号化でカスタムエンドポイントを追加する AWS Certificate Manager (ACM) 証明書とともにプロビジョニングする L3 コンストラクトの例を次に示します。これらはすべて 1 つの再利用可能なコンストラクトです。 S3
// Define the properties passed to the L3 construct export interface CloudFrontWebsiteProps { distributionProps: DistributionProps bucketProps: BucketProps wafProps: CfnWebAclProps zone: IHostedZone } // Define the L3 construct export class CloudFrontWebsite extends Construct { public distribution: Distribution constructor( scope: Construct, id: string, props: CloudFrontWebsiteProps ) { super(scope, id); const certificate = new Certificate(this, "Certificate", { domainName: props.zone.zoneName, validation: CertificateValidation.fromDns(props.zone) }); const defaultBehavior = { origin: new S3Origin(new Bucket(this, "bucket", props.bucketProps)) } const waf = new CfnWebACL(this, "waf", props.wafProps); this.distribution = new Distribution(this, id, { ...props.distributionProps, defaultBehavior, certificate, domainNames: [this.domainName], webAclId: waf.attrArn, }); } }
CloudFront、Amazon S3、Route 53、ACM はすべて L2 コンストラクトを使用しますが、ウェブ ACL (ウェブリクエストを処理するルールを定義する) は L1 コンストラクトを使用することに注意してください。これは、 AWS CDK は完全には完了していない進化するオープンソースパッケージであり、WebAclまだ L2 コンストラクトがないためです。ただし、新しい L2 コンストラクトを作成 AWS CDK することで、誰でも に貢献できます。したがって、 が の L2 コンストラクト AWS CDK を提供するまではWebAcl、L1 コンストラクトを使用する必要があります。L3 コンストラクト を使用して新しいウェブサイトを作成するにはCloudFrontWebsite、次のコードを使用します。
const siteADotCom = new CloudFrontWebsite(stack, "siteA", siteAProps); const siteBDotCom = new CloudFrontWebsite(stack, "siteB", siteBProps); const siteCDotCom = new CloudFrontWebsite(stack, "siteC", siteCProps);
この例では、CloudFront L2 Distribution コンストラクトは L3 コンストラクトのパブリックプロパティとして公開されています。必要に応じて、このような L3 プロパティを公開する必要がある場合もあります。実際には、後で「カスタムリソース」セクションでDistributionもう一度確認します。
AWS CDK には、このようなリソースインタラクションパターンの例がいくつか含まれています。Amazon Elastic Container Service (Amazon ECS) の L2 コンストラクトを含むaws-ecsパッケージに加えて、 AWS CDK には aws-ecs-patterns というパッケージがあります。このパッケージには、Amazon ECS を Application Load Balancer、Network Load Balancer、およびターゲットグループと組み合わせながら、Amazon Elastic Compute Cloud (Amazon EC2) および 用にプリセットされたさまざまなバージョンを提供する複数の L3 コンストラクトが含まれています AWS Fargate。多くのサーバーレスアプリケーションは Fargate でのみ Amazon ECS を使用するため、これらの L3 コンストラクトは開発者の時間と顧客のコストを削減できる利便性を提供します。
リソース拡張機能
一部のユースケースでは、リソースに L2 コンストラクトにネイティブではない特定のデフォルト設定が必要です。スタックレベルでは、これは側面を使用して処理できますが、L2 コンストラクトに新しいデフォルトを付与するもう 1 つの便利な方法は、レイヤー 2 を拡張することです。コンストラクトはクラスを継承する任意のConstructクラスであり、L2 コンストラクトはそのクラスを拡張するため、L2 コンストラクトを直接拡張して L3 コンストラクトを作成することもできます。 L2
これは、顧客の単一のニーズをサポートするカスタムビジネスロジックに特に役立ちます。ある会社で、すべての AWS Lambda 関数コードを という単一のディレクトリに保存src/lambdaし、ほとんどの Lambda 関数が毎回同じランタイムとハンドラー名を再利用しているとします。新しい Lambda 関数を設定するたびにコードパスを設定する代わりに、新しい L3 コンストラクトを作成できます。
export class MyCompanyLambdaFunction extends Function { constructor( scope: Construct, id: string, props: Partial<FunctionProps> = {} ) { super(scope, id, { handler: 'index.handler', runtime: Runtime.NODEJS_LATEST, code: Code.fromAsset(`src/lambda/${props.functionName || id}`), ...props }); }
その後、次のようにリポジトリ内の任意の場所で L2 Functionコンストラクトを置き換えることができます。
new MyCompanyLambdaFunction(this, "MyFunction"); new MyCompanyLambdaFunction(this, "MyOtherFunction"); new MyCompanyLambdaFunction(this, "MyThirdFunction", { runtime: Runtime.PYTHON_3_11 });
デフォルトにより、新しい Lambda 関数を 1 行に作成でき、必要に応じてデフォルトのプロパティを上書きできるように L3 コンストラクトが設定されます。
既存の L2 コンストラクトに新しいデフォルトを追加するだけの場合、L2 コンストラクトを直接拡張するのが最適です。他のカスタムロジックも必要な場合は、 Construct クラスを拡張することをお勧めします。この理由は、コンストラクタ内で呼び出される superメソッドから生じます。他のクラスを拡張するクラスでは、 superメソッドを使用して親クラスのコンストラクタを呼び出します。これは、コンストラクタ内で最初に発生するものです。つまり、渡された引数やその他のカスタムロジックの操作は、元の L2 コンストラクトが作成された後にのみ実行できます。L2 コンストラクトをインスタンス化する前にこのカスタムロジックのいずれかを実行する必要がある場合は、リソースインタラクションセクションで前述したパターンに従うことをお勧めします。
カスタムリソース
カスタムリソースは CloudFormation の強力な機能であり、スタックのデプロイ中にアクティブ化された Lambda 関数からカスタムロジックを実行できます。CloudFormation で直接サポートされていないプロセスがデプロイ中に必要になる場合は、カスタムリソースを使用してそれを実現できます。 AWS CDK には、カスタムリソースをプログラムで作成できるクラスもあります。L3 コンストラクタ内でカスタムリソースを使用することで、ほとんどすべてのものからコンストラクトを作成できます。
Amazon CloudFront を使用する利点の 1 つは、強力なグローバルキャッシュ機能です。ウェブサイトにオリジンに加えられた新しい変更がすぐに反映されるように、そのキャッシュを手動でリセットする場合は、CloudFront 無効化を使用できます。ただし、無効化は、CloudFront ディストリビューションのプロパティではなく、CloudFront ディストリビューションで実行されるプロセスです。これらはいつでも作成して既存のディストリビューションに適用できるため、プロビジョニングとデプロイのプロセスにネイティブには含まれません。
このシナリオでは、ディストリビューションのオリジンが更新されるたびに無効化を作成して実行できます。カスタムリソースのため、次のような L3 コンストラクトを作成できます。
export interface CloudFrontInvalidationProps { distribution: Distribution region?: string paths?: string[] } export class CloudFrontInvalidation extends Construct { constructor( scope: Construct, id: string, props: CloudFrontInvalidationProps ) { super(scope, id); const policy = AwsCustomResourcePolicy.fromSdkCalls({ resources:AwsCustomResourcePolicy.ANY_RESOURCE }); new AwsCustomResource(scope, `${id}Invalidation`, { policy, onUpdate: { service: 'CloudFront', action: 'createInvalidation', region: props.region || 'us-east-1', physicalResourceId: PhysicalResourceId.fromResponse('Invalidation.Id'), parameters: { DistributionId: props.distribution.distributionId, InvalidationBatch: { Paths: { Quantity: props.paths?.length || 1, Items: props.paths || ['/*'] }, CallerReference: crypto.randomBytes(5).toString('hex') } } } } } }
L3 CloudFrontWebsite コンストラクトで先ほど作成したディストリビューションを使用すると、これを非常に簡単に実行できます。
new CloudFrontInvalidation(this, 'MyInvalidation', { distribution: siteADotCom.distribution });
この L3 コンストラクトは、AwsCustomResource と呼ばれる AWS CDK L3 コンストラクトを使用して、カスタムロジックを実行するカスタムリソースを作成します。 AwsCustomResourceは、Lambda コードを記述しなくても 1 つの AWS SDK 呼び出しを正確に行う必要がある場合に非常に便利です。より複雑な要件があり、独自のロジックを実装する場合は、基本的な CustomResource クラスを直接使用できます。
カスタムリソース L3 コンストラクト AWS CDK を使用する のもう 1 つの良い例は、S3 バケットのデプロイです。この L3 コンストラクトのコンストラクタ内のカスタムリソースによって作成された Lambda 関数は、CloudFormation が他の方法で処理できない機能を追加します。S3 バケット内のオブジェクトを追加および更新します。S3 バケットのデプロイがないと、スタックの一部として作成した S3 バケットにコンテンツを配置できないため、非常に不便です。
CloudFormation 構文のリームを書き出す必要がなく AWS CDK なるのに最適な例は、次の基本的な ですS3BucketDeployment。
new BucketDeployment(this, 'BucketObjects', { sources: [Source.asset('./path/to/amzn-s3-demo-bucket')], destinationBucket: amzn-s3-demo-bucket });
同じことを実行するために記述する必要がある CloudFormation コードと比較します。
"lambdapolicyA5E98E09": { "Type": "AWS::IAM::Policy", "Properties": { "PolicyDocument": { "Statement": [ { "Action": "lambda:UpdateFunctionCode", "Effect": "Allow", "Resource": "arn:aws:lambda:us-east-1:123456789012:function:my-function" } ], "Version": "2012-10-17" }, "PolicyName": "lambdaPolicy", "Roles": [ { "Ref": "myiamroleF09C7974" } ] }, "Metadata": { "aws:cdk:path": "CdkScratchStack/lambda-policy/Resource" } }, "BucketObjectsAwsCliLayer8C081206": { "Type": "AWS::Lambda::LayerVersion", "Properties": { "Content": { "S3Bucket": { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, "S3Key": "e2277687077a2abf9ae1af1cc9565e6715e2ebb62f79ec53aa75a1af9298f642.zip" }, "Description": "/opt/awscli/aws" }, "Metadata": { "aws:cdk:path": "CdkScratchStack/BucketObjects/AwsCliLayer/Resource", "aws:asset:path": "asset.e2277687077a2abf9ae1af1cc9565e6715e2ebb62f79ec53aa75a1af9298f642.zip", "aws:asset:is-bundled": false, "aws:asset:property": "Content" } }, "BucketObjectsCustomResourceB12E6837": { "Type": "Custom::CDKBucketDeployment", "Properties": { "ServiceToken": { "Fn::GetAtt": [ "CustomCDKBucketDeployment8693BB64968944B69AAFB0CC9EB8756C81C01536", "Arn" ] }, "SourceBucketNames": [ { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" } ], "SourceObjectKeys": [ "f888a9d977f0b5bdbc04a1f8f07520ede6e00d4051b9a6a250860a1700924f26.zip" ], "DestinationBucketName": { "Ref": "amzn-s3-demo-bucket77F80CC0" }, "Prune": true }, "UpdateReplacePolicy": "Delete", "DeletionPolicy": "Delete", "Metadata": { "aws:cdk:path": "CdkScratchStack/BucketObjects/CustomResource/Default" } }, "CustomCDKBucketDeployment8693BB64968944B69AAFB0CC9EB8756CServiceRole89A01265": { "Type": "AWS::IAM::Role", "Properties": { "AssumeRolePolicyDocument": { "Statement": [ { "Action": "sts:AssumeRole", "Effect": "Allow", "Principal": { "Service": "lambda.amazonaws.com" } } ], "Version": "2012-10-17" }, "ManagedPolicyArns": [ { "Fn::Join": [ "", [ "arn:", { "Ref": "AWS::Partition" }, ":iam::aws:policy/service-role/AWSLambdaBasicExecutionRole" ] ] } ] }, "Metadata": { "aws:cdk:path": "CdkScratchStack/Custom::CDKBucketDeployment8693BB64968944B69AAFB0CC9EB8756C/ServiceRole/Resource" } }, "CustomCDKBucketDeployment8693BB64968944B69AAFB0CC9EB8756CServiceRoleDefaultPolicy88902FDF": { "Type": "AWS::IAM::Policy", "Properties": { "PolicyDocument": { "Statement": [ { "Action": [ "s3:GetBucket*", "s3:GetObject*", "s3:List*" ], "Effect": "Allow", "Resource": [ { "Fn::Join": [ "", [ "arn:", { "Ref": "AWS::Partition" }, ":s3:::", { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, "/*" ] ] }, { "Fn::Join": [ "", [ "arn:", { "Ref": "AWS::Partition" }, ":s3:::", { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" } ] ] } ] }, { "Action": [ "s3:Abort*", "s3:DeleteObject*", "s3:GetBucket*", "s3:GetObject*", "s3:List*", "s3:PutObject", "s3:PutObjectLegalHold", "s3:PutObjectRetention", "s3:PutObjectTagging", "s3:PutObjectVersionTagging" ], "Effect": "Allow", "Resource": [ { "Fn::GetAtt": [ "amzns3demobucket77F80CC0", "Arn" ] }, { "Fn::Join": [ "", [ { "Fn::GetAtt": [ "amzns3demobucket77F80CC0", "Arn" ] }, "/*" ] ] } ] } ], "Version": "2012-10-17" }, "PolicyName": "CustomCDKBucketDeployment8693BB64968944B69AAFB0CC9EB8756CServiceRoleDefaultPolicy88902FDF", "Roles": [ { "Ref": "CustomCDKBucketDeployment8693BB64968944B69AAFB0CC9EB8756CServiceRole89A01265" } ] }, "Metadata": { "aws:cdk:path": "CdkScratchStack/Custom::CDKBucketDeployment8693BB64968944B69AAFB0CC9EB8756C/ServiceRole/DefaultPolicy/Resource" } }, "CustomCDKBucketDeployment8693BB64968944B69AAFB0CC9EB8756C81C01536": { "Type": "AWS::Lambda::Function", "Properties": { "Code": { "S3Bucket": { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, "S3Key": "9eb41a5505d37607ac419321497a4f8c21cf0ee1f9b4a6b29aa04301aea5c7fd.zip" }, "Role": { "Fn::GetAtt": [ "CustomCDKBucketDeployment8693BB64968944B69AAFB0CC9EB8756CServiceRole89A01265", "Arn" ] }, "Environment": { "Variables": { "AWS_CA_BUNDLE": "/etc/pki/ca-trust/extracted/pem/tls-ca-bundle.pem" } }, "Handler": "index.handler", "Layers": [ { "Ref": "BucketObjectsAwsCliLayer8C081206" } ], "Runtime": "python3.9", "Timeout": 900 }, "DependsOn": [ "CustomCDKBucketDeployment8693BB64968944B69AAFB0CC9EB8756CServiceRoleDefaultPolicy88902FDF", "CustomCDKBucketDeployment8693BB64968944B69AAFB0CC9EB8756CServiceRole89A01265" ], "Metadata": { "aws:cdk:path": "CdkScratchStack/Custom::CDKBucketDeployment8693BB64968944B69AAFB0CC9EB8756C/Resource", "aws:asset:path": "asset.9eb41a5505d37607ac419321497a4f8c21cf0ee1f9b4a6b29aa04301aea5c7fd", "aws:asset:is-bundled": false, "aws:asset:property": "Code" } }
4 行と 241 行は大きな違いです。これは、レイヤー 3 を活用してスタックをカスタマイズする場合に可能なことの一例にすぎません。