ぺい

渋谷系アドテクエンジニアの落書き

PackerでAWS AMIを自動で作成する

AWS AMIの管理は面倒

AWSでEC2(IaaS)使ったアプリケーションを構築する時に、AMIの管理が地味に面倒です。例えば、AWS側から提供されているAMIをそのまま使うと、OSがデフォルトに近い状態なので、アプリケーションの実行に必要なものを準備する必要があります。

そこで、実行するために必要な準備を完了させているAMIを作成して、それを使ってインスタンスを作成して、アプリケーションコードを反映するだけで、すぐに使える状態にするということをします。

ただ、これをするのが地味に面倒です。やり方とかは以下の記事に詳しくあります。 tikasan.hatenablog.com

ざっくりいうと、出来上がってるインスタンスからスナップショットを作成して、スナップショットからAMIを作成して、AMIを使ってインスタンスを作成するという手順を踏む必要があります。

これらを自動でやってくれるのが、Packerです。

Packerとは

f:id:tikasan0804:20180621205204p:plain

AWSマネジメントコンソールを使わず、AMIの作成の手順を単純化してくれます。また、プロビジョニング機能があったり、並列実行が出来たりするそうです。

アーティファクト

Packerは最終生成物として、アーティファクトを作成します。アーティファクトとは、Packer独自の抽象化されたマシンイメージの概念のことです。
AWSでいうところのAMIやAMI IDや管理情報。 アーティファクトの作成には、以下の機能を使って作成することができます。(番号は実行順序です)

  1. ビルダー(builder)
    マシンイメージの生成。JSONでテンプレートを定義し、自動で良い感じにしてくれる
  2. プロビジョナー(provisioner)
    マシンイメージ内のミドルウェアやアプリケーションのインストールや設定などを行う。ここではシェルスクリプトはもちろんChefなどの構成管理ツールを実行することもできます
  3. ポスト・プロセッサー(post-processor
    ここでは、最終的な生成物をどうするかということをやる(圧縮とかアップロードとか)

実際にやってみる

インストールはここ見ればわかる Install Packer - Getting Started - Packer by HashiCorp

$ touch hello_ami.json
{
  "variables": {
    "aws_access_key": "hoge",
    "aws_secret_key": "fuga"
  },
  "builders": [
    {
      "type": "amazon-ebs",
      "access_key": "{{user `aws_access_key`}}",
      "secret_key": "{{user `aws_secret_key`}}",
      "region": "ap-northeast-1",
      "source_ami": "ami-06128816a1c781a57",
      "instance_type": "t2.micro",
      "ssh_username": "root",
      "ami_name": "hello_ami {{timestamp}}"
    }
  ]
}
❯ packer build hello_ami.json
amazon-ebs output will be in this color.

==> amazon-ebs: Prevalidating AMI Name: hello_ami 1529395142
    amazon-ebs: Found Image ID: ami-06128816a1c781a57
==> amazon-ebs: Creating temporary keypair: packer_5b28b7c6-9716-5682-837a-45051c4baae6
==> amazon-ebs: Creating temporary security group for this instance: packer_5b28b7c7-913b-2b6d-fa7d-f2dcf8a51770
==> 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-0284843a27b02a39c
==> amazon-ebs: Waiting for instance (i-0284843a27b02a39c) to become ready...
==> amazon-ebs: Waiting for SSH to become available...
==> amazon-ebs: Connected to SSH!
==> 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: hello_ami 1529395142
    amazon-ebs: AMI: ami-02749c4f55b57389c
==> 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-02749c4f55b57389c

f:id:tikasan0804:20180619171155p:plain AMIが作成できました!便利すぎる!w

f:id:tikasan0804:20180619171442p:plain 作成するために使ったEC2インスタンスは自動的に削除までされています。

www.packer.io とりあえず、雑に作成しましたが、Builderに必要な権限やクレデンシャルの設定方法は公式見れば分かります。

プロビジョニングは以下のような感じで軽く書ける。

{
  "variables": {
    "aws_access_key": "hoge",
    "aws_secret_key": "fuga"
  },
  "builders": [
    {
      "type": "amazon-ebs",
      "access_key": "{{user `aws_access_key`}}",
      "secret_key": "{{user `aws_secret_key`}}",
      "region": "ap-northeast-1",
      "source_ami": "ami-06128816a1c781a57",
      "instance_type": "t2.micro",
      "ssh_username": "root",
      "ami_name": "hello_ami {{timestamp}}"
    }
  ],
  "provisioners": [
    {
      "type": "shell",
      "inline": [
        "sleep 30",
        "sudo apt-get update",
        "sudo apt-get install -y redis-server"
      ]
    }
  ]
}

sleep30を最初に書く理由は、ちょっと準備出来るまで余裕ほしいという文脈らしい。なるほど。 www.packer.io

AMI作成自動化最高。