EC2 Image Builder とは
- EC2 の Golden Image (AMI) を作成できるサービス
- Image の更新 / 自動化 / テスト / スケジューリングが行える
- Install する software や Test は YAML で独自に定義 (Build component)
- SSM Agent により build, test が実施される
- local system user NT AUTHORITY/Sysmte により
- build, test は SSM Automation (30個以上の) document により成り立っている
- 裏で AutoScaling が動作して build 用の EC2, test 用の EC2 が順次作成・破棄される
- その instance に SSM session 経由で login して process や進捗を確かめることも可能
- 裏で AutoScaling が動作して build 用の EC2, test 用の EC2 が順次作成・破棄される
- build, test が終わると sysprep が実行される
- Administrator の user は存在するものの、profile が無い為 home directory は存在しない
- login した時点で作成される
- 今のところ Golden Image の配布までしか実施してくれない為、ASG / EC2 への反映は別途仕組みを作る必要がある
Windows OS の Image を作成する
例えば次のような SSM Agent, Chocolatey の install, Chocolatey 経由での awscli の install を行う step を記述したとする。
phases: - name: build steps - name: InstallLatestSSMAgent action: ExecutePowerShell timeoutSeconds: 120 onFailure: Abort maxAttempts: 2 inputs: commands: - Invoke-WebRequest https://s3.amazonaws.com/ec2-downloads-windows/SSMAgent/latest/windows_amd64/AmazonSSMAgentSetup.exe -OutFile C:\Windows\temp\SSMAgent_latest.exe - C:\Windows\temp\SSMAgent_latest.exe /S - Restart-Service AmazonSSMAgent - name: InstallChocolaty action: ExecutePowerShell timeoutSeconds: 120 onFailure: Abort maxAttempts: 2 inputs: commands: - iex ((New-Object System.Net.WebClient).DownloadString('https://chocolatey.org/install.ps1')) - name: InstallAWSCLI action: ExecutePowerShell timeoutSeconds: 120 onFailure: Abort maxAttempts: 2 inputs: commands: - choco install -y awscli
Exit code was '1618' Another installation currently in progress. Try again later..
のような error を SSM Automation が出力する (※1.)。
Progress: 100% - Completed download of C:\Windows\TEMP\chocolatey\awscli\1.17.9\AWSCLI64PY3-1.17.9.msi (21.48 MB). Download of AWSCLI64PY3-1.17.9.msi (21.48 MB) completed. Hashes match. Installing awscli... WARNING: Another installation currently in progress. Try again later. ERROR: Running ["C:\Windows\System32\msiexec.exe" /i "C:\Windows\TEMP\chocolatey\awscli\1.17.9\AWSCLI64PY3-1.17.9.msi" /qn /norestart /l*v "C:\Windows\TEMP\chocolatey\awscli.1.17.9.MsiInstall.log" ] was not successful. Exit code was '1618'. Exit code indicates the following: Another installation currently in progress. Try again later.. awscli may be able to be automatically uninstalled. The install of awscli was NOT successful. Error while running 'C:\ProgramData\chocolatey\lib\awscli\tools\chocolateyinstall.ps1'. See log for details. Chocolatey installed 0/1 packages. 1 packages failed. See the log for details (C:\ProgramData\chocolatey\logs\chocolatey.log).
これは、別で何らかの installer や MSIExecute Mutex (Windows Installer) 等が動いている場合に出力される error である。個々の build step が独立した session では無いことを指し示している。
これを考慮して各々の step を process で独立・待機させる為 Start-Process -Wait
を利用する。
追記: Packer でも同事象が発生し Chocolaty の issue 1616にある通り、Chocolaty での install が不安定なのは MSI installer に対し Choco が制御を渡し、 background で MSI が install されている時に MSI がすぐレスポンスを返すことで Choco が終了したと判断し、次の処理へ移ってしまっている模様。直接 MSI 経由で install を行うのが良さそう。
commands: - Invoke-WebRequest https://s3.amazonaws.com/ec2-downloads-windows/SSMAgent/latest/windows_amd64/AmazonSSMAgentSetup.exe -OutFile C:\Windows\temp\SSMAgent_latest.exe - Start-Process -FilePath C:\Windows\temp\SSMAgent_latest.exe -ArgumentList "/S" -NoNewWindow -Wait - Restart-Service AmazonSSMAgent commands: - Start-Process 'choco' -ArgumentList "install -y awscli" -NoNewWindow -Wait
この状態で This command cannot be run due to the error: The system cannot find the file specified.
の error に遭遇する。
Debug Start executing command C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe [-InputFormat None -Noninteractive -NoProfile -ExecutionPolicy unrestricted -f C:\Windows\TEMP\AWSTOE\script-000.ps1 ; exit $LASTEXITCODE] Error [func1 @ exechandler.go.40] Start-Process : This command cannot be run due to the error: The system cannot find the file specified. At C:\Windows\TEMP\AWSTOE\script-000.ps1:1 char:1 + Start-Process 'choco' -ArgumentList "install -y awscli" -NoNewWindow ... + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + CategoryInfo : InvalidOperation: (:) [Start-Process], InvalidOperationException + FullyQualifiedErrorId : InvalidOperationException,Microsoft.PowerShell.Commands.StartProcessCommand
フルパスで exe を実行する必要があるのと、このまま aws command を別 step (同 session) で利用しようとすると command not found となる為、PATH を再読み込みする必要がある(これは Image Builder 関係なく)。
※ step で refreshenv, exit 等を行っても読み込めない。
commands: - Start-Process 'C:\ProgramData\chocolatey\bin\choco.exe' -ArgumentList "install -y awscli" -NoNewWindow -Wait - $env:Path = [System.Environment]::GetEnvironmentVariable("Path","Machine") + ";" + [System.Environment]::GetEnvironmentVariable("Path","User")
以下のように Chef を S3 から落として install する step があったとする。
- name: DownloadChefClient action: S3Download timeoutSeconds: 60 onFailure: Abort maxAttempts: 2 inputs: - source: xxx/chef-windows.msi destination: C:\Windows\temp\chef-windows.msi - name: InstallChefClient action: ExecuteBinary timeoutSeconds: 300 onFailure: Abort maxAttempts: 2 inputs: path: 'C:\Windows\System32\msiexec.exe' arguments: - "{{ build.DownloadChefClient.inputs[0].destination }}" - "/qb" - "/i"
この定義の仕方だと install 時に execution timed out してしまう (何故だ...)。
Debug Start executing command C:\Windows\System32\msiexec.exe [C:\Windows\temp\chef-windows.msi /quiet] Error [ExecuteCommands @ exechandler.go.53] command execution timed out
こちらも以下のように ExecuteBinary
を諦め process を独立させて wait するようにした。
- name: InstallChefClient action: ExecutePowerShell timeoutSeconds: 300 onFailure: Abort maxAttempts: 2 inputs: commands: - Start-Process "msiexec" -ArgumentList "/qb /i {{ build.DownloadChefClient.inputs[0].destination }}" -NoNewWindow -Wait
Chef の recipe 実行時は次のように ruby.exe
が not recognized とのことで、再度パスの読み込みを行った。
Error [func1 @ exechandler.go.40] '"ruby.exe"' is not recognized as an internal or external command, operable program or batch file.
- name: ApplyChefRecipes action: ExecutePowerShell timeoutSeconds: 300 onFailure: Abort maxAttempts: 2 inputs: commands: - $env:Path = [System.Environment]::GetEnvironmentVariable("Path","Machine") + ";" + [System.Environment]::GetEnvironmentVariable("Path","User") - Start-Process "C:\opscode\chef\bin\chef-client.bat" -ArgumentList "-r 'role[xxx]'" -NoNewWindow -Wait
Packer で上記を実施すると、 EC2 Image Builder で行っている上記のようなことを行わず素直に Build が成功する為、やはりまだ不安定さが拭えない Image Builder よりも現状は枯れた技術を採用した方が良さそうだった (Windows OS に限っては)。
※1. user_data の出力は C:\ProgramData\Amazon\EC2-Windows\Launch\Log\UserdataExecution.log
で確認が可能。