如何使用 CloudFormation 中的 AWS Serverless Application Model (SAM) 模板解决循环依赖关系?

上次更新日期:2021 年 8 月 31 日

如果我在 AWS CloudFormation 中部署 AWS Serverless Application Model (SAM) 模板,会收到类似于以下内容的错误:"Circular dependency between resources: [Function, Bucket, FunctionRole, FunctionUploadPermission]."(“以下资源之间有循环依赖关系:[函数、存储桶、FunctionRole、FunctionUploadPermission]。”)

简短描述

如果您使用以下示例 AWS SAM 模板,则会在 CloudFormation 中收到错误:

AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Description: Circular Dependency
Resources:
  Bucket:
    Type: AWS::S3::Bucket
    Properties:
      BucketName: !Sub "{AWS::StackName}-${AWS::Region}-${AWS::AccountId}"
  Function:
    Type: AWS::Serverless::Function
    Properties:
      CodeUri: s3://mybucket/function.zip
      Runtime: nodejs12.x
      Handler: index.handler
      Policies:
        - Version: 2012-10-17
          Statement:
            - Effect: Allow
              Action: s3:GetObject*
              Resource: !Sub "arn:aws:s3:::${Bucket}*"
      Events:
        Upload:
          Properties:
            Bucket:
              Ref: Bucket
            Events: s3:ObjectCreated:*
          Type: S3

此模板会因为创建以下循环依赖关系而产生错误:

  1. 存储桶资源取决于 FunctionUploadPermission
  2. FunctionUploadPermission 取决于 Function(函数)。
  3. Function(函数)取决于 FunctionRole
  4. FunctionRole 取决于创建循环的 Bucket(存储桶)资源。

注意:在错误消息中,FunctionUploadPermission 资源的类型为 AWS::Lambda::Permission。 当为 AWS::Serverless::Function 指定了 Event(事件)属性时,AWS SAM 会自动生成此资源。FunctionRole 资源的类型为 AWS::IAM::Role。当为 AWS::Serverless::Function 指定了 Role(角色)属性时,AWS SAM 会自动生成此资源。

要解决循环依赖关系,必须通过替换对存储桶资源的动态引用来打破循环。

解决方法

将具有循环依赖关系的 CloudFormation 模板替换为以下模板:

Permission is hereby granted, free of charge, to any person obtaining a copy of this
software and associated documentation files (the "Software"), to deal in the Software
without restriction, including without limitation the rights to use, copy, modify,
merge, publish, distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Description: Circular Dependency
Resources:
  Bucket:
    Type: AWS::S3::Bucket
    Properties:
      BucketName: !Sub "${AWS::StackName}-${AWS::Region}-${AWS::AccountId}"
  Function:
    Type: AWS::Serverless::Function
    Properties:
      CodeUri: s3://mybucket/function.zip
      Runtime: nodejs12.x
      Handler: index.handler
      Policies:
        - Version: 2012-10-17
          Statement:
            - Effect: Allow
              Action: s3:GetObject*
              Resource: !Sub "arn:aws:s3:::${AWS::StackName}-${AWS::Region}-${AWS::AccountId}*"
      Events:
        Upload:
          Properties:
            Bucket:
              Ref: Bucket
            Events: s3:ObjectCreated:*
          Type: S3

在模板中,策略声明的 Resources(资源)部分使用的虚拟参数与存储桶资源的 BucketName 属性中使用的虚拟参数相同。现在,您可以在不直接引用该存储桶的情况下传递存储桶名称。因此,由于循环依赖关系已打破,错误可解决。也就是说,由 FunctionRole 产生的循环依赖关系取决于 Bucket(存储桶)资源。

注意:s3://mybucket/function.zip 替换为您的文件位置。


这篇文章对您有帮助吗?


您是否需要账单或技术支持?