【導入実績300社以上】AWS 構築・運用保守サービス

【導入実績300社以上】AWS 構築・運用保守サービス

【サーバー管理不要】WordPress専用クラウド『WebSpeed』

【サーバー管理不要】WordPress専用クラウド『WebSpeed』

【100URLの登録が0円】Webサイト監視サービス『Appmill』

【100URLの登録が0円】Webサイト監視サービス『Appmill』

【コミュニケーションアプリ開発】LINE アプリ開発サービス

【コミュニケーションアプリ開発】LINE アプリ開発サービス

【ECサイト構築】Shopify カスタムアプリ開発サービス

【ECサイト構築】Shopify カスタムアプリ開発サービス

【音声アプリ開発】Twilio アプリ開発サービス

【音声アプリ開発】Twilio アプリ開発サービス

【グローバル対応】北米リージョン・クラウド / サーバー サポート

【グローバル対応】北米リージョン・クラウド / サーバー サポート

【CPU】AMD EPYC 技術検証(PoC)サービス

【CPU】AMD EPYC 技術検証(PoC)サービス

【Webシステム / サービス開発】SAKARAKU Lab(セカラクラボ)

【Webシステム / サービス開発】SAKARAKU Lab(セカラクラボ)

【取材記事】サーバー系企業ビヨンドが サーバーサイドエンジニアを募集中

【取材記事】サーバー系企業ビヨンドが サーバーサイドエンジニアを募集中

【対談記事】「やっぱクラウド移設っていいですよね」マイネット × ビヨンド エンジニア対談

【対談記事】「やっぱクラウド移設っていいですよね」マイネット × ビヨンド エンジニア対談

【YouTube】ビヨンド公式チャンネル「びよまるチャンネル」

【YouTube】ビヨンド公式チャンネル「びよまるチャンネル」

PackerでHCL2がサポートされたので既存のJson形式のコードを書き換えた話

インフラエンジニアの寺岡です。
Packerで待ちに待ったアップデートがありました。
ついにHCL2をサポートしてくれました!

今回は既存のJsonで書いていたコードをHCL2ベースに書き直してみましたので
それぞれのコードを比較しながらまとめてみたいと思います。

Packerとは

マルチクラウド対応のゴールデンイメージを作成できるCLIツールです。

https://packer.io

この手のゴールデンイメージを作成するツールは
Immutable Infrastructureやブルーグリーンデプロイメントと非常に相性が良く
AutoScalingなどのサーバの作成と破棄が頻繁に繰り返される環境下において重宝します。

開発はHashiCorpによって継続されておりGolangで記述されています。
同じくTerraformも有名なツールなのでご存知の方が多いのではないでしょうか。

PackerはAWS・GCP・Azureなどの主要なクラウドサービスはもちろんのこと
DockerイメージやVMwareなどのハイパーバイザー型のマシンイメージの作成にも対応しています。
多数のサービス(Packerではbuilderと言います)に対応していますが
どのbuilderでも共通の書式でコードを書いて処理を記述できるのがメリットです。

以前まではJson形式でしか記述できませんでしたが
バージョン1.5よりHCL2形式をサポートしました。
本記事を書いた時点(2020/03/31)ではまだベータ版のため
プロダクション環境における利用は事前によく検証してからの方が良いかもしれません。

HCLとは

HashiCorp Configuration Languageの略で同じくHashiCorpにとって開発されています。
実装的にはJson互換ですが、あくまで独自言語のためJsonとは全く違う独自の記述を行うことができます。
コマンドラインツールでの利用が想定されており、Terraformでは以前からサポートされていたので
tfファイルを書いている方からすると馴染み深いものになっていると思います。
ちなみにバージョン違いでHCL1とHCL2があり現在はHCL2が主流になっています。

Packerのテンプレートを書いてみる(Json)

Packerはイメージの作成をテンプレートと呼ばれるものを記述して作成しますが
テンプレートの内容をJson形式と比較しながらHCL2で書いていきたいと思います。
まずはJson形式で書いたものを見てみましょう。

{
    "builders": [
        {
            "type": "amazon-ebs",
            "region": "{{user `region`}}",
            "source_ami_filter": {
                "filters": {
                    "name": "{{user `ami_name`}}*"
                },
                "owners": [
                    "self"
                ],
                "most_recent": true
            },
            "instance_type": "{{user `instance_type`}}",
            "ssh_username": "{{user `ssh_username`}}",
            "ami_name": "{{user `ami_name`}}_{{timestamp}}",
            "tags": {
                "Name": "{{user `ami_name`}}_{{timestamp}}"
            },
            "iam_instance_profile": "{{user `iam_instance_profile`}}"
        }
    ],
    "provisioners": [
        {
            "type": "shell",
            "inline": [
                "sudo yum -y update"
            ]
        }
    ]
}

{{user `ami_name`}}などの部分が変数となっており
格納される値は別ファイルに記述されています。

{
  "ssh_username": "ec2-user",
  "region": "ap-northeast-1",
  "instance_type": "t3.micro",
  "ami_name": "ami-packer-test",
  "iam_instance_profile": "role-packer-test"
}

このテンプレートファイルを用いて

$ packer build main.json -var-file=variables.json

とコマンドを実行することで
variables.jsonから変数に格納する値を読み込みつつイメージをビルドすることができます。
上記のテンプレートの内容通りにビルドを行うと

  • source_ami_filterに記述した内容でベースとなるAMIIDを検索する
  • 検索に該当したAMIをベースにビルド処理を開始する
  • ベースAMIから新しくEC2インスタンスを起動する
  • EC2インスタンスにログインするためのテンポラリのキーペアを作成する
  • SSHでインスタンスにログインしてprovisionersに記述されている処理を実行する
  • EC2インスタンスを停止する
  • 停止したインスタンスからAMIを取得する
  • 取得完了後にインスタンスを削除する

という一連の処理を行います。
AMIの情報を取得するときはIAMロールを利用することができるため
上記の例ではpackerコマンドを実行するEC2インスタンスに
実行に必要なIAMロールを事前に設定しています。
IAMロールに必要な権限は以下にまとめられています。

https://packer.io/docs/builders/amazon.html

Packerのテンプレートを書いてみる(HCL2)

では上記のJsonをHCL2に書き直してみるとどのようになるでしょうか。
まず変数に対して格納する値を書いていきます。
以下の2つのファイルを利用します。

variables.pkrvars.hcl

ssh_username         = "ec2-user"
region               = "ap-northeast-1"
instance_type        = "t3.micro"
ami_name             = "ami-packer-test"
iam_instance_profile = "role-packer-test"

variables.pkr.hcl

variable "ssh_username" {
  type        = string
  description = "SSH User Name"
}

variable "region" {
  type        = string
  description = "AWS Region"
}

variable "instance_type" {
  type        = string
  description = "EC2 Instance Type"
}

variable "ami_name" {
  type        = string
  description = "EC2 AMI Name"
}

variable "iam_instance_profile" {
  type        = string
  description = "EC2 IAM Instance Profile"
}

variables.pkrvars.hclに変数に格納する値を記述します。
Jsonでは「値名:値」でしたがHCL2では「値名 = 値」になります。

HCL2で変数を表現する場合はvariableを利用します。
プログラミング言語と同様に型の概念があり
今回は全て文字列(string)型の変数を利用しています。
その他にも

  • 数値型(number)
  • リスト型(list)
  • マップ型(map)
  • ブーリアン型(bool)

などがあります。

次に実際のビルド処理部分の記述をしていきます。
以下の2つのファイルを利用します。

sources.pkr.hcl

## Source
source "amazon-ebs" "example" {
  region               = var.region
  ami_name             = "${var.ami_name}_{{timestamp}}"
  instance_type        = var.instance_type
  iam_instance_profile = var.iam_instance_profile
  ssh_username         = var.ssh_username

  source_ami_filter {
    owners      = ["self"]
    most_recent = true

    filters {
      virtualization-type = "hvm"
      name                = "${var.ami_name}*"
      root-device-type    = "ebs"
    }
  }

  tags {
    Name = "${var.ami_name}_{{timestamp}}"
  }
}

build.pkr.hcl

## Build
build {
  sources = [
    "source.amazon-ebs.example"
  ]

  provisioner "shell" {
    inline = [
      "sudo yum -y update"
    ]
  }
}

この通り、Json形式では1つのファイルに書いていたものを
sourceとbuildという単位で別ファイルに分けることができます。
またHCL2の場合はコードの途中でコメントを挿入することができるのが特徴です。
変数の参照は「var.変数名」で可能です。

build.pkr.hclではsourceの設定を読み込み
provisionerの部分でビルド時に実行する処理を書いています。
sourcesの部分はlist型になっているため以下のように複数指定することも可能です。

sources = [
    "source.amazon-ebs.example",
    "source.amazon-ebs.example2"
]

ビルドを実行するときはテンプレートファイルが存在するディレクトリに移動して

$ packer build -var-file=variables.pkrvars.hcl ./

とすればカレントディレクトリのファイルを全て読み込んで実行してくれます。

現時点の問題点

Packerには構文チェックを行うvalidateコマンドがありますが
HCLで記述した場合はこれが利用できません。
今後のアップデートに期待です。
https://github.com/hashicorp/packer/issues/8538

まとめ

Packerはクラウドサービスを使ったDevOpsを実践する上で便利なツールとなっています。
CI/CDのフローに組み込みやすくPacker自体の構成も非常にシンプルなため
皆様も是非一度利用してみてください。

この記事がお役に立てば【 いいね 】のご協力をお願いいたします!
0
読み込み中...
0 票, 平均: 0.00 / 10
2,121
facebook twitter はてなブックマーク

この記事をかいた人

About the author

寺岡佑樹

2016年ビヨンド入社、現在6年目のインフラエンジニア
MSPの中の人として障害対応時のトラブルシューティングを行いながら
AWSなどのパブリッククラウドを用いたインフラの設計/構築も行っている。
最近はDockerやKubernetesなどのコンテナ基盤の構築や
運用自動化の一環としてTerraformやPackerなどのHashicorpツールを扱うことが多く
外部の勉強会やセミナーで登壇するEvangelistの役割も担っている。

・GitHub
https://github.com/nezumisannn

・登壇経歴
https://github.com/nezumisannn/my-profile

・発表資料(SpeakerDeck)
https://speakerdeck.com/nezumisannn

・所有資格
AWS Certified Solutions Architect - Associate
Google Cloud Professional Cloud Architect