CloudFormation StackSets + Organizations デプロイオプションの動作について

CloudFormation StackSets + Organizations連携により、組織に属する複数のAWSアカウントへCloudFormationスタックを作成できます。

この連携機能を利用する機会があったので、その際に得た知見を共有します。

新機能: AWS CloudFormation StackSets が AWS Organization のマルチアカウントで利用可能に

以降で詳細を説明しますが、まとめると以下になります。

  • デプロイオプションはスタックセットオペレーションに適用される
  • 設定したデプロイオプションを確認するには aws cloudformation describe-stack-set-operation を使う
  • スタックセット作成 -> Organizational Unit(OU)にAWSアカウントを移動、という方法だとデプロイはAWSアカウント1つずつシリアルに行われる
    • このデプロイ方法ではデプロイオプションは適用されない
    • そもそもOUへAWSアカウントを移動させるAPI自体、AWSアカウント毎に発行されている

設定したデプロイオプションを確認する方法

スタックセットを作成する際、以下のデプロイオプションが設定できます。

複数のAWSアカウントにリソースをデプロイする為、

  • いくつのアカウントに同時デプロイするか
  • いくつのアカウントでデプロイ失敗したらスタック作成を中止するか

を設定できるようになっています。

デプロイオプションはスタックセットオペレーションに適用されます。
後から設定を確認したい場合、オペレーションIDを指定しAWS CLIなどを実行します。

$ aws cloudformation describe-stack-set-operation \ 
  --stack-set-name case1-set \
  --operation-id cf1875f8-a92f-c8f4-c4ff-67181e97338e
{
    "StackSetOperation": {
        "OperationId": "cf1875f8-a92f-c8f4-c4ff-67181e97338e",
        "StackSetId": "case1-set:7c4a561e-0cf0-490b-b46a-7d09aa1c60b4",
        "Action": "CREATE",
        "Status": "SUCCEEDED",
        "OperationPreferences": {
            "RegionOrder": [
                "ap-northeast-1"
            ],
            "FailureTolerancePercentage": 100,
            "MaxConcurrentPercentage": 100
        },
        "AdministrationRoleARN": "arn:aws:iam::111122223333:role/aws-service-role/stacksets.cloudformation.amazonaws.com/AWSServiceRoleForCloudFormationStackSetsOrgAdmin",
        "ExecutionRoleName": "stacksets-exec-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
        "CreationTimestamp": "2020-12-16T07:12:06.600000+00:00",
        "EndTimestamp": "2020-12-16T07:13:26.810000+00:00",
        "DeploymentTargets": {
            "Accounts": [],
            "OrganizationalUnitIds": [
                "ou-xxxx-xxxxxxxx"
            ]
        }
    }
}
$

スタックセット作成時にデプロイオプションを指定するので、オプションはスタックセットに適用されているものと当初私は思っていました。

実際はスタックセットオペレーションにデプロイオプションが適用されています。

ケース1: デプロイオプションが適用される場面

以下のケースだと、デプロイオプションが適用されます。

  1. AWSアカウントをOUに移動
  2. 1のOUを指定しスタックセットを作成

この作業を行うと、スタックセットオペレーションが1つ作成されます。
スタックインスタンスはAWSアカウントぶん作成されます。

オペレーションにデプロイオプション(OperationPreferences)が設定されていることが分かります。

$ aws cloudformation describe-stack-set-operation \
  --stack-set-name case1-set \
  --operation-id cf1875f8-a92f-c8f4-c4ff-67181e97338e
{
    "StackSetOperation": {
        "OperationId": "cf1875f8-a92f-c8f4-c4ff-67181e97338e",
        "StackSetId": "case1-set:7c4a561e-0cf0-490b-b46a-7d09aa1c60b4",
        "Action": "CREATE",
        "Status": "SUCCEEDED",
        "OperationPreferences": {
            "RegionOrder": [
                "ap-northeast-1"
            ],
            "FailureTolerancePercentage": 100,
            "MaxConcurrentPercentage": 100
        },
        "AdministrationRoleARN": "arn:aws:iam::111122223333:role/aws-service-role/stacksets.cloudformation.amazonaws.com/AWSServiceRoleForCloudFormationStackSetsOrgAdmin",
        "ExecutionRoleName": "stacksets-exec-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
        "CreationTimestamp": "2020-12-16T07:12:06.600000+00:00",
        "EndTimestamp": "2020-12-16T07:13:26.810000+00:00",
        "DeploymentTargets": {
            "Accounts": [],
            "OrganizationalUnitIds": [
                "ou-xxxx-xxxxxxxx"
            ]
        }
    }
}
$ 

ケース2: デプロイオプションが適用されない場面

以下のケースだと、デプロイオプションが適用されません。

  1. OUを指定しスタックセットを作成
  2. AWSアカウントを1のOUに移動

この作業を行うと、最初はスタックセットオペレーションがAWSアカウント数+1作成されます。
この時点ではスタックインスタンスは1つだけです。オペレーションがキューイングされ、シリアルにデプロイされていることが分かります。

全体でデプロイが完了すると以下のようになります。

最後に完了したオペレーションのデプロイオプション(OperationPreferences)を確認してみると、特に何も設定されていないことが分かります。

$ aws cloudformation describe-stack-set-operation \
  --stack-set-name case2-set \
  --operation-id c1834277dbc357c7dac8456e3d5ab131
{
    "StackSetOperation": {
        "OperationId": "c1834277dbc357c7dac8456e3d5ab131",
        "StackSetId": "case2-set:f9747434-c5f0-4c0f-95d9-246b95e2d375",
        "Action": "CREATE",
        "Status": "SUCCEEDED",
        "OperationPreferences": {
            "RegionOrder": []
        },
        "RetainStacks": false,
        "AdministrationRoleARN": "arn:aws:iam::111122223333:role/aws-service-role/stacksets.cloudformation.amazonaws.com/AWSServiceRoleForCloudFormationStackSetsOrgAdmin",
        "ExecutionRoleName": "stacksets-exec-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
        "CreationTimestamp": "2020-12-16T07:33:54.888000+00:00",
        "EndTimestamp": "2020-12-16T07:38:01.169000+00:00"
    }
}
$ 

ケース2のような形でリソースのデプロイを行うと、AWSアカウント1つずつシリアルにデプロイされます。

私はこの仕様を知らなかったためデプロイに想定以上の時間がかかってしまったことがありました。

ケース2補足

AWSアカウントをOU配下に移動させる場合、マネジメントコンソール上は複数のアカウントを同時に移動させることが出来ているように見えます。

※ちなみに「アカウントを削除する組織単位 (OU) を選択してください」とありますが英語版は以下なので「アカウントの移動先OUを選択してください」という意味になります。

Choose the organizational unit (OU) you want to move the account to.

しかし実際は、Organizations MoveAccount APIは1つだけAccountIdを指定する形になっています。

MoveAccount

そのためコンソール上では一斉移動したように見えても、内部ではこの移動APIをAWSアカウント毎に叩いているようです。

CloudTrailを見るとそのことがよく分かります。(ちなみにバージニア北部のコンソールで確認可能)

ケース2の場合スタックセットオペレーションがAWSアカウント毎に作成されていましたが、そもそもAWSアカウントをOUへ移動させるAPIもAWSアカウント毎に発行されていました。

まとめ、再掲

  • デプロイオプションはスタックセットオペレーションに適用される
  • 設定したデプロイオプションを確認するには aws cloudformation describe-stack-set-operation を使う
  • スタックセット作成 -> Organizational Unit(OU)にAWSアカウントを移動、という方法だとデプロイはAWSアカウント1つずつシリアルに行われる
    • このデプロイ方法ではデプロイオプションは適用されない
    • そもそもOUへAWSアカウントを移動させるAPI自体、AWSアカウント毎に発行されている

CloudFormationとは?