PackerでWindows Server 2016のAMIを作成してみた

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

おはようございます、加藤です。

業務でActive Directoryを使う必要があったのでPackerでAMIとして作成してみました。

Packerのインストール

使っている端末がMacなのでHomebrewでインストールしました。使用するPackerのバージョンは1.2.2です。

brew install packer
packer --version
# 1.2.2

作ったもの

今回作成した物をGitHubへアップしておきました。

kmd2kmd/packer-winsrv2016-on-aws: Windows Server 2016 に Active Directory をインストールしたAMIを作成する

説明

{
 "builders": [{
 "type": "amazon-ebs",
 "profile": "default",
 "region": "ap-northeast-1",
 "source_ami": "ami-07f2a061",
 "instance_type": "t2.large",
 "ami_name": "Windows_Server-2016-Japanese-Full-Base-Active_Directory-{{timestamp}}",
 "user_data_file": "{{template_dir}}/setup_winrm.txt",
 
 "communicator": "winrm",
 "winrm_username": "Administrator"
 }],
 
 "provisioners": [
 {
 "type": "powershell",
 "scripts": [
 "Scripts/install_ad.ps1",
 "Scripts/sysprep_winsrv2016.ps1"
 ]
 }
 ]
}

Packerのテンプレートファイルです。

特に重要なのは、"user_data_file"と"provisioners"です。

user_data_file ではUserDataを設定しています。

<powershell>
winrm quickconfig -q
winrm set winrm/config/winrs '@{MaxMemoryPerShellMB="300"}'
winrm set winrm/config '@{MaxTimeoutms="1800000"}'
winrm set winrm/config/service '@{AllowUnencrypted="true"}'
winrm set winrm/config/service/auth '@{Basic="true"}'
 
netsh advfirewall firewall add rule name="WinRM 5985" protocol=TCP dir=in localport=5985 action=allow
netsh advfirewall firewall add rule name="WinRM 5986" protocol=TCP dir=in localport=5986 action=allow
 
net stop winrm
sc config winrm start=auto
net start winrm
 
Set-ExecutionPolicy -ExecutionPolicy Bypass -Scope LocalMachine
</powershell>

WinRMを有効化して、PowerShellの実行ポリシーをBypassに変更しています。

scriptsでActive Directory のインストールとSysprepを行うPowerShellスクリプトを呼び出しています。

Install-WindowsFeature AD-Domain-Services,GPMC -IncludeManagementTools -restart
Add-WindowsFeature RSAT-ADDS
Import-Module ADDSDeployment
C:\ProgramData\Amazon\EC2-Windows\Launch\Scripts\InitializeInstance.ps1 -Schedule
C:\ProgramData\Amazon\EC2-Windows\Launch\Scripts\SysprepInstance.ps1

Active Directoryのインストールは下記のページを参考にしました。

Setting up Active Directory via PowerShell – TechNet UK Blog

Sysprepの実行は下記のページを参考にしました。

EC2Launch を使用した Windows インスタンスの設定 - Amazon Elastic Compute Cloud

動かしてみた

packer build build.json
amazon-ebs output will be in this color.

==> amazon-ebs: Prevalidating AMI Name: Windows_Server-2016-Japanese-Full-Base-Active_Directory-1522285155
    amazon-ebs: Found Image ID: ami-07f2a061
==> amazon-ebs: Creating temporary keypair: packer_5abc3a63-61bf-c782-4ebe-b56e75129762
==> amazon-ebs: Creating temporary security group for this instance: packer_5abc3a66-3a3e-e671-77bc-fd07de9aedf8
==> amazon-ebs: Authorizing access to port 5985 from 0.0.0.0/0 in the temporary security group...
==> amazon-ebs: Launching a source AWS instance...
==> amazon-ebs: Adding tags to source instance
    amazon-ebs: Adding tag: "Name": "Packer Builder"
    amazon-ebs: Instance ID: i-0451aae7c35a7c1e1
==> amazon-ebs: Waiting for instance (i-0451aae7c35a7c1e1) to become ready...
==> amazon-ebs: Waiting for auto-generated password for instance...
    amazon-ebs: It is normal for this process to take up to 15 minutes,
    amazon-ebs: but it usually takes around 5. Please wait.
    amazon-ebs:
    amazon-ebs: Password retrieved!
==> amazon-ebs: Waiting for WinRM to become available...
    amazon-ebs: WinRM connected.
    amazon-ebs: #< CLIXML
    amazon-ebs: <Objs Version="1.1.0.1" xmlns="http://schemas.microsoft.com/powershell/2004/04"><Obj S="progress" RefId="0"><TN RefId="0"><T>System.Management.Automation.PSCustomObject</T><T>System.Object</T></TN><MS><I64 N="SourceId">1</I64><PR N="Record"><AV>Preparing modules for first use.</AV><AI>0</AI><Nil /><PI>-1</PI><PC>-1</PC><T>Completed</T><SR>-1</SR><SD> </SD></PR></MS></Obj><Obj S="progress" RefId="1"><TNRef RefId="0" /><MS><I64 N="SourceId">1</I64><PR N="Record"><AV>Preparing modules for first use.</AV><AI>0</AI><Nil /><PI>-1</PI><PC>-1</PC><T>Completed</T><SR>-1</SR><SD> </SD></PR></MS></Obj></Objs>
==> amazon-ebs: Connected to WinRM!
==> amazon-ebs: Provisioning with Powershell...
==> amazon-ebs: Provisioning with powershell script: Scripts/install_ad.ps1
    amazon-ebs:
    amazon-ebs: Success Restart Needed Exit Code      Feature Result
    amazon-ebs: ------- -------------- ---------      --------------
    amazon-ebs: True    No             Success        {Active Directory ドメイン サービス, グループ ポリシーの管理,...
    amazon-ebs: True    No             NoChangeNeeded {}
==> amazon-ebs: Provisioning with powershell script: Scripts/sysprep_winsrv2016.ps1
    amazon-ebs:
    amazon-ebs: TaskPath                                       TaskName                          State
    amazon-ebs: --------                                       --------                          -----
    amazon-ebs: \                                              Amazon Ec2 Launch - Instance I... Ready
==> amazon-ebs: Stopping the source instance...
    amazon-ebs: Stopping instance, attempt 1
==> amazon-ebs: Waiting for the instance to stop...
==> amazon-ebs: Creating the AMI: Windows_Server-2016-Japanese-Full-Base-Active_Directory-1522285155
    amazon-ebs: AMI: ami-********
==> amazon-ebs: Waiting for AMI to become ready...
==> amazon-ebs: Terminating the source AWS instance...
==> amazon-ebs: Cleaning up any extra volumes...
==> amazon-ebs: No volumes to clean up, skipping
==> amazon-ebs: Deleting temporary security group...
==> amazon-ebs: Deleting temporary keypair...
Build 'amazon-ebs' finished.

==> Builds finished. The artifacts of successful builds are:
--> amazon-ebs: AMIs were created:
ap-northeast-1: ami-********

正常に作成が完了しました!確認してみます。

aws ec2 describe-images --owners self | jq '.Images[] | {Name, ImageId}'
{
 "Name": "Windows_Server-2016-Japanese-Full-Base-Active_Directory-1522285155",
 "ImageId": "ami-********"
}

AMIが認識されていました!

このAMIからEC2インスタンスを作成しActive Directoryがインストールされていることも確認できました。

起動直後はWindowsのライセンス認証が失敗していましたが、起動後5分程度で自動的に認証されました。もしうまくいかない場合は下記のページが参考になりそうです。

一般的なメッセージ - Amazon Elastic Compute Cloud

参考

あとがき

簡単にActive Directoryを構築・破棄したかったのでAMI化しました。ScriptsのPowerShellを追加すれば、他のWindowsの機能にも簡単に対応できそうですね。

テストが手動なのがイケてないですね...自動化したいです。さらに下記のページを参考にCodeBuildを活用して実行できるようにすればもっといい感じにできそうです。

AWS CodeBuild と HashiCorp Packer を用いた AMI ビルダーの構築方法 | Amazon Web Services ブログ

今回はAMI作成がメインではないので、ここで切り上げます。