CloudFormationで再起動が必要なソフトウェアをインストールする

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

ウィスキー、シガー、パイプをこよなく愛する大栗です。

最近CloudFormationで環境を構成することが多いのですが、別のツールを使うのが面倒なのでUserDataやCloudFormation::Initを使用してソフトウェアのインストールなどをしています。しかし、Windowsのソフトウェアはインストールに再起動が必須の場合が多々あり、一気に導入する方法に悩んでいました。CloudFormationでは、再起動が伴う処理の後も後続処理を行う機構を備えていたのでまとめてみます。

本内容はWindows以外には対応していないので、ご注意願います。

再起動が必要な場合とは

例えばWindows Server 2012 R2でPackageManagementを使ってVisual Studio Codeをインストールする場合を考えてみましょう。リンク先の記事では、Visual Studio Codeのインストールまでに以下のステップを実行しています。

  1. Windows Management Framework 5.0
  2. Windows Management Framework 5.0(KB3134758)をダウンロードする。
  3. Windows Management Framework 5.0(KB3134758)をインストールする。
  4. Visual Studio Code
  5. PowerShellスクリプトの実行を許可する。
  6. パッケージプロバイダの一覧を表示する。
  7. chocolateyプロバイダでパッケージを確認する。
  8. Visual Studio Codeをインストールする。

1.2.の『Windows Management Framework 5.0(KB3134758)をインストールする。』で再起動が必要になります。しかし、その後の処理は続きます。

CloudFormation化してみる

Visual Studio Codeをインストール処理をCloudFormationに落とし込んでみます。インストール処理はEC2のMetadataの中でAWS::CloudFormation::Initを使って記述しています。

{
  "AWSTemplateFormatVersion" : "2010-09-09",
  "Description" : "Linux Stack",
  "Resources" : {
    "Server01": {
      "Type": "AWS::EC2::Instance",
      "CreationPolicy" : {
        "ResourceSignal": {
          "Timeout": "PT30M"
        }
      },
      "Properties": {
        "ImageId": "ami-0f19db6e",
        "InstanceType": "c4.large",
        "KeyName": "KeyPairName",
        "UserData": { "Fn::Base64": { "Fn::Join": [ "", [
          "<script>", "\n",
          "cfn-init.exe -v -c install -s ", { "Ref": "AWS::StackId" }, " -r Server01 -c sample --region ", { "Ref": "AWS::Region" }, "\n",
          "", "\n",
          "</script>"
        ]]}}
      },
      "Metadata" : {
        "AWS::CloudFormation::Init" : {
          "configSets" : {
            "sample" : [
              "KB3134758",
              "vscode",
              "finalize"
            ]
          },
          "KB3134758" : {
            "files" : {
              "c:\\cm\\Win8.1AndW2K12R2-KB3134758-x64.msu" : {
                "source" : "https://download.microsoft.com/download/2/C/6/2C6E1B4A-EBE5-48A6-B225-2D2058A9CEFB/Win8.1AndW2K12R2-KB3134758-x64.msu"
              }
            },
            "commands" : {
              "wait" : {
                "command" : "wusa.exe c:\\cm\\Win8.1AndW2K12R2-KB3134758-x64.msu /quiet /forcerestart",
                "cwd" : "C:\\cm"
              }
            }
          },
          "vscode" : {
            "commands" : {
              "a-set-execution-policy": {
                "command": "powershell.exe -command Set-ExecutionPolicy RemoteSigned -Force"
              },
              "b-find-package-provider": {
                "command": "powershell.exe -command Find-PackageProvider -ForceBootstrap"
              },
              "c-find-package": {
                "command": "powershell.exe -command Find-Package -ForceBootstrap -Name VisualStudioCode -Provider chocolatey"
              },
              "d-install-package": {
                "command": "powershell.exe -command Install-Package -Name VisualStudioCode -Force"
              }
            }
          },
          "finalize" : {
            "commands" : {
              "a-write-status" : {
                "command" : { "Fn::Join": [ "", [
                  "cfn-signal",
                  " --exit-code 0",
                  " --region \"", { "Ref": "AWS::Region" }, "\"",
                  " --resource Server01",
                  " --stack \"", { "Ref": "AWS::StackName"}, "\""
                ]]}
              }
            }
          }
        }
      }
    }
  }
}

この内容のテンプレートでは正しくCloudFormation Stackを構築できません。『2. Windows Management Framework 5.0をインストールする。』の部分で再起動が必要であるため、このままでは処理が途中で止まってしまい処理を完了できずにEC2がCREATE_FAILEDになってしまいます。このままではWindows Management Framework 5.0のインストールはできますが、Visual Studio Codeをインストールできません。

再起動後の後続処理に対応する

ここでKB3134758の部分にwaitAfterCompletionというオプションを追加します。ドキュメントには、以下の記載があります。

オプション。Windows システムの場合のみ。コマンドによって再起動が行われる場合に、コマンド終了後にどのぐらい待機するかを指定します(秒単位)。デフォルト値は 60 秒です。値を "forever" にすると、cfn-init が終了し、再起動が完了した後に再開されます。

つまり、再起動を行うwusa.exe c:\\cm\\Win8.1AndW2K12R2-KB3134758-x64.msu /quiet /forcerestartというコマンドでwaitAfterCompletionオプションを使用すると、後続処理を行うことができるということです。先ほどのテンプレートを書き換えます。以下の様に42行目にwaitAfterCompletionオプションでforeverを設定しています。

          "KB3134758" : {
            "files" : {
              "c:\\cm\\Win8.1AndW2K12R2-KB3134758-x64.msu" : {
                "source" : "https://download.microsoft.com/download/2/C/6/2C6E1B4A-EBE5-48A6-B225-2D2058A9CEFB/Win8.1AndW2K12R2-KB3134758-x64.msu"
              }
            },
            "commands" : {
              "wait" : {
                "command" : "wusa.exe c:\\cm\\Win8.1AndW2K12R2-KB3134758-x64.msu /quiet /forcerestart",
                "cwd" : "C:\\cm",
                "waitAfterCompletion": "forever"
              }
            }
          },

さいごに

Windowsでは初期構築時に再起動が必要な事が多く面倒でしたが、これで一気に構築することが可能になりました。 Ansibleではwait_for モジュール、chefではchef_win_rebootsのようにすることでOS再起動に対応できるようなので、CloudFormationの場合はどうするのかな?と調べてみました。Windows環境もCloudFormationで一気に環境を作成できるので、試してみてください。