VagrantでEC2も管理しよう

[Vagrantで外部のサーバを管理する](http://qiita.com/hirohero/items/db4a405d752b24afc0d9)で紹介した[managed-servers](https://github.com/tknerr/vagrant-managed-servers)プラグインを使うと、外部のサーバをVagrantで管理できるようになります。
プロビジョニングツールとの連携もやってくれるので、使ってみると思った以上に便利だったりします。

「外部のサーバを管理できる」と見て「じゃあAWS(EC2)も管理できるじゃん。」と思った貴方。正解。
IPとユーザ名、ssh秘密鍵を指定すればOKです。

でも、世の中には凄い人がいるもので、なんと[AWS(EC2)専門のプラグイン](https://github.com/mitchellh/vagrant-aws)が開発されています。
マシン（インスタンス）の起動・停止はおろか、作成・削除までやってくれるオールマイティなプラグインとなってます。
EC2を管理するときはこちらを使いましょう。

# インストール方法
こちらもプラグインをインストールするだけ。コマンド1発でOK。簡単ですね。

```bash
$ vagrant plugin install vagrant-aws
```

# 設定方法
```rb:Vagrantfile
Vagrant.configure("2") do |config|
  config.vm.box = "dummy"

  config.vm.provider :aws do |aws, override|
    aws.access_key_id = "ACCESS KEY ID"
    aws.secret_access_key = "SECRET ACCESS KEY"
    aws.keypair_name = "KEYPAIR NAME"

    aws.ami = "ami-0567c164"                                # ベースとなるAMI
    aws.instance_type = "t2.micro"                          # インスタンスタイプ
    aws.region = 'ap-northeast-1'                           # リージョン
    aws.subnet_id = "subnet-XXXXXXXX"                       # サブネット（VPC）
    aws.security_groups = ['sg-XXXXXXXX', 'sg-XXXXXXXX']    # 適用するセキュリティグループ（複数可）

    aws.tags = {                                            # タグ設定。
      'Name' => 'Vagrant Test',                             # Name
      'Some Key' => 'Some Value'                            # その他のタグ
    }

    aws.elastic_ip = true                                   # Elastic IPを追加する。

    override.ssh.username = "ubuntu"
    override.ssh.private_key_path="/path/to/id_rsa"
    override.nfs.functional = false                         # NFSによるSynced folderを無効にする。
  end

  config.vm.provision "shell", inline: <<-SHELL
    if [ ! -f /usr/bin/python ]; then
      apt-get update
      apt-get install -y --no-install-recommends python
    fi
  SHELL

  config.vm.provision "ansible" do |ansible|
    ansible.playbook = "playbook.yml"
    ansible.extra_vars = {
      ansible_python_interpreter: '/usr/bin/python2'
    }
  end
end
```
こちらのプラグインもダミーのboxが必要です。
事前に本家から提供されているダミーボックスを追加しておいてください。

```bash
$ vagrant box add dummy https://github.com/mitchellh/vagrant-aws/raw/master/dummy.box
```

managed-serversプラグインのときに追加した`tknerr/managed-server-dummy`は使えませんので念のため。

このプラグインが非常に便利なのは、EC2の配置に関する設定（ベースAMI、リージョン、AZ、VPC、サブネット、セキュリティグループ、タグなど）を記述できることです。
ここに設定を書いておけば、`vagrant up`でインスタンスを作成するときにその通りの設定をしてくれます。
自動的にELBにぶら下げることもできるようです。（使ったことはありませんが…。）

managed-serversでは`up`時にプロビジョニングをしてくれませんが、このプラグインなら自動でプロビジョニングをやってくれます。
うーん。正にinfrastructure as code!

```bash
$ vagrant up
Bringing machine 'default' up with 'aws' provider...
==> default: Warning! The AWS provider doesn't support any of the Vagrant
==> default: high-level network configurations (`config.vm.network`). They
==> default: will be silently ignored.
==> default: Warning! You're launching this instance into a VPC without an
==> default: elastic IP. Please verify you're properly connected to a VPN so
==> default: you can access this machine, otherwise Vagrant will not be able
==> default: to SSH into it.
==> default: Launching an instance with the following settings...
==> default:  -- Type: t2.micro
==> default:  -- AMI: ami-0567c164
==> default:  -- Region: ap-northeast-1
==> default:  -- Keypair: aws
==> default:  -- Subnet ID: subnet-XXXXXXXX
==> default:  -- Security Groups: ["sg-XXXXXXXX", "sg-XXXXXXXX"]
==> default:  -- Block Device Mapping: []
==> default:  -- Terminate On Shutdown: false
==> default:  -- Monitoring: false
==> default:  -- EBS optimized: false
==> default:  -- Source Destination check: 
==> default:  -- Assigning a public IP address in a VPC: true
==> default:  -- VPC tenancy specification: default
==> default: Waiting for instance to become "ready"...
==> default: Waiting for SSH to become available...
==> default: Machine is booted and ready for use!
==> default: Rsyncing folder: /Users/XXXXX/Documents/va/ec2/ => /vagrant
==> default: Running provisioner: shell...
    default: Running: inline script
==> default: sudo
==> default: : 
==> default: unable to resolve host ip-172-20-0-236
==> default: mesg: 
==> default: ttyname failed
==> default: : 
==> default: Inappropriate ioctl for device
==> default: Hit:1 http://ap-northeast-1.ec2.archive.ubuntu.com/ubuntu xenial InRelease
==> default: Get:2 http://ap-northeast-1.ec2.archive.ubuntu.com/ubuntu xenial-updates InRelease [95.7 kB]
==> default: Get:3 http://ap-northeast-1.ec2.archive.ubuntu.com/ubuntu xenial-backports InRelease [92.2 kB]
(snip..)
==> default: Fetched 10.8 MB in 8s (1,237 kB/s)
==> default: Reading package lists...
==> default: Reading package lists...
==> default: Building dependency tree...
==> default: Reading state information...
==> default: The following additional packages will be installed:
==> default:   libpython-stdlib libpython2.7-minimal libpython2.7-stdlib python-minimal
==> default:   python2.7 python2.7-minimal
==> default: Suggested packages:
==> default:   python-doc python-tk python2.7-doc binutils binfmt-support
==> default: The following NEW packages will be installed:
==> default:   libpython-stdlib libpython2.7-minimal libpython2.7-stdlib python
==> default:   python-minimal python2.7 python2.7-minimal
==> default: 0 upgraded, 7 newly installed, 0 to remove and 13 not upgraded.
==> default: Need to get 3,907 kB of archives.
==> default: After this operation, 16.6 MB of additional disk space will be used.
==> default: Get:1 http://ap-northeast-1.ec2.archive.ubuntu.com/ubuntu xenial-updates/main amd64 libpython2.7-minimal amd64 2.7.12-1~16.04 [339 kB]
==> default: Get:2 http://ap-northeast-1.ec2.archive.ubuntu.com/ubuntu xenial-updates/main amd64 python2.7-minimal amd64 2.7.12-1~16.04 [1,294 kB]
==> default: Get:3 http://ap-northeast-1.ec2.archive.ubuntu.com/ubuntu xenial/main amd64 python-minimal amd64 2.7.11-1 [28.2 kB]
==> default: Get:4 http://ap-northeast-1.ec2.archive.ubuntu.com/ubuntu xenial-updates/main amd64 libpython2.7-stdlib amd64 2.7.12-1~16.04 [1,877 kB]
==> default: Get:5 http://ap-northeast-1.ec2.archive.ubuntu.com/ubuntu xenial-updates/main amd64 python2.7 amd64 2.7.12-1~16.04 [224 kB]
==> default: Get:6 http://ap-northeast-1.ec2.archive.ubuntu.com/ubuntu xenial/main amd64 libpython-stdlib amd64 2.7.11-1 [7,656 B]
==> default: Get:7 http://ap-northeast-1.ec2.archive.ubuntu.com/ubuntu xenial/main amd64 python amd64 2.7.11-1 [137 kB]
==> default: dpkg-preconfigure: unable to re-open stdin: No such file or directory
==> default: Fetched 3,907 kB in 0s (22.1 MB/s)
==> default: Selecting previously unselected package libpython2.7-minimal:amd64.
==> default: (Reading database ... 
==> default: (Reading database ... 5%
(snip..)
==> default: (Reading database ... 100%
==> default: (Reading database ... 
==> default: 53664 files and directories currently installed.)
==> default: Preparing to unpack .../libpython2.7-minimal_2.7.12-1~16.04_amd64.deb ...
==> default: Unpacking libpython2.7-minimal:amd64 (2.7.12-1~16.04) ...
==> default: Selecting previously unselected package python2.7-minimal.
==> default: Preparing to unpack .../python2.7-minimal_2.7.12-1~16.04_amd64.deb ...
==> default: Unpacking python2.7-minimal (2.7.12-1~16.04) ...
==> default: Selecting previously unselected package python-minimal.
(snip..)
==> default: Setting up libpython2.7-minimal:amd64 (2.7.12-1~16.04) ...
==> default: Setting up python2.7-minimal (2.7.12-1~16.04) ...
==> default: Linking and byte-compiling packages for runtime python2.7...
==> default: Setting up python-minimal (2.7.11-1) ...
==> default: Selecting previously unselected package python.
==> default: (Reading database ... 
==> default: (Reading database ... 5%
(snip..)
==> default: (Reading database ... 100%
==> default: (Reading database ... 
==> default: 54410 files and directories currently installed.)
==> default: Preparing to unpack .../python_2.7.11-1_amd64.deb ...
==> default: Unpacking python (2.7.11-1) ...
==> default: Processing triggers for man-db (2.7.5-1) ...
==> default: Setting up libpython2.7-stdlib:amd64 (2.7.12-1~16.04) ...
==> default: Setting up python2.7 (2.7.12-1~16.04) ...
==> default: Setting up libpython-stdlib:amd64 (2.7.11-1) ...
==> default: Setting up python (2.7.11-1) ...
==> default: Running provisioner: ansible...
    default: Running ansible-playbook...

PLAY [all] *********************************************************************

TASK [setup] *******************************************************************
ok: [default]

TASK [ping] ********************************************************************
ok: [default]

PLAY RECAP *********************************************************************
default                    : ok=2    changed=0    unreachable=0    failed=0   
```

## その他コマンド
managed-serversでは対応していなかった`halt`, `destroy`コマンドもバッチリ対応してくれます。完璧ですね。

```bash
$ vagrant halt
==> default: Stopping the instance...

$ vagrant status
Current machine states:

default                   stopping (aws)

The EC2 instance is stopping. Wait until is completely stopped to
run `vagrant up` and start it.
```

```bash
$ vagrant destroy
    default: Are you sure you want to destroy the 'default' VM? [y/N] y
==> default: Terminating the instance...

$ vagrant status
Current machine states:

default                   not created (aws)

The EC2 instance is not created. Run `vagrant up` to create it.
```

# 参考
- [本家](https://github.com/mitchellh/vagrant-aws)