Packerを利用してECS Container Instance向けのゴールデンイメージを作る

Packerを利用して、AWS ECSで利用するECS Container Instance向けのゴールデンイメージ(つまりami)を作成します。

環境情報

  • Windows 10.0.18362 N/A ビルド 18362
  • Packer v1.4.5

Packerのインストール

WindowsユーザはChocolateyを利用してインストールできます。

> choco install -y packer
> packer version
Packer v1.4.5

Packer Install Options

AWS IAMユーザの作成

Packerを実行する時に利用するIAMユーザを作成します。利用するIAMユーザで必要となるIAMポリシーは下記となります。

{
  "Version": "2012-10-17",
  "Statement": [{
    "Effect": "Allow",
    "Action" : [
      "ec2:AttachVolume",
      "ec2:AuthorizeSecurityGroupIngress",
      "ec2:CopyImage",
      "ec2:CreateFleet",
      "ec2:CreateImage",
      "ec2:CreateKeypair",
      "ec2:CreateLaunchTemplate",
      "ec2:CreateSecurityGroup",
      "ec2:CreateSnapshot",
      "ec2:CreateTags",
      "ec2:CreateVolume",
      "ec2:DeleteKeyPair",
      "ec2:DeleteLaunchTemplate",
      "ec2:DeleteSecurityGroup",
      "ec2:DeleteSnapshot",
      "ec2:DeleteVolume",
      "ec2:DeregisterImage",
      "ec2:DescribeImageAttribute",
      "ec2:DescribeImages",
      "ec2:DescribeInstances",
      "ec2:DescribeInstanceStatus",
      "ec2:DescribeRegions",
      "ec2:DescribeSecurityGroups",
      "ec2:DescribeSnapshots",
      "ec2:DescribeSpotPriceHistory",
      "ec2:DescribeSubnets",
      "ec2:DescribeTags",
      "ec2:DescribeVolumes",
      "ec2:DetachVolume",
      "ec2:GetPasswordData",
      "ec2:ModifyImageAttribute",
      "ec2:ModifyInstanceAttribute",
      "ec2:ModifySnapshotAttribute",
      "ec2:RegisterImage",
      "ec2:RunInstances",
      "ec2:StopInstances",
      "ec2:TerminateInstances"
  ],
    "Resource" : "*"
  }]
}

IAM Task or Instance Role

作成されたIAMユーザのクレデンシャル情報をメモっておきます。

AMIの作成(Packerの実行)

PackerによるAMIの作成方法ですが、デフォルトVPC上に一時的なEC2を作成して、AMIを自動的に取得される、というものになります。

This builder builds an AMI by launching an EC2 instance from a source AMI, provisioning that running machine, and then creating an AMI from that machine. This is all done in your own AWS account. The builder will create temporary keypairs, security group rules, etc. that provide it temporary access to the instance while the image is being created.

テンプレートの作成

Vagrantのように、Packer向けテンプレートファイルを用意する必要があります。なお、今回作成するAMIでは、デフォルトのECS Container Instanceのイメージに対して、以下の処理を追加しています。

  • yum update
  • Cloudwatch Agentインストール&設定
  • SSM Agentインストール
  • Inspector Agentインストール

それを踏まえて、今回用意したファイルは下記です。

フォルダ構成

.                                   
├── ecs-container-instance.json
├── cloudwatch-agent
│   └── amazon-cloudwatch-agent.json
└── script
    └── setup.sh

ecs-container-instance.json

Packerのテンプレートファイル。

{
  "description": "packer template for ecs-container-instance's ami",
  "min_packer_version": "1.4.5",
  "variables": {
    "aws_access_key": "",
    "aws_secret_key": ""
  },
  "builders": [
    {
      "type": "amazon-ebs",
      "access_key": "{{user `aws_access_key`}}",
      "secret_key": "{{user `aws_secret_key`}}",
      "region": "ap-northeast-1",
      "source_ami": "ami-0934e28fe3e390537",
      "instance_type": "t2.micro",
      "ssh_username": "ec2-user",
      "ami_name": "ecs-container-instance-{{isotime | clean_resource_name}}",
      "ami_description": "Amazon Linux AMI 2.0.20191114 x86_64 ECS HVM GP2",
      "tags": {
        "Name": "ecs-container-instance-{{isotime | clean_resource_name}}"
      }
    }
  ],
  "provisioners": [
    {
      "type": "file",
      "source": "./cloudwatch-agent/amazon-cloudwatch-agent.json",
      "destination": "/home/ec2-user/"
    },
    {
      "type": "shell",
      "scripts": [
        "./script/setup.sh"
      ]
    }
  ]
}

cloudwatch-agent/amazon-cloudwatch-agent.json

Cloudwatch Agentの設定ファイル。

{
  "agent": {
    "logfile": "/opt/aws/amazon-cloudwatch-agent/logs/amazon-cloudwatch-agent.log"
  },
  "logs": {
    "logs_collected": {
      "files": {
        "collect_list": [
          {
            "file_path": "/opt/aws/amazon-cloudwatch-agent/logs/amazon-cloudwatch-agent.log",
            "log_group_name": "/opt/aws/amazon-cloudwatch-agent/logs/amazon-cloudwatch-agent",
            "log_stream_name": "{instance_id}",
            "timezone": "Local"
          },
          {
            "file_path": "/var/log/dmesg",
            "log_group_name": "/var/log/dmesg",
            "log_stream_name": "{instance_id}",
            "timezone": "Local"
          },
          {
            "file_path": "/var/log/messages",
            "log_group_name": "/var/log/messages",
            "log_stream_name": "{instance_id}",
            "timezone": "Local"
          },
          {
            "file_path": "/var/log/ecs/ecs-init.log",
            "log_group_name": "/var/log/ecs/ecs-init",
            "log_stream_name": "{instance_id}",
            "timezone": "Local"
          },
          {
            "file_path": "/var/log/ecs/ecs-agent.log",
            "log_group_name": "/var/log/ecs/ecs-agent",
            "log_stream_name": "{instance_id}",
            "timezone": "Local"
          },
          {
            "file_path": "/var/log/ecs/audit.log",
            "log_group_name": "/var/log/ecs/audit",
            "log_stream_name": "{instance_id}",
            "timezone": "Local"
          }
        ]
      }
    },
    "force_flush_interval" : 15
  }
}

script/setup.sh

OS初期設定用シェルスクリプト

#!/bin/sh

cluster_name=smple

sudo yum update -y
sudo yum install -y awscli wget
sudo yum clean all

## Setting ecs-config
sudo sh -c "echo ECS_CLUSTER=${cluster_name} >> /etc/ecs/ecs.config"

# Setting SystemClock
sudo sh -c "cat > /etc/sysconfig/clock" << __EOF__
ZONE="Asia/Tokyo"
UTC=false
__EOF__

# Setting TimeZone
sudo /bin/cp -fp /usr/share/zoneinfo/Asia/Tokyo /etc/localtime

# Install Cloudwatch Agent
wget https://s3.amazonaws.com/amazoncloudwatch-agent/amazon_linux/amd64/latest/amazon-cloudwatch-agent.rpm
sudo rpm -U ./amazon-cloudwatch-agent.rpm
sudo /opt/aws/amazon-cloudwatch-agent/bin/amazon-cloudwatch-agent-ctl -a fetch-config -m ec2 -c file:/home/ec2-user/amazon-cloudwatch-agent.json -s
sudo systemctl restart amazon-cloudwatch-agent.service
rm -f ./amazon-cloudwatch-agent.rpm

# Install SSM Agent
sudo yum localinstall -y https://amazon-ssm-ap-northeast-1.s3.amazonaws.com/latest/linux_amd64/amazon-ssm-agent.rpm
sudo systemctl is-enabled amazon-ssm-agent
sudo systemctl restart amazon-ssm-agent
sudo yum clean all

# install Inspector Agent
wget https://inspector-agent.amazonaws.com/linux/latest/install
sudo bash install
rm -f ./install

Packerテンプレートは、以下の要素により構成されています。

  • builders
    • 作成するイメージを定義するところ
  • description
    • テンプレートの説明
  • min_packer_version
    • 最小の利用可能Packerバージョンを指定するところ
  • post-processors
    • イメージ作成前に実施したい追加処理を定義するところ
  • provisioners
    • イメージ作成時に実施したい追加処理を定義するところ
  • variables
    • 利用する変数を定義するところ

Template Structure


今回のテンプレートで利用した部分に関して。

variables

AWSクレデンシャル情報を変数として渡しています。今回の利用方法では、packer build実行時に変数を渡す方法としているため、この部分は空白としています。

builders

細かいパラメータは、公式マニュアルを参照。

AMI Builder (EBS backed)

以下は最新のECS Container Instance用AMIを確認するコマンド。

$ aws ssm get-parameters --names /aws/service/ecs/optimized-ami/amazon-linux-2/recommended

provisioners

Cloudwatch Agentで利用するコンフィグファイルを、ローカルからUploadしています。

File Provisioner

もろもろ設定するためのシェルスクリプトを実行しています。

Shell Provisioner

テンプレートの検証

以下のコマンドにて、事前にテンプレートの検証が可能です。

> packer validate ecs-container-instance.json
Template validated successfully.

validate Command

AMIの作成

以下のコマンドにて、AMI作成処理が走ります。AMI作成用のEC2が自動的にLaunchされて、AMI取得後に、自動的にTerminateされます。 -var オプションにて、AWSクレデンシャル情報を付与しています。

> packer build ^
-var "aws_access_key=XXXXXXXXXXXXXXXXXXXX" ^
-var "aws_secret_key=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" ^
ecs-container-instance.json

build Command

正常終了すれば、AMIが作成されています。