ブートストラップを完了する前の Amazon EC2 Windows インスタンスが、CREATE_COMPLETE シグナルを返さないようにするにはどうしたらよいですか?
AWS CloudFormation のヘルパースクリプトである cfn-init (cfn-init.exe) と cfn-signal (cfn-signal.exe) を使用して、Amazon Elastic Compute Cloud (Amazon EC2) Windows インスタンスをブートストラップしています。cfn-init スクリプトのシグナルが早く返されすぎます。さらに、この Windows インスタンスがブートストラップを完了する前に、AWS CloudFormation において CREATE_COMPLETE としてマークされてしまいます。
簡単な説明
Windows インスタンスでは、UserData スクリプトを Ec2ConfigService プロセスが実行します。UserData が cfn-init.exe を呼び出します。これは Ec2ConfigService の子プロセスとして実行されます。
次の理由により、Windows インスタンスが CREATE_COMPLETE としてシグナルを返している可能性があります。
- cfn-init.exe で実行される 1 段階処理でシステムの再起動を必要とする場合、システムはシャットダウンしてから、実行を Ec2ConfigService プロセスに返すことができます。システムは UserData スクリプトの処理を続行してから cfn-signal.exe を実行し、AWS CloudFormation にシグナルを返します。
- UserData は 1 度しか実行されないため、再起動後に cfn-signal がシグナルを送り返しません。
以下のコード例では、cfn-signal.exe は UserData から直接呼び出されます。cfn-init.exe プロセスが再起動した場合、UserData は 1 度しか実行されないため、cfn-signal.exe コマンドを呼び出すことはできません。
JSON の例:
"UserData": { "Fn::Base64": { "Fn::Join": [ "", [ "<script>\n", "cfn-init.exe -v -s ", { "Ref": "AWS::StackId" }, " -r WindowsInstance", " --configsets ascending", " --region ", { "Ref": "AWS::Region" }, "\n", "cfn-signal.exe -e %ERRORLEVEL% --stack ", { "Ref": "AWS::StackId" }, " --resource WindowsInstance --region ", { "Ref": "AWS::Region" }, "\n", "</script>" ] ] } }
YAML の例:
UserData: Fn::Base64: !Sub | <script> cfn-init.exe -v -s ${AWS::StackId} -r WindowsInstance --configsets ascending --region ${AWS::Region} cfn-signal.exe -e %ERRORLEVEL% --stack ${AWS::StackId} --resource WindowsInstance --region ${AWS::Region} </script>
解決方法
1. テンプレートの cfn-init Metadata セクションで configsets を使用して、再起動が必要な設定と再起動が不要な設定を分離します。
2. AWS::EC2::Instance または AWS::AutoScaling::LaunchConfiguration のリソースにある UserData セクションから、テンプレートの AWS::CloudFormation::Init Metadata セクションに cfn-signal.exe を移動します。
3. 最後の configset が実行した最後のコマンドとして cfn-signal.exe を実行します。
4. JSON または YAML テンプレートで、UserData を cfn-init に変更し、昇順の configset を指定します。
JSON の例:
{ "AWSTemplateFormatVersion": "2010-09-09", "Description": "cfn-init example using configsets", "Parameters": { "AMI": { "Type": "AWS::EC2::Image::Id" } }, "Resources": { "WindowsInstance": { "Type": "AWS::EC2::Instance", "Metadata": { "AWS::CloudFormation::Init": { "configSets": { "ascending": [ "config1", "config2", "config3" ] }, "config1": { "files": { "C:\\setup\\setenvironment.ps1": { "content": { "Fn::Join": [ "", [ "$Folder = 'C:\\Program Files\\Server\\packages\\bin.20182.18.0826.0815\\'\n", "$OldPath = [System.Environment]::GetEnvironmentVariable('path')\n", "$NewPath = $OldPath + ';' + $Folder\n", "[System.Environment]::SetEnvironmentVariable('path',$NewPath,'Machine')" ] ] } } } }, "config2": { "commands": { "0-restart": { "command": "powershell.exe -Command Restart-Computer", "waitAfterCompletion": "forever" } } }, "config3": { "commands": { "01-setenvironment": { "command": "powershell.exe -ExecutionPolicy Unrestricted C:\\setup\\setenvironment.ps1", "waitAfterCompletion": "0" }, "02-signal-resource": { "command": { "Fn::Join": [ "", [ "cfn-signal.exe -e %ERRORLEVEL% --resource WindowsInstance --stack ", { "Ref": "AWS::StackName" }, " --region ", { "Ref": "AWS::Region" } ] ] } } } } } }, "Properties": { "ImageId": { "Ref": "AMI" }, "InstanceType": "t2.medium", "UserData": { "Fn::Base64": { "Fn::Join": [ "", [ "<script>\n", "cfn-init.exe -v -s ", { "Ref": "AWS::StackId" }, " -r WindowsInstance", " --configsets ascending", " --region ", { "Ref": "AWS::Region" }, "</script>" ] ] } } }, "CreationPolicy": { "ResourceSignal": { "Count": "1", "Timeout": "PT30M" } } } } }
YAML の例:
AWSTemplateFormatVersion: '2010-09-09' Description: cfn-init example using configsets Parameters: AMI: Type: 'AWS::EC2::Image::Id' Resources: WindowsInstance: Type: 'AWS::EC2::Instance' Metadata: AWS::CloudFormation::Init: configSets: ascending: - config1 - config2 - config3 config1: files: C:\setup\setenvironment.ps1: content: !Sub | $Folder = 'C:\Program Files\Server\packages\bin.20182.18.0826.0815\' $OldPath = [System.Environment]::GetEnvironmentVariable('path') $NewPath = $OldPath + ';' + $Folder [System.Environment]::SetEnvironmentVariable('path',$NewPath,'Machine') config2: commands: 0-restart: command: powershell.exe -Command Restart-Computer waitAfterCompletion: forever config3: commands: 01-setenvironment: command: powershell.exe -ExecutionPolicy Unrestricted C:\setup\setenvironment.ps1 waitAfterCompletion: '0' 02-signal-resource: command: !Sub > cfn-signal.exe -e %ERRORLEVEL% --resource WindowsInstance --stack ${AWS::StackName} --region ${AWS::Region} Properties: ImageId: !Ref AMI InstanceType: t2.medium UserData: Fn::Base64: !Sub | <script> cfn-init.exe -v -s ${AWS::StackId} -r WindowsInstance --configsets ascending --region ${AWS::Region} </script> CreationPolicy: ResourceSignal: Count: 1 Timeout: PT30M
前述のテンプレートのようにすると、シグナルは UserData で実行されなくなります。つまり、cfn-init プロセスからの終了コードが取得できなくなります。デフォルトでは、UserData または Metadata からシグナルが受信されない場合、AWS CloudFormation はスタックの作成または更新に失敗します。結果的に、スタックは 「timeout exceeded」エラーを返します。
ヒント: 各種の障害をトラブルシューティングするには、Windows インスタンスの c:\cfn\log にあるログが役立ちます。
5. waitAfterCompletion パラメータを 永続的に設定します。
注: waitAfterCompletion のデフォルト値は 60 秒です。値を永久に変更すると、cfn-init は終了し、再起動の完了後に再び開始します。
関連情報

関連するコンテンツ
- 質問済み 5年前lg...
- 質問済み 6年前lg...
- 質問済み 4年前lg...
- 質問済み 5年前lg...
- 承認された回答質問済み 2ヶ月前lg...
- AWS公式更新しました 2年前
- AWS公式更新しました 1ヶ月前