【问题标题】:AWS Cloudformation template EC2 Role/Policy circular dependencyAWS Cloudformation 模板 EC2 角色/策略循环依赖
【发布时间】:2018-04-05 06:13:19
【问题描述】:

我正在编写一个带有单个 EC2 实例和一个 EBS 卷的 Cloudformation 模板。我稍后会在使用 Powershell 脚本创建机器时附加该卷。当我将通配符“*”放在策略声明资源中时它可以工作,但是我想限制对一个实例和一个 ebs 卷的访问。使用 EBS 卷很容易,我可以在模板中引用它,它是在角色之前创建的,但是对于实例,问题是实例需要首先创建角色,而且还能够创建我们需要创建角色的实例第一的。解决这种循环依赖的好方法是什么?

这是我的模板:

Resources:
  InstanceRole:
    Type: 'AWS::IAM::Role'
    Properties:
      RoleName: InstanceRole
      AssumeRolePolicyDocument:
        Version: '2012-10-17'
        Statement:
          - Effect: Allow
            Principal:
              Service:
                - ec2.amazonaws.com
            Action:
              - 'sts:AssumeRole'
      Path: /
      Policies:
        - PolicyName: AttachVolume
          PolicyDocument:
            Version: '2012-10-17'
            Statement:
              - Effect: Allow
                Action:
                  - 'ec2:AttachVolume'
                Resource:
                  - !Join 
                    - ''
                    - - 'arn:aws:ec2:'
                      - !Ref 'AWS::Region'
                      - ':'
                      - !Ref 'AWS::AccountId'
                      - ':instance/*'
                  - !Join 
                    - ''
                    - - 'arn:aws:ec2:'
                      - !Ref 'AWS::Region'
                      - ':'
                      - !Ref 'AWS::AccountId'
                      - ':volume/'
                      - !Ref DataVolume             
  InstanceProfile:
    Type: 'AWS::IAM::InstanceProfile'
    Properties:
      Roles:
        - !Ref InstanceRole
      InstanceProfileName: InstanceProfile
  Instance:
    Type: 'AWS::EC2::Instance'
    Properties:
      ImageId: !Ref AMI
      InstanceType: !Ref InstanceType
      IamInstanceProfile: !Ref InstanceProfile
      KeyName: ec2key
      BlockDeviceMappings:
        - DeviceName: /dev/sda1
          Ebs:
            VolumeType: gp2
            DeleteOnTermination: 'true'
            VolumeSize: '30'
      Tags:
        - Key: Name
          Value: MyInstance
      SubnetId: !Ref SubnetId
      SecurityGroupIds:
        - !Ref SGId
      UserData: !Base64 
        'Fn::Join':
          - ''
          - - |
              <script>
            - 'cfn-init.exe -v -c config -s '
            - !Ref 'AWS::StackId'
            - ' -r Instance'
            - ' --region '
            - !Ref 'AWS::Region'
            - |+

            - |
              </script>
  DataVolume:
    Type: "AWS::EC2::Volume"
    Properties:  
      AvailabilityZone: !GetAtt 
        - Instance
        - AvailabilityZone
      Size: "100"
      Tags:
        - Key: Name
          Value: InstanceExtraVolume

【问题讨论】:

    标签: amazon-web-services amazon-ec2 amazon-cloudformation


    【解决方案1】:

    在您的特定示例中,您具有以下依赖链:InstanceRole -&gt; DataVolume -&gt; Instance -&gt; InstanceProfile -&gt; InstanceRole

    一般来说,当您的角色取决于您的资源而您的资源取决于您的角色时,这是 AWS::IAM::Policy 资源类型有用的地方。这基本上将 IAM 角色 上的特定政策与 IAM 政策 本身同时解决。

    为此,您需要将 InstanceRole 拆分为 InstanceRoleInstanceRolePolicy

    Resources:
      InstanceRole:
        Type: 'AWS::IAM::Role'
        Properties:
          RoleName: InstanceRole
          AssumeRolePolicyDocument:
            Version: '2012-10-17'
            Statement:
              - Effect: Allow
                Principal:
                  Service:
                    - ec2.amazonaws.com
                Action:
                  - 'sts:AssumeRole'
          Path: /
      InstanceRolePolicy:
        Type: 'AWS::IAM::Policy'
        Properties:
          Roles:
            - !Ref InstanceRole
          PolicyName: AttachVolume
          PolicyDocument:
            Version: '2012-10-17'
            Statement:
              - Effect: Allow
                Action:
                  - 'ec2:AttachVolume'
                Resource:
                  - !Join 
                    - ''
                    - - 'arn:aws:ec2:'
                      - !Ref 'AWS::Region'
                      - ':'
                      - !Ref 'AWS::AccountId'
                      - ':instance/*'
                  - !Join 
                    - ''
                    - - 'arn:aws:ec2:'
                      - !Ref 'AWS::Region'
                      - ':'
                      - !Ref 'AWS::AccountId'
                      - ':volume/'
                      - !Ref DataVolume
    

    这样,InstanceRolePolicy 依赖于 InstanceRoleDataVolume,但 InstanceRole 不依赖在任何东西上,所以DataVolume -&gt; Instance -&gt; InstanceProfile -&gt; InstanceRole 链可以解析。

    【讨论】:

    • 这是推荐的方式吗? AWS 有一个 note 表示我们还应该将 DependsOn 属性分配给资源,即在这种情况下的实例,这将再次引入循环依赖。如果我不添加 DependsOn 属性会怎样?
    【解决方案2】:

    循环依赖的一个常见解决方案是通过多个步骤执行此操作:使用最少的资源创建堆栈,然后修改模板并更新堆栈。

    因此,您的模板 v1 仅创建基本依赖资源,而在 v2 中,您修改模板以添加依赖资源并同时修改原始依赖资源。然后进行堆栈更新。

    另外,请参阅more ideas

    【讨论】:

    • IaC 的主要优势之一是能够快速重新配置堆栈。如果每次从头开始都必须修改模板,那真的违背了这个目的。我管理着数百个堆栈,而且我从来不用求助于这个。
    • 是的,理想情况下你不会有循环依赖,但在少数情况下它可能是不可避免的(我并不是说 this 是其中一种情况),一种选择是创建一个基本堆栈然后更新它。丑,是的。
    猜你喜欢
    • 1970-01-01
    • 2017-06-18
    • 1970-01-01
    • 2019-12-29
    • 2021-02-19
    • 1970-01-01
    • 2021-04-16
    • 2018-11-16
    • 2017-05-13
    相关资源
    最近更新 更多