从一个 CloudFormation 堆栈获取信息以供另一个 CloudFormation 堆栈使用

从一个 CloudFormation 堆栈获取信息以供另一个 CloudFormation 堆栈使用

我正在尝试为 AWS 中的 Web 服务设置构建管道。计划是让服务在 Auto Scale 组中运行,并使用 Jenkins 构建一次性 EC2 实例,运行测试,并在成功后对实例进行映像并将其传递给现有的 Auto Scale 组。

为了创建所有必要的资源,我创建了两个 CloudFormation 模板,一个用于构建 Autoscale 组和周围资源,另一个用于构建一次性可测试实例。

不过,我注意到了一个问题:每个区域和每个 EC2 实例类型都有不同的基础镜像。这意味着,Jenkins 需要知道要构建的区域和实例类型。

理想的解决方案是一种选择目标 CloudFormation 堆栈并从那里提取信息(区域、实例类型等)的方法。这意味着如果我们对 Auto Scale Group 进行任何更改,它们将自动反映在 Jenkins 构建中。如果我们创建了第二个组,我们可以复制 Jenkins 作业并更改一个参数以将其指向新的堆栈。但这似乎不是一个选择……

这些是我能想到的潜在解决方案,但我并不特别喜欢其中任何一个:

  • 在两个模板中对这些信息进行硬编码
    这违背了 CF 模板的想法,因为我理想情况下希望保持这些东西的灵活性。

  • 将信息发送到 API,然后让 Jenkins 查找
    这是相当多的额外工作,因为我必须构建和维护一台机器来存储几个变量。更不用说,我不确定我是否可以从脚本将信息输出到 API,因此必须将其包装在另一个脚本中,以便从 AWS CLI 工具中获取信息。

  • 对最终图像进行分类
    我可以允许所有参数具有灵活性,然后根据这些参数对最终图像进行分类。然后我可以确保自动缩放组仅加载具有正确参数的图像。这可以防止使用不正确的基础图像,但可能会导致使用错误的信息进行构建(如果我们更改一个,我们必须记住更改另一个)。

感觉我想做的事情不应该那么难,但我却想不出最好的方法来实现它。

答案1

CloudFormation 包含一个伪参数AWS::Region,可用于查询其运行所在的区域。请参阅http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/pseudo-parameter-reference.html

您可以使用映射来获取 AMI 映像列表,并根据区域选择 AMI。请参阅http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/intrinsic-function-reference-findinmap.html

通常,AMI 的选择不受实例类型的影响。但是,我不熟悉您的用例,所以这可能很重要。

至于您的工作流程,我不会“更改”您的 Autoscaling 组。应该采取另一种方式:更改您的 CloudFormation 模板,然后更新您的堆栈以更新您的 Autoscaling 组。

因此你会:

  1. 从您的 CFN 模板构建您的单一实例,确认它正常工作并构建您的新 AMI。
  2. 获取新的 AMI 映像 ID 并更新您的 Autoscale 组的 CFN 模板。
  3. 通过更新堆栈来更新 Autoscale 组

直接对自动扩展组进行更改的危险在于,这些更改不会反映在堆栈的模板中。如果您必须重建堆栈或制作副本,则会丢失这些更改。理想情况下,从 CloudFormation 堆栈创建的资源应被视为只读,并且只能通过更改 CFN 模板进行更新。

答案2

比上面列出的选项稍微好一点的选项(实际上也是可能的)是使用 AWS CLI 工具获取有关当前堆栈的信息。这可以包装在脚本中以获取返回的 JSON 并找到所需的参数/输出。

通过将其移动到外部脚本而不是将其放在 CloudFormation 模板中,它仍然会稍微混淆它,所以我将保留这个问题,希望有人有更好的答案。

这是一个极其简单的例子:

<?php

$result = `aws cloudformation describe-stacks --stack-name=GROUPSTACKNAME`;
$stack = json_decode($result);
$stack = $stack->Stacks[0];

if(!$stack) {
    throw new Exception("Stack no found");
}

$parameters = [];
foreach($stack->Parameters as $param) {
    $parameters[$param->ParameterValue] = $param->ParameterKey;
}

echo http_build_query($parameters);

答案3

将需要传输的信息定义为第一个堆栈的输出。使用伪参数该地区等

创建第二个堆栈时,在第一个堆栈上调用 describe-stack 以获取输出,然后将值作为参数传递给第二个堆栈。

相关内容