概要
CloudFormation StackSets を使うと、1 つのテンプレートから、複数のアカウント・複数のリージョンへ同じスタックを配れます。ログの設定や監視用のリソースなど、どこでもそろえておきたいものを配るのに便利です。
ところが運用していると、誰かがある 1 つのリージョンだけ、コンソールから設定を手で変えてしまうことがあります。テンプレートの定義と実際のリソースがずれた状態を ドリフト と呼びます。StackSets には、配ったすべてのスタックインスタンスについて、まとめてドリフトを調べる ドリフト検出 があります。CloudTrail のログから変更を探して回る必要はありません。
この記事では、StackSets の構成要素と、ドリフト検出の結果(StackSet・スタックインスタンス・リソースの 3 段階)の見方を整理します。実践では、1 つのアカウントの東京と大阪の 2 リージョンに StackSet でパラメータを配り、大阪の値だけを手で変えて、ドリフト検出で見つけるところまでを行います。

クラウドおさる長老会が「どの猿山の倉庫も、扉の札はこう書く」と決めて配ったのに、大阪の猿山だけ札が勝手に書き換わっていた。そんなずれを、全部の猿山まとめて見つけに行くのでござる。
この記事のメリット
- StackSets の管理者アカウント・ターゲットアカウント・スタックインスタンスの関係を説明できるようになる
- セルフマネージド型とサービスマネージド型のアクセス許可の違いが分かる
- StackSet のドリフト検出を実行し、どのスタックインスタンスのどのプロパティが変わったかを確認できるようになる
- 手動変更の「検出」と、CloudFormation フックなどの「事前の検証」の違いを整理できる
執筆者とキャラクター紹介
執筆者:土肥(とひ)
株式会社ジェニュインの代表であり元エンジニア。これまでオンプレミスと AWS 環境のインフラ業務を担当。AWS 認定資格の学習で得た知識を、ハンズオンとともに解説するのが得意。直近では新人の教育も行っており、これから技術を学ぶ方が納得できる解説を心がけています。基礎編・Cloud Practitioner の記事では、解説役としても登場します。


クラウドおさる



はじめましてでござる。弊猿はクラウドおさる。IT インフラが異常に発達した猿山から、雲に乗って地上の AWS を学びに降りてきたのでござる。



基礎編や Cloud Practitioner の記事では、とひさんに素朴な疑問をぶつける役でござるな。Security - Specialty などの記事では、要所でワンポイントや注意点をひとこと添えるでござる。



猿山にもデータセンターや監視当番があって、地上で起きることはだいたい猿山にも同じ仕組みがあるのでござる。例え話がつい猿山に寄るのは、弊猿の癖でござる。
技術解説
StackSets の構成要素
| 用語 | 意味 |
|---|---|
| StackSet | 配るテンプレートと設定のまとまり。管理者アカウントの 1 つのリージョン(管理リージョン)に作る |
| 管理者アカウント | StackSet を作るアカウント |
| ターゲットアカウント | スタックが作られるアカウント。管理者アカウント自身もターゲットにできる |
| スタックインスタンス | 「アカウント × リージョン」ごとのスタックへの参照。実体は各リージョンの通常のスタック |
| オペレーション | 作成・更新・削除・ドリフト検出などの処理の単位。履歴が残る |
アクセス許可のモデルは 2 つあります。
| モデル | 仕組み | 向いている場面 |
|---|---|---|
| セルフマネージド型 | 管理者アカウントに管理ロール(AWSCloudFormationStackSetAdministrationRole)、ターゲットアカウントに実行ロール(AWSCloudFormationStackSetExecutionRole)を自分で作る | Organizations を使わない、または単一アカウントで複数リージョンに配る |
| サービスマネージド型 | AWS Organizations と連携し、必要な IAM ロールを StackSets が作る。組織に加わったアカウントへの自動デプロイもできる | 組織の管理アカウント(または委任管理者)から、組織単位でまとめて配る |
セルフマネージド型では、StackSets が管理ロールを引き受け、そこから各ターゲットアカウントの実行ロールを引き受けてスタックを操作します。実行ロールの公式テンプレートは全権限を持つので、配るリソースの種類に合わせて権限を絞るのが推奨です。


StackSet のドリフト検出
StackSet のドリフト検出は、各スタックインスタンスのスタックについて、リソースの現在の状態とテンプレート・パラメータで定義した状態を比べます。結果は 3 段階で積み上がります。
- 1 つでもリソースが変わっていれば、そのスタックインスタンスが
DRIFTED - 1 つでもスタックインスタンスが
DRIFTEDなら、StackSet がDRIFTED - すべて一致していれば
IN_SYNC
リソース単位では、プロパティが変わったものは MODIFIED、消されたものは DELETED と表示され、期待値と現在の値を見比べられます。



StackSet → スタックインスタンス → リソース、と大きい単位から順に絞り込むのでござる。猿山の一覧で赤い札の山を見つけ、その山の倉庫、その倉庫の扉、と降りていく感じでござるな。
押さえておきたい性質があります。
- ドリフトとして扱うのは CloudFormation の外で行われた変更だけ。CloudFormation 経由で個別のスタックを更新した差は対象外
- 1 つの StackSet で同時に実行できるドリフト検出は 1 つだけ
- 各スタックで個別に実行したドリフト検出の結果は、StackSets のコンソールには表示されない
- ドリフト検出は差を「見つける」だけで、元に戻さない。戻すなら手で直すか、意図した変更ならテンプレートを直して StackSet を更新する



CloudFormation フックはリソースを作る前にテンプレートを確かめる仕組み、SCP は操作を止める仕組みでござる。どちらも「作ったあとに手で変えられた」ことは見つけてくれぬ。検出したいならドリフト検出でござるぞ。
単一のスタックを定期的に調べたいときは、AWS Config のマネージドルール cloudformation-stack-drift-detection-check で、スタックのドリフトを継続的に評価する方法もあります。
実践
1 つのアカウントで、東京(管理リージョン)に StackSet soa-stackset-drift を作り、東京 ap-northeast-1 と大阪 ap-northeast-3 の 2 リージョンにスタックインスタンスを配ります。テンプレートは Systems Manager パラメータストアの標準パラメータを 2 つ作るだけなので、課金は発生しません。大阪のパラメータの値を手で書き換えてから、ドリフト検出で見つけます。
前提条件
- リージョン:
ap-northeast-1(東京)を管理リージョンとし、ap-northeast-3(大阪)にも配る - 以下のリソースが作成済みであること
まだ用意していない場合は、「作り方の参考」の記事の手順で作れます。リソース名は、この記事の名前に読み替えてください。
| リソース種別 | リソース名 | 内容 | 作り方の参考 |
|---|---|---|---|
| IAM ロール(管理ロール) | AWSCloudFormationStackSetAdministrationRole | 信頼: cloudformation.amazonaws.com。許可: AWSCloudFormationStackSetExecutionRole への sts:AssumeRole | AWS IAM でユーザー・ロール・ポリシーを作成しアクセス制御する |
| IAM ロール(実行ロール) | AWSCloudFormationStackSetExecutionRole | 信頼: 自分のアカウント。許可: cloudformation:* と SSM パラメータの作成・参照・削除 | 同上 |
StackSet で配るテンプレートは次の内容です。soa-stackset-drift.yaml という名前で手元に保存しておきます。
AWSTemplateFormatVersion: "2010-09-09"
Description: soa12 - StackSets drift detection sample (SSM parameters only)
Resources:
LogLevel:
Type: AWS::SSM::Parameter
Properties:
Name: /soa/stackset/log-level
Type: String
Value: INFO
Description: Application log level (managed by StackSets)
MaintenanceMode:
Type: AWS::SSM::Parameter
Properties:
Name: /soa/stackset/maintenance-mode
Type: String
Value: "off"
Description: Maintenance mode switch (managed by StackSets)作成するリソース一覧
| リソース種別 | リソース名 | 用途 |
|---|---|---|
| StackSet | soa-stackset-drift | 東京・大阪にテンプレートを配る |
| スタックインスタンス | 自分のアカウント × ap-northeast-1 / ap-northeast-3 | 各リージョンのスタック(StackSet-soa-stackset-drift-…) |
| SSM パラメータ | /soa/stackset/log-level、/soa/stackset/maintenance-mode(各リージョン) | StackSet が作る。大阪の log-level を手で変える |
手順 1: StackSet を作る
AWS マネジメントコンソールにログインし、リージョンが ap-northeast-1(東京)であることを確認します。上部の検索バーに CloudFormation と入力し、「CloudFormation」を選択します。
左側ナビゲーションの「StackSets」を選択し、「StackSet を作成」をクリックします。以下を設定します。
- アクセス許可: 「セルフサービスのアクセス許可」(既定は「サービスマネージドアクセス許可」なので切り替えます)
- IAM 管理ロール ARN – オプション: 1 つ目のドロップダウンで「IAM Role Name」、2 つ目で
AWSCloudFormationStackSetAdministrationRoleを選択 - IAM 実行ロール名:
AWSCloudFormationStackSetExecutionRole(最初から入っています) - テンプレートの準備: 「テンプレートの準備完了」
- テンプレートソース: 「テンプレートファイルのアップロード」で
soa-stackset-drift.yamlを選択


アップロードすると、テンプレートの S3 URL が表示されます。CloudFormation が自動で作るバケット(cf-templates- で始まる名前)に置かれたものです。
「次へ」をクリックし、StackSet 名に soa-stackset-drift と入力して「次へ」をクリックします(このテンプレートには入力するパラメータはありません)。「スタックセットオプションの設定」はデフォルトのまま「次へ」をクリックします。
手順 2: 東京と大阪にデプロイする
「デプロイオプションの設定」で以下を設定します。
- スタックセットにスタックを追加: 「新しいスタックのデプロイ」のまま
- アカウントの追加: 「スタックをアカウントにデプロイ」を選び、アカウント番号に自分のアカウント ID(12 桁)を入力
- リージョンの指定: 1 行目で「アジアパシフィック (東京)」、行を追加して 2 行目で「アジアパシフィック (大阪)」を選択
- デプロイオプション: その他はデフォルトのまま


「次へ」をクリックし、確認画面で「送信」をクリックします。StackSet の「スタックインスタンス」タブを開き、2 つのスタックインスタンスの「詳細ステータス」が SUCCEEDED になるまで待ちます(1 分ほど。API の list-stack-instances では Status が CURRENT になります)。「ドリフトステータス」はまだ NOT_CHECKED です。


手順 3: 大阪のパラメータを手で変える
画面右上のリージョンを「アジアパシフィック (大阪)」に切り替えます。上部の検索バーに Systems Manager と入力して開き、左側ナビゲーションの「パラメータストア」を選択します。
/soa/stackset/log-level を開き、「編集」をクリックします。値を INFO から DEBUG に書き換えて「変更を保存」をクリックします。CloudFormation を通さない、いわゆる「手で直した」変更です。
手順 4: ドリフト検出を実行する
リージョンを「アジアパシフィック (東京)」に戻し、CloudFormation の「StackSets」から soa-stackset-drift を開きます。「アクション」→「ドリフトの検出」を選択します。
「オペレーション」タブに、タイプ DETECT_DRIFT のオペレーションが表示されます。ステータスが SUCCEEDED になるまで、1 分ほど待ちます。
「スタックインスタンス」タブを開くと、大阪(ap-northeast-3)の「ドリフトステータス」が DRIFTED、東京(ap-northeast-1)が IN_SYNC になっています。「StackSet の情報」(概要)でも、StackSet 全体のドリフトステータスが DRIFTED になっています。





東京は無事で、大阪だけが赤札でござる。どこで誰かが手を入れたかが、リージョンの単位で一目で分かるのでござるな。
手順 5: どのプロパティが変わったかを確認する
「オペレーション」タブでドリフト検出のオペレーションを選択し、「ドリフトの詳細を表示」をクリックすると、同期中のインスタンスが 1、ドリフトしたインスタンスが 1 と表示されます。閉じたら、オペレーションタブの下のスタックインスタンスの表で大阪を選び、「ドリフト結果を表示」をクリックします。「リソースのドリフトステータス」に、LogLevel(/soa/stackset/log-level)が MODIFIED、MaintenanceMode が IN_SYNC と並びます。
LogLevel を選んで「ドリフトの詳細を表示」をクリックすると、「ドリフトの詳細」の画面の「違い」の表に、Value プロパティの期待値 INFO と現在の値 DEBUG が並んで表示されます。


同じ結果は CloudShell からも確認できます。
aws cloudformation list-stack-instances \
--stack-set-name soa-stackset-drift \
--filters Name=DRIFT_STATUS,Values=DRIFTED \
--query 'Summaries[].[Region,DriftStatus,LastDriftCheckTimestamp]' --output table大阪の 1 行だけが DRIFTED として表示されます。
まとめ
| 確かめたいこと | 見るところ |
|---|---|
| どこかで手動変更されていないか | StackSet の概要のドリフトステータス(DRIFTED / IN_SYNC) |
| どのアカウント・リージョンか | 「スタックインスタンス」タブのドリフトステータス |
| どのリソースのどのプロパティか | 「オペレーション」タブ →「リソースドリフトを表示」→「ドリフトの詳細を表示」 |
- StackSets は 1 つのテンプレートを複数のアカウント・リージョンに配る。配った先ごとにスタックインスタンスができる
- セルフマネージド型は管理ロールと実行ロールを自分で作る。単一アカウントの複数リージョンにも使える。サービスマネージド型は Organizations と連携する
- StackSet のドリフト検出は、全スタックインスタンスのリソースをテンプレートの定義と比べる。同時に実行できるのは 1 つだけ
- ドリフト検出は差を見つけるだけで、元には戻さない
- CloudFormation フック(作成前の検証)や SCP(操作の禁止)は、作成後の手動変更の検出には使えない



「配ったあとで手で変えられたものを、まとめて見つけたい」と来たら StackSet のドリフト検出でござる。作る前に確かめる仕組みや、操作を止める仕組みと取り違えやすいので、いつの何を見る仕組みかで見分けるのでござるな。
参照先
- StackSets を使用したアカウントとリージョン全体でのスタックの管理 – AWS CloudFormation
- StackSets の概念 – AWS CloudFormation
- セルフマネージド型のアクセス許可を付与する – AWS CloudFormation
- CloudFormation StackSets でのドリフト検出の実行 – AWS CloudFormation
- ドリフト検出を使用してスタックとリソースへのアンマネージド型設定変更を検出する – AWS CloudFormation
- リソースタイプのサポート – AWS CloudFormation
- cloudformation-stack-drift-detection-check – AWS Config














