チュートリアル: スタックの更新 - AWS CloudFormation

チュートリアル: スタックの更新

AWS CloudFormation では、既存のスタックのリソースのプロパティを更新できます。単純な構成の変更 (CloudWatch アラームのしきい値を変更するなど) から、もっと複雑な変更 (Amazon EC2 インスタンスで実行されている Amazon マシンイメージ (AMI) を更新するなど) まで、変更は多岐にわたります。テンプレート内の AWS リソースは、その多くが更新に対応しているため、継続的に機能を拡充していくことが可能です。

このセクションでは、実行されているスタックのアップデートのシンプルな進行過程について説明します。テンプレートを使用して、実行中のソフトウェアのバージョン管理と同様に、AWS インフラストラクチャの構成にもバージョン管理システムを使用できることを説明します。以下の手順について説明します。

  1. 初期スタックの作成 - 基本の Amazon Linux AMI を使用してスタックを作成し、AWS CloudFormation ヘルパースクリプトを使用して Apache Web Server と単純な PHP ウェブアプリケーションをインストールします。

  2. アプリケーションの更新 - アプリケーション内のファイルのいずれかを更新し、CloudFormation を使用してソフトウェアをデプロイします。

  3. インスタンスタイプのアップデート - 基盤となる Amazon EC2 インスタンスのインスタンスタイプを変更します。

  4. Amazon EC2 インスタンス上の AMI の更新 - スタック内の Amazon EC2 インスタンスの Amazon マシンイメージ (AMI) を変更します。

  5. インスタンスへのキーペアの追加 - インスタンスに Amazon EC2 キーペアを追加し、セキュリティグループを更新して、インスタンスへの SSH アクセスを可能にします。

  6. スタックのリソースの変更 - テンプレートを更新することでスタックのリソースを追加および削除し、自動スケーリングされ、負荷分散されるアプリケーションに変換します。

単純なアプリケーション

まず、このセクション全体で使用するスタックを作成します。Apache Web Server でホストされ Amazon Linux AMI 上で実行される単一のインスタンス PHP ウェブアプリケーションを起動する単純なテンプレートが用意されています。

Apache Web Server、PHP、および単純な PHP アプリケーションはすべて、Amazon Linux AMI にデフォルトでインストールされている CloudFormation ヘルパースクリプトによってインストールされます。以下のテンプレートスニペットには、インストールするパッケージとファイルを記述するメタデータが表示されています。この場合は、Amazon Linux AMI の Yum リポジトリからの Apache Web Server と PHP 実行環境です。またこのスニペットには、Apache Web Server の実行を確認する Service セクションが含まれています。Amazon EC2 インスタンス定義の Properties セクションでは、UserData プロパティに、パッケージとファイルをインストールするための cfn-init を呼び出す CloudInit スクリプトが含まれています。

"WebServerInstance": { "Type" : "AWS::EC2::Instance", "Metadata" : { "AWS::CloudFormation::Init" : { "config" : { "packages" : { "yum" : { "httpd" : [], "php" : [] } }, "files" : { "/var/www/html/index.php" : { "content" : { "Fn::Join" : ["", [ "<?php\n", "echo '<h1>AWS CloudFormation sample PHP application</h1>';\n", "echo '<p>", { "Ref" : "WelcomeMessage" }, "</p>';\n", "?>\n" ]]}, "mode" : "000644", "owner" : "apache", "group" : "apache" }, }, : "services" : { "sysvinit" : { "httpd" : { "enabled" : "true", "ensureRunning" : "true" } } } } } }, "Properties": { : "UserData" : { "Fn::Base64" : { "Fn::Join" : ["", [ "#!/bin/bash\n", "yum install -y aws-cfn-bootstrap\n", : "# Install the files and packages from the metadata\n", "/opt/aws/bin/cfn-init -v ", " --stack ", { "Ref" : "AWS::StackName" }, " --resource WebServerInstance ", " --region ", { "Ref" : "AWS::Region" }, "\n", : ]]}} } },

アプリケーション自体は 2 行の「Hello World」サンプルで、その全体がテンプレート内で定義されています。実際のアプリケーションでは、ファイルは Amazon S3、GitHub、その他のリポジトリに格納され、テンプレートから参照されます。CloudFormation はパッケージ (RPM や RubyGems など) をダウンロードし、個別のファイルを参照して .zip.tar ファイルを解凍することで、Amazon EC2 インスタンス上にアプリケーションの中間生成物を作成することができます。

テンプレートは cfn-hup デーモンを有効化して構成し、Amazon EC2 インスタンスのメタデータ内で定義された構成への変更をリッスンします。cfn-hup デーモンを使用することで、Apache や PHP のバージョンなどのアプリケーションソフトウェアをアップデートしたり、または AWS CloudFormation から PHP アプリケーションファイル自体を更新したりすることができます。テンプレートの同じ Amazon EC2 リソースから取り出した以下のスニペットには、メタデータへの変更が検出されたときにソフトウェアをアップデートする cfn-init を呼び出す cfn-hup を設定するために必要な部分が示されています。

"WebServerInstance": { "Type" : "AWS::EC2::Instance", "Metadata" : { "AWS::CloudFormation::Init" : { "config" : { : "files" : { : "/etc/cfn/cfn-hup.conf" : { "content" : { "Fn::Join" : ["", [ "[main]\n", "stack=", { "Ref" : "AWS::StackName" }, "\n", "region=", { "Ref" : "AWS::Region" }, "\n" ]]}, "mode" : "000400", "owner" : "root", "group" : "root" }, "/etc/cfn/hooks.d/cfn-auto-reloader.conf" : { "content": { "Fn::Join" : ["", [ "[cfn-auto-reloader-hook]\n", "triggers=post.update\n", "path=Resources.WebServerInstance.Metadata.AWS::CloudFormation::Init\n", "action=/opt/aws/bin/cfn-init -s ", { "Ref" : "AWS::StackId" }, " -r WebServerInstance ", " --region ", { "Ref" : "AWS::Region" }, "\n", "runas=root\n" ]]} } }, : }, "Properties": { : "UserData" : { "Fn::Base64" : { "Fn::Join" : ["", [ : "# Start up the cfn-hup daemon to listen for changes to the Web Server metadata\n", "/opt/aws/bin/cfn-hup || error_exit 'Failed to start cfn-hup'\n", : ]]}} } },

最後に Amazon EC2 セキュリティグループを作成すれば、スタックの完成です。

{ "AWSTemplateFormatVersion" : "2010-09-09", "Description" : "AWS CloudFormation Sample Template: Sample template that can be used to test EC2 updates. **WARNING** This template creates an Amazon Ec2 Instance. You will be billed for the AWS resources used if you create a stack from this template.", "Parameters" : { "InstanceType" : { "Description" : "WebServer EC2 instance type", "Type" : "String", "Default" : "t2.small", "AllowedValues" : [ "t1.micro", "t2.nano", "t2.micro", "t2.small", "t2.medium", "t2.large", "m1.small", "m1.medium", "m1.large", "m1.xlarge", "m2.xlarge", "m2.2xlarge", "m2.4xlarge", "m3.medium", "m3.large", "m3.xlarge", "m3.2xlarge", "m4.large", "m4.xlarge", "m4.2xlarge", "m4.4xlarge", "m4.10xlarge", "c1.medium", "c1.xlarge", "c3.large", "c3.xlarge", "c3.2xlarge", "c3.4xlarge", "c3.8xlarge", "c4.large", "c4.xlarge", "c4.2xlarge", "c4.4xlarge", "c4.8xlarge", "g2.2xlarge", "g2.8xlarge", "r3.large", "r3.xlarge", "r3.2xlarge", "r3.4xlarge", "r3.8xlarge", "i2.xlarge", "i2.2xlarge", "i2.4xlarge", "i2.8xlarge", "d2.xlarge", "d2.2xlarge", "d2.4xlarge", "d2.8xlarge", "hi1.4xlarge", "hs1.8xlarge", "cr1.8xlarge", "cc2.8xlarge", "cg1.4xlarge" ], "ConstraintDescription" : "must be a valid EC2 instance type." } }, "Mappings" : { "AWSInstanceType2Arch" : { "t1.micro" : { "Arch" : "HVM64" }, "t2.nano" : { "Arch" : "HVM64" }, "t2.micro" : { "Arch" : "HVM64" }, "t2.small" : { "Arch" : "HVM64" }, "t2.medium" : { "Arch" : "HVM64" }, "t2.large" : { "Arch" : "HVM64" }, "m1.small" : { "Arch" : "HVM64" }, "m1.medium" : { "Arch" : "HVM64" }, "m1.large" : { "Arch" : "HVM64" }, "m1.xlarge" : { "Arch" : "HVM64" }, "m2.xlarge" : { "Arch" : "HVM64" }, "m2.2xlarge" : { "Arch" : "HVM64" }, "m2.4xlarge" : { "Arch" : "HVM64" }, "m3.medium" : { "Arch" : "HVM64" }, "m3.large" : { "Arch" : "HVM64" }, "m3.xlarge" : { "Arch" : "HVM64" }, "m3.2xlarge" : { "Arch" : "HVM64" }, "m4.large" : { "Arch" : "HVM64" }, "m4.xlarge" : { "Arch" : "HVM64" }, "m4.2xlarge" : { "Arch" : "HVM64" }, "m4.4xlarge" : { "Arch" : "HVM64" }, "m4.10xlarge" : { "Arch" : "HVM64" }, "c1.medium" : { "Arch" : "HVM64" }, "c1.xlarge" : { "Arch" : "HVM64" }, "c3.large" : { "Arch" : "HVM64" }, "c3.xlarge" : { "Arch" : "HVM64" }, "c3.2xlarge" : { "Arch" : "HVM64" }, "c3.4xlarge" : { "Arch" : "HVM64" }, "c3.8xlarge" : { "Arch" : "HVM64" }, "c4.large" : { "Arch" : "HVM64" }, "c4.xlarge" : { "Arch" : "HVM64" }, "c4.2xlarge" : { "Arch" : "HVM64" }, "c4.4xlarge" : { "Arch" : "HVM64" }, "c4.8xlarge" : { "Arch" : "HVM64" }, "g2.2xlarge" : { "Arch" : "HVMG2" }, "g2.8xlarge" : { "Arch" : "HVMG2" }, "r3.large" : { "Arch" : "HVM64" }, "r3.xlarge" : { "Arch" : "HVM64" }, "r3.2xlarge" : { "Arch" : "HVM64" }, "r3.4xlarge" : { "Arch" : "HVM64" }, "r3.8xlarge" : { "Arch" : "HVM64" }, "i2.xlarge" : { "Arch" : "HVM64" }, "i2.2xlarge" : { "Arch" : "HVM64" }, "i2.4xlarge" : { "Arch" : "HVM64" }, "i2.8xlarge" : { "Arch" : "HVM64" }, "d2.xlarge" : { "Arch" : "HVM64" }, "d2.2xlarge" : { "Arch" : "HVM64" }, "d2.4xlarge" : { "Arch" : "HVM64" }, "d2.8xlarge" : { "Arch" : "HVM64" }, "hi1.4xlarge" : { "Arch" : "HVM64" }, "hs1.8xlarge" : { "Arch" : "HVM64" }, "cr1.8xlarge" : { "Arch" : "HVM64" }, "cc2.8xlarge" : { "Arch" : "HVM64" } }, "AWSRegionArch2AMI" : { "us-east-1" : {"HVM64" : "ami-0ff8a91507f77f867", "HVMG2" : "ami-0a584ac55a7631c0c"}, "us-west-2" : {"HVM64" : "ami-a0cfeed8", "HVMG2" : "ami-0e09505bc235aa82d"}, "us-west-1" : {"HVM64" : "ami-0bdb828fd58c52235", "HVMG2" : "ami-066ee5fd4a9ef77f1"}, "eu-west-1" : {"HVM64" : "ami-047bb4163c506cd98", "HVMG2" : "ami-0a7c483d527806435"}, "eu-west-2" : {"HVM64" : "ami-f976839e", "HVMG2" : "NOT_SUPPORTED"}, "eu-west-3" : {"HVM64" : "ami-0ebc281c20e89ba4b", "HVMG2" : "NOT_SUPPORTED"}, "eu-central-1" : {"HVM64" : "ami-0233214e13e500f77", "HVMG2" : "ami-06223d46a6d0661c7"}, "ap-northeast-1" : {"HVM64" : "ami-06cd52961ce9f0d85", "HVMG2" : "ami-053cdd503598e4a9d"}, "ap-northeast-2" : {"HVM64" : "ami-0a10b2721688ce9d2", "HVMG2" : "NOT_SUPPORTED"}, "ap-northeast-3" : {"HVM64" : "ami-0d98120a9fb693f07", "HVMG2" : "NOT_SUPPORTED"}, "ap-southeast-1" : {"HVM64" : "ami-08569b978cc4dfa10", "HVMG2" : "ami-0be9df32ae9f92309"}, "ap-southeast-2" : {"HVM64" : "ami-09b42976632b27e9b", "HVMG2" : "ami-0a9ce9fecc3d1daf8"}, "ap-south-1" : {"HVM64" : "ami-0912f71e06545ad88", "HVMG2" : "ami-097b15e89dbdcfcf4"}, "us-east-2" : {"HVM64" : "ami-0b59bfac6be064b78", "HVMG2" : "NOT_SUPPORTED"}, "ca-central-1" : {"HVM64" : "ami-0b18956f", "HVMG2" : "NOT_SUPPORTED"}, "sa-east-1" : {"HVM64" : "ami-07b14488da8ea02a0", "HVMG2" : "NOT_SUPPORTED"}, "cn-north-1" : {"HVM64" : "ami-0a4eaf6c4454eda75", "HVMG2" : "NOT_SUPPORTED"}, "cn-northwest-1" : {"HVM64" : "ami-6b6a7d09", "HVMG2" : "NOT_SUPPORTED"} } }, "Resources" : { "WebServerInstance": { "Type" : "AWS::EC2::Instance", "Metadata" : { "Comment" : "Install a simple PHP application", "AWS::CloudFormation::Init" : { "config" : { "packages" : { "yum" : { "httpd" : [], "php" : [] } }, "files" : { "/var/www/html/index.php" : { "content" : { "Fn::Join" : ["", [ "<?php\n", "echo '<h1>AWS CloudFormation sample PHP application</h1>';\n", "?>\n" ]]}, "mode" : "000644", "owner" : "apache", "group" : "apache" }, "/etc/cfn/cfn-hup.conf" : { "content" : { "Fn::Join" : ["", [ "[main]\n", "stack=", { "Ref" : "AWS::StackId" }, "\n", "region=", { "Ref" : "AWS::Region" }, "\n" ]]}, "mode" : "000400", "owner" : "root", "group" : "root" }, "/etc/cfn/hooks.d/cfn-auto-reloader.conf" : { "content": { "Fn::Join" : ["", [ "[cfn-auto-reloader-hook]\n", "triggers=post.update\n", "path=Resources.WebServerInstance.Metadata.AWS::CloudFormation::Init\n", "action=/opt/aws/bin/cfn-init -s ", { "Ref" : "AWS::StackId" }, " -r WebServerInstance ", " --region ", { "Ref" : "AWS::Region" }, "\n", "runas=root\n" ]]} } }, "services" : { "sysvinit" : { "httpd" : { "enabled" : "true", "ensureRunning" : "true" }, "cfn-hup" : { "enabled" : "true", "ensureRunning" : "true", "files" : ["/etc/cfn/cfn-hup.conf", "/etc/cfn/hooks.d/cfn-auto-reloader.conf"]} } } } } }, "Properties": { "ImageId" : { "Fn::FindInMap" : [ "AWSRegionArch2AMI", { "Ref" : "AWS::Region" }, { "Fn::FindInMap" : [ "AWSInstanceType2Arch", { "Ref" : "InstanceType" }, "Arch" ] } ] }, "InstanceType" : { "Ref" : "InstanceType" }, "SecurityGroups" : [ {"Ref" : "WebServerSecurityGroup"} ], "UserData" : { "Fn::Base64" : { "Fn::Join" : ["", [ "#!/bin/bash -xe\n", "yum install -y aws-cfn-bootstrap\n", "# Install the files and packages from the metadata\n", "/opt/aws/bin/cfn-init -v ", " --stack ", { "Ref" : "AWS::StackName" }, " --resource WebServerInstance ", " --region ", { "Ref" : "AWS::Region" }, "\n", "# Start up the cfn-hup daemon to listen for changes to the Web Server metadata\n", "/opt/aws/bin/cfn-hup || error_exit 'Failed to start cfn-hup'\n", "# Signal the status from cfn-init\n", "/opt/aws/bin/cfn-signal -e $? ", " --stack ", { "Ref" : "AWS::StackName" }, " --resource WebServerInstance ", " --region ", { "Ref" : "AWS::Region" }, "\n" ]]}} }, "CreationPolicy" : { "ResourceSignal" : { "Timeout" : "PT5M" } } }, "WebServerSecurityGroup" : { "Type" : "AWS::EC2::SecurityGroup", "Properties" : { "GroupDescription" : "Enable HTTP access via port 80", "SecurityGroupIngress" : [ {"IpProtocol" : "tcp", "FromPort" : "80", "ToPort" : "80", "CidrIp" : "0.0.0.0/0"} ] } } }, "Outputs" : { "WebsiteURL" : { "Description" : "Application URL", "Value" : { "Fn::Join" : ["", ["http://", { "Fn::GetAtt" : [ "WebServerInstance", "PublicDnsName" ]}]] } } } }

この例では単一の Amazon EC2 インスタンスを使用しますが、Elastic Load Balancing や Amazon EC2 Auto Scaling グループを利用する複雑なソリューションで同じ仕組みを利用して、一連のアプリケーションサーバーを管理することもできます。ただし Auto Scaling グループについては注意すべき点があります。詳細については、「Auto Scaling グループの更新」を参照してください。

初期スタックの作成

この例の目的上、AWS Management Console を使用して、サンプルテンプレートから初期スタックを作成します。

警告

この手順が完了すると、ライブ AWS サービスがデプロイされます。それらのサービスが実行されている間は、標準使用料が課金されます。

AWS Management Consoleからスタックを作成するには
  1. 前のテンプレートをコピーし、お使いのシステムのローカルにテキストファイルとして保存します。このファイルは後続の手順で必要となるため、保存場所をメモしておいてください。

  2. [https://console.aws.amazon.com/cloudformation] で CloudFormation コンソールにログインします。

  3. [Create New Stack] を選択します。

  4. [新しいスタックの作成] ウィザードの [テンプレートの選択] 画面で、[名前] フィールドに UpdateTutorial と入力します。同じページで [Upload a template to Amazon S3] (テンプレートを Amazon S3 にアップロード) を選択し、最初の手順でダウンロードしたファイルを参照して、[Next] (次へ) を選択します。

  5. [Specify Parameters (パラメータを指定)] 画面の [Instance Type (インスタンスタイプ)] ボックスに t1.micro と入力します。次いで、[次へ] を選択します。

  6. [Options] (オプション) 画面で、[Next] (次へ) を選択します。

  7. [Review] (確認) 画面で、意図したとおりの設定になっていることを確認し、[Create] (作成) を選択します。

スタックのステータスが [CREATE_COMPLETE] に変更された後、出力タブに、あなたのウェブサイトの URL が表示されます。WebsiteURL 出力の値を選択した場合、新しい PHP アプリケーションが実行されていることを確認できます。

アプリケーションの更新

スタックをデプロイしたので、今度はアプリケーションを更新してみましょう。アプリケーションによって出力されるテキストに簡単な変更を加えます。以下のテンプレートスニペットに示したように、index.php ファイルに echo コマンドを追加します。

"WebServerInstance": { "Type" : "AWS::EC2::Instance", "Metadata" : { "AWS::CloudFormation::Init" : { "config" : { : "files" : { "/var/www/html/index.php" : { "content" : { "Fn::Join" : ["", [ "<?php\n", "echo '<h1>AWS CloudFormation sample PHP application</h1>';\n", "echo '<p>Updated version via UpdateStack</p>';\n ", "?>\n" ]]}, "mode" : "000644", "owner" : "apache", "group" : "apache" }, : } },

テキストエディタを使用して、ローカルに保存したテンプレートファイルを手動で編集します。

次にスタックを更新します。

AWS Management Consoleからスタックを更新するには
  1. https://console.aws.amazon.com/cloudformation で、AWS CloudFormation コンソールにログインします。

  2. AWS CloudFormation ダッシュボードで、以前作成したスタックを選択し、[Update Stack] (スタックの更新) を選択します。

  3. [Update Stack] (スタックの更新) ウィザードの [Select Template] (テンプレートの選択) 画面で [Upload a template to Amazon S3] (テンプレートを Amazon S3 にアップロード) を選択し、修正したテンプレートを選択して、[Next] (次へ) を選択します。

  4. [Options] (オプション) 画面で、[Next] (次へ) を選択します。

  5. スタックポリシーはないので [Next] (次へ) を選択します。オーバーライド​ポリシーを使用せずにすべてのリソースを更新できます。

  6. [Review] (確認) 画面で、すべての設定が意図したとおりになっていることを確認し、[Update] (更新) を選択します。

AWS Management Consoleからスタックを更新した場合、[Update Stack (スタックの更新)] ウィザードの [パラメータ] ページに、初期スタックの作成に使用したパラメータが既に設定されていることがわかります。aws cloudformation update-stack コマンドを使用する場合、最初にスタックを作成するときに使用したパラメーターに対して必ず同じ値を入力してください。

スタックの状態が UPDATE_COMPLETE になったら、WebsiteURL の出力値を再度選択して、アプリケーションに対する変更が反映されていることを確認できます。デフォルトでは、cfn-hup デーモンが 15 分間隔で実行されます。スタックが更新されてからアプリケーションが変更されるまでに最大 15 分程度かかる場合があります。

更新された一連のリソースを確認するには、AWS CloudFormation コンソールを使用します。[イベント] タブでスタックイベントに注目してください。この場合は、Amazon EC2 インスタンスのメタデータ WebServerInstance が更新されます。また AWS CloudFormation によって他のリソース (WebServerSecurityGroup) も再評価され、ほかに変更がないことが確認されます。他のスタックリソースは一切変更されていません。AWS CloudFormation によって更新されるスタック内のリソースは、そのスタックに対する変更の影響を受けるリソースだけです。そうした変更には、プロパティやメタデータの変更など直接的なものもあれば、Ref、GetAtt など、組み込みテンプレート関数を介したデータフローや依存関係に起因するものもあります。

単純なアップデート例で必要なプロセスを紹介しましたが、Amazon EC2 インスタンスにデプロイするファイルやパッケージに対し、もっと複雑な変更を行うこともできます。たとえば、インスタンスに MySQL を追加しなければならなくなったとします。MySQL の PHP サポートも必要です。そのための作業は単に、追加サービスと併せて、必要なパッケージとファイルを構成に追加するだけです。そのうえでスタックを更新して変更をデプロイすることになります。次のテンプレートスニペットでは、変更箇所を赤色で示しています。

"WebServerInstance": { "Type" : "AWS::EC2::Instance", "Metadata" : { "Comment" : "Install a simple PHP application", "AWS::CloudFormation::Init" : { "config" : { "packages" : { "yum" : { "httpd" : [], "php" : [], "php-mysql" : [], "mysql-server" : [], "mysql-libs" : [], "mysql" : [] } }, : "services" : { "sysvinit" : { "httpd" : { "enabled" : "true", "ensureRunning" : "true" }, "cfn-hup" : { "enabled" : "true", "ensureRunning" : "true", "files" : ["/etc/cfn/cfn-hup.conf", "/etc/cfn/hooks.d/cfn-auto-reloader.conf"]}, "mysqld" : { "enabled" : "true", "ensureRunning" : "true" } } } } } }, "Properties": { : } }

CloudFormation のメタデータを更新して、アプリケーションで使用するパッケージを新しいバージョンに更新できます。これまでの例では、各パッケージのバージョンプロパティが空になっています。この場合、cfn-init によって最新バージョンのパッケージがインストールされます。

"packages" : { "yum" : { "httpd" : [], "php" : [] }

必要であれば、パッケージのバージョン文字列を指定することもできます。以降のスタック更新要求でバージョン文字列を変更した場合、その新しいバージョンのパッケージがデプロイされます。以下に示したのは、RubyGems パッケージのバージョン番号を使用した例です。バージョニングをサポートするパッケージはすべて、特定のバージョンを持つことができます。

"packages" : { "rubygems" : { "mysql" : [], "rubygems-update" : ["1.6.2"], "rake" : ["0.8.7"], "rails" : ["2.3.11"] } }

Auto Scaling グループの更新

テンプレートで Amazon EC2 インスタンスリソースではなく Auto Scaling グループを使用している場合も、アプリケーションを更新する方法はまったく同じですが、AWS CloudFormation には、Auto Scaling グループ内の Amazon EC2 インスタンス間で同期やシリアル化を行う手段が用意されていません。各ホスト上の cfn-hup デーモンは個別に実行され、独自のスケジュールでアプリケーションを更新します。インスタンス上の構成を cfn-hup を使用して更新する場合、各インスタンスが独自のスケジュールで cfn-hup フックを実行します。スタック内のインスタンス間の調整機能はありません。開発者は次の点を考慮する必要があります。

  • cfn-hup による変更が、Auto Scaling グループ内のすべての Amazon EC2 インスタンスで同時に実行された場合、更新中はサービスが利用できなくなることがあります。

  • cfn-hup による変更がそれぞれ異なるタイミングで実行された場合、古いバージョンと新しいバージョンのソフトウェアが同時に実行される可能性があります。

これらの問題を回避するには、Auto Scaling グループのインスタンスでローリング更新を強制することを検討してください。詳細については、「UpdatePolicy 属性」を参照してください。

リソースのプロパティの変更

AWS CloudFormation では、スタック内の既存のリソースのプロパティを変更することができます。次のセクションでは、特定の問題を解決するための各種のアップデートについて説明します。ただし、スタック内のアップデートをサポートするリソースのすべてのプロパティは、必要に応じて編集することができます。

インスタンスタイプのアップデート

ここまでで構築したスタックは、t1.micro Amazon EC2 インスタンスを使用します。例として、新しく作成したウェブサイトに、t1.micro インスタンスで処理できる以上のトラフィックが発生しているとします。このため、m1.small Amazon EC2 インスタンスタイプに移行する必要が生じました。インスタンスタイプのアーキテクチャーが変わると、異なる AMI でインスタンスが作成されます。テンプレート内でマッピングを調べると、t1.micro と m1.small は両方とも同じアーキテクチャーで、同じ Amazon Linux AMI を使用していることがわかります。

"Mappings" : { "AWSInstanceType2Arch" : { "t1.micro" : { "Arch" : "HVM64" }, "t2.nano" : { "Arch" : "HVM64" }, "t2.micro" : { "Arch" : "HVM64" }, "t2.small" : { "Arch" : "HVM64" }, "t2.medium" : { "Arch" : "HVM64" }, "t2.large" : { "Arch" : "HVM64" }, "m1.small" : { "Arch" : "HVM64" }, "m1.medium" : { "Arch" : "HVM64" }, "m1.large" : { "Arch" : "HVM64" }, "m1.xlarge" : { "Arch" : "HVM64" }, "m2.xlarge" : { "Arch" : "HVM64" }, "m2.2xlarge" : { "Arch" : "HVM64" }, "m2.4xlarge" : { "Arch" : "HVM64" }, "m3.medium" : { "Arch" : "HVM64" }, "m3.large" : { "Arch" : "HVM64" }, "m3.xlarge" : { "Arch" : "HVM64" }, "m3.2xlarge" : { "Arch" : "HVM64" }, "m4.large" : { "Arch" : "HVM64" }, "m4.xlarge" : { "Arch" : "HVM64" }, "m4.2xlarge" : { "Arch" : "HVM64" }, "m4.4xlarge" : { "Arch" : "HVM64" }, "m4.10xlarge" : { "Arch" : "HVM64" }, "c1.medium" : { "Arch" : "HVM64" }, "c1.xlarge" : { "Arch" : "HVM64" }, "c3.large" : { "Arch" : "HVM64" }, "c3.xlarge" : { "Arch" : "HVM64" }, "c3.2xlarge" : { "Arch" : "HVM64" }, "c3.4xlarge" : { "Arch" : "HVM64" }, "c3.8xlarge" : { "Arch" : "HVM64" }, "c4.large" : { "Arch" : "HVM64" }, "c4.xlarge" : { "Arch" : "HVM64" }, "c4.2xlarge" : { "Arch" : "HVM64" }, "c4.4xlarge" : { "Arch" : "HVM64" }, "c4.8xlarge" : { "Arch" : "HVM64" }, "g2.2xlarge" : { "Arch" : "HVMG2" }, "g2.8xlarge" : { "Arch" : "HVMG2" }, "r3.large" : { "Arch" : "HVM64" }, "r3.xlarge" : { "Arch" : "HVM64" }, "r3.2xlarge" : { "Arch" : "HVM64" }, "r3.4xlarge" : { "Arch" : "HVM64" }, "r3.8xlarge" : { "Arch" : "HVM64" }, "i2.xlarge" : { "Arch" : "HVM64" }, "i2.2xlarge" : { "Arch" : "HVM64" }, "i2.4xlarge" : { "Arch" : "HVM64" }, "i2.8xlarge" : { "Arch" : "HVM64" }, "d2.xlarge" : { "Arch" : "HVM64" }, "d2.2xlarge" : { "Arch" : "HVM64" }, "d2.4xlarge" : { "Arch" : "HVM64" }, "d2.8xlarge" : { "Arch" : "HVM64" }, "hi1.4xlarge" : { "Arch" : "HVM64" }, "hs1.8xlarge" : { "Arch" : "HVM64" }, "cr1.8xlarge" : { "Arch" : "HVM64" }, "cc2.8xlarge" : { "Arch" : "HVM64" } }, "AWSRegionArch2AMI" : { "us-east-1" : {"HVM64" : "ami-0ff8a91507f77f867", "HVMG2" : "ami-0a584ac55a7631c0c"}, "us-west-2" : {"HVM64" : "ami-a0cfeed8", "HVMG2" : "ami-0e09505bc235aa82d"}, "us-west-1" : {"HVM64" : "ami-0bdb828fd58c52235", "HVMG2" : "ami-066ee5fd4a9ef77f1"}, "eu-west-1" : {"HVM64" : "ami-047bb4163c506cd98", "HVMG2" : "ami-0a7c483d527806435"}, "eu-west-2" : {"HVM64" : "ami-f976839e", "HVMG2" : "NOT_SUPPORTED"}, "eu-west-3" : {"HVM64" : "ami-0ebc281c20e89ba4b", "HVMG2" : "NOT_SUPPORTED"}, "eu-central-1" : {"HVM64" : "ami-0233214e13e500f77", "HVMG2" : "ami-06223d46a6d0661c7"}, "ap-northeast-1" : {"HVM64" : "ami-06cd52961ce9f0d85", "HVMG2" : "ami-053cdd503598e4a9d"}, "ap-northeast-2" : {"HVM64" : "ami-0a10b2721688ce9d2", "HVMG2" : "NOT_SUPPORTED"}, "ap-northeast-3" : {"HVM64" : "ami-0d98120a9fb693f07", "HVMG2" : "NOT_SUPPORTED"}, "ap-southeast-1" : {"HVM64" : "ami-08569b978cc4dfa10", "HVMG2" : "ami-0be9df32ae9f92309"}, "ap-southeast-2" : {"HVM64" : "ami-09b42976632b27e9b", "HVMG2" : "ami-0a9ce9fecc3d1daf8"}, "ap-south-1" : {"HVM64" : "ami-0912f71e06545ad88", "HVMG2" : "ami-097b15e89dbdcfcf4"}, "us-east-2" : {"HVM64" : "ami-0b59bfac6be064b78", "HVMG2" : "NOT_SUPPORTED"}, "ca-central-1" : {"HVM64" : "ami-0b18956f", "HVMG2" : "NOT_SUPPORTED"}, "sa-east-1" : {"HVM64" : "ami-07b14488da8ea02a0", "HVMG2" : "NOT_SUPPORTED"}, "cn-north-1" : {"HVM64" : "ami-0a4eaf6c4454eda75", "HVMG2" : "NOT_SUPPORTED"}, "cn-northwest-1" : {"HVM64" : "ami-6b6a7d09", "HVMG2" : "NOT_SUPPORTED"} }

前のセクションで編集したテンプレートを使用して、インスタンスタイプを変更しましょう。InstanceType はテンプレートへの入力パラメータであるため、テンプレートを変更する必要はありません。Stack Update ウィザードの [Specify Parameters] (パラメータを指定) ページでパラメータの値を変更できます。

AWS Management Consoleからスタックを更新するには
  1. https://console.aws.amazon.com/cloudformation で、AWS CloudFormation コンソールにログインします。

  2. CloudFormation ダッシュボードで、以前作成したスタックを選択し、[Update Stack] (スタックの更新) を選択します。

  3. [Update Stack] (スタックの更新) ウィザードの [Select Template] (テンプレートの選択) 画面で [Use current template] (現在のテンプレートの使用) を選択して、[Next] (次へ) を選択します。

    [詳細の指定] ページの [パラメータを指定] セクションに、初期スタックを作成した際に使用したパラメータがあらかじめ入力された状態で表示されます。

  4. [InstanceType] テキストボックスの値を t1.micro から m1.small に変更します。[次へ] を選択します。

  5. [Options] (オプション) 画面で、[Next] (次へ) を選択します。

  6. スタックポリシーはないので [Next] (次へ) を選択します。オーバーライド​ポリシーを使用せずにすべてのリソースを更新できます。

  7. [Review] (確認) 画面で、すべての設定が意図したとおりになっていることを確認し、[Update] (更新) を選択します。

インスタンスを起動および停止することで、EBS-backed Amazon EC2 インスタンスのインスタンスタイプを動的に変更できます。AWS CloudFormation は、インスタンスタイプを更新してインスタンスを再起動することによって変更を最適化しようとします。そのため、インスタンス ID は変更されません。ただしインスタンスが再開されると、インスタンスのパブリック IP アドレスは変更されます。変更後に Elastic IP アドレスが正しくバインドされるよう、AWS CloudFormation は Elastic IP アドレスも更新します。AWS CloudFormation コンソールの [Events] タブで変更を見ることができます。

AWS Management Console からインスタンスタイプを調べるには、Amazon EC2 コンソールを開き、インスタンスを探します。

Amazon EC2 インスタンス上の AMI の更新

今度は、インスタンス上で実行されている Amazon マシンイメージ (AMI) の変更方法について見ていきます。AMI の変更を開始するにあたり、ここではまず、新しい Amazon EC2 インスタンスタイプ (HVM64 インスタンスタイプである t2.medium など) を使用するようにスタックを更新します。

前のセクションと同様、既存のテンプレートを使用して、サンプルスタックで使用されているインスタンスタイプを変更します。Stack Update ウィザードの [Specify Parameters] ページで、[ Instance Type] の値を変更します。

このケースでは、単純にインスタンスの開始と停止によって AMI を変更することはできません。このような変更は、AWS CloudFormation によって不変のリソースプロパティに対する変更とみなされます。不変のプロパティに変更を加える場合、AWS CloudFormation は、代替リソース (このケースでは、新しい AMI を実行する新しい Amazon EC2 インスタンス) を起動する必要があります。

新しいインスタンスが実行状態になった後、AWS CloudFormation は、スタック内の他のリソースが新しいリソースを指し示すように更新します。新しいリソースがすべて作成されると、古いリソースは削除されます。このプロセスを UPDATE_CLEANUP といいます。更新後、スタック内のインスタンスの ID とアプリケーション URL が変わっています。Event テーブル内のイベントには、"Requested update has a change to an immutable property and hence creating a new physical resource" という説明が表示され、リソースが置き換えられたことがわかります。

更新対象の AMI に組み込むアプリケーションコードを記述した場合、同じスタック更新メカニズムを使用して AMI を更新し、新しいアプリケーションをロードすることができます。

スタック上のインスタンスの AMI を更新するには
  1. アプリケーションまたはオペレーティング システムの変更を含んだ新しい AMI を作成します。詳細については、「Linux インスタンス用 Amazon EC2 ユーザーガイド」の「Creating your own AMIs」(独自の AMI の作成) を参照してください。

  2. テンプレートに新しい AMI ID を追加します。

  3. AWS Management Console (「アプリケーションの更新」を参照) から、または AWS コマンド aws cloudformation update-stack を使用してスタックを更新します。

スタックが更新されると、AMI ID が変更されたことを CloudFormation が検出し、先ほどと同じようにスタックの更新を開始します。

Auto Scaling グループに必要な Amazon EC2 起動構成の更新

Amazon EC2 インスタンスではなく Auto Scaling グループを使用している場合、実行中のインスタンスを更新する手順が若干異なります。Auto Scaling リソースでは、Amazon EC2 インスタンスの構成 (インスタンスタイプ、AMI ID など) が Auto Scaling 起動構成にカプセル化されています。起動構成の変更方法は、前のセクションで説明した Amazon EC2 インスタンスリソースに対する変更と同じです。ただし、起動構成を変更しても、Auto Scaling グループ内の実行中の Amazon EC2 インスタンスにはいずれも、その変更が反映されません。更新した起動構成が適用されるのは、更新後に作成された新しいインスタンスのみです。

起動構成の変更を Auto Scaling グループ内のすべてのインスタンスに伝達する場合には、更新の属性を使用できます。詳細については、「UpdatePolicy 属性」を参照してください。

リソースのプロパティの追加

ここまでで、テンプレート内でリソースの既存のプロパティを変更する方法を見てきました。テンプレート内で元々指定されていなかったプロパティを追加することもできます。これについて学ぶため、Amazon EC2 キーペアを既存の EC2 インスタンスに追加し、Amazon EC2 Security Group でポート 22 を開きます。これにより、Secure Shell (SSH) を使用してインスタンスにアクセスできるようになります。

インスタンスへのキーペアの追加

既存の Amazon EC2 インスタンスに SSH アクセスを追加するには
  1. 既存の Amazon EC2 キーペアおよび SSH ロケーションの名前を渡すため、テンプレートに 2 つのパラメーターを追加します。

    "Parameters" : { "KeyName" : { "Description" : "Name of an existing Amazon EC2 key pair for SSH access", "Type": "AWS::EC2::KeyPair::KeyName" }, "SSHLocation" : { "Description" : " The IP address range that can be used to SSH to the EC2 instances", "Type": "String", "MinLength": "9", "MaxLength": "18", "Default": "0.0.0.0/0", "AllowedPattern": "(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})/(\\d{1,2})", "ConstraintDescription": "must be a valid IP CIDR range of the form x.x.x.x/x." } : },
  2. Amazon EC2 インスタンスに KeyName プロパティを追加します。

    "WebServerInstance": { "Type" : "AWS::EC2::Instance", : "Properties": { : "KeyName" : { "Ref" : "KeyName" }, : } },
  3. Amazon EC2 セキュリティグループの Ingress ルールに、ポート 22 と SSH ロケーションを追加します。

    "WebServerSecurityGroup" : { "Type" : "AWS::EC2::SecurityGroup", "Properties" : { "GroupDescription" : "Enable HTTP and SSH", "SecurityGroupIngress" : [ {"IpProtocol" : "tcp", "FromPort" : "22", "ToPort" : "22", "CidrIp" : { "Ref" : "SSHLocation"}}, {"IpProtocol" : "tcp", "FromPort" : "80", "ToPort" : "80", "CidrIp" : "0.0.0.0/0"} ] } },
  4. AWS Management Console (「アプリケーションの更新」を参照) から、または AWS コマンド aws cloudformation update-stack を使用してスタックを更新します。

スタックのリソースの変更

アプリケーションのニーズは時とともに変化するため、AWS CloudFormation は、スタックを構成するリソースセットの変更を許可します。これを説明するため、「リソースのプロパティの追加」の単一インスタンスアプリケーションを例に取り、スタックを更新することで、自動スケーリングされ負荷分散されるアプリケーションに変換します。

このテンプレートは、Elastic IP アドレスを使用して、シンプルな単一インスタンスの PHP アプリケーションを作成するものです。ここでは、更新の際にリソースを変更することで、自動スケーリングされ負荷分散される、可用性の高いアプリケーションに変換します。

  1. Elastic Load Balancing リソースを追加します。

    "ElasticLoadBalancer" : { "Type" : "AWS::ElasticLoadBalancing::LoadBalancer", "Properties" : { "CrossZone" : "true", "AvailabilityZones" : { "Fn::GetAZs" : "" }, "LBCookieStickinessPolicy" : [ { "PolicyName" : "CookieBasedPolicy", "CookieExpirationPeriod" : "30" } ], "Listeners" : [ { "LoadBalancerPort" : "80", "InstancePort" : "80", "Protocol" : "HTTP", "PolicyNames" : [ "CookieBasedPolicy" ] } ], "HealthCheck" : { "Target" : "HTTP:80/", "HealthyThreshold" : "2", "UnhealthyThreshold" : "5", "Interval" : "10", "Timeout" : "5" } } }
  2. テンプレート内の EC2 インスタンスを Auto Scaling Launch Configuration に変換します。プロパティは同一ですので、タイプの名前を変更するだけです。これまでの名前:

    "WebServerInstance": { "Type" : "AWS::EC2::Instance",

    変更先:

    "LaunchConfig": { "Type" : "AWS::AutoScaling::LaunchConfiguration",

    テンプレート内で明確にするため、リソースの名前を WebServerInstance から LaunchConfig に変更してあります。このため、cfn-init および cfn-hup が参照するリソース名を更新する必要があります (WebServerInstance を探して LaunchConfig に変更。cfn-signal を除く)。cfn-signal の場合、次のスニペットに示すように、インスタンスではなく、Auto Scaling グループ (WebServerGroup) に対してシグナルを送信する必要があります。

    "# Signal the status from cfn-init\n", "/opt/aws/bin/cfn-signal -e $? ", " --stack ", { "Ref" : "AWS::StackName" }, " --resource WebServerGroup ", " --region ", { "Ref" : "AWS::Region" }, "\n"
  3. Auto Scaling グループリソースを追加します。

    "WebServerGroup" : { "Type" : "AWS::AutoScaling::AutoScalingGroup", "Properties" : { "AvailabilityZones" : { "Fn::GetAZs" : "" }, "LaunchConfigurationName" : { "Ref" : "LaunchConfig" }, "MinSize" : "1", "DesiredCapacity" : "1", "MaxSize" : "5", "LoadBalancerNames" : [ { "Ref" : "ElasticLoadBalancer" } ] }, "CreationPolicy" : { "ResourceSignal" : { "Timeout" : "PT15M" } }, "UpdatePolicy": { "AutoScalingRollingUpdate": { "MinInstancesInService": "1", "MaxBatchSize": "1", "PauseTime" : "PT15M", "WaitOnResourceSignals": "true" } } }
  4. トラフィックを、ロードバランサーからのインスタンスに絞るよう、Security Group 定義を更新します。

    "WebServerSecurityGroup" : { "Type" : "AWS::EC2::SecurityGroup", "Properties" : { "GroupDescription" : "Enable HTTP access via port 80 locked down to the ELB and SSH access", "SecurityGroupIngress" : [ {"IpProtocol" : "tcp", "FromPort" : "80", "ToPort" : "80", "SourceSecurityGroupOwnerId" : {"Fn::GetAtt" : ["ElasticLoadBalancer", "SourceSecurityGroup.OwnerAlias"]}, "SourceSecurityGroupName" : {"Fn::GetAtt" : ["ElasticLoadBalancer", "SourceSecurityGroup.GroupName"]}}, {"IpProtocol" : "tcp", "FromPort" : "22", "ToPort" : "22", "CidrIp" : { "Ref" : "SSHLocation"}} ] } }
  5. Elastic Load Balancing の DNS Name をアプリケーションの場所として返すために Outputs を更新します。更新前:

    "WebsiteURL" : { "Value" : { "Fn::Join" : ["", ["http://", { "Fn::GetAtt" : [ "WebServerInstance", "PublicDnsName" ]}]]}, "Description" : "Application URL" }

    変更先:

    "WebsiteURL" : { "Value" : { "Fn::Join" : ["", ["http://", { "Fn::GetAtt" : [ "ElasticLoadBalancer", "DNSName" ]}]]}, "Description" : "Application URL" }

参考のために、完成したテンプレートを以下に示します。このテンプレートを使用してスタックを更新すると、単純な単一インスタンスのアプリケーションが、自動スケーリングされ、負荷分散される、可用性の高い、Multi-AZ のアプリケーションに変換されます。更新の必要があるリソースのみが変更されますので、このアプリケーション用に格納されたデータが存在する場合、それらのデータは変更されません。これで、ニーズが変化したときにも、AWS CloudFormation を使用してスタックを拡大することができます。

{ "AWSTemplateFormatVersion" : "2010-09-09", "Description" : "AWS CloudFormation Sample Template: Sample template that can be used to test EC2 updates. **WARNING** This template creates an Amazon Ec2 Instance. You will be billed for the AWS resources used if you create a stack from this template.", "Parameters" : { "KeyName": { "Description" : "Name of an existing EC2 KeyPair to enable SSH access to the instance", "Type": "AWS::EC2::KeyPair::KeyName", "ConstraintDescription" : "must be the name of an existing EC2 KeyPair." }, "SSHLocation" : { "Description" : " The IP address range that can be used to SSH to the EC2 instances", "Type": "String", "MinLength": "9", "MaxLength": "18", "Default": "0.0.0.0/0", "AllowedPattern": "(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})/(\\d{1,2})", "ConstraintDescription": "must be a valid IP CIDR range of the form x.x.x.x/x." }, "InstanceType" : { "Description" : "WebServer EC2 instance type", "Type" : "String", "Default" : "t2.small", "AllowedValues" : [ "t1.micro", "t2.nano", "t2.micro", "t2.small", "t2.medium", "t2.large", "m1.small", "m1.medium", "m1.large", "m1.xlarge", "m2.xlarge", "m2.2xlarge", "m2.4xlarge", "m3.medium", "m3.large", "m3.xlarge", "m3.2xlarge", "m4.large", "m4.xlarge", "m4.2xlarge", "m4.4xlarge", "m4.10xlarge", "c1.medium", "c1.xlarge", "c3.large", "c3.xlarge", "c3.2xlarge", "c3.4xlarge", "c3.8xlarge", "c4.large", "c4.xlarge", "c4.2xlarge", "c4.4xlarge", "c4.8xlarge", "g2.2xlarge", "g2.8xlarge", "r3.large", "r3.xlarge", "r3.2xlarge", "r3.4xlarge", "r3.8xlarge", "i2.xlarge", "i2.2xlarge", "i2.4xlarge", "i2.8xlarge", "d2.xlarge", "d2.2xlarge", "d2.4xlarge", "d2.8xlarge", "hi1.4xlarge", "hs1.8xlarge", "cr1.8xlarge", "cc2.8xlarge", "cg1.4xlarge" ], "ConstraintDescription" : "must be a valid EC2 instance type." } }, "Mappings" : { "AWSInstanceType2Arch" : { "t1.micro" : { "Arch" : "HVM64" }, "t2.nano" : { "Arch" : "HVM64" }, "t2.micro" : { "Arch" : "HVM64" }, "t2.small" : { "Arch" : "HVM64" }, "t2.medium" : { "Arch" : "HVM64" }, "t2.large" : { "Arch" : "HVM64" }, "m1.small" : { "Arch" : "HVM64" }, "m1.medium" : { "Arch" : "HVM64" }, "m1.large" : { "Arch" : "HVM64" }, "m1.xlarge" : { "Arch" : "HVM64" }, "m2.xlarge" : { "Arch" : "HVM64" }, "m2.2xlarge" : { "Arch" : "HVM64" }, "m2.4xlarge" : { "Arch" : "HVM64" }, "m3.medium" : { "Arch" : "HVM64" }, "m3.large" : { "Arch" : "HVM64" }, "m3.xlarge" : { "Arch" : "HVM64" }, "m3.2xlarge" : { "Arch" : "HVM64" }, "m4.large" : { "Arch" : "HVM64" }, "m4.xlarge" : { "Arch" : "HVM64" }, "m4.2xlarge" : { "Arch" : "HVM64" }, "m4.4xlarge" : { "Arch" : "HVM64" }, "m4.10xlarge" : { "Arch" : "HVM64" }, "c1.medium" : { "Arch" : "HVM64" }, "c1.xlarge" : { "Arch" : "HVM64" }, "c3.large" : { "Arch" : "HVM64" }, "c3.xlarge" : { "Arch" : "HVM64" }, "c3.2xlarge" : { "Arch" : "HVM64" }, "c3.4xlarge" : { "Arch" : "HVM64" }, "c3.8xlarge" : { "Arch" : "HVM64" }, "c4.large" : { "Arch" : "HVM64" }, "c4.xlarge" : { "Arch" : "HVM64" }, "c4.2xlarge" : { "Arch" : "HVM64" }, "c4.4xlarge" : { "Arch" : "HVM64" }, "c4.8xlarge" : { "Arch" : "HVM64" }, "g2.2xlarge" : { "Arch" : "HVMG2" }, "g2.8xlarge" : { "Arch" : "HVMG2" }, "r3.large" : { "Arch" : "HVM64" }, "r3.xlarge" : { "Arch" : "HVM64" }, "r3.2xlarge" : { "Arch" : "HVM64" }, "r3.4xlarge" : { "Arch" : "HVM64" }, "r3.8xlarge" : { "Arch" : "HVM64" }, "i2.xlarge" : { "Arch" : "HVM64" }, "i2.2xlarge" : { "Arch" : "HVM64" }, "i2.4xlarge" : { "Arch" : "HVM64" }, "i2.8xlarge" : { "Arch" : "HVM64" }, "d2.xlarge" : { "Arch" : "HVM64" }, "d2.2xlarge" : { "Arch" : "HVM64" }, "d2.4xlarge" : { "Arch" : "HVM64" }, "d2.8xlarge" : { "Arch" : "HVM64" }, "hi1.4xlarge" : { "Arch" : "HVM64" }, "hs1.8xlarge" : { "Arch" : "HVM64" }, "cr1.8xlarge" : { "Arch" : "HVM64" }, "cc2.8xlarge" : { "Arch" : "HVM64" } }, "AWSRegionArch2AMI" : { "us-east-1" : {"HVM64" : "ami-0ff8a91507f77f867", "HVMG2" : "ami-0a584ac55a7631c0c"}, "us-west-2" : {"HVM64" : "ami-a0cfeed8", "HVMG2" : "ami-0e09505bc235aa82d"}, "us-west-1" : {"HVM64" : "ami-0bdb828fd58c52235", "HVMG2" : "ami-066ee5fd4a9ef77f1"}, "eu-west-1" : {"HVM64" : "ami-047bb4163c506cd98", "HVMG2" : "ami-0a7c483d527806435"}, "eu-west-2" : {"HVM64" : "ami-f976839e", "HVMG2" : "NOT_SUPPORTED"}, "eu-west-3" : {"HVM64" : "ami-0ebc281c20e89ba4b", "HVMG2" : "NOT_SUPPORTED"}, "eu-central-1" : {"HVM64" : "ami-0233214e13e500f77", "HVMG2" : "ami-06223d46a6d0661c7"}, "ap-northeast-1" : {"HVM64" : "ami-06cd52961ce9f0d85", "HVMG2" : "ami-053cdd503598e4a9d"}, "ap-northeast-2" : {"HVM64" : "ami-0a10b2721688ce9d2", "HVMG2" : "NOT_SUPPORTED"}, "ap-northeast-3" : {"HVM64" : "ami-0d98120a9fb693f07", "HVMG2" : "NOT_SUPPORTED"}, "ap-southeast-1" : {"HVM64" : "ami-08569b978cc4dfa10", "HVMG2" : "ami-0be9df32ae9f92309"}, "ap-southeast-2" : {"HVM64" : "ami-09b42976632b27e9b", "HVMG2" : "ami-0a9ce9fecc3d1daf8"}, "ap-south-1" : {"HVM64" : "ami-0912f71e06545ad88", "HVMG2" : "ami-097b15e89dbdcfcf4"}, "us-east-2" : {"HVM64" : "ami-0b59bfac6be064b78", "HVMG2" : "NOT_SUPPORTED"}, "ca-central-1" : {"HVM64" : "ami-0b18956f", "HVMG2" : "NOT_SUPPORTED"}, "sa-east-1" : {"HVM64" : "ami-07b14488da8ea02a0", "HVMG2" : "NOT_SUPPORTED"}, "cn-north-1" : {"HVM64" : "ami-0a4eaf6c4454eda75", "HVMG2" : "NOT_SUPPORTED"}, "cn-northwest-1" : {"HVM64" : "ami-6b6a7d09", "HVMG2" : "NOT_SUPPORTED"} } }, "Resources" : { "ElasticLoadBalancer" : { "Type" : "AWS::ElasticLoadBalancing::LoadBalancer", "Properties" : { "CrossZone" : "true", "AvailabilityZones" : { "Fn::GetAZs" : "" }, "LBCookieStickinessPolicy" : [ { "PolicyName" : "CookieBasedPolicy", "CookieExpirationPeriod" : "30" } ], "Listeners" : [ { "LoadBalancerPort" : "80", "InstancePort" : "80", "Protocol" : "HTTP", "PolicyNames" : [ "CookieBasedPolicy" ] } ], "HealthCheck" : { "Target" : "HTTP:80/", "HealthyThreshold" : "2", "UnhealthyThreshold" : "5", "Interval" : "10", "Timeout" : "5" } } }, "WebServerGroup" : { "Type" : "AWS::AutoScaling::AutoScalingGroup", "Properties" : { "AvailabilityZones" : { "Fn::GetAZs" : "" }, "LaunchConfigurationName" : { "Ref" : "LaunchConfig" }, "MinSize" : "1", "DesiredCapacity" : "1", "MaxSize" : "5", "LoadBalancerNames" : [ { "Ref" : "ElasticLoadBalancer" } ] }, "CreationPolicy" : { "ResourceSignal" : { "Timeout" : "PT15M" } }, "UpdatePolicy": { "AutoScalingRollingUpdate": { "MinInstancesInService": "1", "MaxBatchSize": "1", "PauseTime" : "PT15M", "WaitOnResourceSignals": "true" } } }, "LaunchConfig": { "Type" : "AWS::AutoScaling::LaunchConfiguration", "Metadata" : { "Comment" : "Install a simple PHP application", "AWS::CloudFormation::Init" : { "config" : { "packages" : { "yum" : { "httpd" : [], "php" : [] } }, "files" : { "/var/www/html/index.php" : { "content" : { "Fn::Join" : ["", [ "<?php\n", "echo '<h1>AWS CloudFormation sample PHP application</h1>';\n", "echo 'Updated version via UpdateStack';\n ", "?>\n" ]]}, "mode" : "000644", "owner" : "apache", "group" : "apache" }, "/etc/cfn/cfn-hup.conf" : { "content" : { "Fn::Join" : ["", [ "[main]\n", "stack=", { "Ref" : "AWS::StackId" }, "\n", "region=", { "Ref" : "AWS::Region" }, "\n" ]]}, "mode" : "000400", "owner" : "root", "group" : "root" }, "/etc/cfn/hooks.d/cfn-auto-reloader.conf" : { "content": { "Fn::Join" : ["", [ "[cfn-auto-reloader-hook]\n", "triggers=post.update\n", "path=Resources.LaunchConfig.Metadata.AWS::CloudFormation::Init\n", "action=/opt/aws/bin/cfn-init -s ", { "Ref" : "AWS::StackId" }, " -r LaunchConfig ", " --region ", { "Ref" : "AWS::Region" }, "\n", "runas=root\n" ]]} } }, "services" : { "sysvinit" : { "httpd" : { "enabled" : "true", "ensureRunning" : "true" }, "cfn-hup" : { "enabled" : "true", "ensureRunning" : "true", "files" : ["/etc/cfn/cfn-hup.conf", "/etc/cfn/hooks.d/cfn-auto-reloader.conf"]} } } } } }, "Properties": { "ImageId" : { "Fn::FindInMap" : [ "AWSRegionArch2AMI", { "Ref" : "AWS::Region" }, { "Fn::FindInMap" : [ "AWSInstanceType2Arch", { "Ref" : "InstanceType" }, "Arch" ] } ] }, "InstanceType" : { "Ref" : "InstanceType" }, "KeyName" : { "Ref" : "KeyName" }, "SecurityGroups" : [ {"Ref" : "WebServerSecurityGroup"} ], "UserData" : { "Fn::Base64" : { "Fn::Join" : ["", [ "#!/bin/bash -xe\n", "yum install -y aws-cfn-bootstrap\n", "# Install the files and packages from the metadata\n", "/opt/aws/bin/cfn-init -v ", " --stack ", { "Ref" : "AWS::StackName" }, " --resource LaunchConfig ", " --region ", { "Ref" : "AWS::Region" }, "\n", "# Start up the cfn-hup daemon to listen for changes to the Web Server metadata\n", "/opt/aws/bin/cfn-hup || error_exit 'Failed to start cfn-hup'\n", "# Signal the status from cfn-init\n", "/opt/aws/bin/cfn-signal -e $? ", " --stack ", { "Ref" : "AWS::StackName" }, " --resource WebServerGroup ", " --region ", { "Ref" : "AWS::Region" }, "\n" ]]}} } }, "WebServerSecurityGroup" : { "Type" : "AWS::EC2::SecurityGroup", "Properties" : { "GroupDescription" : "Enable HTTP access via port 80 locked down to the ELB and SSH access", "SecurityGroupIngress" : [ {"IpProtocol" : "tcp", "FromPort" : "80", "ToPort" : "80", "SourceSecurityGroupOwnerId" : {"Fn::GetAtt" : ["ElasticLoadBalancer", "SourceSecurityGroup.OwnerAlias"]},"SourceSecurityGroupName" : {"Fn::GetAtt" : ["ElasticLoadBalancer", "SourceSecurityGroup.GroupName"]}}, {"IpProtocol" : "tcp", "FromPort" : "22", "ToPort" : "22", "CidrIp" : { "Ref" : "SSHLocation"}} ] } } }, "Outputs" : { "WebsiteURL" : { "Description" : "Application URL", "Value" : { "Fn::Join" : ["", ["http://", { "Fn::GetAtt" : [ "ElasticLoadBalancer", "DNSName" ]}]] } } } }

アベイラビリティーと影響に関する検討事項

プロパティによって、スタック内のリソースに異なる影響が及ぼされます。CloudFormation を使用してあらゆるプロパティを更新できますが、変更を加える前に、以下の点について検討する必要があります。

  1. アップデートによって、リソース自体にどのような影響が与えられるか。たとえば、アラームのしきい値を変更すると、アップデート中にアラームが非アクティブになります。既に説明したように、インスタンスタイプを変更するには、インスタンスをいったん停止して再開する必要があります。AWS CloudFormation は、基盤となるリソースの更新または変更アクションを使用してリソースに変更を加えます。アップデートの影響を理解するには、特定のリソースのドキュメントを参照してください。

  2. 変更は可変か不変か。Amazon EC2 インスタンスでの AMI の変更など、リソースプロパティへの変更のタイプによっては、基盤となるサービスにサポートされていない場合があります。可変の変更の場合、CloudFormation は、基盤となるリソースの Update または Modify タイプの API を使用します。不変のプロパティの変更の場合、CloudFormation は、アップデートされたプロパティを使用して新しいリソースを作成し、古いリソースを削除する前にそれらをスタックにリンクします。CloudFormation はスタックリソースのダウンタイムを削減しようとしますが、リソースは複数のステップが必要な処理であり、ある程度の時間がかかります。スタックの再構成中、アプリケーションは完全には機能しません。たとえば、要求への応答や、データベースへのアクセスができない可能性があります。

関連リソース

CloudFormation を使用してアプリケーションを開始する方法と、Puppet や Opscode Chef のようなその他の構成やデプロイメントサービスと統合する方法については、以下のホワイトペーパーをご参照ください。

このセクションを通じて使用したテンプレートは、「Hello World」PHP アプリケーションです。テンプレートライブラリには、 Amazon ElastiCache キャッシュクラスターの構成の変更に対応するために cfn- hup と cfn-init を使用して PHP アプリケーションを ElasticCache と統合する方法 (すべて Update Stack により実行可能) を示した、Amazon ElastiCache サンプルテンプレートも含まれています。