Packerで最新のイメージを使用してAMIを作成する(Amazon Linux 2/Windows Server 2016対応)
こんにちは。サービスグループの武田です。
Packer使ってますか?ゴールデンイメージを簡単に作れて便利ですよね。Packerって何?という方は大瀧のエントリを参考にしてください。
今回はPackerで、「その時の最新のイメージ」を利用してAMIを作成する方法を試してみたので紹介します。また試したのはAmazon Linux 2
とWindows Server 2016
となります。その他の環境についてもできるはずですのでぜひやってみてください。
環境
次の環境で検証しています。
$ sw_vers ProductName: Mac OS X ProductVersion: 10.13.6 BuildVersion: 17G65 $ packer version Packer v1.3.1 $ aws --version aws-cli/1.16.21 Python/3.7.0 Darwin/17.7.0 botocore/1.12.11 $ jq --version jq-1.5
またAWS CLI用のdefault
プロファイルが設定されています。
ファイルの用意
それではそれぞれのOS用のビルドファイルを作成していきます。なおビルドするタイミングによって最新のAMIが変わるため、タグにどのAMIをベースとしたのか残すようにしておきます。こちらについては吉江が記事を書いています。
Amazon Linux 2
まずはAmazon Linux 2用にビルドファイルを用意します。
{ "variables": { "PROFILE": "default" }, "builders": [{ "type": "amazon-ebs", "profile": "{{user `PROFILE`}}", "region": "ap-northeast-1", "source_ami_filter": { "filters": { "name": "amzn2-ami-hvm-*-x86_64-gp2" }, "owners": ["137112412989"], "most_recent": true }, "instance_type": "t3.micro", "ssh_username": "ec2-user", "ssh_timeout": "5m", "ami_name": "amazon-linux-2-{{timestamp}}", "tags": { "Base_AMI_ID": "{{ .SourceAMI }}", "Base_AMI_NAME": "{{ .SourceAMIName }}" } }], "provisioners": [{ "type": "shell", "inline": [ "sudo yum update -y" ] }] }
ポイントはbuilders[].source_ami_filter
です。filters.name
にamzn2-ami-hvm-*-x86_64-gp2
と日付などが入る部分をワイルドカードとし、most_recent
にtrue
を指定します。こうすることで自動的にマッチするAMIの最新のものが使用されます。
Windows Server 2016
続いて同様のファイルをWindows Server 2016でも準備します。Windows Server 2016の場合、ビルドファイルだけではなくSysprep用のファイルなども用意する必要があります。基本的な流れは加藤のエントリと同じです。
{ "variables": { "PROFILE": "default" }, "builders": [{ "type": "amazon-ebs", "profile": "{{user `PROFILE`}}", "region": "ap-northeast-1", "source_ami_filter": { "filters": { "name": "Windows_Server-2016-Japanese-Full-Base-*" }, "owners": ["801119661308"], "most_recent": true }, "instance_type": "t3.micro", "ami_name": "Windows_Server-2016-Japanese-{{timestamp}}", "user_data_file": "{{template_dir}}/setup_winrm.txt", "tags": { "Base_AMI_ID": "{{ .SourceAMI }}", "Base_AMI_NAME": "{{ .SourceAMIName }}" }, "communicator": "winrm", "winrm_username": "Administrator" }], "provisioners": [{ "type": "powershell", "scripts": [ "scripts/sysprep_winsvr2016.ps1" ] }] }
ポイントは先ほどと同じくbuilders[].source_ami_filter
です。filters.name
にWindows_Server-2016-Japanese-Full-Base-*
と日付などが入る部分をワイルドカードとし、most_recent
にtrue
を指定します。こうすることで自動的にマッチするAMIの最新のものが使用されます。
他に必要なファイルを用意します。
<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>
C:\ProgramData\Amazon\EC2-Windows\Launch\Scripts\InitializeInstance.ps1 -Schedule C:\ProgramData\Amazon\EC2-Windows\Launch\Scripts\SysprepInstance.ps1
ビルドしてみる
それではそれぞれ準備ができたので実際にビルドしてAMIを作成してみましょう。
まずはAmazon Linux 2から。
$ packer build build-amzn2.json amazon-ebs output will be in this color. ==> amazon-ebs: Prevalidating AMI Name: amazon-linux-2-1538123173 amazon-ebs: Found Image ID: ami-08847abae18baa040 ==> amazon-ebs: Creating temporary keypair: packer_5bade5a5-1a8e-11d8-253c-cda50d4d8a47 ==> amazon-ebs: Creating temporary security group for this instance: packer_5bade5a7-3870-a8f6-55ab-00937fb87047 ==> amazon-ebs: Authorizing access to port 22 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-00e78919f5fc637eb ==> amazon-ebs: Waiting for instance (i-00e78919f5fc637eb) to become ready... ==> amazon-ebs: Using ssh communicator to connect: 13.230.41.126 ==> amazon-ebs: Waiting for SSH to become available... ==> amazon-ebs: Connected to SSH! ==> amazon-ebs: Provisioning with shell script: /var/folders/v9/hpwnqvc94fqc23jdh8w9b30r0000gp/T/packer-shell682948240 amazon-ebs: Loaded plugins: extras_suggestions, langpacks, priorities, update-motd amazon-ebs: Existing lock /var/run/yum.pid: another copy is running as pid 2462. amazon-ebs: Another app is currently holding the yum lock; waiting for it to exit... amazon-ebs: The other application is: yum amazon-ebs: Memory : 92 M RSS (383 MB VSZ) amazon-ebs: Started: Fri Sep 28 08:26:35 2018 - 00:04 ago amazon-ebs: State : Running, pid: 2462 amazon-ebs: Existing lock /var/run/yum.pid: another copy is running as pid 2474. amazon-ebs: Another app is currently holding the yum lock; waiting for it to exit... amazon-ebs: The other application is: yum amazon-ebs: Memory : 76 M RSS (295 MB VSZ) amazon-ebs: Started: Fri Sep 28 08:26:35 2018 - 00:07 ago amazon-ebs: State : Running, pid: 2474 amazon-ebs: Resolving Dependencies amazon-ebs: --> Running transaction check amazon-ebs: ---> Package GeoIP.x86_64 0:1.5.0-11.amzn2 will be updated amazon-ebs: ---> Package GeoIP.x86_64 0:1.5.0-11.amzn2.0.2 will be an update 〜中略〜 amazon-ebs: zip.x86_64 0:3.0-11.amzn2.0.2 amazon-ebs: zlib.x86_64 0:1.2.7-17.amzn2.0.2 amazon-ebs: amazon-ebs: Complete! ==> amazon-ebs: Stopping the source instance... amazon-ebs: Stopping instance, attempt 1 ==> amazon-ebs: Waiting for the instance to stop... ==> amazon-ebs: Creating unencrypted AMI amazon-linux-2-1538123173 from instance i-00e78919f5fc637eb amazon-ebs: AMI: ami-0a249cc29bf0094f8 ==> amazon-ebs: Waiting for AMI to become ready... ==> amazon-ebs: Adding tags to AMI (ami-0a249cc29bf0094f8)... ==> amazon-ebs: Tagging snapshot: snap-09ae9e836c78840d1 ==> amazon-ebs: Creating AMI tags amazon-ebs: Adding tag: "Base_AMI_ID": "ami-08847abae18baa040" amazon-ebs: Adding tag: "Base_AMI_NAME": "amzn2-ami-hvm-2.0.20180810-x86_64-gp2" ==> amazon-ebs: Creating snapshot tags ==> 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-0a249cc29bf0094f8
成功したみたいです。同様にWindows Server 2016もビルドしてみます。
$ packer build build-win2016.json amazon-ebs output will be in this color. ==> amazon-ebs: Prevalidating AMI Name: Windows_Server-2016-Japanese-1538123950 amazon-ebs: Found Image ID: ami-001b1a5edbc1aa135 ==> amazon-ebs: Creating temporary keypair: packer_5bade8ae-e76f-44de-5938-ef9a43f40902 ==> amazon-ebs: Creating temporary security group for this instance: packer_5bade8b1-9938-ac28-b167-237113adcd2b ==> 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-0daddbf70f1377afa ==> amazon-ebs: Waiting for instance (i-0daddbf70f1377afa) 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: Using winrm communicator to connect: 18.179.58.253 ==> amazon-ebs: Waiting for WinRM to become available... amazon-ebs: #< CLIXML amazon-ebs: WinRM connected. 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/sysprep_winsvr2016.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 unencrypted AMI Windows_Server-2016-Japanese-1538123950 from instance i-0daddbf70f1377afa amazon-ebs: AMI: ami-0af559687a3b3c270 ==> amazon-ebs: Waiting for AMI to become ready... ==> amazon-ebs: Adding tags to AMI (ami-0af559687a3b3c270)... ==> amazon-ebs: Tagging snapshot: snap-003f8e7ce7a2957d9 ==> amazon-ebs: Creating AMI tags amazon-ebs: Adding tag: "Base_AMI_ID": "ami-001b1a5edbc1aa135" amazon-ebs: Adding tag: "Base_AMI_NAME": "Windows_Server-2016-Japanese-Full-Base-2018.09.15" ==> amazon-ebs: Creating snapshot tags ==> 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-0af559687a3b3c270
Windows Server 2016も問題ないですね。それでは作成できたAMIを確認してみます。
$ aws ec2 describe-images --owner self | jq 'del(.Images[] | .BlockDeviceMappings)' { "Images": [ { "Architecture": "x86_64", "CreationDate": "2018-09-28T08:28:17.000Z", "ImageId": "ami-0a249cc29bf0094f8", "ImageLocation": "123456789012/amazon-linux-2-1538123173", "ImageType": "machine", "Public": false, "OwnerId": "123456789012", "State": "available", "EnaSupport": true, "Hypervisor": "xen", "Name": "amazon-linux-2-1538123173", "RootDeviceName": "/dev/xvda", "RootDeviceType": "ebs", "SriovNetSupport": "simple", "Tags": [ { "Key": "Base_AMI_ID", "Value": "ami-08847abae18baa040" }, { "Key": "Base_AMI_NAME", "Value": "amzn2-ami-hvm-2.0.20180810-x86_64-gp2" } ], "VirtualizationType": "hvm" }, { "Architecture": "x86_64", "CreationDate": "2018-09-28T08:49:12.000Z", "ImageId": "ami-0af559687a3b3c270", "ImageLocation": "123456789012/Windows_Server-2016-Japanese-1538123950", "ImageType": "machine", "Public": false, "OwnerId": "123456789012", "Platform": "windows", "State": "available", "EnaSupport": true, "Hypervisor": "xen", "Name": "Windows_Server-2016-Japanese-1538123950", "RootDeviceName": "/dev/sda1", "RootDeviceType": "ebs", "SriovNetSupport": "simple", "Tags": [ { "Key": "Base_AMI_ID", "Value": "ami-001b1a5edbc1aa135" }, { "Key": "Base_AMI_NAME", "Value": "Windows_Server-2016-Japanese-Full-Base-2018.09.15" } ], "VirtualizationType": "hvm" } ] }
タグも付与されていてバッチリですね!
まとめ
わざわざAMIが更新されたかチェックし、更新されていたらビルドファイルを修正する。なんてことをしたくなかったで、常に最新のAMIを使用する方法を試してみました。
どなたかの助けになれば幸いです。