vagrantではじめるクラウド開発環境（DigitalOcean編）


# DigitalOceanとは

![digitalocean01](https://24.media.tumblr.com/c649a91fc06782103b524e2f5f9e162a/tumblr_n5hi5rwJIP1tbcnimo1_1280.png)

[DigitalOcean](https://www.digitalocean.com/?refcode=1253632a31d5)公式の説明ではこうあります。

> DigitalOcean is a platform created for developers who need to launch and scale their applications quickly. Additionally, DigitalOcean provides the perfect environment for developers to play around on the command line and learn more about customizing their own servers.

[DigitalOcean](https://www.digitalocean.com/?refcode=1253632a31d5)は、AWSのEC2の機能のみを特化させたようなクラウドプラットフォームです。

## 特徴

* 見易くシンプルな管理画面
* 高性能（ディスクはどのプランでもSSD）
* 安い
* 料金体系が明確（$5/month〜）

## AWSとの比較

[DigitalOcean](https://www.digitalocean.com/?refcode=1253632a31d5)のサービスはAWSのEC2に非常に似ており、基本的にはオンデマンドでインスタンスを作成して手軽に利用できるというものです。EC2と比較するとそのシンプルさゆえに **以下に挙げる機能はありません** 。

* RI（Reserved Instance）
* Marketplace
* AvailabilityZone
* SecurityGroup
* ElasticIP
* ELB
* VPC

複雑なNW構成を必要とするシステムには向きませんが、ちょっとした技術検証や構成管理ツールのテスト、静的サイトのホストといった用途にはかなり便利に使えます。最安プランでもSSD/20GBという大盤振る舞いです。

# 背景

前に「[vagrantではじめるクラウド開発環境（AWS編）](http://qiita.com/msykiino/items/1a8c8157978abff51229)」という記事を書いてみたんですが、同僚からは「AWSはいいからDigitalOceanの記事はよ。つーか、おまえいまDigitalOceanしか使ってなくね？」というしょんぼりなツッコミくらったので、[DigitalOcean](https://www.digitalocean.com/?refcode=1253632a31d5)版も書いてみました。

社内で[ansible](http://www.ansible.com/)の使い方を説明した時に[DigitalOcean](https://www.digitalocean.com/?refcode=1253632a31d5)のインスタンスを使ってDEMOしてみたところ、ansibleよりも[DigitalOcean](https://www.digitalocean.com/?refcode=1253632a31d5)の方に興味がいってしまったようです。たしかに、ぼくも業務ではAWSを使いますが、個人的な技術検証などは[DigitalOcean](https://www.digitalocean.com/?refcode=1253632a31d5)ばかり使っています。

AWSは料金体系が分かりづらいので結局いくら請求くるんだ？！という潜在的な恐怖がありますが、[DigitalOcean](https://www.digitalocean.com/?refcode=1253632a31d5)の場合はこのプランのインスタンスなら1ヶ月フルで使い続けてもいくら（正しくは時間単位の課金ですが）という目安が分かり易いので、そういった意味ではクラウドサービスを利用するはじめの一歩としては心理的障壁が非常に低いというメリットがあります。

**$5/month** からSSDのインスタンスが使えること、Singaporeリージョンができて日本から使う場合の地理的デメリットが（だいぶ）解消されたことも大きな魅力です。

例によって、こちらもネタとしては旬な時期は終わってますけど。。

# したごしらえ

vagrantからはじめて[DigitalOcean](https://www.digitalocean.com/?refcode=1253632a31d5)を使うために最低限、必要なことを説明します。

プロジェクトやチームで本格的に利用する際は、ssh秘密鍵の管理方法含め、所属している会社や部署の運用ポリシーやセキュリティーポリシー等に従うようにしてください。

## アカウントの作成

[DigitalOcean](https://www.digitalocean.com/?refcode=1253632a31d5)のアカウントがまだなければ[こちら](https://www.digitalocean.com/?refcode=1253632a31d5)からサインアップします。
メールアドレスの認証 && クレジットカード登録かPayPalでデポジット（$5〜）が必要です。

ぼくはクレジットカードを登録してます。

後から支払い方法の変更をする場合は、ログイン後に左メニューの```Billing```からできますが、メールアドレスを変更した場合は先に変更後のメールアドレスの認証を済ませておかないと支払い方法の変更や明細確認ができないので、そこだけ注意です。


## sshキーペアの生成

id：pwによる認証も可能ですが、ここはAWSに倣ってssh鍵認証方式を採用します。

MacBookなら以下のコマンドを実行してsshキーペアを生成できます。

秘密鍵にパスワードを設定しない場合は、そのまま```ENTER```を押して進んでください。
（ぼくはパスワードなしの鍵にしてます）

```
ssh-keygen -t rsa -b 4096 -f ~/.ssh/vagrant_do.pem
```

実行結果

```
$ ls ~/.ssh/
vagrant_do.pem     # ssh秘密鍵
vagrant_do.pem.pub # ssh公開鍵
```

生成したらpermissionを設定します

```
chmod 700 ~/.ssh ;
chmod 600 ~/.ssh/vagrant_do.pem ;
chmod 644 ~/.ssh/vagrant_do.pem.pub ;
```

以降は、秘密鍵にこの **vagrant_do.pem** を使う前提で進めます。

## ssh公開鍵の登録

sshキーペアの生成ができたら、生成した公開鍵を[DigitalOcean](https://www.digitalocean.com/?refcode=1253632a31d5)に登録します。

公開鍵の登録はログイン後に左メニューの```SSH Keys```からできます。

```Add SSH Key```ボタンを押して、```Enter Name```の項目に **vagrant** と入力します。
キー名は大文字/小文字を区別するので注意！

```Public SSH Key```の項目には公開鍵の中身を貼り付けます。

```
cat ~/.ssh/vagrant_do.pem.pub
```

できたら```CREATE SSH KEY```を押して公開鍵の登録はおしまい。

## API Keyの発行

vagrantから[DigitalOcean](https://www.digitalocean.com/?refcode=1253632a31d5)を操作するための```API Key```を発行します。

```API Key```はログイン後に左メニューの```API```の画面で```Generate New Key```で発行できます。
発行したら以下の情報を確実に控えておきます（特に```API Key```は後から確認できません）

* Client ID
* API Key

以降は、この認証情報を使う前提で進めます。

# 導入

したごしらえが済んだらvagrantを使う準備をしましょう。

## 環境

作業環境は **MacOSX 10.9.2 Mavericks** を使う前提で進めます。

## vagrantのインストール

[公式サイト](http://www.vagrantup.com/downloads.html)からインストーラーをダウンロードしてインストールします。
特に躓くことはないと思います。

## vagrantプラグインのインストール

vagrantから[DigitalOcean](https://www.digitalocean.com/?refcode=1253632a31d5)を操作するには[vagrant-digitalocean](https://github.com/smdahlen/vagrant-digitalocean)というプラグインを利用します。
設定ファイルを個別に管理できる[dotenv](https://github.com/bkeepers/dotenv)というプラグインもインストールしておきましょう。

以下のコマンドを実行します。

```
vagrant plugin install dotenv ;
vagrant plugin install vagrant-digitalocean ;
vagrant plugin list ;
```

# 設定

以降は、以下のディレクトリで作業する前提で進めます。

```
/Users/ユーザー名/vagrant-do-test
```

## Vagrantfile

vagrantから[DigitalOcean](https://www.digitalocean.com/?refcode=1253632a31d5)を操作するための設定ファイルを作ります。
下記のコードを **Vagrantfile** というファイル名で保存します。

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

Dotenv.load

# change default provider to digital_ocean
ENV['VAGRANT_DEFAULT_PROVIDER'] = "digital_ocean"

# Vagrantfile API/syntax version. Don't touch unless you know what you're doing!
VAGRANTFILE_API_VERSION = "2"

Vagrant.configure(VAGRANTFILE_API_VERSION) do |config|

  config.vm.provider :digital_ocean do |provider, override|
    override.vm.hostname          = "vagrant-do-test"
    override.vm.box               = "digital_ocean"
    override.vm.box_url           = "https://github.com/smdahlen/vagrant-digitalocean/raw/master/box/digital_ocean.box"
    override.ssh.username         = ENV['DO_SSH_USERNAME']
    override.ssh.private_key_path = ENV['DO_SSH_KEY']

    provider.client_id            = ENV['DO_CLIENT_ID']
    provider.api_key              = ENV['DO_API_KEY']
    provider.ssh_key_name         = "vagrant"
    provider.region               = "Singapore 1"
    provider.image                = "CentOS 6.5 x64"
    provider.size                 = "512MB" # 512MB | 1GB | 2GB | 4GB | 8GB | 16GB
    provider.private_networking   = true
    provider.ca_path              = "/usr/local/share/ca-bundle.crt"
    provider.setup                = true

    # disable synced_folder: rsync is not installed on DigitalOcean's guest machine
    override.vm.synced_folder "./", "/vagrant", disabled: true

    # provision
    # Do whatever you wanna do !!
  end

end

```

### image

このパラメーターには、管理画面からDropletを作成するときに選択可能なイメージならなんでも指定できます。素のCentOSのイメージから、```Ruby on Rails```などのアプリケーションが設定済みのイメージ、Dropletから自分で作ったイメージ（Snapshot）まで指定できます。

時間のかかる構築系の処理を予め終えたうえで```Snapshot```を作成して、その```Snapshot```からDropletを作るような運用をすればかなりの時間が節約できます。

ただし、```Snapshot```からDropletを作成するには以下の制限があります。

* Snapshot元のDropletと同じリージョン（Snapshotのリージョン間コピーは可能）
* Snapshot元のDropletと同じサイズのディスク


### private_networking

このパラメーターを```true```にすると、private_networking用のNIC（eth1）が追加されます。

スタンドアロンサーバーとして使うぶんには```Private Network```は設定しなくても困りませんが、例えばmysqlのレプリケーションのテストをしたいときなどGlobal側のNICでコネクションを張りたくはないので、そういった場合はprivate_networkingを有効にしておくとよろしいかと。

private_networkingを有効にしても料金は変わりませんし、後述する理由からぼくは基本的にすべてのDropletで最初からprivate_networkingを有効にしています。

### setup

このパラメーターを```true```にすると、```ssh.username```で指定したユーザーが存在しなければ自動でそのユーザーを作成して、パスワードなしで```sudo```できるように設定してくれます。

### vm.synced_folder

このパラメーターは同期フォルダの設定に使われます。

この機能を有効にするにはrsyncパッケージがインストールされている必要がありますが、[DigitalOcean](https://www.digitalocean.com/?refcode=1253632a31d5)の```CentOS 6.5 x64```イメージにはrsyncパッケージがインストールされていないため、この機能を有効にするとエラーになります。

同期フォルダの機能を使いたい場合は、Droplet作成後にsshでログインしてrsyncパッケージをインストールしてからVagrantfileで```synced_folder```を有効にして再度、```vagrant provision```すれば使えます。

## .env

続いて、APIの認証情報を **.env** というファイルに記述します。
.envはVagrantfileと **同じ場所** に保存します。

以下のテンプレートを編集して使います。

```
# enable SSL communication with DigitalOcean
SSL_CERT_FILE=/usr/local/share/ca-bundle.crt

DO_SSH_USERNAME="ec2-user"
DO_SSH_KEY=${HOME}/.ssh/vagrant_do.pem
DO_CLIENT_ID="置き換える"
DO_API_KEY="置き換える"
```

ここでは、```ssh.username``` に渡す値に ```ec2-user``` を指定しています。
AWSとsshのユーザーを揃えることで、後々のAWSへの移行のしやすさなど意識しています。


以上で設定は終わりです。

# 使い方

では早速、使ってみましょう。

**Vagrantfile** のある場所に移動して以下のコマンドを実行します。

```
vagrant up --provider=digital_ocean
```

Vagrantfileで```VAGRANT_DEFAULT_PROVIDER=digital_ocean```を設定しているのでプロバイダーの指定は実は省略可能ですが、ひとつの```Vagrantfile```で複数プロバイダーに対応させることもできるので、使用するプロバイダーは明示する癖をつけておきましょう。

初回は **Droplet** の起動に少々時間がかかるかもしれません。
（[DigitalOcean](https://www.digitalocean.com/?refcode=1253632a31d5)ではAWSのEC2インスタンスに相当するものを **Droplet** と呼びます）

起動できたか現在のステータスを確認してみましょう。

```
vagrant status
```

無事に起動できたらsshでログインしてみます。

```
vagrant ssh
```

拍子抜けするほど簡単ですね？

以下のコマンドを実行しておけばvagrant経由でなくともDropletにsshできるようになります。
いちいちPublicIPを調べなくていいので非常に便利です。

```
# sshの設定をvagrant-do-testという名前で書き出す
vagrant ssh-config --host vagrant-do-test >> ~/.ssh/config

# vagrant-do-testと名前を付けたDropletにsshでログインする
ssh vagrant-do-test
```

[DigitalOcean](https://www.digitalocean.com/?refcode=1253632a31d5)のDropletは起動していても停止していても時間あたり課金される額は同じです。
使い終わったDropletは不要であれば **削除** しましょう。

```
# シャットダウン
vagrant halt

# 削除
vagrant destroy
```

AWSと違いこのまま1ヶ月起動放置でいくら？が、かなり明確なのでさほど恐怖感はないですｗｗ
これ、個人でクラウドを利用するときはかなり重要なファクターです！

# プロビジョニングしてみる

せっかくなので、```vagrant up```でプロビジョニングも同時に実行するようにしてみましょう。
```shell provisioner```と[ansible](http://www.ansible.com/home)を組み合わせたサンプルコードを用意しました。

```git clone``` してからブランチをcheckoutします。

```
git clone https://github.com/msykiino/codebox.git vagrant-casual-do ;
cd vagrant-casual-do ;
git checkout vagrant-casual-do ;
```

**.env** の認証情報を書き換えます。
これまでの行程をすべてやっていれば、先で作った **.env** をそのままコピーして使えます。

```
vim ./.env
```

認証情報を書き換えたらいざ、実行。

```
vagrant up --provider=digital_ocean --provision
```

Dropletが作成され、nginxとelasticsearch、elasticsearchのMarvelプラグインがインストールされすぐに利用できる状態になっているはずです（コマンド実行から構築が終わるまで5分少々かかるかもしれません）

```vagrant up```が終わったらサーバーのIPアドレスを確認しましょう。

```
vagrant ssh-config # HostNameの項目のIPアドレスをコピーしてブラウザでアクセス
```

IPを確認したらブラウザでアクセスします。

```
＃ elasticsearch Marvel
http://IPアドレス/_plugin/marvel/
```

Marvel（kibana製）のかっこいい画面が出てきましたか？

![digitalocean02](https://24.media.tumblr.com/657987b4f04243def2b65c15a1a502eb/tumblr_n5hi5rwJIP1tbcnimo2_1280.png)

ブラウザで表示できたらMarvelにアクセスしつつ[htop](http://hisham.hm/htop/)でリソースをチェックしてみましょう。
```vagrant ssh```してサーバーにログインしたら以下のコマンドを実行します。

```
htop
```

![digitalocean03](https://24.media.tumblr.com/4e75667f1ea219e68c3d37ff03742edb/tumblr_n5hi5rwJIP1tbcnimo3_1280.png)

構成管理ツールと組み合わせることで、いつでも必要な時に、必要な環境が作れてしまいます。
ほんと三流インフラエンジニアなんてそろそろお仕事がなくなりそうですね；；

# 知っておくといいこと

[DigitalOcean](https://www.digitalocean.com/?refcode=1253632a31d5)を使う際に知っておくといいことなど、参考までに。

## セキュリティー対策

AWSであればマネジメントコンソールで **SecurityGroup＝Firewall** を設定することができます。
[DigitalOcean](https://www.digitalocean.com/?refcode=1253632a31d5)にはそういった機能がないため、自分でfirewallを設定をする必要があります。

Linuxの場合は **iptables** を利用することが多いと思います。

これまで自分でiptablesを設定する機会がなかったひとは是非この機会にトライしてみましょう！
すぐに使える設定は[こちら](http://centos.server-manual.com/centos6_iptables.html)のサイトが参考になります。

もう少し詳しく（でも分かり易く）知りたいひとは下記のサイトが参考になるとおもいます。

* http://www.atmarkit.co.jp/ait/articles/0912/01/news113.html
* http://itpro.nikkeibp.co.jp/article/COLUMN/20070327/266505/
* http://oxynotes.com/?p=6361

## Dropletの識別子

[DigitalOcean](https://www.digitalocean.com/?refcode=1253632a31d5)では **vm.hostname** がそのままDropletの識別子になります。

つまり、 **vm.hostname** が同じ値の **Vagrantfile** を使い回すとDropletがまだ存在しなければ作成されますが、既に存在する場合は新たに作成されずそのDropletへの参照が設定されます。

複数人で同じインスタンスを共有したい場合（共有サーバー的な使い方）は```vagrant ssh```すれば共有サーバーにログインできるのでこれはこれで便利です。デメリットとしては誰かが誤って```vagrant destroy```してしまうと共有サーバーが問答無用に削除されてしまいます:;(∩´﹏`∩);:

このあたりは運用ポリシーでカバーという形になりますが、複数人いるチームでメンバーがそれぞれ独立した開発インスタンスを持つ場合は、以下の構成をおすすめします。

* メンバー単位でsshの公開鍵を別々に設定する
* vm.hostnameにはメンバー名をprefixとして付けるルールにする（ **_** は使えません）

こうすることで、他のメンバーにDropletを削除されたり、間違ってログインされるのを防げます。

なお、AWSの場合は内部で別途インスタンス識別子をもっているため、 **vm.hostname** が同じ値の **Vagrantfile** を使い回しても **.vagrant** ディレクトリがない場合は```vagrant up```するたびに新しいインスタンスが作成されます。ただし、マネジメントコンソールのインスタンス一覧には```Name```が同じインスタンスがずらっと並んでしまいますが。。

## PublicIP

[DigitalOcean](https://www.digitalocean.com/?refcode=1253632a31d5)には、AWSのElasticIPのような機能はありません。
そのため固定IPのみを確保してそれを特定のDropletに付けたり外したりはできません。

Dropletを作成すると自動的にPublicIPが1つ割り当てられます。
このIPはDropletを削除するまで解放されないため固定IPとして利用することができます。
（Dropletを停止してもIPは解放されません）

Dropletを削除した場合でも一定期間はアカウントに紐付けられているようなので、
Dropletを削除して直後に新しいDropletを作成すると同じPublicIPが割り当てられます。
```vagrant rebuild```することで同じIPでDropletを作り直すことができます。


## Private Network

[DigitalOcean](https://www.digitalocean.com/?refcode=1253632a31d5)を使いはじめた当初はスタンドアローンな使い方しかしていなかったのですが、
クラスター構成でmysqlのレプリケーションをPrivateIPでやろうとしたとき見事に嵌りました。

公式サイトによると、後からPrivateIPを割り当てるには一度Dropletを停止してから、
Dropletの```Settings```で```Private Network```を有効にしてDropletを起動し直せば良いとあります。

実際、その通りにやったところDropletが起動しなくなりました。
サポートに問い合わせた回答がコレ↓

>
Sorry for the trouble! Right now, there is an issue when enabling private networking on a droplet in our Singapore datacenter. Our engineers are aware of it and working on it, but they have given us a work around so you can get all of your droplets enabled with private networking. At this time, I disabled private networking in your droplet so it can boot up properly!

>
To enable private networking, you will have to do a snapshot and redeploy, while making sure to check the Private Networking checkbox. The process for this is:
1) create a snapshot of your server
2) delete your server to release the IP
3) immediately after the delete is finished, create a new droplet, choose the same datacenter, and in the "select images" section switch to "my images" and select your snapshot. This server will almost always capture the IP just released.

Singaporeデータセンターで起きているバグで、エンジニアも認識しているとのこと。
とりま、以下の手順で対応できるよとのこと。

1. PrivateIPを有効にしたいDropletのSnapshotをとる
1. SnapshotをとったらDropletを削除してPublicIPを解放する
1. 削除した直後に同じリージョンにSnapshotから新しくDropletを作り直す

Dropletを削除してIPを解放した直後にDropletを作成すると解放したIPをキャプチャできるとのこと。
（現時点では **ほぼ** 必ずそうなるようですが、保証はされていません）

上記のworkaroundで無事対応できましたが[DigitalOcean](https://www.digitalocean.com/?refcode=1253632a31d5)はまだまだこれからという部分もあるので、
このあたりは上手く付き合っていく必要があるとおもいます。

## サポート

[DigitalOcean](https://www.digitalocean.com/?refcode=1253632a31d5)を使っているとサポートに問い合わせることが少なくありません。
まぁ、これはAWSでも一緒ですが。。

サポート体制にはかなり力を入れているようで問い合わせてから数時間、早いと数十分で回答がきます。
問い合わせた内容を調査したうえで、かなり具体的に回答してくれるので個人的には高く評価しています。
サポート料は別途、みたいなこともありません。。

サポートへは、ログイン後に左メニューの```Support```から```New Ticket```を作成して問い合わせできます。
やり取りが終わって問題が解決したらticketは```close```しましょう。

やり取りは **英語** のみですが、これは英語の練習をするチャンス！と思いどんどん活用すればいいです。
ただし、質問する前に **過去ログ** はきちんとチェックするようにしましょう！

# まとめ

個人的に[DigitalOcean](https://www.digitalocean.com/?refcode=1253632a31d5)を使い始めてからしばらく経ちますが、ほんとに気に入ってます。安くて、手軽で、使い易くていま一番気に入ってるサービスのひとつです。

社内で勉強会やハッカソンをやるときなど、サンプルコードひとつ動かすにしてもまず環境を整えるのが手間だったりしますが、こうしたクラウドサービスを活用することで同じ環境をみんなで手軽に共有できるので、いままで構築にかけていた時間を実装に回せるなどかなりのメリットがあります。

もちろん、VirtualboxやVMwareでも同じ事はできますが、みんなが同じマシンを使っていることなどまずないので、スペックの違いから足並みが揃わなかったり、動作が遅くてストレスフルだったり、FANが爆音立ててフルパワーで回りまくって精神衛生上よろしくなかったりといろいろ問題もあります。なにより、物理マシンの場合はHWの保守という最悪に面倒くさい作業がつきまといます。古くなったマシンの処分にも困りますし。。

そういった問題がたった **$0.007/hour** で解決できます、すごいですよね！

日本でも、もっと[DigitalOcean](https://www.digitalocean.com/?refcode=1253632a31d5)の利用が広まってくれて、
そしていつか **Japanリージョン** できてくれたらいいのになーぁーなんて...