上下文值和 AWS CDK - AWS Cloud Development Kit (AWS CDK) v2

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

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

上下文值和 AWS CDK

上下文值是可以與應用程序,堆棧或構造關聯的鍵值對。它們可以從文件(通常或在您的項目目錄中)cdk.jsoncdk.context.json在命令行上提供給您的應用程序。

該CDK工具包使用上下文緩存在合成期間從您的 AWS 帳戶中檢索到的值。值包括帳戶中的可用區域,或 Amazon 執行個體IDs目前可用的 EC2 Amazon 機器映像 (AMI)。由於這些值是由您的 AWS 帳戶提供的,因此它們可以在CDK應用程式執行之間進行變更。這使得它們成為意外改變的潛在來源。CDKToolkit 的緩存行為「凍結」您的CDK應用程序的這些值,直到您決定接受新值。

想像下面沒有上下文緩存的情況。假設您為您的 Amazon 實例指定了「最新AMI的 EC2 Amazon Linux」,並發布AMI了新版本的版本。然後,下次您部署CDK堆疊時,您已經部署的執行個體將會使用過期的執行個體 (「錯誤」),AMI而且需要升級。升級將導致用新的實例替換所有現有實例,這可能是意外且不希望的。

相反,將您的帳戶CDK記錄AMIs在項目cdk.context.json文件中可用,並將存儲值用於 future 的合成操作。這樣,列表不再AMIs是潛在的變化來源。您還可以確保堆棧將始終合成到相同的 AWS CloudFormation 模板中。

並非所有上下文值都是從您的 AWS 環境中緩存的值。 AWS CDK 特徵旗標也是上下文值。您也可以建立自己的內容值,供應用程式或建構使用。

上下文鍵是字符串。值可以是支持的任何類型JSON:數字,字符串,數組或對象。

提示

如果您的構造創建自己的上下文值,請將庫的包名稱合併到其鍵中,以便它們不會與其他軟件包的上下文值衝突。

許多上下文值都與特定 AWS 環境相關聯,並且給定的CDK應用程序可以部署在多個環境中。這些值的鍵包括 AWS 帳戶和區域,以便來自不同環境的值不會發生衝突。

下列內容索引鍵說明了使用的格式 AWS CDK,包括帳戶與區域。

availability-zones:account=123456789012:region=eu-central-1
重要

快取的內容值由 AWS CDK 及其建構管理,包括您可以撰寫的建構。請勿透過手動編輯檔案來新增或變更快取的內容值。不過,cdk.context.json偶爾檢閱以查看快取的值可能會很有用。不代表快取值的內容值應儲存在的context索引鍵下cdk.json。這樣,當緩存值被清除時,它們不會被清除。

上下文值的來源

上下文值可以通過六種不同的方式提供給您的 AWS CDK 應用程序:

  • 自動從當前 AWS 帳戶。

  • 通過--context選項的cdk命令。(這些值始終是字符串。)

  • 在專案的cdk.context.json檔案中。

  • 在項目cdk.json文件的context密鑰中。

  • 在你的~/.cdk.json文件的context密鑰。

  • 在您的 AWS CDK 應用程序中使用該construct.node.setContext()方法。

專案檔案cdk.context.json是 AWS CDK 快取從您 AWS 帳戶擷取的內容值的位置。例如,引入新的可用區域時,此做法可避免部署發生非預期的變更。 AWS CDK 不會將內容資料寫入列出的任何其他檔案。

重要

因為它們是應用程序狀態的一部分,cdk.json並且cdk.context.json必須與應用程序的源代碼的其餘部分一起致力於源代碼控制。否則,在其他環境 (例如 CI 管線) 中的部署可能會產生不一致的結果。

前後關聯值的範圍是建立它們的建構;它們對子建構是可見的,但父項或同層級則不可見。由 AWS CDK Toolkit (cdk命令) 設定的前後關聯值可以自動設定、從檔案或從--context選項設定。這些來源的前後關聯值會在App建構上隱含地設定。因此,應用程序中每個堆棧中的每個構造都可以看到它們。

您的應用程序可以使用該construct.node.tryGetContext方法讀取上下文值。如果在當前構造或其任何父項上找不到請求的條目,則結果為undefined。(或者,結果可能是您的語言的等價物,例如None在 Python 中。)

內容方法

AWS CDK 支援數種內容方法,可讓 AWS CDK 應用程式從 AWS 環境中取得內容資訊。例如,您可以使用堆疊取得指定 AWS 帳戶和區域中可用的可用區域清單。 availabilityZones方法。

以下是上下文方法:

HostedZone.fromLookup

取得帳戶中的託管區域。

堆疊。 availabilityZones

取得支援的可用區域。

StringParameter.valueFromLookup

從目前區域的 Amazon EC2 Systems Manager 參數存放區取得值。

VPC。 fromLookup

取得您帳戶中現有的 Amazon 虛擬私有雲。

LookupMachineImage

查詢機器映像檔,以便與 Amazon 虛擬私有雲中的NAT執行個體搭配使用。

如果所需的上下文值不可用, AWS CDK 應用程序會通知 CDK Toolkit 缺少上下文信息。接下來,會CLI查詢目前 AWS 帳戶中的資訊,並將產生的前後關聯資訊儲存在cdk.context.json檔案中。然後,它使用上下文值再次執行 AWS CDK 應用程序。

檢視及管理前後關聯

使用cdk context指令檢視和管理cdk.context.json檔案中的資訊。若要查看此資訊,請不要使用任何選項的cdk context指令。輸出應該是如下所示。

Context found in cdk.json:

┌───┬─────────────────────────────────────────────────────────────┬─────────────────────────────────────────────────────────┐
│ # │ Key                                                         │ Value                                                   │
├───┼─────────────────────────────────────────────────────────────┼─────────────────────────────────────────────────────────┤
│ 1 │ availability-zones:account=123456789012:region=eu-central-1 │ [ "eu-central-1a", "eu-central-1b", "eu-central-1c" ]   │
├───┼─────────────────────────────────────────────────────────────┼─────────────────────────────────────────────────────────┤
│ 2 │ availability-zones:account=123456789012:region=eu-west-1    │ [ "eu-west-1a", "eu-west-1b", "eu-west-1c" ]            │
└───┴─────────────────────────────────────────────────────────────┴─────────────────────────────────────────────────────────┘

Run cdk context --reset KEY_OR_NUMBER to remove a context key. If it is a cached value, it will be refreshed on the next cdk synth.

要刪除上下文值,請運行cdk context --reset,並指定該值的對應鍵或數字。下列範例會移除與前述範例中第二個索引鍵對應的值。此值代表歐洲 (愛爾蘭) 區域的可用區域清單。

cdk context --reset 2
Context value
availability-zones:account=123456789012:region=eu-west-1
reset. It will be refreshed on the next SDK synthesis run.

因此,如果您想要更新到最新版本的 Amazon LinuxAMI,請使用上述範例對內容值進行控制更新並重設。然後,再次合成並部署您的應用程序。

cdk synth

若要清除應用程式的所有儲存內容值,請執行cdk context --clear下列步驟。

cdk context --clear

只有儲存在中的前後關聯值cdk.context.json可以重設或清除。 AWS CDK 不會接觸其他內容值。因此,若要防止使用這些指令重設前後關聯值,您可以將值複製到cdk.json

AWS CDK 工具包--context標誌

在合成或部署期間,使用--context-c簡稱)選項將運行時上下文值傳遞給您的CDK應用程序。

cdk synth --context key=value MyStack

若要指定多個內容值,請重複--context此選項任意次數,每次提供一個索引鍵值配對。

cdk synth --context key1=value1 --context key2=value2 MyStack

合成多個堆棧時,指定的上下文值將傳遞給所有堆棧。要為單個堆棧提供不同的上下文值,請為值使用不同的鍵,或者使用多個cdk synthcdk deploy命令。

從命令行傳遞的上下文值始終是字符串。如果值通常是其他類型,您的程式碼必須準備好轉換或剖析該值。您可能有以其他方式提供的非字串內容值 (例如,在中cdk.context.json)。若要確定這種值如預期般運作,請在轉換之前確認該值是字串。

範例

以下是使用使用上下 AWS CDK 文現有的 Amazon 的一VPC個例子。

TypeScript
import * as cdk from 'aws-cdk-lib'; import * as ec2 from 'aws-cdk-lib/aws-ec2'; import { Construct } from 'constructs'; export class ExistsVpcStack extends cdk.Stack { constructor(scope: Construct, id: string, props?: cdk.StackProps) { super(scope, id, props); const vpcid = this.node.tryGetContext('vpcid'); const vpc = ec2.Vpc.fromLookup(this, 'VPC', { vpcId: vpcid, }); const pubsubnets = vpc.selectSubnets({subnetType: ec2.SubnetType.PUBLIC}); new cdk.CfnOutput(this, 'publicsubnets', { value: pubsubnets.subnetIds.toString(), }); } }
JavaScript
const cdk = require('aws-cdk-lib'); const ec2 = require('aws-cdk-lib/aws-ec2'); class ExistsVpcStack extends cdk.Stack { constructor(scope, id, props) { super(scope, id, props); const vpcid = this.node.tryGetContext('vpcid'); const vpc = ec2.Vpc.fromLookup(this, 'VPC', { vpcId: vpcid }); const pubsubnets = vpc.selectSubnets({subnetType: ec2.SubnetType.PUBLIC}); new cdk.CfnOutput(this, 'publicsubnets', { value: pubsubnets.subnetIds.toString() }); } } module.exports = { ExistsVpcStack }
Python
import aws_cdk as cdk import aws_cdk.aws_ec2 as ec2 from constructs import Construct class ExistsVpcStack(cdk.Stack): def __init__(scope: Construct, id: str, **kwargs): super().__init__(scope, id, **kwargs) vpcid = self.node.try_get_context("vpcid") vpc = ec2.Vpc.from_lookup(self, "VPC", vpc_id=vpcid) pubsubnets = vpc.select_subnets(subnetType=ec2.SubnetType.PUBLIC) cdk.CfnOutput(self, "publicsubnets", value=pubsubnets.subnet_ids.to_string())
Java
import software.amazon.awscdk.CfnOutput; import software.amazon.awscdk.services.ec2.Vpc; import software.amazon.awscdk.services.ec2.VpcLookupOptions; import software.amazon.awscdk.services.ec2.SelectedSubnets; import software.amazon.awscdk.services.ec2.SubnetSelection; import software.amazon.awscdk.services.ec2.SubnetType; import software.constructs.Construct; public class ExistsVpcStack extends Stack { public ExistsVpcStack(Construct context, String id) { this(context, id, null); } public ExistsVpcStack(Construct context, String id, StackProps props) { super(context, id, props); String vpcId = (String)this.getNode().tryGetContext("vpcid"); Vpc vpc = (Vpc)Vpc.fromLookup(this, "VPC", VpcLookupOptions.builder() .vpcId(vpcId).build()); SelectedSubnets pubSubNets = vpc.selectSubnets(SubnetSelection.builder() .subnetType(SubnetType.PUBLIC).build()); CfnOutput.Builder.create(this, "publicsubnets") .value(pubSubNets.getSubnetIds().toString()).build(); } }
C#
using Amazon.CDK; using Amazon.CDK.AWS.EC2; using Constructs; class ExistsVpcStack : Stack { public ExistsVpcStack(Construct scope, string id, StackProps props) : base(scope, id, props) { var vpcId = (string)this.Node.TryGetContext("vpcid"); var vpc = Vpc.FromLookup(this, "VPC", new VpcLookupOptions { VpcId = vpcId }); SelectedSubnets pubSubNets = vpc.SelectSubnets([new SubnetSelection { SubnetType = SubnetType.PUBLIC }]); new CfnOutput(this, "publicsubnets", new CfnOutputProps { Value = pubSubNets.SubnetIds.ToString() }); } }

您可以使cdk diff用在命令行上查看傳遞上下文值的效果:

cdk diff -c vpcid=vpc-0cb9c31031d0d3e22
Stack ExistsvpcStack
Outputs
[+] Output publicsubnets publicsubnets: {"Value":"subnet-06e0ea7dd302d3e8f,subnet-01fc0acfb58f3128f"}

您可以檢視產生的前後關聯值,如下所示。

cdk context -j
{
  "vpc-provider:account=123456789012:filter.vpc-id=vpc-0cb9c31031d0d3e22:region=us-east-1": {
    "vpcId": "vpc-0cb9c31031d0d3e22",
    "availabilityZones": [
      "us-east-1a",
      "us-east-1b"
    ],
    "privateSubnetIds": [
      "subnet-03ecfc033225be285",
      "subnet-0cded5da53180ebfa"
    ],
    "privateSubnetNames": [
      "Private"
    ],
    "privateSubnetRouteTableIds": [
      "rtb-0e955393ced0ada04",
      "rtb-05602e7b9f310e5b0"
    ],
    "publicSubnetIds": [
      "subnet-06e0ea7dd302d3e8f",
      "subnet-01fc0acfb58f3128f"
    ],
    "publicSubnetNames": [
      "Public"
    ],
    "publicSubnetRouteTableIds": [
      "rtb-00d1fdfd823c82289",
      "rtb-04bb1969b42969bcb"
    ]
  }
}