PR

マシン・イメージを自動構築し、作業効率を高める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のWebサイトにログインすることでさまざまな限定特典を入手できるようになります。

Think IT会員サービスのご案内

関連記事