オブジェクトの広場は株式会社オージス総研グループのエンジニアによる技術発表サイトです

仮想環境

Vagrant と Chef による仮想環境構築の自動化(AWS 編)

株式会社オージス総研 技術部 IoTセンター
大西洋平
2015年3月12日

AWS のようなクラウドサービスが一般に浸透したことにより、仮想環境を前提とした開発が一般的になってきました。必要になったときに必要な構成のリソースにアクセスできるクラウドの強みを活かすため、オンデマンドで仮想環境を構築し直す機会が以前よりも増えてきています。このような状況では、仮想環境をより効率的に構築する必要があります。本記事のシリーズでは効率的な仮想環境構築の手段の一つとして、Vagrant と Chef というツールで環境構築を自動化する方法を紹介します。第 1 回 VirtualBox 編に続く、第2回である本記事はAWSでの環境構築方法を紹介します。

はじめに

本記事では第 1 回 VirtualBox 編で構築した仮想環境と同じものを AWS 上に構築します。環境構築対象が異なり、設定ファイルの記述が異なりますが、Vagrant や Chef の概要、基本的な使い方は共通です。両ツールの概要については、第1回の記事を参照ください。また、本記事では AWS の基礎知識については割愛します。

Vagrant と Chef で AWS の環境構築を行うメリット

AWS 上でインスタンスの構成を再利用される場合、多くの方が AMI を利用されていると思います。設定が完了した EC2 インスタンスのスナップショットを AMI として保存しておくと、AMI から全く同じ構成の EC2 インスタンスを立ち上げることができます。一方で、Vagrant と Chef を利用するメリットしては以下のものが挙げられます。

  • Vagrant を使うメリット
    • コマンド 1 つで設定ファイルに従って仮想環境を立ち上げることができます。EC2 のインスタンスを繰り返し立ち上げる必要がある場合に、手動操作より非常に効率的です。
  • Chef を使うメリット
    • 手順書を Ruby の DSL として記述するため、手順書と実際の手順が食い違うことがなくなります。また、境構築手順の保守が容易になります。
    • OS やミドルウェアなど部分的に構成が異なるEC2インスタンスを複数立ち上げる際に環境構築手順の作成が容易です。クックブックを一部変更するだけで対処できます。

(注)本記事では、Vagrant でインスタンスの起動、Chef でソフトウェアのインストールまで一気に行う手順を紹介しますが、Chef によるソフトウェアのインストール作業は時間がかかるため、必ずしも、毎回、Chef を実行する必要はありません。Chef を使って各種設定を施したインスタンスを AMI 化しておき、次回インスタンス起動時には Vagrant で AMI から起動することも可能です。その場合、ソフトウェアをアップデートする際など、定期的に Chef で最新の構成でインスタンスを再構築し、ベースにする AMI を再構築すると良いでしょう。

AWS で環境構築を行う際の注意点

VirtualBox を使ってローカルで仮想環境を使う場合と比較すると、以下の点に注意が必要です。

  • AWS のアカウントが必要
    • AWS を利用する際にはAWSのアカウントが必要です。本記事ではアカウント作成手順は割愛します。
  • Vagrant から AWS へアクセスするためのユーザが必要
    • AWS 上のユーザの認証情報(access key ID、secret access key)をもって AWS にアクセスする必要があります。本記事では、Vagrant 専用のユーザ・グループを作成します。
  • 社内プロキシで SSH ポートが停止されている場合、プロキシの外側で Vagrant を利用する方法が必要
    • 企業によっては社内プロキシのネットワーク設定として、デフォルトのSSHポートを使って外部にアクセスすることが禁止されている場合があると思います。その場合、VagrantがAWSに直接アクセスできなくなります。
    • そのため、環境構築対象とは別の EC2 インスタンスをホストとして用意し、そこで Vagrant を動かすことで EC2 インスタンスを起動する必要があります。
    • 本記事では、社内プロキシがない前提でローカルのホストから Vagrant を起動する前提で手順を紹介します。
  • ゲスト上の Chef Client からホスト上の Chef Zero Server へアクセスできるようにセキュリティグループを設定する
    • VagrantとChefをプラグインで連携して環境構築を自動化する場合、ゲスト側のChef Clientは、ゲスト上の Chef Zero Server に対して、ポート4000番へHTTPでアクセスし、クックブックを取得します。このため、ゲストからホストへアクセスできるようにポートを開放してください。
    • ホストがEC2インスタンスの場合、セキュリティグループの設定で、ゲストからホストに対してポート4000番でアクセスを許可するようセキュリティグループの設定が必要です。

環境構築に使ったホスト環境

本記事は以下の環境をベースに動作検証を行いました。ただし、各種設定は他のOSでも利用できます。

  • ホストOS: Mac OS X 10.10.2 (Yosemite)
  • Vagrant 1.6.5
  • Chef 0.3.5

環境構築手順

本記事では以下の順番で環境を構築します。第1回の記事の通り、環境準備に少し時間がかかりますが、1度準備するとその後は何度でも同じ構成のインスタンスを起動できます。手動で何度も環境構築することに比べると効率的です。

  • 環境準備
    • 1) Vagrant用のユーザとグループを作成する
    • 2) セキュリティグループを作成する
    • 3) キーペアを作成する
    • 4) VagrantとChefのインストール
    • 5) 設定ファイルの準備
  • 環境構築

環境準備

ここから実際に環境構築を行う手順を紹介します。

1) Vagrant用のユーザとグループを作成する

AWS の管理コンソールにログイン後、以下の手順で Vagrant が AWS にアクセスするためのユーザとグループを作成します。以降は、ユーザ名とグループ名ともに vagrant であることを前提に説明を行います。なお、作成済みのユーザを利用しても問題ありません。

ユーザの作成

  1. Services > Administration & Security > IAM を選択
  2. 左のメニューの Users をクリック
  3. Create New Users
  4. ユーザ名を入力(例. vagrant)
  5. Create をクリック(AWSアクセスに必要な AWS の認証情報(access key id, secret access key)が表示されます。後で利用しますので、メモしておいてください。)

グループの作成

  1. 左のメニューの Groups をクリック
  2. Create New Group をクリック
  3. グループ名を入力(例. vagrant)
  4. Attach Policy で「PowerUserAcess」を選択(注:PowerUserAccess は最上位のユーザ権限 AdministratorAccess から IAM の操作権を取り除いたポリシー)
  5. Create Group をクリック

グループにユーザを登録

  1. 左のメニューの Groups をクリック
  2. 作成したグループを選択
  3. Group Action -> Add Users to Group を選択
  4. 作成したユーザをグループ追加対象として選択
  5. Add User をクリック

以上でユーザとグループの作成は完了です。

2) セキュリティグループを作成する

以下の手順でセキュリティグループを作成します。アプリケーション稼動に必要な HTTP・HTTPS、管理に必要な SSH を設定しています。

  1. Services > Computing > EC2 を選択
  2. 左側メニューの NETWORK SECURITY で Security Group を選択
  3. Create Security Groupをクリック
  4. Security Group Name (例:vagrant)と Description を入力
  5. Inboud のルールに以下を追加して Create をクリック
Type Protocol Port Source
SSH TCP 22 SSHを行うクライアントのIPアドレスもしくはアドレス範囲を指定。詳細はドキュメントを参照。
HTTP TCP 80 Anywhere
HTTPS TCP 443 Anywhere

3) キーペアを作成する

Vagrant が AWS にアクセスする際のキーペアを作成します。

  1. 左側のメニューから Service > Compute & Networking > EC2 を選択
  2. NETWORK & SECURITY > Key Pairs に移動
  3. Create Key Pairをクリック
  4. キーペア名(vagrant)を入力して Create をクリック
  5. 秘密鍵をダウンロードする
  6. ホストの ~/.ssh に秘密鍵を格納

4) Vagrant と Chef のインストール

Vagrant と Chef のインストールについては第 1 回を参照ください。また、今回は以下の Vagrant プラグインを利用しますので、インストールを行ってください。

プラグイン名 概要
vagrant-aws AWS を利用するためのプラグイン。
vagrant-omnibus ゲスト側に Chef Client をインストールするためのプラグイン。
vagrant-chef-zero ホスト側に Chef Zero Server を起動するためのプラグイン。
vagrant-dotenv 外部設定ファイルから設定情報を環境変数に取り込むためのプラグイン。本記事では AWS の認証情報を取得する際に利用する。

インストールは以下のように行います。

$ vagrant plugin install vagrant-aws
$ vagrant plugin install vagrant-omnibus
$ vagrant plugin install vagrant-chef-zero
$ vagrant plugin install dotenv

5) 設定ファイルの準備

5-1) Vagrantfile

次に Vagrant の設定ファイルを用意します。ここでは github リポジトリにアップしているものを参照します。以下で取得してください。

git clone https://github.com/ogis-onishi/vagrant-chef-aws.git

Vagrantfile が Vagrant の設定ファイルです。VirtualBox を環境構築する場合との違いとして、VM プロバイダの設定が AWS に置き換わっている点です。Chef Client の設定は共通です。

# -*- mode: ruby -*-
# vi: set ft=ruby :

# dotenvプラグインで設定を環境変数に読み込み
Dotenv.load

VAGRANTFILE_API_VERSION = "2"

Vagrant.configure(VAGRANTFILE_API_VERSION) do |config|
  config.vm.box = "dummy"
  config.vm.box_url = "https://github.com/mitchellh/vagrant-aws/raw/master/dummy.box"
  # Chef Zero を起動する
  config.chef_zero.chef_repo_path = "."
  # ゲストにChef Clientをインストールする
  config.omnibus.chef_version = :latest

  # AWS設定
  config.vm.provider :aws do |provider, override|
    # AWS認証情報
    provider.access_key_id          = ENV['AWS_ACCESS_KEY_ID']
    provider.secret_access_key      = ENV['AWS_SECRET_ACCESS_KEY']
    provider.keypair_name           = ENV['AWS_KEYPAIR_NAME']

    # EC2インスタンスの設定
    provider.region                 = "ap-northeast-1"
    provider.availability_zone      = "ap-northeast-1a"

    # Amazon LinuxのAMIを指定
    provider.ami                    = "ami-18869819"

    provider.instance_type          = "t2.micro"
    provider.instance_ready_timeout = 120
    provider.terminate_on_shutdown  = false

    # セキュリティグループ
    provider.security_groups        = [ ENV['AWS_SECURITY_GROUP'] ]
    # タグ(任意)。インスタンスに分かりやすい目印を付けたい場合。
    provider.tags                   = {
      "Name"        => "vagrant-aws",
      "Description" => "Boot from vagrant-aws",
    }

    # ログイン後、sudo できるようにする
    provider.user_data = <<-USER_DATA
    #!/bin/sh
    sed -i -e 's/^\\(Defaults.*requiretty\\)/#\\1/' /etc/sudoers
    USER_DATA

    # AWSへの接続ユーザおよび秘密鍵の指定
    override.ssh.username = ENV['AWS_SSH_USERNAME']
    override.ssh.private_key_path   = ENV['AWS_SSH_KEY']
    override.ssh.pty = true

    override.vm.synced_folder ".", "/home/ec2-user/vagrant", disabled: true
  end

    # Chef Client によるプロビジョンに設定
  config.vm.provision :chef_client do |chef|
    chef.custom_config_path = "chef_custom_config"
    chef.run_list = [
        "postgresql::server",
        "postgresql::client",
        "postgresql::contrib",
        "database::postgresql",
        "postgresql_config",
        "java",
        "play-sample"
    ]
    chef.json = {
      :postgresql => {
        :password => 'postgres'
      },
      :java => {
        :jdk_version => '7'
      }
    }
  end
end

5-2) .env(環境変数の設定)

上記の Vagrantfile には AWS の認証情報を直接記述せず、ENV['変数名'] の形で指定しています。これは Vagrantfile に AWS の認証情報を直接記述してしまうと、第三者に見える状態になってしまうためです。本記事では、Vagrant を利用するユーザが dotenv プラグインの設定ファイルをローカルに用意することで、認証情報を第三者に開示せずに、Vagrant で利用できるようにしています。

Vagrantfile と同じディレクトリに「.env」というファイルを用意し、以下を記述してください。

# デフォルトのプロバイダーは AWS
VAGRANT_DEFAULT_PROVIDER="aws"
# AWSにSSHアクセスする際のユーザ名
AWS_SSH_USERNAME="ec2-user"
# 作成した秘密鍵のパス
AWS_SSH_KEY="~/.ssh/vagrant.pem"
# ユーザ作成時のAccess Key Id
AWS_ACCESS_KEY_ID=""
# ユーザ作成時のSecret Access Key
AWS_SECRET_ACCESS_KEY=" "
# 作成したキーペア名
AWS_KEYPAIR_NAME="vagrant"
# セキュリティグループ名
AWS_SECURITY_GROUP="vagrant"

以上で準備は完了です。

環境構築

準備が完了すれば、以下のコマンドで実際に EC2 インスタンスを構築してください。設定に問題なければ EC2 インスタンスが立ち上がり、ゲスト側で Chef Client がクックブックを実行して、環境設定が完了します。アプリケーションの内容は第 1 回と同じですので、ここでは割愛します。

# クックブックを cookbooks ディレクトリに配置
berks vendor cookbooks
# インスタンス起動
vagrant up

おわりに

Vagrant と Chef で環境構築をしてみて、いかがだったでしょうか?第1回と同じく、一番初めの環境準備に時間がかかると思いますが、ベースが出来上がってしまえば、あとはコマンド1発で何度でも同じ環境を簡単に立ち上げることができます。

今回はサンプルをシンプルにとどめておくため、ユーザ作成や RDS での DB 構築など実際のアプリケーション開発で使いそうな応用的なトピックは紹介できませんでした。次回の記事では、実際の開発で使いそうなトピックをご紹介します。