AWS CloudFormation による Amazon EC2 へのアプリケーションのデプロイ - AWS CloudFormation

AWS CloudFormation による Amazon EC2 へのアプリケーションのデプロイ

AWS CloudFormation を使用して、Amazon EC2 インスタンスにアプリケーションを自動的にインストールし、設定および起動することができます。これにより、インスタンスへ直接接続することなく、簡単にデプロイを複製し、既存のインストールを更新できるので、多くの時間と労力を節約することができます。

CloudFormation には、cloud-init に基づくヘルパースクリプトのセット (cfn-init、cfn-signal、cfn-get-metadata、および cfn-hup) が含まれています。同じテンプレートに存在する Amazon EC2 インスタンスにアプリケーションをインストールし、設定および更新するには、CloudFormation テンプレートからこれらのヘルパースクリプトを呼び出します

以降のウォークスルーでは、cfn ヘルパースクリプトを使用して LAMP スタックを起動し、Apache、MySQL、および PHP をインストール、設定および起動するためのテンプレートを作成する方法について説明します。最初は、Amazon Linux を実行する基本的な Amazon EC2 インスタンスを設定するシンプルなテンプレートを取り上げます。次に、テンプレートに機能を追加して完全な LAMP スタックを完成させます。

CloudFormation を使用してアプリケーションをデプロイするためのその他の方法や例については、AWS CloudFormation を介してアプリケーションをブートストラップの記事を参照してください。

基本的な Amazon EC2 インスタンス

最初に取り上げる基本的なテンプレートでは、ポート 22 での SSH トラフィックとポート 80 での HTTP トラフィックを許可するセキュリティグループを含む単独の Amazon EC2 インスタンスを定義します。以下に例を挙げます。

{ "AWSTemplateFormatVersion" : "2010-09-09", "Description" : "AWS CloudFormation sample template LAMP_Single_Instance: Create a LAMP stack using a single EC2 instance and a local MySQL database for storage. This template demonstrates using the AWS CloudFormation bootstrap scripts to install the packages and files necessary to deploy the Apache web server, PHP, and MySQL at instance launch time. **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" : "Can contain only ASCII characters." }, "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." }, "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" } }, "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", "Properties": { "ImageId" : { "Fn::FindInMap" : [ "AWSRegionArch2AMI", { "Ref" : "AWS::Region" }, { "Fn::FindInMap" : [ "AWSInstanceType2Arch", { "Ref" : "InstanceType" }, "Arch" ] } ] }, "InstanceType" : { "Ref" : "InstanceType" }, "SecurityGroups" : [ {"Ref" : "WebServerSecurityGroup"} ], "KeyName" : { "Ref" : "KeyName" } } }, "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"}, {"IpProtocol" : "tcp", "FromPort" : 22, "ToPort" : 22, "CidrIp" : { "Ref" : "SSHLocation"}} ] } } }, "Outputs" : { "WebsiteURL" : { "Description" : "URL for newly created LAMP stack", "Value" : { "Fn::Join" : ["", ["http://", { "Fn::GetAtt" : [ "WebServerInstance", "PublicDnsName" ]}]] } } } }

Amazon EC2 インスタンスおよびセキュリティグループに加えて、インスタンスタイプ、SSH アクセスに使用する Amazon EC2 キーペア、およびインスタンスへの SSH 接続に使用できる IP アドレス範囲を指定するための 3 つの入力パラメータを作成します。Mapping セクションでは、CloudFormation がスタックのリージョンと Amazon EC2 インスタンスタイプに対して正しい AMI ID を使用するように指定できます。最後に、ウェブサーバーのパブリック URL が出力セクションに出力されます。

基本的な Amazon EC2 インスタンス

AWSTemplateFormatVersion: 2010-09-09 Description: >- AWS CloudFormation sample template LAMP_Single_Instance: Create a LAMP stack using a single EC2 instance and a local MySQL database for storage. This template demonstrates using the AWS CloudFormation bootstrap scripts to install the packages and files necessary to deploy the Apache web server, PHP, and MySQL at instance launch time. **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: Can contain only ASCII characters. 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. 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 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' Properties: ImageId: !FindInMap - AWSRegionArch2AMI - !Ref 'AWS::Region' - !FindInMap - AWSInstanceType2Arch - !Ref InstanceType - Arch InstanceType: !Ref InstanceType SecurityGroups: - !Ref WebServerSecurityGroup KeyName: !Ref KeyName 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 - IpProtocol: tcp FromPort: 22 ToPort: 22 CidrIp: !Ref SSHLocation Outputs: WebsiteURL: Description: URL for newly created LAMP stack Value: !Join - '' - - 'http://' - !GetAtt - WebServerInstance - PublicDnsName

LAMP インストール

自動的に Apache、MySQL、PHP をインストールするには、上記の基本的な Amazon EC2 テンプレートを土台にします。アプリケーションをインストールするには、UserData プロパティと Metadata プロパティを追加します。ただし、アプリケーションの設定や起動が行われるのは、次のセクションに到達してからです。

以下の例では、簡潔にするため、省略符号 (...) が付いているセクションは省略されています。テンプレートに追加された部分は、赤い斜体文字で示されています。

{ "AWSTemplateFormatVersion" : "2010-09-09", "Description" : "AWS CloudFormation Sample Template LAMP_Install_Only: ...", "Parameters" : { "KeyName" : { ... }, "InstanceType" : { ... }, "Mappings" : { ... }, "Resources" : { "WebServerInstance": { "Type": "AWS::EC2::Instance", "Metadata" : { "Comment1" : "Configure the bootstrap helpers to install the Apache Web Server and PHP", "Comment2" : "Save website content to /var/www/html/index.php", "AWS::CloudFormation::Init" : { "configSets" : { "Install" : [ "Install" ] }, "Install" : { "packages" : { "yum" : { "mysql" : [], "mysql-server" : [], "mysql-libs" : [], "httpd" : [], "php" : [], "php-mysql" : [] } }, "files" : { "/var/www/html/index.php" : { "content" : { "Fn::Join" : [ "", [ "<html>\n", " <head>\n", " <title>AWS CloudFormation PHP Sample</title>\n", " <meta http-equiv=\"Content-Type\" content=\"text/html; charset=ISO-8859-1\">\n", " </head>\n", " <body>\n", " <h1>Welcome to the AWS CloudFormation PHP Sample</h1>\n", " <p/>\n", " <?php\n", " // Print out the current data and time\n", " print \"The Current Date and Time is: <br/>\";\n", " print date(\"g:i A l, F j Y.\");\n", " ?>\n", " <p/>\n", " <?php\n", " // Setup a handle for CURL\n", " $curl_handle=curl_init();\n", " curl_setopt($curl_handle,CURLOPT_CONNECTTIMEOUT,2);\n", " curl_setopt($curl_handle,CURLOPT_RETURNTRANSFER,1);\n", " // Get the hostname of the instance from the instance metadata\n", " curl_setopt($curl_handle,CURLOPT_URL,'http://169.254.169.254/latest/meta-data/public-hostname');\n", " $hostname = curl_exec($curl_handle);\n", " if (empty($hostname))\n", " {\n", " print \"Sorry, for some reason, we got no hostname back <br />\";\n", " }\n", " else\n", " {\n", " print \"Server = \" . $hostname . \"<br />\";\n", " }\n", " // Get the instance-id of the instance from the instance metadata\n", " curl_setopt($curl_handle,CURLOPT_URL,'http://169.254.169.254/latest/meta-data/instance-id');\n", " $instanceid = curl_exec($curl_handle);\n", " if (empty($instanceid))\n", " {\n", " print \"Sorry, for some reason, we got no instance id back <br />\";\n", " }\n", " else\n", " {\n", " print \"EC2 instance-id = \" . $instanceid . \"<br />\";\n", " }\n", " $Database = \"", {"Ref" : "DBName"}, "\";\n", " $DBUser = \"", {"Ref" : "DBUsername"}, "\";\n", " $DBPassword = \"", {"Ref" : "DBPassword"}, "\";\n", " print \"Database = \" . $Database . \"<br />\";\n", " $dbconnection = mysql_connect('localhost', $DBUser, $DBPassword, $Database)\n", " or die(\"Could not connect: \" . mysql_error());\n", " print (\"Connected to $Database successfully\");\n", " mysql_close($dbconnection);\n", " ?>\n", " <h2>PHP Information</h2>\n", " <p/>\n", " <?php\n", " phpinfo();\n", " ?>\n", " </body>\n", "</html>\n" ]]}, "mode" : "000600", "owner" : "apache", "group" : "apache" } }, "services" : { "sysvinit" : { "httpd" : { "enabled" : "true", "ensureRunning" : "true" } } } } }, "Properties": { "ImageId" : { "Fn::FindInMap" : [ "AWSRegionArch2AMI", { "Ref" : "AWS::Region" }, { "Fn::FindInMap" : [ "AWSInstanceType2Arch", { "Ref" : "InstanceType" }, "Arch" ] } ] }, "InstanceType" : { "Ref" : "InstanceType" }, "SecurityGroups" : [ {"Ref" : "WebServerSecurityGroup"} ], "KeyName" : { "Ref" : "KeyName" }, "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 ", " --configsets Install ", " --region ", { "Ref" : "AWS::Region" }, "\n" ]]}} } }, "WebServerSecurityGroup" : { ... } }, "Outputs" : { ... } }

UserData プロパティにより、2 つのシェルコマンドが実行され、CloudFormation ヘルパースクリプトがインストールされた後、cfn-init ヘルパースクリプトが実行されます。ヘルパースクリプトは定期的に更新されるため、yum install -y aws-cfn-bootstrap コマンドを実行することで、確実に最新のヘルパースクリプトを取得できます。cfn-init を実行すると、AWS::CloudFormation::Init リソースからメタデータが読み込まれます。これは、cfn-init によって実行されるアクションが記述されたものです。たとえば、cfn-init および AWS::CloudFormation::Init を使用して、パッケージのインストール、ディスクへのファイルの書き込み、またはサービスの起動を実行できます。ここでは、cfn-init によって、リストされているパッケージ (httpd、mysql、php) がインストールされ、/var/www/html/index.php ファイル (サンプルの PHP アプリケーション) が作成されます。

LAMP 構成

Linux、Apache、MySQL、PHP をインストールするテンプレートを作成したので、Apache、MySQL、PHP を自動的に設定および実行するようにテンプレートを拡張する必要があります。以下の例は、Parameters セクション、AWS::CloudFormation::Init リソース、UserData プロパティを拡張して設定を完了します。前出のテンプレートと同様、簡潔にするため、省略符号 (...) が付いているセクションは省略されています。テンプレートに追加された部分は、赤い斜体文字で示されています。

例では、NoEcho プロパティを true に設定して DBUsername および DBPassword パラメータを定義しています。NoEcho 属性を true に設定すると、CloudFormation は、スタックまたはスタックイベントを記述するすべての呼び出しに対して、アスタリスク (*****) としてマスクされたパラメータ値を返します。ただし、以下に指定された場所に保存されている情報は除きます。

重要

NoEcho 属性を使用しても、以下に保存されている情報はマスクされません。

  • Metadata テンプレートセクション。CloudFormation は、Metadata セクションに含める情報の変換、変更、または編集を行いません。詳細については、「メタデータ」を参照してください。

  • Outputs テンプレートセクション。詳細については、「出力」を参照してください。

  • リソース定義の Metadata 属性。詳細については、「メタデータ属性」を参照してください。

パスワードやシークレットなどの機密情報を含めるには、これらのメカニズムを使用しないことを強くお勧めします。

重要

機密情報は、CloudFormation テンプレートに直接埋め込まずに、スタックテンプレートの動的パラメータを使用して CloudFormation の外部 (AWS Systems Manager のパラメータストアや AWS Secrets Manager など) に保存して管理し、これを参照することをお勧めします。

詳細については、「テンプレートに認証情報を埋め込まない」のベストプラクティスを参照してください。

{ "AWSTemplateFormatVersion" : "2010-09-09", "Description" : "AWS CloudFormation Sample Template LAMP_Single_Instance: Create a LAMP stack using a single EC2 instance and a local MySQL database for storage. This template demonstrates using the AWS CloudFormation bootstrap scripts to install the packages and files necessary to deploy the Apache web server, PHP and MySQL at instance launch time. **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" : { ... }, "DBName": { "Default": "MyDatabase", "Description" : "MySQL database name", "Type": "String", "MinLength": "1", "MaxLength": "64", "AllowedPattern" : "[a-zA-Z][a-zA-Z0-9]*", "ConstraintDescription" : "Must begin with a letter and contain only alphanumeric characters" }, "DBUsername": { "NoEcho": "true", "Description" : "Username for MySQL database access", "Type": "String", "MinLength": "1", "MaxLength": "16", "AllowedPattern" : "[a-zA-Z][a-zA-Z0-9]*", "ConstraintDescription" : "Must begin with a letter and contain only alphanumeric characters" }, "DBPassword": { "NoEcho": "true", "Description" : "Password for MySQL database access", "Type": "String", "MinLength": "1", "MaxLength": "41", "AllowedPattern" : "[a-zA-Z0-9]*", "ConstraintDescription" : "Must contain only alphanumeric characters" }, "DBRootPassword": { "NoEcho": "true", "Description" : "Root password for MySQL", "Type": "String", "MinLength": "1", "MaxLength": "41", "AllowedPattern" : "[a-zA-Z0-9]*", "ConstraintDescription" : "Must contain only alphanumeric characters" }, "InstanceType" : { ... } }, "Mappings" : { ... }, "Resources" : { "WebServerInstance": { "Type": "AWS::EC2::Instance", "Metadata" : { "Comment1" : "Configure the bootstrap helpers to install the Apache Web Server and PHP", "Comment2" : "Save website content to /var/www/html/index.php", "AWS::CloudFormation::Init" : { "configSets" : { "InstallAndRun" : [ "Install", "Configure" ] }, "Install" : { "packages" : { "yum" : { "mysql" : [], "mysql-server" : [], "mysql-libs" : [], "httpd" : [], "php" : [], "php-mysql" : [] } }, "files" : { "/var/www/html/index.php" : { "content" : { ... }, "mode" : "000600", "owner" : "apache", "group" : "apache" }, "/tmp/setup.mysql" : { "content" : { "Fn::Join" : ["", [ "CREATE DATABASE ", { "Ref" : "DBName" }, ";\n", "GRANT ALL ON ", { "Ref" : "DBName" }, ".* TO '", { "Ref" : "DBUsername" }, "'@localhost IDENTIFIED BY '", { "Ref" : "DBPassword" }, "';\n" ]]}, "mode" : "000400", "owner" : "root", "group" : "root" }, "/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 -v ", " --stack ", { "Ref" : "AWS::StackName" }, " --resource WebServerInstance ", " --configsets InstallAndRun ", " --region ", { "Ref" : "AWS::Region" }, "\n", "runas=root\n" ]]} } }, }, "services" : { "sysvinit" : { "mysqld" : { "enabled" : "true", "ensureRunning" : "true" }, "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"]} } } }, "Configure" : { "commands" : { "01_set_mysql_root_password" : { "command" : { "Fn::Join" : ["", ["mysqladmin -u root password '", { "Ref" : "DBRootPassword" }, "'"]]}, "test" : { "Fn::Join" : ["", ["$(mysql ", { "Ref" : "DBUsername" }, " -u root --password='", { "Ref" : "DBRootPassword" }, "' >/dev/null 2>&1 </dev/null); (( $? != 0 ))"]]} }, "02_create_database" : { "command" : { "Fn::Join" : ["", ["mysql -u root --password='", { "Ref" : "DBRootPassword" }, "' < /tmp/setup.mysql"]]}, "test" : { "Fn::Join" : ["", ["$(mysql ", { "Ref" : "DBUsername" }, " -u root --password='", { "Ref" : "DBRootPassword" }, "' >/dev/null 2>&1 </dev/null); (( $? != 0 ))"]]} } } } } }, "Properties": { "ImageId" : { "Fn::FindInMap" : [ "AWSRegionArch2AMI", { "Ref" : "AWS::Region" }, { "Fn::FindInMap" : [ "AWSInstanceType2Arch", { "Ref" : "InstanceType" }, "Arch" ] } ] }, "InstanceType" : { "Ref" : "InstanceType" }, "SecurityGroups" : [ {"Ref" : "WebServerSecurityGroup"} ], "KeyName" : { "Ref" : "KeyName" }, "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 ", " --stack ", { "Ref" : "AWS::StackName" }, " --resource WebServerInstance ", " --configsets InstallAndRun ", " --region ", { "Ref" : "AWS::Region" }, "\n" ]]}} } }, "WebServerSecurityGroup" : { ... } }, "Outputs" : { ... } }

この例では、データベース名、ユーザー名、パスワード、ルートパスワードなど、MySQL データベースを設定するための情報を取得するために、パラメーターが追加されています。これらのパラメータには、CloudFormation によってスタックの作成が開始される前に不適切にフォーマットされた値を検出する制約が含まれています。

AWS::CloudFormation::Init リソースには、データベース名、ユーザー名、およびパスワードを含む MySQL セットアップファイルを追加しました。この例では、さらに services プロパティを追加して、httpd および mysqld サービスが実行され (ensureRunningtrue に設定)、インスタンスが再起動された場合にはサービスが再開されるように (enabledtrue に設定) します。また、cfn-hup ヘルパースクリプトも含めることもお勧めします。これにより、スタックテンプレートを更新することで、実行中のインスタンスの設定を更新できるからです。たとえば、サンプル PHP アプリケーションを変更してから、スタックの更新を実行することで、変更をデプロイすることができます。

この例では、インストールの完了後に MySQL コマンドを実行するために、コマンド実行用の別の設定セットを追加しています。設定セットは、特定の順序で実行しなければならない一連の作業がある場合に役立ちます。この例では、最初に Install 設定セットを実行してから、Configure 設定セットを実行します。Configure 設定セットはデータベースのルートパスワードを指定してから、データベースを作成します。コマンドセクションのコマンドはコマンド名によってアルファベット順に処理されるので、この例では、各コマンド名の先頭に実行順序を示す番号を追加しています。

CreationPolicy 属性

最後に、すべてのスタックリソースが作成された後ではなく、すべてのサービス (Apache や MySQL など) が実行された後で初めて、CloudFormation に対してスタックの作成を完了するように指示する方法が必要になります。つまり、前のセクションのテンプレートを使用してスタックを起動すると、CloudFormation はすべてのリソースを正常に作成した後で、スタックのステータスを CREATE_COMPLETE に設定します。ただし、1 つ以上のサービスが起動されなかった場合でも、CloudFormation はスタックのステータスを CREATE_COMPLETE に設定します。すべてのサービスが正常に起動されてから初めてステータスを CREATE_COMPLETE に変更させるには、インスタンスに CreationPolicy 属性を追加します。この属性により、CloudFormation が必要な数の成功シグナルを受け取るか、タイムアウト期間が経過するまで、インスタンスのステータスは CREATE_IN_PROGRESS のままになるので、インスタンスが正常に作成されるタイミングを制御できます。

以下の例では、Amazon EC2 インスタンスに作成ポリシーが追加されています。これにより、cfn-init はスタックの作成が完了する前に LAMP のインストールと設定を完了させます。この例では、作成ポリシーと同時に cfn-signal ヘルパースクリプトを実行し、すべてのアプリケーションがインストールおよび設定された場合に CloudFormation がシグナルを受け取るようにします。

{ "AWSTemplateFormatVersion" : "2010-09-09", "Description" : "AWS CloudFormation Sample Template LAMP_Single_Instance: ...", "Parameters" : { ... }, "Mappings" : { ... }, "Resources" : { "WebServerInstance": { "Type": "AWS::EC2::Instance", "Metadata" : { ... }, "Properties": { "ImageId" : { "Fn::FindInMap" : [ "AWSRegionArch2AMI", { "Ref" : "AWS::Region" }, { "Fn::FindInMap" : [ "AWSInstanceType2Arch", { "Ref" : "InstanceType" }, "Arch" ] } ] }, "InstanceType" : { "Ref" : "InstanceType" }, "SecurityGroups" : [ {"Ref" : "WebServerSecurityGroup"} ], "KeyName" : { "Ref" : "KeyName" }, "UserData" : { "Fn::Base64" : { "Fn::Join" : ["", [ "#!/bin/bash -xe\n", "yum update aws-cfn-bootstrap\n", "# Install the files and packages from the metadata\n", "/opt/aws/bin/cfn-init ", " --stack ", { "Ref" : "AWS::StackName" }, " --resource WebServerInstance ", " --configsets InstallAndRun ", " --region ", { "Ref" : "AWS::Region" }, "\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" : { ... } }, "Outputs" : { "WebsiteURL" : { ... } } }

作成ポリシーの属性には ISO 8601 の形式を使用して、5 分のタイムアウト期間を定義します。また、設定完了を待機しているインスタンスは 1 つであるため、待機する成功シグナル数はデフォルトの 1 です。

テンプレートの UserData プロパティでは cfn-signal スクリプトが実行され、すべてのサービスが正常に設定および起動された場合には、終了コードに基づいて成功シグナルが送信されるようになっています。cfn-signal スクリプトを使用する際には、シグナル対象のスタック IDまたはスタック名、およびリソースの論理 ID を指定する必要があります。設定が失敗すると、cfn-signal は失敗シグナルを送信し、リソースの作成が失敗したことになります。タイムアウト期間内に CloudFormation が成功シグナルを受信しない場合、リソースの作成も失敗します。

以下の例は、最終的に完成したテンプレートを示しています。

テンプレートは、次の場所でも確認できます。

https://s3.amazonaws.com/cloudformation-templates-us-east-1/LAMP_Single_Instance.template

{ "AWSTemplateFormatVersion" : "2010-09-09", "Description" : "AWS CloudFormation Sample Template LAMP_Single_Instance: Create a LAMP stack using a single EC2 instance and a local MySQL database for storage. This template demonstrates using the AWS CloudFormation bootstrap scripts to install the packages and files necessary to deploy the Apache web server, PHP and MySQL at instance launch time. **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" : "Can contain only ASCII characters." }, "DBName": { "Default": "MyDatabase", "Description" : "MySQL database name", "Type": "String", "MinLength": "1", "MaxLength": "64", "AllowedPattern" : "[a-zA-Z][a-zA-Z0-9]*", "ConstraintDescription" : "Must begin with a letter and contain only alphanumeric characters" }, "DBUsername": { "NoEcho": "true", "Description" : "User name for MySQL database access", "Type": "String", "MinLength": "1", "MaxLength": "16", "AllowedPattern" : "[a-zA-Z][a-zA-Z0-9]*", "ConstraintDescription" : "Must begin with a letter and contain only alphanumeric characters" }, "DBPassword": { "NoEcho": "true", "Description" : "Password for MySQL database access", "Type": "String", "MinLength": "1", "MaxLength": "41", "AllowedPattern" : "[a-zA-Z0-9]*", "ConstraintDescription" : "Must contain only alphanumeric characters" }, "DBRootPassword": { "NoEcho": "true", "Description" : "Root password for MySQL", "Type": "String", "MinLength": "1", "MaxLength": "41", "AllowedPattern" : "[a-zA-Z0-9]*", "ConstraintDescription" : "Must contain only alphanumeric characters" }, "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." }, "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" } }, "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" : { "AWS::CloudFormation::Init" : { "configSets" : { "InstallAndRun" : [ "Install", "Configure" ] }, "Install" : { "packages" : { "yum" : { "mysql" : [], "mysql-server" : [], "mysql-libs" : [], "httpd" : [], "php" : [], "php-mysql" : [] } }, "files" : { "/var/www/html/index.php" : { "content" : { "Fn::Join" : [ "", [ "<html>\n", " <head>\n", " <title>AWS CloudFormation PHP Sample</title>\n", " <meta http-equiv=\"Content-Type\" content=\"text/html; charset=ISO-8859-1\">\n", " </head>\n", " <body>\n", " <h1>Welcome to the AWS CloudFormation PHP Sample</h1>\n", " <p/>\n", " <?php\n", " // Print out the current data and time\n", " print \"The Current Date and Time is: <br/>\";\n", " print date(\"g:i A l, F j Y.\");\n", " ?>\n", " <p/>\n", " <?php\n", " // Setup a handle for CURL\n", " $curl_handle=curl_init();\n", " curl_setopt($curl_handle,CURLOPT_CONNECTTIMEOUT,2);\n", " curl_setopt($curl_handle,CURLOPT_RETURNTRANSFER,1);\n", " // Get the hostname of the intance from the instance metadata\n", " curl_setopt($curl_handle,CURLOPT_URL,'http://169.254.169.254/latest/meta-data/public-hostname');\n", " $hostname = curl_exec($curl_handle);\n", " if (empty($hostname))\n", " {\n", " print \"Sorry, for some reason, we got no hostname back <br />\";\n", " }\n", " else\n", " {\n", " print \"Server = \" . $hostname . \"<br />\";\n", " }\n", " // Get the instance-id of the intance from the instance metadata\n", " curl_setopt($curl_handle,CURLOPT_URL,'http://169.254.169.254/latest/meta-data/instance-id');\n", " $instanceid = curl_exec($curl_handle);\n", " if (empty($instanceid))\n", " {\n", " print \"Sorry, for some reason, we got no instance id back <br />\";\n", " }\n", " else\n", " {\n", " print \"EC2 instance-id = \" . $instanceid . \"<br />\";\n", " }\n", " $Database = \"", {"Ref" : "DBName"}, "\";\n", " $DBUser = \"", {"Ref" : "DBUsername"}, "\";\n", " $DBPassword = \"", {"Ref" : "DBPassword"}, "\";\n", " print \"Database = \" . $Database . \"<br />\";\n", " $dbconnection = mysql_connect('localhost', $DBUser, $DBPassword, $Database)\n", " or die(\"Could not connect: \" . mysql_error());\n", " print (\"Connected to $Database successfully\");\n", " mysql_close($dbconnection);\n", " ?>\n", " <h2>PHP Information</h2>\n", " <p/>\n", " <?php\n", " phpinfo();\n", " ?>\n", " </body>\n", "</html>\n" ]]}, "mode" : "000600", "owner" : "apache", "group" : "apache" }, "/tmp/setup.mysql" : { "content" : { "Fn::Join" : ["", [ "CREATE DATABASE ", { "Ref" : "DBName" }, ";\n", "GRANT ALL ON ", { "Ref" : "DBName" }, ".* TO '", { "Ref" : "DBUsername" }, "'@localhost IDENTIFIED BY '", { "Ref" : "DBPassword" }, "';\n" ]]}, "mode" : "000400", "owner" : "root", "group" : "root" }, "/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 -v ", " --stack ", { "Ref" : "AWS::StackName" }, " --resource WebServerInstance ", " --configsets InstallAndRun ", " --region ", { "Ref" : "AWS::Region" }, "\n", "runas=root\n" ]]} } }, "services" : { "sysvinit" : { "mysqld" : { "enabled" : "true", "ensureRunning" : "true" }, "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"]} } } }, "Configure" : { "commands" : { "01_set_mysql_root_password" : { "command" : { "Fn::Join" : ["", ["mysqladmin -u root password '", { "Ref" : "DBRootPassword" }, "'"]]}, "test" : { "Fn::Join" : ["", ["$(mysql ", { "Ref" : "DBUsername" }, " -u root --password='", { "Ref" : "DBRootPassword" }, "' >/dev/null 2>&1 </dev/null); (( $? != 0 ))"]]} }, "02_create_database" : { "command" : { "Fn::Join" : ["", ["mysql -u root --password='", { "Ref" : "DBRootPassword" }, "' < /tmp/setup.mysql"]]}, "test" : { "Fn::Join" : ["", ["$(mysql ", { "Ref" : "DBUsername" }, " -u root --password='", { "Ref" : "DBRootPassword" }, "' >/dev/null 2>&1 </dev/null); (( $? != 0 ))"]]} } } } } }, "Properties": { "ImageId" : { "Fn::FindInMap" : [ "AWSRegionArch2AMI", { "Ref" : "AWS::Region" }, { "Fn::FindInMap" : [ "AWSInstanceType2Arch", { "Ref" : "InstanceType" }, "Arch" ] } ] }, "InstanceType" : { "Ref" : "InstanceType" }, "SecurityGroups" : [ {"Ref" : "WebServerSecurityGroup"} ], "KeyName" : { "Ref" : "KeyName" }, "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 ", " --configsets InstallAndRun ", " --region ", { "Ref" : "AWS::Region" }, "\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"}, {"IpProtocol" : "tcp", "FromPort" : "22", "ToPort" : "22", "CidrIp" : { "Ref" : "SSHLocation"}} ] } } }, "Outputs" : { "WebsiteURL" : { "Description" : "URL for newly created LAMP stack", "Value" : { "Fn::Join" : ["", ["http://", { "Fn::GetAtt" : [ "WebServerInstance", "PublicDnsName" ]}]] } } } }