Packerで作成したWebサーバAMIをTerraformで構築する

やりたいこと

  1. PackerでAmazon AMIを作成する
    • 下図の左側に示すように、jsonファイルを用意し、Packerを実行してAMIを作成する
    • 今回作成するAMIは、HTTPアクセスすると任意のメッセージを表示するApacheプロセスが自動起動するという簡単なもの
  2. TerraformでEC2インスタンスを起動する
    • 下図の右側に示すように、Packerで作成したAMIを使ってEC2インスタンスを構築するtfファイルを作り、Terraformを実行する

検証環境

  • Packer: v1.3.4
  • Terraform: v0.11.11
  • AWSリージョン: ap-northeast-1(東京)

前準備:IAMでAPI実行用のグループとユーザを作成

まずはIAMグループページでグループを作成。グループ名は任意でOK

今回の検証ではEC2のみの利用であるため、必要なポリシーは「AmazonEC2FullAccess」のみ

次にIAMユーザページでユーザを作成。ユーザ名は任意でOK。アクセスの種類は「プログラムによるアクセス」を選択

先程作成したグループをこのユーザに適用する

タグはなんでもよいが「Name」タグを作っておくのが一般的。

最後に「アクセスキー ID」と「シークレットアクセスキー」が表示される。この二つのキーを忘れずに控えておくこと

PackerでAMI作成

jsonファイル作成

以下のjsonファイルを作成する

今回の例ではファイル名は「simple-http-ami.json」としている

後半の”provisioners”句で、Apacheをインストールして、ドキュメントルートに任意のメッセージが書かれたテキストファイルを配置して、自動起動を有効化している

{
    "variables": {
        "aws_access_key": "{{env `AWS_ACCESS_KEY_ID`}}",
        "aws_secret_key": "{{env `AWS_SECRET_ACCESS_KEY`}}",
        "region":         "ap-northeast-1"
    },
    "builders": [
        {
            "access_key": "{{user `aws_access_key`}}",
            "ami_name": "packer-linux-aws-demo-{{timestamp}}",
            "instance_type": "t2.micro",
            "region": "{{user `region`}}",
            "secret_key": "{{user `aws_secret_key`}}",
            "source_ami_filter": {
              "filters": {
                  "name": "amzn2-ami-hvm-*-x86_64-gp2"
              },
              "owners": ["137112412989"],
              "most_recent": true
            },
            "ssh_username": "ec2-user",
            "type": "amazon-ebs"
        }
    ],
    "provisioners": [{
        "type": "shell",
        "inline": [
            "sleep 30",
            "sudo yum -y install httpd",
            "sudo bash -c \"echo 'This is a simple web page.<br/>The AMI is created by Packer and this server is built by Terraform.' >> /var/www/html/index.html\"",
            "sudo systemctl enable httpd"
        ]
    }]
}

jsonファイルの構文チェック

packer validate コマンドを使って構文チェックする

「Template validated successfully.」と表示されればOK

$ packer validate simple-http-ami.json
Template validated successfully.

AMI作成

まずはアクセスキー等を環境変数に設定する

$ export AWS_ACCESS_KEY_ID=[アクセスキーID]
$ export AWS_SECRET_ACCESS_KEY=[シークレットアクセスキー]

packer build コマンドでAMIを作成する

$ packer build simple-http-ami.json
(中略)
==> Builds finished. The artifacts of successful builds are:
--> amazon-ebs: AMIs were created:
ap-northeast-1: ami-0b8314be1d52e879e

成功すれば、最後の行にがAMI IDが表示される

TerraformでEC2インスタンス構築

tfファイル作成

「simple-http-instance.tf」ファイルを作成し、以下の内容を記述する

(この記事ではEC2インスタンスのみ構築する方法を記載している。一応これだけでもインスタンスは作成される。しかし本来はVPCやサブネット、セキュリティグループを作成する必要がある。VPC等を含めたterraformのコードについてはこちらを参考にしてほしい)

variable "access_key" {}
variable "secret_key" {}
variable "ami" {}
 
provider "aws" {
    access_key = "${var.access_key}"
    secret_key = "${var.secret_key}"
    region = "ap-northeast-1"
}
 
resource "aws_instance" "app_main" {
    ami           = "${var.ami}"
    associate_public_ip_address = "true"
    instance_type = "t2.micro"
 
    tags = {
        Name = "simple http instance"
    }
}
 
output "public_ip" {
  value = "${aws_instance.app_main.public_ip}"
}

Terraform実行確認

まずは環境変数を設定する

$ export TF_VAR_access_key=[アクセスキーID]
$ export TF_VAR_secret_key=[シークレットアクセスキー]
$ export TF_VAR_ami=ami-0b8314be1d52e879e (先程Packerで作成したAMI)

terraform plan コマンドで実行内容を確認する

$ terraform plan
Refreshing Terraform state in-memory prior to plan...
(中略)
Plan: 1 to add, 0 to change, 0 to destroy.

Terraform実行

teffaform apply コマンドでEC2インスタンスを構築する

$ terraform apply
(中略)
Plan: 1 to add, 0 to change, 0 to destroy.
 
Do you want to perform these actions?
  Terraform will perform the actions described above.
  Only 'yes' will be accepted to approve.
 
  Enter a value: yes
(中略)
Apply complete! Resources: 1 added, 0 changed, 0 destroyed.
 
Outputs:
 
public_ip = x.x.x.x

起動したEC2インスタンスはデフォルトのセキュリティグループが適用されている。デフォルトのセキュリティグループにて、検証環境から80番ポートのアクセスを許可し、ブラウザでアクセスすると以下の文言が記載されたWebページが表示される。

This is a simple web page.
The AMI is created by Packer and this server is built by Terraform.