CloudFormation StackSetsに触ったメモ

触る機会があったのでメモ。CloudFormation StackSetsとは、

AWS CloudFormation StackSets は、複数のアカウントおよびリージョンのスタックを 1 度のオペレーションで、作成、更新、削除できるようにすることで、スタックの機能を拡張します。管理者アカウントを使用して、AWS CloudFormation テンプレートを定義および管理し、指定のリージョンの選択されたターゲットアカウントにスタックをプロビジョニングする基盤としてテンプレートを使用します。

概念図

理解したかぎり、こんな感じでしょうか。

f:id:goodbyegangster:20190724003423p:plain

必要IAM Roleの設定

Administrator AccountにIAM Role作成

Administrator Accountに、各Target Acountに対してAssume RoleするRoleを作成します。標準となるIAM Role作成用のCFnを下記に公開してくれています。

https://s3.amazonaws.com/cloudformation-stackset-sample-templates-us-east-1/AWSCloudFormationStackSetAdministrationRole.yml

今回はResource対象となるAWSアカウントを限定して、以下のようなCFnに変更しています。

AWSTemplateFormatVersion: 2010-09-09
Description: Configure the AWSCloudFormationStackSetAdministrationRole to enable use of AWS CloudFormation StackSets.

Resources:
  AdministrationRole:
    Type: AWS::IAM::Role
    Properties:
      RoleName: AWSCloudFormationStackSetAdminRoleA
      AssumeRolePolicyDocument:
        Version: 2012-10-17
        Statement:
          - Effect: Allow
            Principal:
              Service: cloudformation.amazonaws.com
            Action:
              - sts:AssumeRole
      Path: /
      Policies:
        - PolicyName: AssumeRole-AWSCloudFormationStackSetExecutionRole
          PolicyDocument:
            Version: 2012-10-17
            Statement:
              - Effect: Allow
                Action:
                  - sts:AssumeRole
                Resource:
                  - "arn:aws:iam::11111*****:role/AWSCloudFormationStackSetExecutionRole"
                  - "arn:aws:iam::22222*****:role/AWSCloudFormationStackSetExecutionRole"

Target AccountにIAM Role作成

各Target Accountにて、上記のAdministrator Acount用RoleがAssume RoleするRoleを作成します。標準となるIAM Role作成用のCFnを下記に公開してくれています。

https://s3.amazonaws.com/cloudformation-stackset-sample-templates-us-east-1/AWSCloudFormationStackSetExecutionRole.yml

Roleに付与されているPolicyがAdministratorAccessとなっているので、必要に応じて変更してください。

AWSTemplateFormatVersion: 2010-09-09
Description: Configure the AWSCloudFormationStackSetExecutionRole to enable use of your account as a target account in AWS CloudFormation StackSets.

Parameters:
  AdministratorAccountId:
    Type: String
    Description: AWS Account Id of the administrator account (the account in which StackSets will be created).
    MaxLength: 12
    MinLength: 12

Resources:
  ExecutionRole:
    Type: AWS::IAM::Role
    Properties:
      RoleName: AWSCloudFormationStackSetExecutionRole
      AssumeRolePolicyDocument:
        Version: 2012-10-17
        Statement:
          - Effect: Allow
            Principal:
              AWS:
                - !Ref AdministratorAccountId
            Action:
              - sts:AssumeRole
      Path: /
      ManagedPolicyArns:
        - arn:aws:iam::aws:policy/AdministratorAccess

CloudFormation StackSetsを設定

実際にStackSetsを実行して、Target AccountにAWSリソースを作成してみます。以下が今回StackSetsとして実行するCloudFormationテンプレートです。簡単なDynamoDBテーブルを作成するもの。これをAdministrator Accountの適当なS3にアップロードしておきます。

AWSTemplateFormatVersion: "2010-09-09"
Description: "Create DynamoDB Table - sample"

Parameters:
  RCU:
    Type: Number
    Default: 5
  WCU:
    Type: Number
    Default: 5

Resources:
  myDynamoDBTable:
    Type: "AWS::DynamoDB::Table"
    DeletionPolicy: "Delete"
    Properties:
      AttributeDefinitions:
        - AttributeName: "name"
          AttributeType: "S"
      KeySchema:
        - AttributeName: "name"
          KeyType: "HASH"
      BillingMode: "PROVISIONED"
      ProvisionedThroughput:
        ReadCapacityUnits: !Ref RCU
        WriteCapacityUnits: !Ref WCU
      TableName: "sample"

Administraotr Accountにて、StackSetを作成します。

> aws cloudformation create-stack-set ^
--stack-set-name example ^
--description example ^
--template-url https://kiritan-love-zunchan.s3-ap-northeast-1.amazonaws.com/cf/DynamoDB.yml ^
--administration-role-arn arn:aws:iam::00000000000:role/AWSCloudFormationStackSetAdminRoleA ^
--execution-role-name AWSCloudFormationStackSetExecutionRole ^
--tags Key=system,Value=common

AWS CLI - create-stack-set


作成したStackSet内に、StackInstanceを作成します。まずはTarget Account 11111***** に対して、CloudFormationパラメータの各CapacityUnit値を1とOverrideして実行します。

> aws cloudformation create-stack-instances ^
--stack-set-name example ^
--accounts "11111*****" ^
--regions "ap-northeast-1" ^
--parameter-overrides ^
ParameterKey=RCU,ParameterValue=1 ^
ParameterKey=WCU,ParameterValue=1 ^
--operation-preferences FailureToleranceCount=0,MaxConcurrentCount=1

次にTarget Account 22222***** に対して、CloudFormationパラメータの各CapacityUnit値を3として実行します。

> aws cloudformation create-stack-instances ^
--stack-set-name example ^
--accounts "22222*****" ^
--regions "ap-northeast-1" ^
--parameter-overrides ^
ParameterKey=RCU,ParameterValue=3 ^
ParameterKey=WCU,ParameterValue=3 ^
--operation-preferences FailureToleranceCount=0,MaxConcurrentCount=1

この処理にて、Target Accountに紐付いたStackInstanceが作成され、Target Account内でCloudFormationが実行されます。CloudFormationのパラメータ値は、各StackInstanceごとに管理できるため、これによりAccountごとに異なるCapacityUnitを設定できます。

なお、CLIからはTarget Accountを直接指定していますが、GUIからですと、OrganizationのOU単位で指定することができます。

FailureToleranceCountパラメータの説明。

This means that a maximum of one stack deployment can fail in one of your specified regions before AWS CloudFormation stops deployment in the current region, and cancels deployment in remaining regions.

MaxConcurrentCountパラメータの説明。

This means that AWS CloudFormation deploys your stack in only one account at one time.

AWS CLI - create-stack-instances

Target Accountや対象Regionを追加したい

create-stack-instancesコマンドにて、対象のAWSアカウント/Regionを指定して、StackInstanceを追加します。

利用するCloudFormationのテンプレートを更新したい

update-stack-setコマンドにて、StackSet内の利用CloudFormationテンプレートを更新します。

  • 注意点
    • 紐づくStanckInstance(Target Account)で、CloudFormationの更新が走る
    • CloudFormationテンプレートのパラメータ部分は、StackInstanceごとに管理されることになるので、StackInstance作成時にパラメータ値をoverrideしていた場合、更新されない

StackInstanceにてoverrideされたパラメータ値を更新したい

update-stack-instanceコマンドにて、更新します。

Target Accountを削除したい

つまり、対象となるAWSアカウント内のCloudFormationスタックを削除したい場合。

delete-stack-instancesコマンドにて、該当のStackInstance(対象AWSアカウントのRegion)を削除します。

StackSetを削除したい

delete-stack-setコマンドにて、対象StackSetを削除します。

StackSet内にStackInstanceがある場合、StackSetを削除することはできないので、事前にStackInstanceから削除します。