さくらのクラウドでAuto Scaling ~ Docker活用編 ~


# 前書き

## この記事を書くきっかけ

先日さくらのナレッジに[【TIPS】さくらのクラウドでAuto Scaling](http://cloud-news.sakura.ad.jp/2016/03/18/auto-scaling/)という記事が上がっていました。

この記事では

  - ロードバランサ アプライアンス
  - スイッチ + ルーター
  - クローン機能
  - APIクライアントライブラリ`Saklient`
  - `Saklient`を使った監視~スケールイン/アウトの操作を行うRubyプログラム

という構成でAutoScalingを実現しています。

この記事を読んだ時、少し気になる点がありました。

## さくらのナレッジのAutoScalingには気になる点が、、

上記の方法だと、 **費用**が結構気になります。
最小構成でも、、

#### さくらのクラウドAutoScale費用(ロードバランサ + スイッチ/ルーター方式)

| 品目                | 費用(月額)          |
|:--------------------|------------------:|
|ロードバランサ(標準プラン) | 2,571円|
|スイッチ + ルーター(100Mbps) | 4,320円|
|追加IPアドレス(16個) | 3,456円|
| Webサーバ(1コア1GBメモリ、20GBディスク) | 1,954円|
|**合計** |    **12,301**円|


うーん、そんなにちゃんとしたやつじゃなくていいから、もうちょい安くできないか、、
ということで今回、Docker、DockerMachineとさくらのクラウドの
GSLB(広域負荷分散)を用いることで安価なAutoScalingする構成を考えてみました。


# 安価なAutoScalingの方法/構成

----

**デモプログラムを以下で公開しています。**
https://github.com/yamamoto-febc/sakura-auto-scaling-with-docker

----


## 概要

以下のような構成を考えてみました。

  * [さくらのクラウドのGSLB(広域負荷分散)](http://cloud-news.sakura.ad.jp/gslb/)でDNSラウンドロビン
  * [さくらのクラウドAPI](http://developer.sakura.ad.jp/cloud/api/1.1/server/#get_server_serverid_monitor)でサーバのCPU負荷を測定
  * サーバーは1台常に起動させておく(基本サーバ)
  * CPU負荷に応じてスケールアウト/スケールインを行う。
    - サーバの追加/削除にはDockerMachine + [さくらのクラウド用ドライバ](https://github.com/yamamoto-febc/docker-machine-sakuracloud)を使う
    
    :star: docker-machine-sakuracloudでのマシン作成時/削除時にGSLBへのサーバー自動登録が行えます

まず、アクセスが閑散としている状態の時は以下のような構成となります。

### アクセスが閑散としている状態での構成(最小構成)

![basic.png](https://qiita-image-store.s3.amazonaws.com/0/20668/3b6f15bc-b1c3-5c79-bad6-e2ea40f95774.png "basic.png")


GSLBには常に起動させておく`基本サーバ`のIPのみが登録された状態です。
クライアントからのDNS参照時は常に`基本サーバ`のIPが応答されます。

基本サーバではあらかじめApache(PHP)+コンテンツをDockerイメージとして構築しておき、
Dockerコンテナ上で動かします。
スケールアウト時に作成されるサーバ上でもこのイメージを使ってDockerコンテナを起動します。

### スケールアウトの流れ

![Scaling.png](https://qiita-image-store.s3.amazonaws.com/0/20668/16cc174b-834f-2326-ecd2-0bdef0698cdd.png "Scaling.png")


#### 処理の流れ

監視プログラムはcronなどで定期的に起動させます。


    ①  さくらのAPI経由でCPU負荷を取得、判定
    
    ②  DockerMachineでさくらのクラウド上にマシンを作成
        マシン作成と同時にGSLBヘの登録、Dockerコンテナの起動が行われます。
       
    ③  GSLBが死活監視で追加されたサーバでのサービス起動を確認します。
        確認ができたら新サーバのIPをDNS応答するようになります。
   
クライアントからのDNS参照時は基本サーバのIPと新サーバのIPが
ラウンドロビンで応答されます。

### スケールアウト時の構成

![ScaleOut.png](https://qiita-image-store.s3.amazonaws.com/0/20668/62f68496-48bd-02b6-7303-cfb6a0f9cc68.png "ScaleOut.png")


## 気になる費用は、、、

#### さくらのクラウドAutoScale費用(GSLB + Docker + DockerMachine方式)

| 品目                | 費用(月額)          |
|:--------------------|------------------:|
|GSLB(広域負荷分散) | 540円|
|DNSサーバ(1ゾーン) **※さくらのクラウド以外のDNSサーバでも可** | 43円|
| Webサーバ(1コア1GBメモリ、20GBディスク) | 1,954円|
|**合計** |    **2,537**円|

ロードバランサ + スイッチ/ルーター方式に比べて **月額9,764円もお得** !!
さらにこの方式なら基本サーバに[さくらのVPS](http://vps.sakura.ad.jp/)を使うこともできます。そうしたらさらにお安くできますね！

# 早速実践してみよう

## 必要なもの

  - ドメイン + DNSレコードの追加(CNAME)

  - Docker関連ソフトウェア
    - Docker
    - Docker Machine
    - Docker Machine さくらのクラウド用ドライバ
    - Docker Compose

※gitなどのコマンドは使えるようになっているという前提です。

## 手順

  1) Docker関連インストール
  2) オートスケールのデモプログラムをGitHubからクローン
  3) さくらのクラウドAPIキー取得、設定ファイルに記載
  4) 初回実行(基本マシンの作成、GSLB/DNS設定も)
  5) RUN!!!
  
  なお、以下手順はMac(OSX)にて説明していますが、
  Windows環境でもbashが使えればほぼそのままで実施できると思います。
  
## 手順詳細

### 1) Docker関連インストール

#### Docker Toolbox

[Docker Toolbox](https://www.docker.com/products/docker-toolbox)をインストールすると、以下がまとめてインストールできます。

  - Docker
  - Docker Machine
  - Docker Compose

もちろん上記を個別にインストールしても構いません。

Docker Toolboxは[こちら](https://www.docker.com/products/docker-toolbox)からダウンロードしてインストールしてください。

#### Docker Machine さくらのクラウド用ドライバ

[Github上のリリースページ](https://github.com/yamamoto-febc/docker-machine-sakuracloud/releases)からバイナリをダウンロード & 実行権を与えるだけでOKです。

以下のコマンドで/usr/local/bin配下にダウンロード + 実行権付与が行えます。

```
curl -L https://github.com/yamamoto-febc/docker-machine-sakuracloud/releases/download/v0.0.10-p1/docker-machine-driver-sakuracloud-`uname -s`-`uname -m` >/usr/local/bin/docker-machine-driver-sakuracloud && \
  chmod +x /usr/local/bin/docker-machine/docker-machine-driver-sakuracloud
```

### 2) オートスケールのデモプログラムをGitHubからクローン

以下コマンドでGitHubからデモプログラムをクローンします。

```bash
git clone https://github.com/yamamoto-febc/sakura-auto-scaling-with-docker.git
cd sakura-auto-scaling-with-docker
```

### 3) さくらのクラウドAPIキー取得、設定ファイルへの記載

さくらのクラウドのコントロールパネルにログインしAPIキーを発行します。
以下を参考に実施してください。

#### さくらのクラウド(IaaS)を選択

![01_コンパネ.png](https://qiita-image-store.s3.amazonaws.com/0/20668/d92259d1-383c-f6a3-ede0-5f49dcd095ef.png "01_コンパネ.png")

#### APIキー発行画面へ移動

![02_APIキー.png](https://qiita-image-store.s3.amazonaws.com/0/20668/d921fbc3-e7db-7dcf-75e9-db28200f7de3.png "02_APIキー.png")

#### APIキーの発行

![03_APIキー.png](https://qiita-image-store.s3.amazonaws.com/0/20668/a217f3ac-af08-e06f-0906-0b3cbd79ad08.png "03_APIキー.png")

#### 発行されたAPIキーの確認

![04_APIキー.png](https://qiita-image-store.s3.amazonaws.com/0/20668/778ed38e-ee37-b9df-e408-cbf0d2b33940.png "04_APIキー.png")

#### APIキーの設定

控えたAPIキーを設定ファイルに記載します。

```bash
cp env.sample .env    # 設定ファイルひな形をコピー
vi .env               # 設定ファイルを編集

#==============================================================================
# APIキー(アクセストーン、シークレット)を記入してください
export SAKURACLOUD_ACCESS_TOKEN=先ほど控えたトークンを入力
export SAKURACLOUD_ACCESS_TOKEN_SECRET=先ほど控えたシークレットを入力

# 利用するリージョン(石狩第1、石狩第2、東京いづれか)を指定してください。
export SAKURACLOUD_REGION=is1a / is1b / tk1a のいずれかを入力
#==============================================================================
```

#### オプション：オートスケールの閾値などの設定を変更したい場合

`settings.sh`にオートスケール関連の設定が記載されています。
オートスケールの負荷判定閾値は以下２つのパラメータで設定します。

デフォルトでは、各サーバの平均CPU使用率が

  - 60%以上でスケールアウト
  - 40%以下でスケールイン

となっています。

##### settings.sh該当箇所抜粋
```bash
#******************************************************************************
# Name       : CPU_TIME_SCALE_OUT_THRESHOLD
# Description: スケールアウト閾値(CPU時間:)
#              1コアあたり1の時100%の使用率となる(あくまで目安らしい)
#              http://cloud-news.sakura.ad.jp/activity/#server
#              複数コアのマシンでスケールアウトさせる場合は計算に注意
#******************************************************************************
CPU_TIME_SCALE_OUT_THRESHOLD=0.6 #60%以上のCPU負荷でスケールアウト

#******************************************************************************
# Name       : CPU_TIME_SCALE_IN_THRESHOLD
# Description: スケールイン閾値(CPU時間:)
#              CPU_TIME_SCALE_OUT_THRESHOLDの説明を参照
#******************************************************************************
CPU_TIME_SCALE_IN_THRESHOLD=0.4 #40%以下のCPU負荷でスケールイン

```

#### オプション：Webサーバーのコンテンツを変更したい場合

以下のディレクトリにWebサーバーのコンテンツが格納されています。
`[GitHubからのクローン先ディレクトリ]/apps/html/`
クローンした状態ではデモ用のPHPファイルが一つだけ置いてある状態です。
ここにコンテンツを配置すればOKです。

### 4) 初回実行(基本マシンの作成、GSLB/DNS設定も)

以下のコマンドで初回起動を行います。

初回起動では以下の処理が行われます。

  - 基本マシン(Masterノード)の作成
  - さくらのクラウドへGSLB作成(デフォルトでは`sakura-autoscaling-gslb`という名前で作成される)

```bash

chmod +x auto_scaling.sh
./auto_scaling.sh

```

#### 参考：初回実行時の出力例

```bash
$./auto_scaling.sh 
Creating CA: /Users/hogehoge/.docker/machine/certs/ca.pem
Creating client certificate: /Users/hogehoge/.docker/machine/certs/cert.pem
Running pre-create checks...
Creating machine...
(sakura-autoscaling-master) Creating SSH public key...
(sakura-autoscaling-master) password is not set, generated password:xxxxx
(sakura-autoscaling-master) Created Server ID: 11280xxxxx
(sakura-autoscaling-master) Created Disk ID: 112800xxxxxx
(sakura-autoscaling-master) Waiting for disk to become available
(sakura-autoscaling-master) Editted Disk Id: 112800xxxxxxx
(sakura-autoscaling-master) Waiting for disk to become available
(sakura-autoscaling-master) Setting SakuraCloud GSLB: sakura-autoscaling-gslb
(sakura-autoscaling-master) Added GSLB,Please Set CNAME Record : ex. 'your-lb-hostname IN CNAME [site-1128003xxxxx.gslb3.sakura.ne.jp]'
(sakura-autoscaling-master) Waiting for server to become Running
(sakura-autoscaling-master) Waiting for server to become Stopped
(sakura-autoscaling-master) Waiting for server to become Running
Waiting for machine to be running, this may take a few minutes...
Detecting operating system of created instance...
Waiting for SSH to be available...
Detecting the provisioner...
Provisioning with ubuntu(upstart)...
Installing Docker...
Copying certs to the local machine directory...
Copying certs to the remote machine...
Setting Docker configuration on the remote daemon...
Checking connection to Docker...
Docker is up and running!
To see how to connect your Docker Client to the Docker Engine running on this virtual machine, run: /usr/local/bin/docker-machine env sakura-autoscaling-master
Creating network "apps_default" with the default driver
Building web
Step 1 : FROM php:apache
apache: Pulling from library/php
efd26ecc9548: Pull complete
a3ed95caeb02: Pull complete
589a9d9a7c64: Pull complete
4683f98d2423: Pull complete
d5f645469de1: Pull complete
2950971584b0: Pull complete
6fdfa3810627: Pull complete
75061bf48855: Pull complete
0f5751ac9b60: Pull complete
d14da6152c4e: Pull complete
ff7b20e586d5: Pull complete
c068e3c63576: Pull complete
f0b34f661a58: Pull complete
Digest: sha256:f14c45f43edd52947ca4e17db4f796ca4aebb72687ad63b2e19e6e5583a09715
Status: Downloaded newer image for php:apache
 ---> dc7c95ca2afc
Step 2 : MAINTAINER Kazumichi Yamamoto <yamamoto.febc@gmail.com>
 ---> Running in 3fd84af01152
 ---> 473bd6db11d3
Removing intermediate container 3fd84af01152
Step 3 : COPY html/ /var/www/html
 ---> 8037f0951d27
Removing intermediate container 1053bbc54724
Successfully built 8037f0951d27
Creating apps_web_1
******************************************************************
MasterNode created. Please re-run this script after a few minutes.
******************************************************************
```

#### GSLBの確認

初回起動できたらGSLBが作成されているはずです。
さくらのクラウドのコントロールパネルで確認してみましょう。
**確認時にDNSへのCNAMEレコード登録用にFQDNを控えておいてください。**

![05_GSLB一覧.png](https://qiita-image-store.s3.amazonaws.com/0/20668/da4d7da5-952c-d0a6-c9a6-4ba0760d4873.png "05_GSLB一覧.png")

#### DNSレコードの登録(さくらのクラウドDNS以外でも可)

GSLBのFQDNをスケールさせたいWebサーバのホスト名のCNAMEレコードとして登録します。
DNSサーバはさくらのクラウド以外のものでも良いですが、ここではさくらのクラウドDNSで説明します。

以下手順ではスケールさせたいWebサーバのホスト名を`auto-scaling.fe-bc.net`としています。
**さくらのクラウドDNSを使う場合は事前にDNSゾーン登録が必要です。**
DNSゾーン登録は[マニュアル](http://cloud-news.sakura.ad.jp/cloud_dns/)などを参考にあらかじめ行っておいてください。


まずはコントロールパネルからDNS管理画面を開きます。
![06_DNSゾーン一覧.png](https://qiita-image-store.s3.amazonaws.com/0/20668/896c5cf5-e7ba-e208-d41a-aea98601aeb4.png "06_DNSゾーン一覧.png")

次にレコードの追加画面を開きます。
![07_DNSゾーン.png](https://qiita-image-store.s3.amazonaws.com/0/20668/84d4e9c7-60c2-5713-e123-19eb85d48f9b.png "07_DNSゾーン.png")

追加画面では以下のように入力します。

  - 名前 : ホスト名(今回は`auto-scaling`と入力)
  - タイプ : `CNAME`を選択
  - FQDN : 控えておいたGSLBのFQDNをリストから選択
  - TTL : 10秒に設定

![08_DNSゾーン.png](https://qiita-image-store.s3.amazonaws.com/0/20668/10f77d3b-9895-51fa-d0cd-19d7af3a2eed.png "08_DNSゾーン.png")

作成後は「反映」ボタンを押すのを忘れずに!!

![09_DNSゾーン.png](https://qiita-image-store.s3.amazonaws.com/0/20668/950ff97d-0687-cc8c-04ca-8727fe067fa3.png "09_DNSゾーン.png")


#### Webサーバの動作確認

ここまででWebサーバにアクセスできるはずです。
ブラウザを開き先ほどCNAME登録したホスト名を入力します。
(当記事では`auto-scaling.fe-bc.net`で登録しましたね。)

うまくいけば以下のような画面が表示されるはずです。
名前解決ができない場合は少し待ってからアクセスしてみてください。

![kobito.1460281670.938568.png](https://qiita-image-store.s3.amazonaws.com/0/20668/09f05b7c-a32a-d2b0-93d2-77860a174bf4.png "kobito.1460281670.938568.png")


###  5) RUN!!!

あとは定期実行の設定をするだけです。
5分に一度起動するようにします。

```bash
crontab -e

# 5分ごとに実行する場合
# パスは各自読み替えてください。
*/5 * * * * /path/to/your/directory/auto_scaling.sh >> /var/log/sakura-auto-scaling.log 2>&1

```

CPU負荷の計測、スケールイン/アウトの様子は上記のログ`/var/log/sakura-auto-scaling.log`に出力されています。

後は負荷をかけてみてスケールイン/アウトする様子を観察してください。
負荷は例えば以下のようにしてかけます。

```bash

# 現在実行中のマシンの確認
$ docker-machine ls

NAME                         ACTIVE   DRIVER        STATE     URL                          SWARM   DOCKER    ERRORS
sakura-autoscaling-client1   -        sakuracloud   Running   tcp://153.127.193.231:2376           v1.10.3   
sakura-autoscaling-master    -        sakuracloud   Running   tcp://153.120.171.11:2376            v1.10.3   

# 負荷をかけたいマシンへ接続
$docker-machine ssh [マシン名]

# 接続後、以下コマンドを実施
$ openssl speed #CPU利用率がほぼ100%になります。5分程度で終了します。


```

### おまけ

#### Webサーバのログを見たいんだけど？

以下コマンドで見れます。
複数のコンソールを並べて、負荷の分散状況を確認するもよしですね。

```bash

# ログを見たいマシンのDockerデーモンを使うように環境変数設定
$ eval $(docker-machine env [マシン名])

# ログ確認
$ docker logs -f `docker ps -aq`


```

#### 後片付け

デモプログラムを動かした後はdocker-machineさくらのクラウド用ドライバでマシンを削除してください。
GSLBからの登録解除、もしGSLBにサーバが一台も登録されなくなる場合にはGSLBの削除も同時に行ってくれます。

```bash
$ docker-machine rm [マシン名]
```


## 今後の課題

さくらのVPSとの連携や、スケール対象のサーバ間でのデータ共有をどうするかなど
まだまだ改良の余地はあります。

スケール判定のためのメトリクスはCPU負荷のみしか現状取得できないですが、
取得に使っているDockerイメージを差し替えることで他の監視(zabbixとかcAdvisorとか)からでも
メトリクス集計が可能なはずです。

また、今回はシンプルにDocker+シェルスクリプトで動くように意識して作りました。
メトリクス収集〜判定〜スケーリングといった一連の流れをすべてDockerコンテナで実施するようにすれば
Dockerさえあればオートスケールできる！というのも可能かもしれないですね。

今後もDocker、DockerMachine、さくらのクラウドなどの各プロダクト/サービスの動向を見ながら
気軽にスケールできる環境を目指して開発を続けていきたいです。


以上です。