PackerでWindows Server 2019のAMIを作ってみた

2021.10.25

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

はじめに

業務でAWS環境上の新規EC2インスタンスにActiveDirectoryを導入する機会がありました。

別業務でPackerに入門したばかりだったこともあり、いい機会なのでPackerでAMIを作成してみます。

本ブログの全体の流れについては、WindowsServer2016版の検証を行なっている下記ブログを参考にしています。

Packerとは?

Packerとは、皆さんご存知のTerraformで有名なHashiCorp社が提供しているマシンイメージ自動作成ツールです。

Terraformの会社のツールということもあり、AWSを含むさまざまな環境(GCP/Azule/Docker/Vagrantなど)のマシンイメージを作成することが可能です。

実際Packerってどういうことやってるの?な説明については、コンサルティング部が誇る作図大将チバユキの図解が超絶わかりやすかったのでこちらを参照ください。

実行環境

今回は下記のような環境からお届けします。

OS(ローカルPC)

% sw_vers
ProductName:	macOS
ProductVersion:	11.6
BuildVersion:	20G165

Packerバージョン

% packer --version
1.7.6

事前準備

今回使用するテンプレートファイルはすべてGitHubにアップロードしておりますので、そちらをご利用ください。

h-ashisan/packer_winsrv2019_ad

上記リポジトリからPullするなどして、Packer実行に必要なテンプレートを準備します。

build-ad-win2019.json

{
  "variables": {
    "PROFILE": "default"
  },
  "builders": [{
    "type": "amazon-ebs",
    "profile": "{{user `PROFILE`}}",
    "region": "ap-northeast-1",
    "source_ami_filter": {
      "filters": {
        "name": "Windows_Server-2019-Japanese-Full-Base*"
      },
      "owners": ["801119661308"],
      "most_recent": true
    },
    "instance_type": "t3.micro",
    "ami_name": "windows-server-2019-{{isotime | clean_resource_name}}",
    "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": [
      "{{template_dir}}/scripts/install_ad.ps1",
      "{{template_dir}}/scripts/sysprep_winsvr2019.ps1"
    ]
  }]
}

テンプレートについての補足説明

今回記述したPackerテンプレートの説明を少ししだけします。

builders[]

EC2起動時のビルド設定をここで定義します。

builders[].source_ami_filter

builders[].most_recentの値をtrue指定することで、「Windows_Server-2019-Japanese-Full-Base*」でフィルタリングされた一覧から最新のものをSourceAMIとして選択することが可能です。

builders[].user_data_file

Packerではユーザーデータとして実行するコードをファイルからインポートすることが可能です。

今回はWinRMの設定変更を行い、実行ポリシーをBypassに変更する内容のファイルを外部ファイル(setup_winrm.txt)として使用しています。

CFnのテンプレートでよくあるユーザーデータへの直書き&テンプレート肥大化を防げるのでとても便利だな、と思いました。

builders[].tags

タグにSourceAMIのIDとAMI名を付与します。

AMIにタグをつけたら何が嬉しいのか?はこのブログが参考になります。

provisioners[]

EC2の起動後のプロビジョニング設定をここで定義します。

今回のテンプレートでは「powershell」で下記2つのスクリプトを実行させます。

  • ./scripts/install_ad.ps1
  • ./scripts/sysprep_winsvr2019.ps1

前者のスクリプトではActive Directoryをインストールし、後者のスクリプトでSysgrepを実行しています。

SysgrepはAMI等でWindowsを複製する時にSID重複防止のために新しいマシンIDを付与するツールです。

なんでSysgrepをやらなきゃいけないの?を把握するために、下記ブログが参考になりました。

EC2を起動しインスタンス上でスクリプトを実行してくれるので、本番環境でやってみたら動かないとかそういった環境差異がなさそうというとことが嬉しいポイントだな、と思いました。

やってみた

実行

準備ができたら下記コマンドでPackerを実行しましょう

packer build build-ad-win2019.json

参考までに実行ログを添付しておきます。

Builds finished.〜〜 ap-northeast-1: ami-XXXXXXXXXXXXXXXと出力されたら実行完了です。

bash-3.2$ packer build build-ad-win2019.json
amazon-ebs: output will be in this color.

==> amazon-ebs: Prevalidating any provided VPC information
==> amazon-ebs: Prevalidating AMI Name: windows-server-2019-2021-10-24T10-14-49Z
    amazon-ebs: Found Image ID: ami-XXXXXXXXXXXXXXX
==> amazon-ebs: Creating temporary keypair: packer_61753219-4dac-3afe-c973-5fc11ae1cd56
==> amazon-ebs: Creating temporary security group for this instance: packer_6175321b-97db-e99a-3014-bac250581e10
==> amazon-ebs: Authorizing access to port 5985 from [0.0.0.0/0] in the temporary security groups...
==> 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-XXXXXXXXXXXXXXX
==> amazon-ebs: Waiting for instance (i-XXXXXXXXXXXXXXX) 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: 54.238.87.249
==> amazon-ebs: Waiting for WinRM to become available...
    amazon-ebs: WinRM connected.
==> 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_winsvr2019.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
==> amazon-ebs: Waiting for the instance to stop...
==> amazon-ebs: Creating AMI windows-server-2019-2021-10-24T10-14-49Z from instance i-XXXXXXXXXXXXXXX
    amazon-ebs: AMI: ami-XXXXXXXXXXXXXXX
==> amazon-ebs: Waiting for AMI to become ready...
==> amazon-ebs: Adding tags to AMI (ami-XXXXXXXXXXXXXXX)...
==> amazon-ebs: Tagging snapshot: snap-019aeff0d7f076bd2
==> amazon-ebs: Creating AMI tags
    amazon-ebs: Adding tag: "Base_AMI_ID": "ami-XXXXXXXXXXXXXXX"
    amazon-ebs: Adding tag: "Base_AMI_NAME": "Windows_Server-2019-Japanese-Full-Base-2021.10.13"
==> amazon-ebs: Creating snapshot tags
==> amazon-ebs: Skipping Enable AMI deprecation...
==> 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 after 9 minutes 51 seconds.

==> Wait completed after 9 minutes 51 seconds

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

確認

作成したAMIからEC2インスタンスを起動し、正しくビルド、プロビジョニングできているか確認します。

  • コンソール上からAMIが作成されていること

  • AMIから作成したEC2インスタンスでActive Direcrotyがインストールされていること

まとめ

  • Packerは初心者でも簡単にAMIを自動作成できるお手軽ツール
  • IaCやメンテナンス性の観点で優れている
    • 基本的に環境定義はjsonファイル1つでOK
    • ビルド時に実行するユーザーデータについて、別ファイル管理可能
    • プロビジョニング時に実行したいシェルについて、別ファイル管理可能

おわりに

今回はPackerを実際手を動かしてみて使ってみたことでPackerを使うことで何が嬉しいのか?を身をもって実感できたことがよかっです。

皆さんもぜひPackerを使ってみてください。