[アップデート]AWS CloudFormation は ConcurrencyMode を使用してスタックセットをより迅速にデプロイできるようになりました

2023.11.21

こんにちは。たかやまです。

CloudFormation StackSets で新たなオプション ConcurrencyMode(同時実行モード) がサポートされました。

コンソールにも新しいデプロイオプションが追加されていますね

何が嬉しい

いままで

いままでのデプロイオプションでは「Failure tolerance(障害耐性)」を設定している場合、「Maximum concurrent accounts(同時アカウントの最大数)」は障害耐性の値 + 1 が最大値でした。

そのため、「Failure tolerance」を設定している場合は、「Maximum concurrent accounts」を任意の値を設定できずデプロイ速度を上げることができませんでした。

障害耐性とは?

この設定は、ワークフローの作成、更新、削除で利用でき、各リージョンで発生する場合があるスタックオペレーションの失敗の最大数や割合を指定できます。この値を超えると、オペレーションは CloudFormation によって自動的に停止されます。
StackSets の概念 - AWS CloudFormation

これから

今回のアップデートでデプロイオプションにConcurrencyModeが追加され新たな動作が選択できるようになったことで、「Failure tolerance」を設定しつつ、任意の「Maximum concurrent accounts」を設定することができるようになりました。

ConcurrencyModeの動作はSTRICT_FAILURE_TOLERANCE(厳格な耐障害性)SOFT_FAILURE_TOLERANCE(ソフト障害耐性)があります。
いままでの動作はSTRICT_FAILURE_TOLERANCEとして扱われ、こちらは今後もデフォルト設定となります。

そして、今回のアップデートで新たな動作としてSOFT_FAILURE_TOLERANCEが追加されています。

STRICT_FAILURE_TOLERANCESOFT_FAILURE_TOLERANCEの動作の違いは以下のようになります。
以下のドキュメントに詳細な説明がありますので、こちらも合わせてご確認ください。

Concurrency Mode parameter - AWS CloudFormation

STRICT_FAILURE_TOLERANCE

STRICT_FAILURE_TOLERANCEを設定している場合、Maximum concurrent accounts(同時アカウントの最大数)で10を設定していてもFailure tolerance(障害耐性)に5を設定している場合は、同時にデプロイされるアカウント最大数はFailure toleranceに+1した「6」が最大値となります。

その後、同時デプロイ中に失敗したアカウント数の分だけ、次の同時実行数から減算されていきます。

例は、6アカウントに対して同時デプロイを行い、そのうちの1アカウントが失敗した場合の動作を示しています。

その後の同時デプロイされるアカウントは失敗したアカウント数を減算した数の「5」になります。

その後も失敗したアカウント数分だけ同時デプロイ数は減算されていきます。
ここまでに3アカウントがデプロイに失敗しているため、最初の同時デプロイされるアカウント最大数「6」からデプロイに失敗したアカウント「3」を減算した「3」が同時デプロイ数となります。

最終的にFailure toleranceの値を超えた段階でデプロイは停止します。
ここではFailure toleranceの値を5に設定しているため、デプロイに失敗したアカウント数が5を超えた6に達した段階でデプロイは停止します。

SOFT_FAILURE_TOLERANCE

SOFT_FAILURE_TOLERANCEを設定している場合は、Failure tolerance(障害耐性)を5に設定していてもMaximum concurrent accounts(同時アカウントの最大数)で10を設定していれば同時にデプロイされるアカウント最大数はMaximum concurrent accountsの「10」が最大値となります。

また、デプロイが失敗しても、次の同時デプロイ数から減算されることはありません。(常に10アカウント)

そのため、同時デプロイ中にFailure toleranceで定義した5を超えるアカウントが失敗しても、同時実行のキューにアカウントが残っている場合にはデプロイは停止しません。

この例では最終的にFailure toleranceに定義した5を大幅に超える8アカウント失敗した状態でデプロイが停止します。

ざっくりまとめると

  • STRICT_FAILURE_TOLERANCE : デプロイ速度は遅くても問題なく、失敗したアカウントがFailure tolerance(障害耐性)に定義したアカウント数を超えた段階で必ず止まってほしいときに使用するモード
  • SOFT_FAILURE_TOLERANCE : デプロイ速度を重視しつつ、失敗したアカウントがFailure tolerance(障害耐性)に定義したアカウント数をオーバーすることを許容できるときに使用するモード

やってみる

事前準備

StackSetsのデプロイで使用するテンプレートはこちらです。
各アカウントにtestbucket-<アカウントID>-<リージョン名>という名前のS3バケットを作成します。

AWSTemplateFormatVersion: "2010-09-09"
Description: An AWS CloudFormation template that creates a unique S3 bucket.
Resources:
  MyS3Bucket:
    Type: "AWS::S3::Bucket"
    Properties:
      BucketName:
        Fn::Sub:
          - "testbucket-${AWS::AccountId}-${AWS::Region}"
          - {}
    DeletionPolicy: Delete

今回デプロイするアカウントは以下のようになっています。
管理アカウントとなるManagementアカウントを除く7アカウントにデプロイしていきます。

また、事前に Sub1 - Sub4 にはCloudFormationで作成されるS3バケットと同名のバケットを用意してスタック作成が失敗するようにしています。

コンソールからやってみる

と思ったのですが、Failure tolerance(障害耐性)を「2」で設定して、Maximum concurrent accounts(同時アカウントの最大数)にアカウント最大数の「7」が登録できないようでした...

まだ現時点ではコンソールでの設定はできないようです。

CLIからやってみる: STRICT_FAILURE_TOLERANCE

以下のコマンドでまずStackSetを作成します。

aws cloudformation create-stack-set \
--stack-set-name strict-stackset \
--template-body file://s3.yml \
--permission-model SERVICE_MANAGED \
--auto-deployment Enabled=false

次に、以下のコマンドでConcurrencyModeをSTRICT_FAILURE_TOLERANCEに設定したStackSetのインスタンスを作成します。
オプションは以下の通りです。

  • Maximum concurrent accounts(同時アカウントの最大数) : 7
  • Failure tolerance(障害耐性) : 2
  • ConcurrencyMode(同時実行モード) : STRICT_FAILURE_TOLERANCE
aws cloudformation create-stack-instances \
--stack-set-name strict-stackset \
--operation-preferences FailureToleranceCount=2,MaxConcurrentCount=7,ConcurrencyMode=STRICT_FAILURE_TOLERANCE \
--deployment-targets OrganizationalUnitIds='["r-xxxx"]' \
--regions '["ap-northeast-1"]

デプロイ後のコンソールを確認すると、事前に設定したFailure tolerance(障害耐性)の値である「2」を超えた3アカウント目が失敗した段階でデプロイが停止していることが確認できます。

CLIからやってみる: SOFT_FAILURE_TOLERANCE

次に新たな動作として追加されたSOFT_FAILURE_TOLERANCEを試していきます。

以下のコマンドでさきほどと別のStackSetを作成します。

aws cloudformation create-stack-set \
--stack-set-name soft-stackset \
--template-body file://s3.yml \
--permission-model SERVICE_MANAGED \
--auto-deployment Enabled=false

次に、以下のコマンドでConcurrencyModeをSOFT_FAILURE_TOLERANCEに設定したStackSetのインスタンスを作成します。
オプションは以下の通りです。

  • Maximum concurrent accounts(同時アカウントの最大数) : 7
  • Failure tolerance(障害耐性) : 2
  • ConcurrencyMode(同時実行モード) : SOFT_FAILURE_TOLERANCE
aws cloudformation create-stack-instances \
--stack-set-name soft-stackset \
--operation-preferences FailureToleranceCount=2,MaxConcurrentCount=7,ConcurrencyMode=SOFT_FAILURE_TOLERANCE \
--deployment-targets OrganizationalUnitIds='["r-xxxx"]' \
--regions '["ap-northeast-1"]'

こちらもデプロイ後のコンソールを確認してみます。

コンソールを確認すると2つのアカウントがCANCELLEDになっていることが確認できます。
こちらは想定と違い、Maximum concurrent accounts(同時アカウントの最大数)で「7」を設定していたのですべてにデプロイが実施されると思っていました。

こちらはまだ動作として安定していない可能性もあるので後日また実行してみたいと思います。

最後に

いままではMaximum concurrent accountとFailure toleranceを同じ値にして障害耐性を落として、デプロイ速度を上げることができましたが、今回のアップデートでデプロイ速度を上げつつ、障害耐性を確保しながらデプロイを行うことができるようになりました。

まだ、動作的に安定していない部分もありそうなので、後日また試してみたいと思います。

以上、たかやま(@nyan_kotaroo)でした。