話題の記事

AWS CloudFormationで手動で行った変更が検出可能になりました!!!

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

大栗です。

CloudFormationはAWSインフラのオーケストレーションを担っており、Infrastructure as Codeで構成のバージョン管理ができる素晴らしいサービスです。しかし大きな難点がありました。それはCloudFormation外の変更を認識しないことで、テンプレートの変更時に意図しない環境になることでした。今回のアップデートでCloudFormation外の変更(ドリフト)も検出可能になり、その様な問題発生を抑止できるようになりましたのでレポートします。

ドリフト検出とは?

概要

今回のアップデートであるドリフト検知はre:Invent 2017のセッションで発表されていた機能で、現在の状態とCloudFormationで定義されているあるべき状態の差分を検知することができる機能です。

初期の構築ではCloudFormationを利用するが、後のアップデートではUpdate Stackを実行せずに手動で変更したりCloudFormation以外の手段で変更してしまうことが多々あります。一旦別の手段へ変更してしまうと、テンプレートとの差が分からなくなりCloudFormationを利用した構成管理が行えなくなり、大きな問題になっていました。

実際のリソースとCloudFormationテンプレートの内容に乖離があることをドリフトと言い、それが可視化できる様になりました。

ドリフト検出は、一般の商用リージョン全てで利用可能です。

ドリフトを検出できるリソース

ドリフトを検出できるサービスは、2018年11月14日現在で以下となります。各サービスの対象となるリソースの詳細についてはドキュメントをご参照ください。

  • API Gateway
  • Auto Scaling
  • CloudTrail
  • CloudWatch Events
  • CloudWatch Logs
  • DynamoDB
  • Amazon EC2
  • Amazon ECS
  • Elastic Load Balancing
  • IAM
  • AWS IoT
  • Lambda
  • Amazon RDS
  • Route 53
  • Amazon S3
  • Amazon SNS
  • Amazon SQS

ドリフト検出のステータス

ドリフトのステータスにはいくつかの種類があります。

  • ドリフト検出オペレーションステータス: ドリフトの操作の現在のステータスを記述する。
  • スタックドリフトステータス: そのリソースのドリフト状態に基づいて、スタック全体のドリフト状態を記述します。
  • リソースドリフトステータス:   個々のリソースのドリフト状況を記述します。

ドリフト検出オペレーションステータス

ドリフト検出オペレーションステータス 説明
DETECTION_COMPLETE ドリフト検出をサポートするスタック内のすべてのリソースについて、スタックドリフト検出オペレーションが正常に完了した。
DETECTION_FAILED スタックドリフト検出オペレーションは、スタック内の少なくとも1つのリソースで失敗した。結果はCloudFormationがドリフト検出を正常に完了したリソースで利用できる。
DETECTION_IN_PROGRESS スタックドリフト検出オペレーションは現在進行中です。

スタックドリフトステータス

スタックドリフトステータス 説明
DRIFTED スタックは、予想されるテンプレート構成と異なるか、またはドリフトがある。1つ以上のリソースにドリフトがある場合、スタックはドリフトがあるみなされる
NOT_CHECKED AWS CloudFormationは、スタックが予想されるテンプレート設定と異なるかチェックしていない
IN_SYNC サポートされている各リソースの現在の構成は、期待されるテンプレート構成と一致します。ドリフト検出をサポートするリソースのないスタックもIN_SYNCのステータスを持つ

リソースドリフトステータス

リソース自体

リソースドリフトステータス 説明
DELETED リソースが削除されたため、リソースは予想されるテンプレート構成とは異なる
MODIFIED リソースは予想されるテンプレート構成とは異なる
NOT_CHECKED CloudFormationはリソースが予想されるテンプレート構成と異なるかどうかをチェックしていない
IN_SYNC リソースの現在の構成は予想されるテンプレート構成と一致する

リソースのプロパティ

プロパティの違いの種類 説明
ADD 配列またはリストのデータ型であるリソースプロパティに値が追加された
REMOVE このプロパティは現在のリソース構成から削除された
NOT_EQUAL 現在のプロパティの値はスタックテンプレートで定義されている期待値とは異なる

注意

スタック上のドリフトを正常に検出するためには、以下の権限が必要です。

  • スタックに含まれるリソースの読み込み権限
  • cloudformation:DetectStackDrift
  • cloudformation:DetectStackResourceDrift

特定のエッジケースの場合、正確なドリフトの結果を返せないことがあります。ドリフト結果を正しく解釈するためにエッジケースに注意してください。エッジケースはこちらのドキュメントをご参照ください。

やってみた

ここでは東京リージョンを前提として、マネージメントコンソールから実行します。マネージメントコンソールは新しいコンソールを使用するものとします。

以下の流れで動作を確認します。

  • 事前のスタック作成
  • 環境の手動変更
  • ドリフトの検知

事前のスタック作成

CloudFormationの画面でCreate stackをクリックします。

Use a sample templateを選択して、Multi_AZ_SimpleLAMP Stackを選択します。テンプレートのURLはhttps://s3-ap-northeast-1.amazonaws.com/cloudformation-templates-ap-northeast-1/LAMP_Multi_AZ.templateです。

Configure stack optionsでは、以下の設定を行いました。

項目 備考
Stack name DRIFT-TEST
DBAllocatedStorage 5
DBInstanceClass db.t2.small
DBName myDatabase
DBPassword mypassword
DBUser awsuser
InstanceType t2.small
KeyName <任意>
MultiAZDatabase true
SSHLocation 0.0.0.0/0
Subnets <任意> ここではap-northeast-1a, ap-northeast-1c, ap-northeast-1dの2サブネットを設定
VpcId <任意> ここではデフォルト VPCを設定
WebServerCapacity 2

内容を確認してスタックを実行します。

スタックが作成完了すると以下のリソースが作成されます。

Logical ID Type ドリフト検知対象
ALBListener AWS::ElasticLoadBalancingV2::Listener Yes
ALBTargetGroup AWS::ElasticLoadBalancingV2::TargetGroup No
ApplicationLoadBalancer AWS::ElasticLoadBalancingV2::LoadBalancer Yes
DBEC2SecurityGroup AWS::EC2::SecurityGroup Yes
LaunchConfig AWS::AutoScaling::LaunchConfiguration Yes
MySQLDatabase AWS::RDS::DBInstance Yes
WebServerGroup AWS::AutoScaling::AutoScalingGroup Yes
WebServerSecurityGroup AWS::EC2::SecurityGroup Yes

環境の手動変更

ここで、以下のリソースを変更してみます。

  • ApplicationLoadBalancer
  • MySQLDatabase
  • WebServerSecurityGroup

ApplicationLoadBalancerの変更

ApplicationLoadBalancerの属性を変更します。

項目 変更前 変更後
削除保護 無効 有効
アイドルタイムアウト 60 秒 120 秒
HTTP/2 有効 無効
アクセスログ 無効 <変更無し>
変更前

変更後

MySQLDatabaseの変更

MySQLDatabase詳細を以下のように変更します。

項目 変更前 変更後
IAM DB 認証 が有効です いいえ はい
マルチ AZ はい いいえ
メンテナンスウィンドウ wed:18:58-wed:19:28 UTC (GMT) wed:20:00-wed:21:00 UTC (GMT)

変更前

変更後

WebServerSecurityGroupの変更

WebServerSecurityGroupインバウンドのルールについて以下の内容を追加します。

タイプ プロトコル ポート範囲 ソース 説明
HTTPS (443) TCP (6) 443 0.0.0.0/0
変更前

変更後

ドリフトの検知

CloudFormationテンプレートと差がある環境を構築できたのでドリフトの検知を行います。

マネージメントコンソールで対象のテンプレートを選択して、ActionsからDetect driftをクリックします。

ドリフトの検出が開始されました。

スタックのドリフト結果を確認します。対象のスタックを選択してActionsからView drift resultsをクリックします。

ドリフトの結果を確認すると変更を行ったApplicationLoadBalancerが検出されておらす、以下のリソースが検知されています。

  • MySQLDatabase
  • WebServerSecurityGroup

テンプレート上ではApplicationLoadBalancerはサブネットしか定義されていなかったため差を検出できなかったと思われます。エッジケースとしてデフォルト値の設定はまだ検出できないためです。今後のアップデートに期待しましょう。

    "ApplicationLoadBalancer" : {
      "Type" : "AWS::ElasticLoadBalancingV2::LoadBalancer",
      "Properties" : {
        "Subnets" : { "Ref" : "Subnets"}
      }
    },

MySQLDatabaseの詳細を確認するために、対象をリソースを選択してView drift detailsをクリックします。

詳細を確認してみてもリソースレベルのドリフトの内容が分かりませんでした。設定した項目が、まだ検出をサポートしていないのかもしれません。

次にWebServerSecurityGroupの詳細を確認してみます。

WebServerSecurityGroupでは追加したHTTPSのルールが確認できました。

現時点ではリソースによって取得できるドリフトの詳細に差があるようです。

さいごに

CloudFormationユーザー待望の機能がお目見えしました。これが欲しかったんだ!という機能です。今まで一旦手動で変更を行った時にはCloudFormationの利用を諦めざるを得なかったですが、差が分かることで対応が楽になります。

現時点では取れる情報が限定的ですが、CloudFormation運用を行いやすくなるアップデートですので有効活用していきましょう。