Amazon Linux 2が出たのでVagrantでの開発環境を試してみる

# はじめに
AmazonLinuxは今までEC2とDockerImageしか配布されていなかったのですが、
12/13に[Amazon Linux 2](https://aws.amazon.com/jp/amazon-linux-2/)が公開されてVirtualmachine用のImageが公式配布されたので早速立ててみました。
Vagrant Boxの作成手順から記載していますが、とりあえず立ててみたいという人はBoxを配布しているので下記からダウンロードして [7. Vagrantfileを作成します。](### 7. Vagrantfileを作成します。)以降から試してみて下さい。
https://app.vagrantup.com/winky/boxes/amazonlinux-2/versions/1.0

## 検証環境
Macbook Pro
Vagrant version 2.0.1

## イメージをダウンロード
https://cdn.amazonlinux.com/os-images/2017.12.0.20171212.2/virtualbox/
上記のURLから「amzn2-virtualbox-2017.12.0.20171212.2-x86_64.xfs.gpt.vdi」をダウンロードします。

## 初期セットアップ用のイメージを作成する
AmazonLinuxでは初期のセットアップにcloud-initを使用しています。
(cloud-initについては[Developers.IOさんの記事](https://dev.classmethod.jp/cloud/aws/cloud-init-cfg/)を参考にさせてもらいました。)
Vagrantで起動するためにVagrant用に設定を追加したイメージを作成します。

今回はこのイメージをMacで作成してみます。
Debianなどgenisoimageパッケージが使えるところならMacじゃなくても作れます。

Macなのでgenisoimageではなく `hdiutil ` コマンドを使用します。
cloud-init用のISOイメージを作るために必要なディレクトリ構成は下記のようになっているのでまずはこれを作ります。

```
./
└── amazonlinux-vagrant
    ├── meta-data
    └── user-data
```

###  meta-dataファイルを設定します

```yml:meta-data
local-hostname: localhost.localdomain
```

### user-dataファイルを設定します

```yml:user-data
#cloud-config
# vim:syntax=yaml
users:
# A user by the name ec2-user is created in the image by default.
  - default
  - name: vagrant
    groups: wheel
    sudo: ['ALL=(ALL) NOPASSWD:ALL']
    plain_text_passwd: vagrant
    ssh-authorized-keys:
      - ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEA6NF8iallvQVp22WDkTkyrtvp9eWW6A8YVr+kz4TjGYe7gHzIw+niNltGEFHzD8+v1I2YJ6oXevct1YeS0o9HZyN1Q9qgCgzUFtdOKLv6IedplqoPkcmF0aYet2PkEDo3MlTBckFXPITAMzF8dJSIFo9D8HfdOV0IAdx4O7PtixWKn5y2hMNG0zQPyUecp4pzC6kivAIhyfHilFR61RGL+GPXQ2MWZWFYbAGjyiYJnAmCP3NOTd0jMZEnDkbUvxhMmBYSdETk1rRgm+R4LOzFUGaHqHDLKLX+FIPKcF96hrucXzcWyLbIbEgE98OHlnVYCzRdK8jlqm8tehUc9c9WhQ== vagrant insecure public key
    lock_passwd: false

chpasswd:
  list:
    root:vagrant
  expire: False

# Default Install Packages for Guest Additions
packages:
  - gcc
  - make
  - kernel-devel
  - kernel-headers
  - dkms
  - perl
  - bzip2
```

#### users
ユーザーの作成するためのタスクです
`default` は `amazonlinux` でのデフォルトユーザーである `ec2-user` を作成します。
Vagrant用なので追加でvagrantユーザーも作ります。
Vagrantで起動したりする際にrootユーザーになれる必要があるのでそれも設定しておきます。
また `vagrant` ユーザーのSSH鍵にはVagrant公式の[Insecure Keypair](https://github.com/hashicorp/vagrant/blob/master/keys/vagrant.pub)を設定しておきます。

#### chpasswd
ここでは `list`のところで設定している `ユーザー名:パスワード`の組み合わせになるようにパスワードを変更します。

#### packages
ここでは初期にインストールするパッケージ群です。
VagrantでGuestAdditionsを使用するために必要なパッケージを設定しています。
GuestAdditionsに必要なパッケージ群は[こちらの記事](https://linuxfan.info/virtualbox-guest-additions)を参考にしました。

以上の設定をしたら `cloud-init-data` のあるディレクトリで下記のコマンドを実行します。

```
$ hdiutil makehybrid -iso -joliet -o amazonlinux-vagrant.iso amazonlinux-vagrant
```

これによって `cloud-init` 用のISOイメージが作成されました。
実際作ったものを[ここ](https://github.com/wink-y/cloud-init-data/blob/master/amazonlinux-vagrant.iso)においてあるので作るのが面倒な場合は使って下さい。

## Vagrant用のBoxを作成する
### 1. 仮想マシンを作成する
 - Name: Amazon Linux 2（好きな名前でよい）
 - Memory size: 1024MB（割り当てすぎないようにデフォルトを選択）
 - Hard disk: `Use an existing virtaul hard disk file`を選択し、さきほどダウンロードしたAmazonLinuxのイメージを選択する

<img width="899" alt="Screen Shot 2017-12-21 at 17.35.17.png" src="https://qiita-image-store.s3.amazonaws.com/0/34776/bcc25214-7ac7-14da-b4af-17d183f61519.png">

### 2. 周辺機器の無効化とcloud-initイメージの読み込み
下記2つの不要な周辺機器を無効化しておく
 - オーディオ
 - USB

先程作成したcloud-init用のISOファイルをマウントします。

<img width="895" alt="Screen Shot 2017-12-21 at 17.52.09.png" src="https://qiita-image-store.s3.amazonaws.com/0/34776/a1bcd965-73b9-bacb-977f-d584ccc18e5a.png">

マウントが終わったらAmazonLinuxの仮想マシンを起動させます。

### 3. Guest Additionsのインストール
1. マシンの起動後、先程マウントしたcloud-init用のISOをアンマウントします。  
<img width="1015" alt="Screen Shot 2017-12-22 at 15.54.05.png" src="https://qiita-image-store.s3.amazonaws.com/0/34776/d3889f6a-aa0b-9c70-9692-2eb3160bf5fd.png">
2. VirtualBox VMのメニューからDevices->insert Guest Additions CD imageを選択し、Guest Additionsのイメージをマウントします。  
3. rootユーザーになったのち、以下のコマンドを実行してGuest Additionsをインストールします。  

```
[root@localhost ~]# mount /dev/cdrom /mnt
[root@localhost ~]# /mnt/VBoxLinuxAdditions.run
[root@localhost ~]# umount /mnt
[root@localhost ~]# systemctl enable vboxadd.service
```

### 4. 軽量化処理を行います。
1. コマンド履歴を削除
2. yumのキャッシュ削除
3. 仮想ハードディスクの領域を削除
4. シャットダウン

```
[root@localhost ~]# export HISTSIZE=0
[root@localhost ~]# yum clean all
[root@localhost ~]# rm -rf /var/cache/yum
[root@localhost ~]# dd if=/dev/zero of=/ZERO bs=1M
[root@localhost ~]# rm -f /ZERO
[root@localhost ~]# shutdown -h now
```

### 5. 仮想マシンからVagrant Boxの作成
作成したVirtualMachineからVagrant Boxを作成します。
`--base` には先程作成したVirtualMachineの名前を入れます。

```
$ vagrant package --base Amazon\ Linux\ 2 --output amazonlinux-2.box
```

### 6. VagrantにBoxを登録します。

```
$ vagrant box add --name amazonlinux-2 amazonlinux-2.box
```

### 7. Vagrantfileを作成します。

```
$ vagrant init amazonlinux-2
```

### 8.Vagrantfileを編集します。
このままだとVagrantがAmazonLinuxのOSを認識できないくて下記のようなエラーが出るので`Vagrantfile`に設定を追加します。

```
The guest operating system of the machine could not be detected!
Vagrant requires this knowledge to perform specific tasks such
as mounting shared folders and configuring networks. Please add
the ability to detect this guest operating system to Vagrant
by creating a plugin or reporting a bug.
```

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

# All Vagrant configuration is done below. The "2" in Vagrant.configure
# configures the configuration version (we support older styles for
# backwards compatibility). Please don't change it unless you know what
# you're doing.
Vagrant.configure("2") do |config|
  # The most common configuration options are documented and commented below.
  # For a complete reference, please see the online documentation at
  # https://docs.vagrantup.com.

  # Every Vagrant development environment requires a box. You can search for
  # boxes at https://atlas.hashicorp.com/search.
  config.vm.box = "amazonlinux-2"
  config.vm.guest = :amazon
```

```ruby:
config.vm.guest = :amazon
```
上記の設定を追記して下さい。

### 9. Vagrantを起動します。

```
$ vagrant up
Bringing machine 'default' up with 'virtualbox' provider...
==> default: Importing base box 'amazonlinux-2'...
==> default: Matching MAC address for NAT networking...
==> default: Setting the name of the VM: vagrant_default_1513928756749_90132
==> default: Clearing any previously set network interfaces...
==> default: Preparing network interfaces based on configuration...
    default: Adapter 1: nat
==> default: Forwarding ports...
    default: 22 (guest) => 2222 (host) (adapter 1)
==> default: Booting VM...
==> default: Waiting for machine to boot. This may take a few minutes...
    default: SSH address: 127.0.0.1:2222
    default: SSH username: vagrant
    default: SSH auth method: private key
    default:
    default: Vagrant insecure key detected. Vagrant will automatically replace
    default: this with a newly generated keypair for better security.
    default:
    default: Inserting generated public key within guest...
    default: Removing insecure key from the guest if it's present...
    default: Key inserted! Disconnecting and reconnecting using new SSH key...
==> default: Machine booted and ready!
==> default: Checking for guest additions in VM...
==> default: [vagrant-hostsupdater] Checking for host entries
==> default: Mounting shared folders...
    default: /vagrant => /Users/winky/amzonlinux2/vagrant
```

```
$ vagrant ssh
Last login: Fri Dec 22 07:23:40 2017

       __|  __|_  )
       _|  (     /   Amazon Linux 2 AMI
      ___|\___|___|

https://aws.amazon.com/amazon-linux-2/
No packages needed for security; 2 packages available
Run "sudo yum update" to apply all updates.
[vagrant@localhost ~]$
```

SSH接続してこのようになれば成功です。

### まとめ
いままではDokcer Imageしか配布されていなかったのでEC2の構築などをローカルでテストしづらかったのですが、今回のリリースによってここらへんがすごく楽になりました。

### 参考文献
[LinuxにVirtualBox Guest Additionsを入れる方法まとめ](https://linuxfan.info/virtualbox-guest-additions)
[VagrantでAmazon Linux 2を実行する](https://dev.classmethod.jp/server-side/run-amazon-linux-2-on-vagrant/)
[cloud-initのデフォルト挙動を徹底的に調べてまとめてみた](https://dev.classmethod.jp/cloud/aws/cloud-init-cfg/)