输出和导出的区别

27
在 CloudFormation 中,我们可以将一些模板的值输出,以便其他进程、堆栈等可以检索到这些值。通常这是某个东西的名称,可能是 URL 或在堆栈创建(部署)期间生成的某些内容等。
我们还可以从模板中“导出”。作为“输出”和作为“导出”返回值之间的区别是什么?
2个回答

37

普通输出值不能从其他堆栈引用。当您链接嵌套您的堆栈时,它们的范围/可见性是本地的,因此可以很有用。导出的输出在帐户和区域内全局可见,并且可以由您将要部署的任何未来堆栈使用。

链接

当您链接您的堆栈时,您部署一个堆栈,获取其输出值,并将其用作第二个要部署的堆栈的输入参数。

例如,假设您有两个名为instance.yamleip.yaml的模板。 instance.yaml输出其实例ID(不导出),而eip.yaml将实例ID作为输入参数。

要同时部署它们,您必须将它们链接在一起:

  1. 部署instance.yaml并等待其完成。
  2. 注意其输出值(即实例ID)-通常以编程方式执行,而非手动操作。
  3. 部署eip.yaml并将实例ID作为其输入参数传递。

嵌套

当您嵌套堆栈时,您将拥有一个父模板和一个子模板。子堆栈将从父堆栈内部创建。在这种情况下,子堆栈将为父堆栈生成一些输出值(不是导出),供其使用。

例如,我们再次使用 instance.yamleip.yaml。但是这一次,eip.yaml 将作为父模板,而 instance.yaml 将成为子模板。此外,eip.yaml 不需要任何输入参数,但是 instance.yaml 输出其实例 ID(不导出)。
在这种情况下,要部署它们,您需要执行以下操作:
  1. 将子模板 (instance.yaml) 上传到 s3。
  2. eip.yaml 中使用 AWS::CloudFormation::Stack 和步骤 1 中的 s3 url 创建子实例堆栈。
这样,eip.yaml 将能够使用 GetAtt 访问嵌套堆栈的输出中的实例 ID。 交叉引用 当您跨越不同的堆栈进行引用时,您只需一个导出其输出以供同区域和帐户中的任何其他堆栈使用的堆栈即可。例如,我们再次使用instance.yamleip.yamlinstance.yaml将导出其输出(实例ID)。为了使用实例ID,eip.yaml必须在其模板中使用ImportValue,无需任何输入参数或嵌套堆栈。
在这种情况下,要部署它们,请执行以下操作:
  1. 部署instance.yaml并等待其完成。
  2. 部署eip.yaml,该文件将导入实例ID。
尽管交叉引用似乎非常有用,但它有一个主要问题,即很难更新或删除交叉引用的堆栈
“另一个堆栈导入输出值后,您无法删除导出输出值的堆栈或修改已导出的输出值。必须先删除所有导入,然后才能删除导出堆栈或修改输出值。”
如果您正在开始设计并且您的模板经常会更改,则这非常棘手。 什么时候使用哪个?

当您在给定区域和账户中有一些将要共享的全局资源,并且它们不经常更改时,请使用交叉引用(导出值)。常见的例子包括:用于集中日志位置的全局存储桶、VPC。此外,由于这些全局资源很难修改,因此也应该减少其更改次数。

当您有一些常见组件需要部署,但每次都可能稍有不同时,请使用嵌套堆栈(未导出输出),例如ALB、跳板主机实例、VPC接口端点。

最后,链式堆栈(未导出输出)非常适用于设计松耦合模板,在其中可以根据新需求混合和匹配模板。


2
在上面的嵌套中,您将子项命名为eip.yml。这是打字错误吗?在上面的段落中,您将子项命名为instance.yml。那么哪个是正确的呢?请澄清一下。 - user3477108
@user3477108 谢谢。EIP模板应该是父级。错别字已更正。 - Marcin
1
在“嵌套”下的编号列表中,您说要将eip.yaml上传到S3,但接下来的项目却说要在eip.yml中使用S3 url。这不是循环引用吗?您是否意味着要上传子文件instance.yml到S3呢? - The Unknown Dev
@TheUnknownDev 是的,我相当确定是这样的。我要求编辑问题,现在我看到已经被编辑了。 - Alexandro Nadal

6

这里的简短回答来看,在堆栈之间使用export 来共享信息,在嵌套堆栈中使用output

Export

为了在堆栈之间共享信息,请导出一个堆栈的输出值。其他在同一AWS账户和区域内的堆栈可以导入导出的值。

Output

对于嵌套堆栈,您可以从单个堆栈部署和管理所有资源。您可以在嵌套堆栈组中的一个堆栈中使用另一个堆栈的输出作为输入。这与导出值不同。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接