演練:更新堆疊 - AWS CloudFormation

本文為英文版的機器翻譯版本,如內容有任何歧義或不一致之處,概以英文版為準。

演練:更新堆疊

使用 CloudFormation,您可以更新現有堆疊中資源的屬性。這些變更的範圍從簡單的組態變更 (例如更新警示上的 CloudWatch 警示閾值) 到更複雜的變更 (例如更新 Amazon EC2 執行個體上執行的 Amazon Machine Image (AMI)。模板中的許多 AWS 資源都可以更新,我們將繼續添加更多的支持。

本節會逐步講解更新運作中堆疊的簡易程序,它顯示範本的使用如何讓您可以使用版本控制系統來設定 AWS 基礎結構,就像您對正在執行的軟體使用版本控制一樣。我們將逐步解說以下步驟:

  1. 建立初始堆疊— 使用基礎 Amazon Linux AMI 創建一個堆棧,安裝 Apache Web 服務器和使用 CloudFormation輔助腳本的簡單 PHP 應用程序。

  2. 更新應用程式— 更新應用程序中的文件之一,並使用部署軟件 CloudFormation.

  3. 更新執行個體類型 – 變更基礎 Amazon EC2 執行個體的執行個體類型。

  4. 更新 Amazon EC2 執行個體上的 AMI – 變更堆疊中 Amazon EC2 執行個體的 Amazon Machine Image (AMI)。

  5. 將金鑰對新增至執行個體 – 將 Amazon EC2 金鑰對新增至執行個體,接著更新安全群組以允許 SSH 存取該執行個體。

  6. 變更堆疊的資源 – 從堆疊中新增與移除資源,並更新範本以將其轉換成可自動調整規模、負載平衡的應用程式。

簡易的應用程式

我們將開始建立堆疊,而本節其餘的部分皆可使用此堆疊。我們所提供的簡易範本能啟動 Apache Web 伺服器上託管的單一執行個體 PHP Web 應用程式,並在 Amazon Linux AMI 上執行該應用程式。

Apache 網頁伺服器、PHP 和簡單的 PHP 應用程式都由預設安裝在 Amazon Linux AMI 上的 CloudFormation 協助程式指令碼安裝。下列範本程式碼片段所顯示的中繼資料會說明要安裝的套件與檔案,此處將以來自 Amazon Linux AMI Yum 儲存庫的 Apache Web 伺服器與 PHP 基礎設施為例。而藉由出現在該程式碼片段中的 Services 區段,可確保系統正在執行 Apache Web 伺服器。在 Amazon EC2 執行個體定義的「屬性」區段中, 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", : ]]}} } },

應用程式本身會採用兩行字 "Hello, World" 作為範例,且範本會完整定義此範例。對於真實世界的應用程式,檔案可以存放在 Amazon S3 或其他儲存庫中 GitHub,並從範本中參考。 CloudFormation 可以下載套件 (例如 RPM 或 RubyGems),並參照個別檔案並擴展.zip和檔案,以在 Amazon EC2 執行個體上建立應用程式構.tar件。

範本會啟用並設定 cfn-hup 常駐程式,以便偵聽 Amazon EC2 執行個體中繼資料內針對組態所定義的變更。透過使用 cfn-hup 精靈,您可以更新應用程式軟體,例如 Apache 或 PHP 的版本,或者您也可以從中更新 PHP 應用程式檔案本身。 CloudFormation範本中相同的 Amazon EC2 資源會提供下列程式碼片段,藉此說明設定 cfn-hup 以呼叫 cfn-init 更新軟體的必要部分,進而因應系統所偵測到的任何中繼資料變更:

"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. Create New Stack (建立新堆疊) 精靈的 Select Template (選取範本) 畫面上,將 UpdateTutorial 輸入至 Name (名稱) 欄位。在相同的頁面上,選取 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 應用程式開始運作。

更新應用程式

既然我們已經將堆疊部署完成,接下來便要更新應用程式。我們會簡單地更改應用程式所印出的文字。若要執行此作業,便需要將 echo 命令新增至 index.php 檔案,如下列範本程式碼片段所示:

"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. 請在以下位置登入 CloudFormation 主控台:https://console.aws.amazon.com/cloudformation

  2. 在 CloudFormation 儀表板上,選擇您先前建立的堆疊,然後選擇 [更新堆疊]。

  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,您會注意到用來建立初始堆疊的參數已預先填入「更新堆疊」精靈的「參數」頁面上。如果您是使用 aws cloudformation update-stack 命令,輸入的值請務必與原先用來建立堆疊的參數相同。

當堆疊的狀態變成 UPDATE_COMPLETE 時,即可再選擇 WebsiteURL 輸出值,藉此確認應用程式的變更已經生效。在預設情況下,系統每 15 分鐘會執行 cfn-hup 常駐程式一次;因此堆疊更新後,應用程式最多可能需要 15 分鐘才能完成變更。

若要查看已更新的資源集,請移至主 CloudFormation 控台。您可以在 Events (事件) 標籤上檢視堆疊事件。在此特定情況下,Amazon EC2 執行個體的中繼資料 WebServerInstance 已更新,因 CloudFormation 此也會重新評估其他資源 (WebServerSecurityGroup) 以確保沒有其他變更。沒有其他堆棧資源被修改。 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 群組

如果您在範本中使用 Auto Scaling 群組,而不是 Amazon EC2 執行個體資源,則更新應用程式的運作方式完全相同;不過, CloudFormation 不會在 Auto Scaling 群組中跨 Amazon EC2 執行個體提供任何同步或序列化。每部主機上的 cfn-hup 常駐程式均會獨立運作,並按照自身排程來更新應用程式。當您藉由 cfn-hup 來更新執行個體上的組態時,每個執行個體皆會依照自身排程執行 cfn-hup 勾點;而堆疊中的執行個體之間沒有協調性。因此,您應該考量下列事項:

  • 如果 Auto Scaling 群組中的所有 Amazon EC2 執行個體同時執行 cfn-hup 變更,更新期間可能無法使用服務。

  • 如果系統在不同時間執行 cfn-hup 變更,舊版本與新版本的軟體可能會同時運作。

請考慮強制輪流更新 Auto Scaling 群組中的執行個體,以避免上述問題。如需詳細資訊,請參閱 UpdatePolicy 屬性

變更資源屬性

使用 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 是範本的輸入參數,所以我們不需要修改範本;我們可以在 [堆疊更新] 精靈的 [指定參數] 頁面上變更參數的值。

從 AWS Management Console更新堆疊
  1. 請在 https://console.aws.amazon.com/cloudformation 登入 CloudFormation 主控台。

  2. 在 CloudFormation 儀表板上,選擇您先前建立的堆疊,然後選擇 [更新堆疊]。

  3. Update Stack (更新堆疊) 精靈的 Select Template (選取範本) 畫面上,選取 Use current template (使用目前的範本),然後選擇 Next (下一步)。

    Specify Details (指定詳細資訊) 頁面即會顯示,其中 Specify Parameters (指定參數) 區段會預先填入要用來建立初始堆疊的參數。

  4. InstanceType文字方塊的值從變更t1.microm1.small。然後選擇下一步

  5. Options (選項) 畫面上,選擇 Next (下一步)。

  6. 堆疊沒有堆疊政策,因此請選擇 Next (下一步)。在沒有覆寫政策的情況下,所有資源皆可進行更新。

  7. 確認 Review (檢閱) 畫面上的所有設定皆符合需求,接著選擇 Update (更新)。

您可以啟動和停止執行個體,以動態方式變更 EBS 支援之 Amazon EC2 執行個體的執行個體類型。 CloudFormation 嘗試透過更新執行個體類型並重新啟動執行個體來最佳化變更,因此執行個體 ID 不會變更。然而,重新啟動執行個體時,該執行個體的公有 IP 地址會隨之變更。為了確保彈性 IP 地址在更改後正確綁定,還 CloudFormation 將更新彈性 IP 地址。您可以在 [事件] 索引標籤上的 CloudFormation 主控台中查看變更。

若要從中檢查執行個體類型 AWS Management Console,請開啟 Amazon EC2 主控台,然後在該處找到您的執行個體。

更新 Amazon EC2 執行個體上的 AMI

現在,讓我們看看如何變更執行個體上所執行的 Amazon Machine Image (AMI)。我們會更新堆疊以啟動 AMI 變更作業,藉此使用新的 Amazon EC2 執行個體類型,例如屬於 HVM64 執行個體類型的 t2.medium。

如先前一節所述,我們將透過現有的範本來變更範例堆疊所使用的執行個體類型。請在 Stack Update (更新堆疊) 精靈的 Specify Parameters (指定參數) 頁面上,變更執行個體類型的值。

在這種情況下,我們不能簡單地啟動和停止實例來修改 AMI; CloudFormation 認為這是對資源不可變屬性的更改。為了對不可變屬性進行變更, CloudFormation 必須啟動替換資源,在此情況下是執行新 AMI 的新 Amazon EC2 執行個體。

執行新執行個體之後, 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,其包含應用程式或作業系統變更內容。如需詳細資訊,請前往 Amazon EC2 使用者指南的建立您自己的 AMI

  2. 更新範本,以便採納新的 AMI ID。

  3. 更新堆疊,可以從中所 AWS Management Console 述更新應用程式或使用 AWS 指令來更新堆疊aws cloudformation update-stack

當您更新堆棧時, CloudFormation 檢測 AMI ID 是否已更改,然後以與我們啟動上述內容相同的方式觸發堆棧更新。

更新 Auto Scaling 群組的 Amazon EC2 啟動組態

如果您是使用 Auto Scaling 群組,而非 Amazon EC2 執行個體,則更新執行中的執行個體的程序會稍有不同。您可以透過 Auto Scaling 資源,將 Amazon EC2 執行個體的組態 (如執行個體類型或 AMI ID) 封裝在 Auto Scaling 啟動組態中。您可以採用先前各節所示的 Amazon EC2 執行個體資源變更方式,以便變更啟動組態。不過,變更啟動組態並不會影響 Auto Scaling 群組中任何正在運作的 Amazon EC2 執行個體;而更新的啟動組態僅適用於更新後所建立的新執行個體。

透過更新屬性,即可將變更傳播至 Auto Scaling 群組中所有執行個體的啟動組態。如需詳細資訊,請參閱 UpdatePolicy 屬性

新增資源屬性

到目前為止,我們已經了解範本中資源現有屬性的變更方式。除此之外,您還可以在範本中新增原本沒有指定的屬性。為了說明這項操作,我們會將 Amazon EC2 金鑰對新增至現有的 EC2 執行個體,接著在 Amazon EC2 安全群組中開啟連接埠 22,即可使用 Secure Shell (SSH) 來存取該執行個體。

將金鑰對新增至執行個體

在現有的 Amazon EC2 執行個體中新增 SSH 存取
  1. 將兩個額外參數新增至範本,藉此傳遞現有的 Amazon EC2 金鑰對名稱與 SSH 位置。

    "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. 將 KeyName 屬性新增至亞馬遜 EC2 執行個體。

    "WebServerInstance": { "Type" : "AWS::EC2::Instance", : "Properties": { : "KeyName" : { "Ref" : "KeyName" }, : } },
  3. 將連接埠 22 與 SSH 位置新增至 Amazon EC2 安全群組的輸入規則。

    "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

變更堆疊的資源

應用程序需求可以隨著時間的推移而改變, CloudFormation 允許您更改組成堆棧的資源集。我們會從新增資源屬性取得單一執行個體應用程式,接著更新堆疊以將其轉換成可自動調整規模、負載平衡的應用程式,藉此說明這項操作。

此操作會使用彈性 IP 地址來建立簡易的單一執行個體 PHP 應用程式。我們現在會在更新期間變更該應用程式的資源,進而將其轉換為具備高可用性、可自動調整規模且負載平衡的應用程式。

  1. 新增 Elastic Load Balancer 資源。

    "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 啟動組態。兩者屬性完全相同,因此僅需變更類型名稱,從:

    "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. 更新安全群組定義,藉此鎖定負載平衡器傳入執行個體的流量。

    "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. 更新 Outputs,進而傳回 Elastic Load Balancer 的 DNS 名稱,並將該名稱作為應用程式的位置;從:

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

    至:

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

下列範例顯示完整範本,以供參考。若您使用此範本更新堆疊,則可將簡易的單一執行個體應用程式轉換為具備高可用性、支援多個可用區域、可自動調整規模且負載平衡的應用程式。系統僅會修改需要更新的資源,所以此應用程式所存放的任何資料將不會受到影響。現在,您可以隨著需求的變化使用 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. 更新作業對資源本身有何影響? 舉例來說,更新警示閾值會導致警示在更新期間處於非作用中狀態。正如我們所看到的,更改實例類型需要停止並重新啟動實例。 CloudFormation 使用基礎資源的更新或修改動作來變更資源。如需了解更新造成的影響,請查閱特定資源的文件。

  2. 更改內容屬於可變或不可變項目? 基礎服務並不支援部分資源屬性變更操作,例如:更改 Amazon EC2 執行個體上的 AMI。在可變更的情況下, CloudFormation 將針對基礎資源使用更新或修改類型 API。對於不可變的屬性更改, CloudFormation 將創建具有更新屬性的新資源,然後在刪除舊資源之前將它們鏈接到堆棧。雖然 CloudFormation 試圖減少堆疊資源的停機時間,但取代資源是一個多步驟的程序,而且需要一些時間。重新設定堆疊期間,應用程式將無法完全正常運作。例如,應用程式可能無法處理請求或存取資料庫;

相關資源

如需有關使用啟動應用程式 CloudFormation 以及與其他組態和部署服務 (例如 Puppet 和 Opscode Chef) 整合的詳細資訊,請參閱下列白皮書:

本節中所使用的範本為 "Hello World" PHP 應用程式。範本程式庫也有一個 Amazon ElastiCache 範例範本,顯示如何整合 PHP 應用程式,並 ElasticCache 使用 cfn-hup 和 cfn-init 來回應 Amazon ElastiCache 快取叢集組態中的變更,所有這些變更都可由更新堆疊執行。