Amazon EC2 Windows 인스턴스에서 인스턴스가 부트스트래핑을 완료하기 전에 CREATE_COMPLETE를 표시하여 다시 신호를 보내지 않도록 하려면 어떻게 해야 하나요?

4분 분량
0

AWS CloudFormation에서 cfn-init(cfn-init.exe) 및 cfn-signal(cfn-signal.exe) 헬퍼 스크립트를 사용하여 Amazon Elastic Compute Cloud (Amazon EC2) Windows 인스턴스의 부트스트랩을 수행하고 있습니다. cfn-init 스크립트가 너무 일찍 신호를 다시 보냅니다. 그러면 AWS CloudFormation은 인스턴스가 부트스트래핑을 완료하기 전에 내 Windows 인스턴스를 CREATE_COMPLETE로 표시합니다.

간략한 설명

Windows 인스턴스에서 UserData 스크립트는 Ec2ConfigService 프로세스에 의해 실행됩니다. UserDataEc2ConfigService의 하위 프로세스로 실행되는 cfn-init.exe를 호출합니다.

다음과 같은 이유로 Windows 인스턴스가 CREATE_COMPLETE으로 표시하여 다시 신호를 보낼 수 있습니다.

  • cfn-init.exe에서 실행하는 단계 중 하나에서 시스템 재부팅이 필요한 경우 시스템을 종료한 후 실행을 Ec2ConfigService 프로세스로 다시 반환합니다. 시스템은 UserData 스크립트를 계속 처리하고 cfn-signal.exe를 실행합니다. 그러면 여기서 AWS CloudFormation으로 신호를 다시 전송합니다.
  • cfn-signal은 재부팅 후에 신호를 다시 전송하지 않습니다. UserData는 한 번만 실행되기 때문입니다.

아래 코드 예제에서, cfn-signal.exe는 UserData에서 직접 호출됩니다. cfn-init.exe 프로세스가 재부팅을 수행하는 경우 cfn-signal.exe 명령을 호출할 수 없습니다. UserData는 한 번만 실행되기 때문입니다.

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 템플릿에서 UserDatacfn-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 파라미터를 forever로 설정합니다.

참고: waitAfterCompletion의 기본값은 60초입니다. 값을 forever로 변경하면 cfn-init가 종료되고 재부팅을 완료한 후에만 재개됩니다.


관련 정보

AWS CloudFormation Windows 스택 부트스트래핑

AWS CloudFormation 사용 설명서

AWS 공식
AWS 공식업데이트됨 4년 전