CloudFormation 跨区域参考

Posted

技术标签:

【中文标题】CloudFormation 跨区域参考【英文标题】:CloudFormation Cross-Region Reference 【发布时间】:2020-05-03 14:10:06 【问题描述】:

当您在同一区域内运行多个 CloudFormation 堆栈时,您可以使用 CloudFormation Outputs 跨堆栈共享引用

但是,正如该文档强调的那样,输出不能用于跨区域引用。

您不能跨区域创建跨堆栈引用。您可以使用内部函数 Fn::ImportValue 仅导入已在同一区域内导出的值。

您如何在 CloudFormation 中跨区域引用值?

举个例子,我在us-east-1 中部署了一个Route 53 hosted zone。但是,我在 us-west-2 中有一个后端,我想创建一个 DNS-validated ACM certificate,它需要引用托管区域才能创建适当的 CNAME 来证明所有权。

我将如何从us-west-2 中引用在us-east-1 中创建的托管区域ID?

【问题讨论】:

【参考方案1】:

cdk库已经更新,需要修改代码如下:

import  Construct  from '@aws-cdk/core';
import  AwsCustomResource, AwsSdkCall  from '@aws-cdk/custom-resources';
import iam = require("@aws-cdk/aws-iam");

interface SSMParameterReaderProps 
  parameterName: string;
  region: string;


export class SSMParameterReader extends AwsCustomResource 
  constructor(scope: Construct, name: string, props: SSMParameterReaderProps) 
    const  parameterName, region  = props;

    const ssmAwsSdkCall: AwsSdkCall = 
      service: 'SSM',
      action: 'getParameter',
      parameters: 
        Name: parameterName
      ,
      region,
      physicalResourceId: id:Date.now().toString() // Update physical id to always fetch the latest version
    ;

    super(scope, name,  onUpdate: ssmAwsSdkCall,policy:
        statements:[new iam.PolicyStatement(
        resources : ['*'],
        actions   : ['ssm:GetParameter'],
        effect:iam.Effect.ALLOW,
      
      )]
    );
  

  public getParameterValue(): string 
    return this.getResponseField('Parameter.Value').toString();
  

【讨论】:

【参考方案2】:

我发现这样做的最简单方法是将您要共享的引用(即在本例中为您的托管区域 ID)写入 Systems Manager Parameter Store,然后在单独区域的“子”堆栈中引用该值使用custom resource。

幸运的是,如果您的模板是使用 Cloud Development Kit (CDK) 创建的,这将非常容易。

对于要从 SSM 读取的自定义资源,您可以使用如下内容:

// ssm-parameter-reader.ts

import  Construct  from '@aws-cdk/core';
import  AwsCustomResource, AwsSdkCall  from '@aws-cdk/custom-resources';

interface SSMParameterReaderProps 
  parameterName: string;
  region: string;


export class SSMParameterReader extends AwsCustomResource 
  constructor(scope: Construct, name: string, props: SSMParameterReaderProps) 
    const  parameterName, region  = props;

    const ssmAwsSdkCall: AwsSdkCall = 
      service: 'SSM',
      action: 'getParameter',
      parameters: 
        Name: parameterName
      ,
      region,
      physicalResourceId: Date.now().toString() // Update physical id to always fetch the latest version
    ;

    super(scope, name,  onUpdate: ssmAwsSdkCall );
  

  public getParameterValue(): string 
    return this.getData('Parameter.Value').toString();
  


要将托管区域 id 写入参数存储,您可以简单地执行以下操作:

// route53.ts (deployed in us-east-1)

import  PublicHostedZone  from '@aws-cdk/aws-route53';
import  StringParameter  from '@aws-cdk/aws-ssm';

export const ROUTE_53_HOSTED_ZONE_ID_SSM_PARAM = 'ROUTE_53_HOSTED_ZONE_ID_SSM_PARAM';

/**
 * Other Logic
 */

const hostedZone = new PublicHostedZone(this, 'WebsiteHostedZone',  zoneName: 'example.com' );

new StringParameter(this, 'Route53HostedZoneIdSSMParam', 
  parameterName: ROUTE_53_HOSTED_ZONE_ID_SSM_PARAM,
  description: 'The Route 53 hosted zone id for this account',
  stringValue: hostedZone.hostedZoneId
);

最后,您可以使用我们刚刚创建的自定义资源从该区域的参数存储中读取该值,并使用它在us-west-2 中创建证书。

// acm.ts (deployed in us-west-2)

import  DnsValidatedCertificate  from '@aws-cdk/aws-certificatemanager';
import  PublicHostedZone  from '@aws-cdk/aws-route53';

import  ROUTE_53_HOSTED_ZONE_ID_SSM_PARAM  from './route53';
import  SSMParameterReader  from './ssm-parameter-reader';

/**
 * Other Logic
 */

const hostedZoneIdReader = new SSMParameterReader(this, 'Route53HostedZoneIdReader', 
  parameterName: ROUTE_53_HOSTED_ZONE_ID_SSM_PARAM,
  region: 'us-east-1'
);
const hostedZoneId: string = hostedZoneIdReader.getParameterValue();
const hostedZone = PublicHostedZone.fromPublicHostedZoneId(this, 'Route53HostedZone', hostedZoneId);

const certificate = new DnsValidatedCertificate(this, 'ApiGatewayCertificate',  'pdx.example.com', hostedZone );

【讨论】:

像魅力一样工作。我将其用于全球加速器,因为这需要来自不同地区的 arns 如何用无服务器框架之类的东西做类似的事情?? @Marzouk 是的。无服务器框架提供免费仪表板,该仪表板具有称为输出的功能,可让您在部署时导出值,如 CloudFormation ARN 等,然后使用 $outputs 语法导入它们。更多详情:serverless.com/framework/docs/dashboard/output-variables 很遗憾,如果存储中的参数发生变化,我不相信 cloudformation 会检测到这一点并使用更新的值重新部署。

以上是关于CloudFormation 跨区域参考的主要内容,如果未能解决你的问题,请参考以下文章

PubSubLite:跨区域访问 PubSub Lite

S3 跨区域复制

以递增方式跨区域复制RDS数据库快照

云图说|云数据库RDS跨区域备份

HDFS数据跨区域存储分布

HDFS数据跨区域存储分布