[無料]Arukas上のコンテナを外形監視~Slack通知も~

# お題

  - [Arukas](https://arukas.io)はエンドポイント以外のグローバルIP/ポートは変わっちゃうことがあるよ
  - グローバルIP/ポートが変わったらすぐわかるように外形監視しておくよ
  - 監視はさくらのクラウドの[シンプル監視](http://cloud-news.sakura.ad.jp/simplemonitor/)を使えば無料だよ
  - Terraformを使えばArukas/シンプル監視を紐付けてコマンド一発で構築できるよ

# 概要

[Arukas](https://arukas.io)はさくらインターネットが提供するDockerコンテナのホスティングサービスです。

現状β版で、[無料](https://arukas.io/#pricing)で使えます。
手軽にコンテナを起動しておける便利な環境なのですが、

    一定期間でコンテナが再起動される = (エンドポイント以外の)グローバルIP/ポート番号が変化する

という仕様になっています。(参考：[Arukas:サービス仕様](https://arukas.io/help/help-specification/))

そこでグローバルIP/ポートが変わったら気づけるように、さくらのクラウドの[シンプル監視](http://cloud-news.sakura.ad.jp/simplemonitor/)を用いて監視し、変更があったらメール or Slackへ通知が来るようにしてみます。

また、単純に監視設定するだけでは、変化がある度にシンプル監視の対象グローバルIP/ポート番号を変更しないといけません。
これはちょっと面倒なため、[Terraform](https://www.terraform.io)を用いることでコマンド一発で設定できるようにしてみます。

なお、さくらのクラウドの[シンプル監視](http://cloud-news.sakura.ad.jp/simplemonitor/)は、対象がさくらインターネットの提供するグローバルIP、かつ監視対象をIPアドレスで指定すれば無料で使えちゃいます。嬉しいですね:bangbang:

# 構築

## 準備

以下が必要です。

  - `Terraform`のインストール
  - `Terraform for さくらのクラウド`のインストール + APIキーの発行
  - `Terraform for Arukas`のインストール + APIキーの発行

下記ページを参考に準備してください。

[Terraform for さくらのクラウドのインストール](https://github.com/yamamoto-febc/terraform-provider-sakuracloud/blob/master/docs/installation.md)
[Terraform for Arukasのインストール](https://github.com/yamamoto-febc/terraform-provider-arukas/wiki/Install)

APIキーを取得したら以下コマンドで環境変数に設定しておいてください。

```bash:APIキーを環境変数に設定
# さくらのクラウド APIキー
$ export SAKURACLOUD_ACCESS_TOKEN=[取得したAPIキー]
$ export SAKURACLOUD_ACCESS_TOKEN_SECRET=[取得したAPIシークレット]

# Arukas APIキー
$ export ARUKAS_JSON_API_TOKEN=[取得したAPIキー]
$ export ARUKAS_JSON_API_SECRET=[取得したAPIシークレット]
```

## 定義ファイル作成

今回は例としてArukasでNginxコンテナを立ち上げ、80番ポートをEXPOSEします。
シンプル監視にてArukasが割り当てたグローバルIP/ポートの監視を行います。
通知はメールで行います。

以下のようなファイルを作成します。

```sakura.tf:Arukasとシンプル監視登録

# Arukasコンテナ定義
resource "arukas_container" "ct" {
    name = "arukas-with-simple-monitor"
    image = "nginx:latest"
    ports = {
        protocol = "tcp"

        # 80番ポートをEXPOSE
        number = "80"
    }
}

# さくらのクラウド シンプル監視定義
resource "sakuracloud_simple_monitor" "demo_monitor" {

    # 監視対象IPアドレス:arukas側の情報を参照
    target = "${arukas_container.ct.port_mappings.0.ipaddress}"

    health_check = {

        # tcpで指定ポートを監視
        protocol = "tcp"

        # 監視対象ポート番号:arukas側の情報を参照
        port = "${arukas_container.ct.port_mappings.0.service_port}"

    }

    # Eメールでの通知有効化
    notify_email_enabled = true

    # Slack通知を行う場合は以下2つのパラメータを設定すればOK
    # notify_slack_enabled = true
    # notify_slack_webhook = "https://hooks.slack.com/services/xxxxx"
}
```

各定義の詳細は以下のリファレンスを参照ください。

  - [Arukasコンテナ定義リファレンス](https://github.com/yamamoto-febc/terraform-provider-arukas/wiki/Configuration-Resource-Container)
  - [シンプル監視定義リファレンス](https://github.com/yamamoto-febc/terraform-provider-sakuracloud/wiki/Configuration-Resource-SimpleMonitor)

## コンテナ起動 & 監視登録

以下コマンドを実行してArukasでのコンテナ起動とシンプル監視の登録を行います。

```bash:terraform実行
$ terraform apply
```

出来ましたね？コントロールパネルなどから確認してみてください。

## コンテナを再起動させてみる & 監視再登録

Arukasのコントロールパネルからコンテナを再起動させてみましょう。
グローバルIP/ポート番号が変更され、シンプル監視でエラー検知されると思います。

、、、通知メール(or Slackへの通知)が届きましたか？

このままだと次回コンテナが再起動されたことを検知できないため、以下コマンドでシンプル監視を再登録しておきましょう。

```bash:シンプル監視再登録
# 再実行
$ terraform apply
```

これでコンテナ再起動で割り当てられた新しいグローバルIP/ポート番号への監視が行われます。
以降は通知が来たら都度`terraform apply`を実行するようにしてあげればOKです。

# まとめ

ArukasでIP/ポートが変わったら通知が来るようにできました。

例えばArukasで複数のポートをEXPOSEしている場合、エンドポイントが割り当てられるのは
最初のポートだけなため、２番目以降のポートは動的にポート番号が変わってしまう可能性があります。

こんな場合に今回の方法は有効だと思います。

また、今回使った`Terraform`なら複数のサービスにまたがったインフラ構成でも
作成/管理しやすいのでオススメです。是非使ってみてください。


### ボツネタ：現行Terraformバージョンでは使えない書き方

本当は以下のように書きたいんですが、、、現状できません。
`count`に対し、他のリソースを参照して値を設定する機能はTerraformに未実装です。
(2016/6/20現在:v0.6.16)
[Github:Issue](https://github.com/hashicorp/terraform/issues/1497#issuecomment-105874601)

以下のように書ければtfファイル作成がかなり楽になるのですが、、残念です。

```sakura.tf:現状この書き方だとダメ

resource "sakuracloud_simple_monitor" "demo_monitor" {
    # arukas側で公開したポート数分の監視設定を作成する
    count = "${length(arukas_container.ct.port_mappings)}"
    
    # 監視対象IPアドレス,arukas側の情報を参照
    target = "${arukas_container.ct.port_mappings.*.ipaddress[count.index]}"
    health_check = {
        protocol = "tcp"

        # 監視対象ポート番号,arukas側の情報を参照
        port = "${arukas_container.ct.port_mappings.*.service_port[count.index]}"
    }
    notify_email_enabled = true
}

```