マシン・イメージを自動構築し、作業効率を高めるPacker入門

2015年4月13日(月)
前佛 雅人(ぜんぶつ まさひと)

Packerとは?

Packerはマシン・イメージの自動生成や管理をするコマンドライン・ツールです。Packerの背景や機能解説のほか、AWS(Amazon Web Services)とDigitalOceanで実際にPackerを使う方法、Atlasとの連携方法をご紹介します。

マシン・イメージ管理とPacker

Packerは何を解決するのか?

クラウド(IaaS)や仮想化環境を使う上で避けて通れないのが、マシン・イメージをどのように管理するべきかという課題です。ベンダーから用意されているマシン・イメージは、OS環境がほぼ初期状態のままです。その状態から、タイムゾーンや言語設定、管理用アカウントの作成、開発環境のインストール、ミドルウェアや各種サーバのセットアップなどを済ませて、実際に使える環境を整えるのに時間がかかります。

この課題を解決するのが、ある程度準備された環境をテンプレート的なマシン・イメージとして扱う「ゴールデンイメージ」を持つ考えです(図1)。ゴールデンイメージをチームや社内で共有することで、共通している環境構築の手間が省けるため。開発環境や本番環境を迅速に利用できるようになります。またそれにより、各々の担当者は本来の役割である、コーディングやテスト、運用などに専念できるようになります。

ゴールデンイメージ作成・利用の流れ

図1:ゴールデンイメージ作成・利用の流れ

このようにマシン・イメージをテンプレートのように扱うのは便利ですが、反面マシン・イメージの作成や管理が煩雑になりがちです。例えば、Amazon Web Services(以下、AWS)の場合、EBS-Backed Linux AMI を元に自分のマシン・イメージを作るには、インスタンスを起動し、環境構築、スナップショット作成後にAMIの登録作業が必要です(図2)。この作業は、OSのバージョン変更やリージョンごとに行う必要があります。またセットアップする開発環境・ミドルウェアの環境が変わっても、この一連の作業が必要になります。

AWSで新しいAMIを作成する流れ

図2:AWSで新しいAMIを作成する流れ

これらの一連の作業は、マシン・イメージの更新頻度は低くても面倒になりがちです。そこでPackerの出番となります。Packerは、マシン・イメージに関する面倒な問題を解決するための、コマンドライン上のツールです。PackerはVagrantと同じくHashiCorpによる開発が行われており、オープンソースとして公開されています。

Packerの特徴

Packerは、マシン・イメージに関する面倒な作業を単純化します。クラウド上のGUIを使わなくても、マシン・イメージを自動生成できます。それだけでなく、開発環境やミドルウェアやアプリケーションの設定を自動的に行う、プロビジョニング機能も備えています。また、複数のクラウド・仮想化環境のマシン・イメージを抽象化するだけでなく、並列に処理することもできるため、作業の共通化や時間短縮に役立ちます。

Packerを使ったマシン・イメージの管理には、常にPacker用のテンプレート・ファイルを使います。このファイルには、どこのクラウド環境を使うか、どのようなマシン・イメージを作成するかなどを記述します。テンプレートの内容はJSON形式のファイルのため、構成に些細な変更を加えたり、別のクラウドで同様の環境を再現したりするのも容易になります。

Packerの機能とアーティファクト

Packerは、様々なパーツによって構成されていますが、その全てを使う必要はありません。最低限必要なのはビルダー(builder)であり、これはベンダーが提供するマシン・イメージを元に、アーティファクト(artifact)を作成するものです。

アーティファクトとは、Packer独自の抽象化されたマシン・イメージの概念です。Packerを通して自動生成したマシン・イメージや管理に付随する情報が、アーティファクトと呼ばれています。アーティファクトの内容とは、利用するクラウドや仮想化システムの環境によって異なります。以下は一例です。

アーティファクトの例

AWSAMIと、AMI IDなど付属する管理情報
DigitalOceanテンプレート
VMwareディレクトリ内のファイル群

このように、それぞれの環境により最終的なマシン・イメージの形態は異なります。これらを抽象化した成果物という意味で、アーティファクトという言葉が用いられています。

Packerが持つ機能は、アーティファクトの作成だけではありません。Packerの基本機能は、前述のビルダーと呼ばれるマシン・イメージ作成・管理機能ですが、ほかにもプロビジョナー、ポスト・プロセッサーの各機能で構成されています(図3)。

Packerの機能とアーティファクト

図3:Packerの機能とアーティファクト

それぞれの機能は、次のような役割があります。

ビルダー(builder)

Packerの主要部分であり、マシン・イメージの生成を行います。JSON形式のテンプレートを元に、特定の環境上でマシン・イメージの起動、設定適用、作成を自動的に行います。最終的に、成果物としての新しいマシン・イメージを作成します。Packerでは、これら管理情報を含めてアーティファクトと呼ばれる単位で管理できるようになります。

プロビジョナー(provisioner)

マシン・イメージの中に、ミドルウェアやアプリケーションなど、ソフトウェアのインストールや設定を自動的に行います。シェルスクリプトの自動実行のほか、構成管理ツールであるChefかPuppetを実行する機能を持ちます。既にChefやPuppetをお使いであれば、Packerで自動実行できる便利な機能です。

ポスト・プロセッサー(post-processor)

ビルダーの実行結果を元に、新しいアーティファクトを作ります。ある環境向けに作られたものをTar形式で圧縮する機能や、DockerやAtlasの環境にアップロード(プッシュ)する機能があります。

Packerの中でビルダーを使うことは必須ですが、プロビジョナーやポスト・プロセッサーは必要がなければ使わなくても構いません。作業に合致する部分、とりわけ繰り返し作業で当てはまる所があればPackerを使うことが、時間の節約や効率化につながります。こういったPackerのような提案型スタイルは、HashiCorpが提供する他のツールやサービスと同様の設計思想に基づいています。

対応しているプラットフォーム

Packerの特徴の1つとして、様々なプラットフォームに対応している点が挙げられます。AWSのAmazon EC2向けAMIのほか、DigitalOcean、Google Compute Engine、Docker、OpenStack、VirtualBox、VMware、QEMUなどの環境に対応しています。

Packerのセットアップ方法

Packerを使うためには、GitHubで配布されているソースコードからコンパイルするか、バイナリをダウンロードします。多くの環境に対応していますので、バイナリファイルのダウンロードが手軽です。

ダウンロード用URL(https://packer.io/downloads.html)から、使いたいOSやマシン環境に合わせたPackerをダウンロードします。次の手順は、Linux環境(x86_64)でPackerのセットアップを行う方法です。wgetでアーカイブを取得した後、中のバイナリを/opt/packerに展開し、パスを通しています。

$ wget -O packer_0.7.5_linux_amd64.zip https://dl.bintray.com/mitchellh/packer/packer_0.7.5_linux_amd64.zip
$ unzip packer_0.7.5_linux_amd64.zip
$ sudo unzip ./packer_0.7.5_linux_amd64.zip -d /opt/packer/
$ export PATH=/opt/packer:$PATH
$ echo 'export PATH=/opt/packer:$PATH' >> ~/.bashrc

パスが正しく通っていれば、次のように実行してバージョン情報を確認できます。

$ packer version
Packer v0.7.5

これでPackerを使う準備が整いました。

クラウド上でPackerを使うには?

ここでは、実際にDigitalOceanとAWS上で、Packerを使う方法を見ていきます。作業はコマンドライン上で行いますが、覚える項目はとても少ないですし、JSON形式のテンプレートは見慣れなくても、さほど難しいものではありません。一歩ずつ試してみましょう。

DigitalOcean上で展開する方法

Packerを使う上で、一番シンプルで分かりやすいのは、DigitalOceanを使って新しいマシン・イメージを作る方法です。DigitalOceanは、SSDの基盤上で利用できるVPSサービスで、シンプルかつ速く利用できるものとして注目されています。

DigitalOceanで提供されているマシン・イメージは、他のクラウド同様にOS環境は初期状態のままです。ドロップレット(droplet)と呼ばれる仮想サーバを起動後、初期設定を済ませたものは、スナップショットを作成できます。DigitalOceanでは、このスナップショットとして保存されたイメージを元に、新しくサーバを起動できます。

DigitalOceanとPacker

図4:DigitalOceanとPacker

事前準備として、DigitalOceanのアカウントが必要です。それから、アクセストークンを発行します。DigitalOceanのAPI画面から「Personal Access Tokens」列にある「Generate New Token」をクリックし、「Token Name」にはPacker等を記入し、「Generate Token」をクリックすると文字列が表示されます。これがPackerで使うトークンなのでエディタ等に控えておきます。なお、実際にPackerを走らせると、課金が必要となりますので、ご注意ください。

続いて、テンプレートとなるファイルを用意します。エディタを用いて、「example.json」という名称のファイルを作成・編集します。以下の例は、Packerを使う上で基本となるテンプレートです。シンガポール・リージョン「sgp1」に、マシン・イメージはUbuntu Server 14.04 LTSの「ubuntu-14-04-x64」を使います。仮想サーバの名称は「packer-example タイムスタンプ」とします。リージョンやマシン・イメージだけでなく、名前も任意のものを使えますので、自分の環境に合わせて自由に書き換えても構いません。

リスト1;DigitalOcean用のテンプレート

{
  "builders": [{
    "type": "digitalocean",
    "api_token": "<自分のtoken>'",
    "image": "ubuntu-14-04-x64",
    "region": "sgp1",
    "snapshot_name": "packer-sample {{timestamp}}"
  }],
  "provisioners": [{
    "type": "shell",
    "inline": [
      "sleep 30",
      "sudo apt-get update",
      "sudo apt-get install -y apache2"
    ]
  }]
}

ここで重要なのは「builders」と「provisioners」で囲まれた範囲です。

「builders」ではPackerのビルダーとして、どのようなマシン環境を作成するのかという挙動を指定します。この例ではDigitalOceanの環境なので「type」に「digitalocean」を記述しましたが、環境が変わる場合は他のビルダーに書き換えます(例:AWSを使う場合は、「"type": "amazon-ebs"」になります)。またオプションも変わる場合がありますので、ご注意ください。

もう一方の「provisioners」で囲まれた部分には、プロビジョナーがサーバの中で自動的に行う処理を記述します。この例ではOS起動から30秒待機し、その後シェルスクリプト上でコマンドを実行し、Apacheサーバをインストールします。ほかにChefやPuppetも使えます。もしプロビジョニングが不要であれば、provisionersの記述は不要です。プロビジョナーの詳細については、ドキュメントをご確認ください。

テンプレート作成後は、文法チェックのコマンド「packer validate 」を実行します。JSONの記法に問題がなければ、次のように問題がない旨の表示がされます。

$ packer validate example.json
Template validated successfully.

次に、Packerを使って新しいイメージを自動的にビルドしてみましょう。「packer build」コマンドの引数で、JSONファイルを指定します。

$ packer build example.json
digitalocean output will be in this color.


==> digitalocean: Creating temporary ssh key for droplet...
==> digitalocean: Creating droplet...
==> digitalocean: Waiting for droplet to become active...
(省略)
==> digitalocean: Gracefully shutting down droplet...
==> digitalocean: Creating snapshot: packer-sample 1428040540
==> digitalocean: Waiting for snapshot to complete...
==> digitalocean: Destroying droplet...
==> digitalocean: Deleting temporary ssh key...
Build 'digitalocean' finished.

==> Builds finished. The artifacts of successful builds are:
--> digitalocean: A snapshot was created: 'packer-sample xxxx' in region 'Singapore 1'

この後、自動的にドロップレットの作成、プロビジョニング(Apacheセットアップ)が進行します。その後、自動的に作業時に使ったドロップレットを停止し、テンプレートを作成した後、ドロップレットを削除します。

このようにPackerは数分間に渡る作業を自動的に行い、最終的に「packer-sample xxxx」という名称のテンプレートを作成します。これで新しくドロップレットを作成する際は、このテンプレートを元に起動できるようになります。以降は、必要に応じてビルダーやプロビジョナーの内容を書き換えることで、類似の環境を簡単に再現できます。

AWSで新しいAMI(マシン・イメージ)をビルドする方法

手作業でAMIを作成するには、イメージを起動後に環境を構築し、新しくスナップショットを作成した後に新しいAMIを登録する必要があります。Packerは、これらの手順を一括して行えます。

AWSとPacker

図5:AWSとPacker

Packerは環境構築のためにAmazon Virtual Private Cloud(Amazon VPC)を使います。そのため、事前にAWSマネジメント・コンソールで作業用のVPC環境を用意し、VPC IDとサブネットIDを控えておきます。また事前に「aws_access_key」と「aws_secret_key」の情報を確認しておきます。また、AWS IAMの権限設定を詳細に行う場合は、Packerのドキュメントを参考にお願いします。

事前準備の後、テンプレートとなるファイルを用意します。エディタを使い、「example.json」という名称のファイルを作成・編集します。以下の例は、東京リージョン「ap-northeast-1」に、Ubuntu Server 14.04 LTSのAMI「ami-bebda6bf」を元に、インスタンス「t1.micro」で「packer-example タイムスタンプ」という名称のAMIを作成するものです。

リスト2:AWS用のテンプレート

{
  "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-bebda6bf",
    "vpc_id": "vpc-<自分のVPC ID>",
    "subnet_id": "subnet-<自分のサブネットID>",
    "ssh_private_ip": false,
    "associate_public_ip_address": true,
    "instance_type": "t1.micro",
    "ssh_username": "ubuntu",
    "ami_name": "packer-example {{timestamp}}"
  }],
  "provisioners": [{
    "type": "shell",
    "inline": [
      "sleep 30",
      "sudo apt-get update",
      "sudo apt-get install -y apache2"
    ]
  }]
}

先ほどのDigitalOceanの例と同様、「builders」で囲まれた中でPackerの挙動を指定します。今回はAWSの環境なので「type」に「amazon-ebs」を選びます。それにともない、AWS独自のVPSのオプションが増えています。またAWSの場合は、アクセスキーとシークレットキーをJSONに記述する必要はありません。

「packer validate example.json」を実行して、文法上の問題がないことを確認します。それから、AWSに新しいイメージを自動的にビルドするため、「packer build」コマンドの引数で、AWSのアクセスキーとシークレットキーを指定します。

$ packer build \
    -var 'aws_access_key=<アクセスキー>' \
    -var 'aws_secret_key=<シークレットキー>' \
    example.json

後は自動的に処理が進行します。最終的にAWSのEC2コンソール上の「IMAGES」から「AMIs」をクリックすると「packer-example」という名称で作成されていることが分かります。

AWSを使う上で、AMIはS3に保管されるため、課金が発生します。また、Packerが作成するのはAMIだけでなく、作成過程でスナップショットも使用していますので、不要な場合はあわせて削除することにもご注意ください。

著者
前佛 雅人(ぜんぶつ まさひと)
クリエーションライン株式会社

Technology Evangelist
ホスティングサービスで運用保守サポートに携わった後、現職へ。サポート業務や新技術検証や開発業務を行う傍ら、実家で農作業のため東京と富山を往復する日々。趣味で監視や自動化に関するOSS検証や翻訳を行う。とりわけ運用・監視の省力化・最適化に興味。辛口の日本酒が大好き。
Twitter: @zembutsu (https://twitter.com/zembutsu)

連載バックナンバー

Think ITメルマガ会員登録受付中

Think ITでは、技術情報が詰まったメールマガジン「Think IT Weekly」の配信サービスを提供しています。メルマガ会員登録を済ませれば、メルマガだけでなく、さまざまな限定特典を入手できるようになります。

Think ITメルマガ会員のサービス内容を見る

他にもこの記事が読まれています