如何使用 aws cdk 管理多个环境?

Kes*_*uri 9 amazon-web-services typescript aws-cdk

我正在将我们的基础设施代码从 Terraform 转移到 AWS cdk。我正在尝试找到一种最佳方式来管理具有多个要部署的堆栈的多个环境。如果我遵循文档中的建议,我将不得不为多个环境定义多个堆栈,这可能会让人感到困惑。例如

const app = new cdk.App();

new DevStack1(app, 'dev-stack-1', settings.dev)
new DevStack2(app, 'dev-stack-2', settings.dev)
.
.


new ProdStack1(app, 'prod-stack-1', settings.prod)
new ProdStack2(app, 'prod-stack-2', settings.prod)
.
.

Run Code Online (Sandbox Code Playgroud)

在相同环境中的不同堆栈之间共享设置。然后我必须一个接一个地部署每个堆栈。有没有更好的方法来做到这一点?

Ole*_*oha 7

编辑:由于此答案具有合理数量的视图,我想对其进行更新以反映更好、更 CDK 的本机方法。我会在下面保留原始答案,因为它可能对某人更有效。

CDK 参数可以直接存储在cdk.jsonunder contextkey 中并使用ConstructNode.try_get_context(param_name).

查看官方文档:https : //docs.aws.amazon.com/cdk/latest/guide/get_context_var.html

因此,这是cdk.json针对不同环境使用不同参数的示例:

{
  "app": "python3 app.py",
  "context": {
    "dev": {
      "vpc": {
        "vpc_id": "blabla"
      }
    },
    "stage": {
      "vpc": {
        "vpc_id": "bleble"
      }
    }
}
Run Code Online (Sandbox Code Playgroud)

现在,您还可以通过 CLI 键提供上下文参数,--context env_name=dev并在代码中使用其值来获取相关设置。

实际上,大多数(如果不是全部)常用构造(如Stack, AppNestedStack都具有node属性,因此您可以从应用程序的任何位置访问上下文。

使用它有两个注意事项:

  1. 它不允许访问较低级别的密钥(或者至少没有记录)。这意味着您不能使用self.try_get_context("dev.vpc.vpc_id"),您需要通过检索顶级密钥self.try_get_context("dev")并自行下路。

  2. 如果您bool的上下文中有params 并尝试使用 CLI key 覆盖它们--context key=False,这些 params 将变成str,如果您使用以下常识语法,很容易陷入陷阱:

if self.try_get_context("deploy_vpc"):
    MyVPC(app, "my new vpc")
Run Code Online (Sandbox Code Playgroud)

由于“False”被评估True为非空字符串,因此您不会得到预期的结果。


旧答案

我不确定这是否存在共识,因为 CDK 仍然是一个新事物并且还支持多种语言。但我个人所做的是将不同环境的设置存储在 YAML 文件中,然后通过环境变量提供该文件。

蟒蛇示例:

Config 是一个 YAML 文件,其中包含资源所需的标签、应用程序级别的一些设置(如帐户 ID 和区域)和一些堆栈级别的设置(如资源名称等)等项目。

假设标准项目布局,您有app.py主文件和cdk/cdk_stack.py带有堆栈描述的文件。在app.py

if self.try_get_context("deploy_vpc"):
    MyVPC(app, "my new vpc")
Run Code Online (Sandbox Code Playgroud)

然后在cdk/cdk_stack.py

from ruamel.yaml import YAML
...
from cdk.cdk_stack import MyStack


def load_config() -> dict:
    """
    Import settings from YAML config
    :return: dict with configuration items
    """
    # This variable should always be set
    # CDK doesn't work well with argparse
    config_path = os.getenv("CONFIG_PATH")
    if not config_path:
        raise RuntimeError("You need to supply config file path with CONFIG_PATH env variable")
    # We don't verify config content, let fail in case something is missing
    with open(config_path) as config_file:
        config = YAML().load(config_file.read())
    return config

def init_app() -> core.App:
    """
    Initiates CDK main_app for deployment
    :return: main_app
    """
    main_app = core.App()
    config = load_config()
    # Account ID and region have to be explicitly set in order to import existing resources
    MyStack(
        main_app,
        "my stack",
        env={
            'account': config["account_id"],
            'region': config["region"]
        },
        config=config
    )
    # Tags are applied to all tagable resources in the stack
    for key, value in config["tags"].items():
        core.Tag.add(scope=main_app, key=key, value=value)
    return main_app


if __name__ == '__main__':
    app = init_app()
    app.synth()
Run Code Online (Sandbox Code Playgroud)