從建構資料庫自訂 AWS 建構 - AWS Cloud Development Kit (AWS CDK) V2

這是 AWS CDK v2 開發人員指南。較舊的 CDK 第 1 版已於 2022 年 6 月 1 日進入維護,並於 2023 年 6 月 1 日結束支援。

本文為英文版的機器翻譯版本,如內容有任何歧義或不一致之處,概以英文版為準。

從建構資料庫自訂 AWS 建構

透過逸出剖面線、原始取代和自訂資源,自訂 AWS 建構資源庫中的建構。

使用逃生艙口

AWS 構庫提供了不同級別的抽象的構造。

在最高層級,您的 AWS CDK 應用程式及其中的堆疊本身就是整個雲端基礎架構的抽象概念,或其中的重要區塊。它們可以被參數化,以將它們部署在不同的環境或不同的需求。

抽象是設計和實作雲端應用程式的強大工具。您不僅可以使用其抽象來構建,還可以創建新的抽象。 AWS CDK 使用現有的開放原始碼 L2 和 L3 建構做為指引,您可以建置自己的 L2 和 L3 建構,以反映您自己組織的最佳做法和意見。

沒有抽象是完美的,即使是好的抽象也不能涵蓋每個可能的用例。在開發過程中,您可能會發現幾乎符合您需求的構造,需要小型或大型定制。

因此, AWS CDK 提供了拆解建構模型的方法。這包括移動到較低級別的抽象或完全不同的模型。逃生艙口可讓您逃脫 AWS CDK 範式,並以適合您需求的方式對其進行自定義。然後,您可以將更改包裝在新構造中,以抽像出底層複雜性並為其他開發人員提供乾淨的 API。

以下是您可以使用逸出填充線的情況範例:

  • AWS 服務功能可透過使用 AWS CloudFormation,但沒有 L2 建構。

  • AWS 服務功能可透過使用 AWS CloudFormation,而且有 L2 結構的服務,但這些結構尚未公開此功能。由於 L2 結構是由 CDK 團隊策劃的,因此它們可能無法立即用於新功能。

  • 該功能 AWS CloudFormation 根本無法通過使用。

    若要判斷功能是否可透過使用 AWS CloudFormation,請參閱AWS 資源和屬性類型參考

開發 L1 構造的逃生艙口

如果 L2 建構不可用於服務,您可以使用自動產生的 L1 建構。這些資源可以透過名稱開頭來辨識Cfn,例如CfnBucketCfnRole。您可以像使用對等 AWS CloudFormation 資源一樣實例化它們。

例如,若要在啟用分析的情況下實例化低階 Amazon S3 儲存貯體 L1,您可以撰寫類似下列內容。

TypeScript
new s3.CfnBucket(this, 'MyBucket', { analyticsConfigurations: [ { id: 'Config', // ... } ] });
JavaScript
new s3.CfnBucket(this, 'MyBucket', { analyticsConfigurations: [ { id: 'Config' // ... } ] });
Python
s3.CfnBucket(self, "MyBucket", analytics_configurations: [ dict(id="Config", # ... ) ] )
Java
CfnBucket.Builder.create(this, "MyBucket") .analyticsConfigurations(Arrays.asList(java.util.Map.of( // Java 9 or later "id", "Config", // ... ))).build();
C#
new CfnBucket(this, 'MyBucket', new CfnBucketProps { AnalyticsConfigurations = new Dictionary<string, string> { ["id"] = "Config", // ... } });

在極少數情況下,您想要定義沒有對應CfnXxx類別的資源。這可能是尚未在資源規格中發佈的新資 AWS CloudFormation 源類型。在這種情況下,您可以cdk.CfnResource直接實例化並指定資源類型和屬性。如以下範例所示。

TypeScript
new cdk.CfnResource(this, 'MyBucket', { type: 'AWS::S3::Bucket', properties: { // Note the PascalCase here! These are CloudFormation identifiers. AnalyticsConfigurations: [ { Id: 'Config', // ... } ] } });
JavaScript
new cdk.CfnResource(this, 'MyBucket', { type: 'AWS::S3::Bucket', properties: { // Note the PascalCase here! These are CloudFormation identifiers. AnalyticsConfigurations: [ { Id: 'Config' // ... } ] } });
Python
cdk.CfnResource(self, 'MyBucket', type="AWS::S3::Bucket", properties=dict( # Note the PascalCase here! These are CloudFormation identifiers. "AnalyticsConfigurations": [ { "Id": "Config", # ... } ] } )
Java
CfnResource.Builder.create(this, "MyBucket") .type("AWS::S3::Bucket") .properties(java.util.Map.of( // Map.of requires Java 9 or later // Note the PascalCase here! These are CloudFormation identifiers "AnalyticsConfigurations", Arrays.asList( java.util.Map.of("Id", "Config", // ... )))) .build();
C#
new CfnResource(this, "MyBucket", new CfnResourceProps { Type = "AWS::S3::Bucket", Properties = new Dictionary<string, object> { // Note the PascalCase here! These are CloudFormation identifiers ["AnalyticsConfigurations"] = new Dictionary<string, string>[] { new Dictionary<string, string> { ["Id"] = "Config" } } } });

開發 L2 結構的逃生艙口

如果 L2 建構遺失特徵,或者您嘗試解決問題,您可以修改由 L2 建構封裝的 L1 建構。

所有 L2 建構都包含相應的 L1 建構。例如,高層Bucket建構會包裝低層CfnBucket建構。由CfnBucket於直接對應於 AWS CloudFormation 資源,因此它會公開透過 AWS CloudFormation提供的所有功能。

訪問 L1 構造的基本方法是使用 construct.node.defaultChild (Python:default_child),將其轉換為正確的類型(如有必要),並修改其屬性。同樣地,讓我們以Bucket.

TypeScript
// Get the CloudFormation resource const cfnBucket = bucket.node.defaultChild as s3.CfnBucket; // Change its properties cfnBucket.analyticsConfiguration = [ { id: 'Config', // ... } ];
JavaScript
// Get the CloudFormation resource const cfnBucket = bucket.node.defaultChild; // Change its properties cfnBucket.analyticsConfiguration = [ { id: 'Config' // ... } ];
Python
# Get the CloudFormation resource cfn_bucket = bucket.node.default_child # Change its properties cfn_bucket.analytics_configuration = [ { "id": "Config", # ... } ]
Java
// Get the CloudFormation resource CfnBucket cfnBucket = (CfnBucket)bucket.getNode().getDefaultChild(); cfnBucket.setAnalyticsConfigurations( Arrays.asList(java.util.Map.of( // Java 9 or later "Id", "Config", // ... ));
C#
// Get the CloudFormation resource var cfnBucket = (CfnBucket)bucket.Node.DefaultChild; cfnBucket.AnalyticsConfigurations = new List<object> { new Dictionary<string, string> { ["Id"] = "Config", // ... } };

您也可以使用此物件來變更 AWS CloudFormation 選項,例如MetadataUpdatePolicy

TypeScript
cfnBucket.cfnOptions.metadata = { MetadataKey: 'MetadataValue' };
JavaScript
cfnBucket.cfnOptions.metadata = { MetadataKey: 'MetadataValue' };
Python
cfn_bucket.cfn_options.metadata = { "MetadataKey": "MetadataValue" }
Java
cfnBucket.getCfnOptions().setMetadata(java.util.Map.of( // Java 9+ "MetadataKey", "Metadatavalue"));
C#
cfnBucket.CfnOptions.Metadata = new Dictionary<string, object> { ["MetadataKey"] = "Metadatavalue" };

非逃生艙口

該 AWS CDK 還提供了上抽象級別的能力,我們可以將其稱為「未逃脫」孵化。如果您有 L1 建構,例如CfnBucket,您可以建立新的 L2 建構 (Bucket在本例中為) 來包裝 L1 建構。

當您建立 L1 資源,但想要將其與需要 L2 資源的建構搭配使用時,這很方便。當您想要使用 L1 構造中不可用的便利方法時,.grantXxxxx()這也很有幫助。

您可以使用 L2 類別上的靜態方法移至較高的抽象層級,.fromCfnXxxxx()例如 Amazon S3 儲存貯Bucket.fromCfnBucket()體。L1 資源是唯一的參數。

TypeScript
b1 = new s3.CfnBucket(this, "buck09", { ... }); b2 = s3.Bucket.fromCfnBucket(b1);
JavaScript
b1 = new s3.CfnBucket(this, "buck09", { ...} ); b2 = s3.Bucket.fromCfnBucket(b1);
Python
b1 = s3.CfnBucket(self, "buck09", ...) b2 = s3.from_cfn_bucket(b1)
Java
CfnBucket b1 = CfnBucket.Builder.create(this, "buck09") // .... .build(); IBucket b2 = Bucket.fromCfnBucket(b1);
C#
var b1 = new CfnBucket(this, "buck09", new CfnBucketProps { ... }); var v2 = Bucket.FromCfnBucket(b1);

從 L1 建構建立的 L2 建構是參考 L1 資源的 Proxy 物件,類似於從資源名稱、ARN 或查詢建立的物件。對這些結構的修改不會影響最終的合成 AWS CloudFormation 模板(因為您有 L1 資源,但是,您可以改為修改它)。如需代理物件的更多資訊,請參閱參考您 AWS 帳戶中的資源

為避免混淆,請勿建立多個參考相同 L1 建構的 L2 建構。例如,如果您CfnBucket上一節中的 using 技術中提取,則不應通過調BucketBucket.fromCfnBucket()用該Bucket實例來創建第二個實例CfnBucket。它實際上按照您的期望工作(只AWS::S3::Bucket有一個合成),但它使您的代碼更難維護。

原始取代

如果 L1 建構中缺少某些性質,您可以使用原始取代略過所有鍵入。這也使得可以刪除合成屬性。

使用其中一個addOverride方法 (Python:add_override) 方法,如下列範例所示。

TypeScript
// Get the CloudFormation resource const cfnBucket = bucket.node.defaultChild as s3.CfnBucket; // Use dot notation to address inside the resource template fragment cfnBucket.addOverride('Properties.VersioningConfiguration.Status', 'NewStatus'); cfnBucket.addDeletionOverride('Properties.VersioningConfiguration.Status'); // use index (0 here) to address an element of a list cfnBucket.addOverride('Properties.Tags.0.Value', 'NewValue'); cfnBucket.addDeletionOverride('Properties.Tags.0'); // addPropertyOverride is a convenience function for paths starting with "Properties." cfnBucket.addPropertyOverride('VersioningConfiguration.Status', 'NewStatus'); cfnBucket.addPropertyDeletionOverride('VersioningConfiguration.Status'); cfnBucket.addPropertyOverride('Tags.0.Value', 'NewValue'); cfnBucket.addPropertyDeletionOverride('Tags.0');
JavaScript
// Get the CloudFormation resource const cfnBucket = bucket.node.defaultChild ; // Use dot notation to address inside the resource template fragment cfnBucket.addOverride('Properties.VersioningConfiguration.Status', 'NewStatus'); cfnBucket.addDeletionOverride('Properties.VersioningConfiguration.Status'); // use index (0 here) to address an element of a list cfnBucket.addOverride('Properties.Tags.0.Value', 'NewValue'); cfnBucket.addDeletionOverride('Properties.Tags.0'); // addPropertyOverride is a convenience function for paths starting with "Properties." cfnBucket.addPropertyOverride('VersioningConfiguration.Status', 'NewStatus'); cfnBucket.addPropertyDeletionOverride('VersioningConfiguration.Status'); cfnBucket.addPropertyOverride('Tags.0.Value', 'NewValue'); cfnBucket.addPropertyDeletionOverride('Tags.0');
Python
# Get the CloudFormation resource cfn_bucket = bucket.node.default_child # Use dot notation to address inside the resource template fragment cfn_bucket.add_override("Properties.VersioningConfiguration.Status", "NewStatus") cfn_bucket.add_deletion_override("Properties.VersioningConfiguration.Status") # use index (0 here) to address an element of a list cfn_bucket.add_override("Properties.Tags.0.Value", "NewValue") cfn_bucket.add_deletion_override("Properties.Tags.0") # addPropertyOverride is a convenience function for paths starting with "Properties." cfn_bucket.add_property_override("VersioningConfiguration.Status", "NewStatus") cfn_bucket.add_property_deletion_override("VersioningConfiguration.Status") cfn_bucket.add_property_override("Tags.0.Value", "NewValue") cfn_bucket.add_property_deletion_override("Tags.0")
Java
// Get the CloudFormation resource CfnBucket cfnBucket = (CfnBucket)bucket.getNode().getDefaultChild(); // Use dot notation to address inside the resource template fragment cfnBucket.addOverride("Properties.VersioningConfiguration.Status", "NewStatus"); cfnBucket.addDeletionOverride("Properties.VersioningConfiguration.Status"); // use index (0 here) to address an element of a list cfnBucket.addOverride("Properties.Tags.0.Value", "NewValue"); cfnBucket.addDeletionOverride("Properties.Tags.0"); // addPropertyOverride is a convenience function for paths starting with "Properties." cfnBucket.addPropertyOverride("VersioningConfiguration.Status", "NewStatus"); cfnBucket.addPropertyDeletionOverride("VersioningConfiguration.Status"); cfnBucket.addPropertyOverride("Tags.0.Value", "NewValue"); cfnBucket.addPropertyDeletionOverride("Tags.0");
C#
// Get the CloudFormation resource var cfnBucket = (CfnBucket)bucket.node.defaultChild; // Use dot notation to address inside the resource template fragment cfnBucket.AddOverride("Properties.VersioningConfiguration.Status", "NewStatus"); cfnBucket.AddDeletionOverride("Properties.VersioningConfiguration.Status"); // use index (0 here) to address an element of a list cfnBucket.AddOverride("Properties.Tags.0.Value", "NewValue"); cfnBucket.AddDeletionOverride("Properties.Tags.0"); // addPropertyOverride is a convenience function for paths starting with "Properties." cfnBucket.AddPropertyOverride("VersioningConfiguration.Status", "NewStatus"); cfnBucket.AddPropertyDeletionOverride("VersioningConfiguration.Status"); cfnBucket.AddPropertyOverride("Tags.0.Value", "NewValue"); cfnBucket.AddPropertyDeletionOverride("Tags.0");

自訂資源

如果該功能無法通過使用 AWS CloudFormation,但僅通過直接 API 調用,則必須編寫 AWS CloudFormation 自定義資源以進行所需的 API 調用。您可以使用編寫 AWS CDK 自訂資源,並將其封裝到一般建構介面中。從構造的消費者的角度來看,體驗將感覺到原生。

建置自訂資源涉及撰寫 Lambda 函數來回應資源的CREATEUPDATE、和DELETE生命週期事件。如果您的自訂資源只需要進行單一 API 呼叫,請考慮使用 AwsCustomResource. 這樣可以在 AWS CloudFormation 部署期間執行任意 SDK 呼叫。否則,您應該編寫自己的 Lambda 函數來執行完成所需的工作。

主題太廣泛了,無法完全涵蓋在這裡,但是以下鏈接應該可以幫助您開始: