この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。
こんにちは。サービスグループの武田です。
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用にビルドファイルを用意します。
build-amzn2.json
{
"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用のファイルなども用意する必要があります。基本的な流れは加藤のエントリと同じです。
build-win2016.json
{
"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の最新のものが使用されます。
他に必要なファイルを用意します。
setup_winrm.txt
<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>
scripts/sysprep_winsvr2016.ps1
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を使用する方法を試してみました。
どなたかの助けになれば幸いです。