Check! OpenWhisk on Microsoft Azure !

こんにちは、 @dz_ こと大平かづみです。

Prologue - はじめに
====
[OpenWhisk Advent Calendar](http://qiita.com/advent-calendar/2016/openwhisk) 11日目の記事です。 まだまだ枠空いているので、ご参加お待ちしています！

さて、 Advent Calendar ネタを探していると、タイムリーにもマルチクラウドで　[OpenWhisk](https://developer.ibm.com/openwhisk/) をデプロイできるよ！という記事を見つけたので、便乗して OpenWhisk on Azure をやってみます！ヾ(･ω･oU三Uo･ω･)ﾉﾞ

- [MultiCloud OpenWhisk: Creating your own OpenWhisk deployment on IBM Bluemix Infrastructure and Amazon Web Services (AWS) | OpenWhisk](https://developer.ibm.com/openwhisk/2016/12/09/multicloud-openwhisk-creating-your-own-openwhisk-deployment-on-ibm-bluemix-infrastructure-and-aws/ "MultiCloud OpenWhisk: Creating your own OpenWhisk deployment on IBM Bluemix Infrastructure and Amazon Web Services (AWS) | OpenWhisk")
- [openwhisk/README_DISTRIBUTED.md · openwhisk/openwhisk](https://github.com/openwhisk/openwhisk/blob/master/ansible/README_DISTRIBUTED.md "openwhisk/README_DISTRIBUTED.md at master · openwhisk/openwhisk")

なお、上記のうち、上段の記事はいくつか誤りがあったので、下段の `README_DISTRIBUTED.md` も参考にするとよいです。また、今回は Azure に構築していますが、単なる Ubuntu インスタンスなので、AWS やほかの環境でもほぼ同等の手順となります。和訳記事としてご参考になれば幸いです！

作業環境
----
| 用途 | 台数 | 説明 |
|------|-----|------|
| ブートストラップ用 | 1 | `bootstrapper machine`. セットアップのため、稼働用インスタンスにSSH接続できるマシン。上記記事に従い、Ubuntu 14.04 を利用。お手元のマシンでも可能。 |
| OpenWhisk 稼働用 | 8 | OpenWisk を稼働させるインスタンス。 Ubuntu ベースで、それぞれ役割が異なる。 |

Azure Virtual Machine に OpenWhisk をセットアップする
====
ブートストラップ用マシンのセットアップ
----
ブートストラップ用マシンとして、Azure に、 HHD, A1 Basic で Ubuntu Server 14.04 LTS のインスタンスを用意しました。

てはじめに、 OpenWhisk のリポジトリをクローンし、ブートストラップ用のセットアップを行います。

```bash
# Clone openwhisk repository
$ sudo apt-get install git
$ git clone git@github.com:openwhisk/openwhisk.git

# Change current directory to openwhisk
$ cd openwhisk

# Install all required software
(cd tools/ubuntu-setup && source all.sh)
```

次に、Ansible に OpenWhisk 稼働用インスタンスにログインするための SSH の設定を行います。

```bash
# sshキー作成
$ ssh-keygen -t rsa -b 4096
$  eval $(ssh-agent -s)
$  ssh-add ~/.ssh/id_rsa

# 公開鍵を表示して、コピーし控えておいてください（のちに OpenWhisk 稼働用インスタンス作成時に指定します。）
$ cat ~/.ssh/id_rsa.pub

# Ansible.cfg ファイルを編集する
$ vi ansible/Ansible.cfg
```

`openwhisk/Ansible/Ansible.cfg` に `remote_user` を指定します。このユーザー名は、のちに OpenWhisk 稼働用インスタンス作成時に指定します。

```diff:openwhisk/ansible/ansible.cfg
 [defaults]
+remote_user = <login user>
```

なお、当初は 16.04 でも試しましたが、下記の @tokida さんの記事のような事象に出くわします。2016年12月の段階では、 14.04 をお勧めします。

- [Install OpenWhisk on Ubuntu 16.04 (2016.12.06) — Fail](https://medium.com/@tokida/install-openwhisk-on-ubuntu-16-04-2016-12-06-6d163ba66f63#.uw8nmwfp9)

ネットワークセキュリティグループの準備
----

OpenWhisk 稼働用インスタンスの作成前に、ネットワーク セキュリティ グループを用意しておきます。

AWS の場合はデフォルトのセキュリティーグループ（同一セキュリティグループでのインバウンドは全許可）とのことなので、Azure では、同一仮想ネットワーク内のインバウンドを許可したネットワーク セキュリティ グループを作成します。また、便宜上、自マシンからのみ SSH も開けておきました。


OpenWhisk 稼働用インスタンスの準備
----

さて、 8台の仮想マシンインスタンスを作成します。Azure ではテンプレートを使うと楽に量産できるのですが、プログラマの私は慣れてないので、泥臭くポータルから作ります…！

AWS での推奨スペックは `m3.large` とのことなので、CPUとメモリで候補を挙げてみました。だがしかし、懐への負担が大きいため `A1` にします！検証終わったら、すぐ落とすよ…！

| クラウド | インスタンスタイプ/仮想マシンサイズ | vCPU/CPU | メモリ | 1 台分の価格 | 8 台分の価格 |
|---------|----------------------|-------|--------|-------------------|----|
| AWS | m3.large | 2 | 7.5 GiB | 約 16,290 円/月 | 約 130,317 円/月 |
| Azure | A2 v2 | 2 | 4.00 GB | 約 8,576 円/月 | 約 68,608 円/月 |
| Azure | A4 v2 | 4 | 8.00 GB | 約 18,062 円/月 | 約 144,496 円/月 |

- [インスタンスタイプ - Amazon EC2 | AWS](https://aws.amazon.com/jp/ec2/instance-types/ "インスタンスタイプ - Amazon EC2 | AWS")
- [Windows VM のサイズ | Microsoft Docs](https://docs.microsoft.com/ja-jp/azure/virtual-machines/virtual-machines-windows-sizes?toc=%2fazure%2fvirtual-machines%2fwindows%2ftoc.json "Windows VM のサイズ | Microsoft Docs")


Virtual Machine インスタンス作成の細かな手順に関しては割愛しますが、以下の 2 点をご対応ください。

### SSH 公開キーの指定
「1. 基本　基本設定の構成」では、「認証の種類」を「SSH 公開キー」とし、先ほど控えた SSH 公開キーを指定してください。それ以外は任意で構いません。

### ネットワーク セキュリティ グループについて

「3. 設定 オプション機能の設定」では、先ほど作成した ネットワーク セキュリティ グループを指定しましょう。それ以外は任意で構いません。

なお、今回は検証であるため、上記以外のセキュリティについて考慮しません。ご了承ください。

Ansible のデプロイ先を更新
----
`openwhisk/ansible/environments/distributed/hosts` に、実際の IPアドレスを反映します。

私の環境ではこうなりました。

```yaml:openwhisk/ansible/environments/distributed/hosts
; the first parameter in a host is the inventory_hostname which has to be
; either an ip
; or a resolvable hostname

; used for local actions only
ansible ansible_connection=local
[registry]
10.0.0.5
[edge]
10.0.0.6
[controllers]
10.0.0.7
[kafka]
10.0.0.9
[consul_servers]
10.0.0.10
[invokers]
10.0.0.11
10.0.0.12
[db]
10.0.0.8
```

疎通確認は、以下のコマンドを実行します。

```bash
$ cd ansible
$ ansible all -i environments/distributed/hosts -m ping

ansible | SUCCESS => {
    "changed": false,
    "ping": "pong"
}
10.0.0.9 | SUCCESS => {
    "changed": false,
    "ping": "pong"
}
10.0.0.12 | SUCCESS => {
    "changed": false,
    "ping": "pong"
}
10.0.0.5 | SUCCESS => {
    "changed": false,
    "ping": "pong"
}
10.0.0.8 | SUCCESS => {
    "changed": false,
    "ping": "pong"
}
10.0.0.11 | SUCCESS => {
    "changed": false,
    "ping": "pong"
}
10.0.0.6 | SUCCESS => {
    "changed": false,
    "ping": "pong"
}
10.0.0.10 | SUCCESS => {
    "changed": false,
    "ping": "pong"
}
10.0.0.7 | SUCCESS => {
    "changed": false,
    "ping": "pong"
}
```

`registry` インスタンスの準備
----

`registry` のインスタンスにログインし、以下のように `git` をインストールしておきます。

```bash
$ sudo apt-get update
$ sudo apt-get install git
```

Ansible 実行して OpenWhisk 環境をデプロイ
----

それでは、準備が整ったので、 Ansible でセットアップを流していきましょう!

```bash
# config を生成する
$ ansible-playbook -i environments/distributed/hosts setup.yml
```

```bash
# 各インスタンスの環境をセットアップする
$ ansible-playbook -i environments/distributed/hosts prereq_build.yml
```

ここで、もし以下のように `UNREACHABLE` で失敗してしまっても、再度 `prereq_build.yml` を実施することで未完だった部分を実施することができます。

```
fatal: [10.0.0.5]: UNREACHABLE! => {"changed": false, "msg": "Failed to connect to the host via ssh.", "unreachable": true}
```

次に、いよいよ OpenWhisk のビルドとデプロイを行います。

```bash
# レジストリをデプロイする
$ ansible-playbook -i environments/distributed/hosts registry.yml

# Docker イメージを配布する (root 権限で実行)
$ sudo -i

cd <path-to-openwhisk>

./gradlew distDocker -PdockerHost=<registry_vm_ip>:4243 -PdockerRegistry=<registry_vm_ip>:5000

exit # root から抜ける
```

`registry_vm_ip` には、 `registry` のインスタンスの IP を指定してください。なお、この `./gradlew distDocker` は時間がかかります。スペックをケチったので、なおさらかかってる模様です…！

```
BUILD SUCCESSFUL

Total time: 1 hrs 32 mins 51.646 secs
```
やっとビルド終わったー！

さて、次に CouchDB のセットアップをします。

```bash
# CouchDB をセットアップする
$ cd ansible
$ ansible-playbook -i environments/distributed/hosts couchdb.yml
$ ansible-playbook -i environments/distributed/hosts initdb.yml
$ ansible-playbook -i environments/distributed/hosts wipe.yml
$ ansible-playbook -i environments/distributed/hosts openwhisk.yml
$ ansible-playbook -i environments/distributed/hosts postdeploy.yml
```

動作確認！
----

最後に、ちゃんと構築できたか確認してみましょう！

`<edge_url>` には `edge` のインスタンスの IP を指定してください。

```bash
# OpenWhisk にプロパティを設定する
$ ../bin/wsk property set --auth $(cat files/auth.whisk.system) --apihost <edge_url>

ok: whisk auth set to 789c46b1-71f6-4ed5-8c54-816aa4f8c502:abczO3xZCLrMN6v2BKK1dXYFpXlPkccOFqm12CdAsMgRU4VrNZ9lyGVCGuMDGIwP
ok: whisk API host set to <edge_url>
```

```bash
# OpenWhisk のアクションを実行する
$ ../bin/wsk -i -v action invoke /whisk.system/samples/helloWorld --blocking --result

REQUEST:
[POST]  https://<edge_url>/api/v1/namespaces/whisk.system/actions/samples/helloWorld?blocking=true
Req Headers
{
  "Authorization": [
    "Basic XXXXXXXXYjEtNzFmNi00ZWQ1LThjNTQtODE2YWE0ZjhjNTAyOmFiY3pPM3haQ0xyTU42djJCS0sxZFhZRnBYbFBrY2NPRnFtMTJDZEFzTWdSVTRWck5aOWx5R1ZDR3VNREdJd1A="
  ]
}RESPONSE:Got response with code 200
Response body size is 559 bytes
Response body received:
{
  "duration": 2266,
  "name": "helloWorld",
  "subject": "whisk.system",
  "activationId": "9b6c16fe9bc84d7c80dd2276e5807907",
  "publish": false,
  "annotations": [{
    "key": "limits",
    "value": {
      "timeout": 60000,
      "memory": 256,
      "logs": 10
    }
  }, {
    "key": "path",
    "value": "whisk.system/samples/helloWorld"
  }],
  "version": "0.0.1",
  "response": {
    "result": {

    },
    "success": true,
    "status": "success"
  },
  "end": 1481497829558,
  "logs": [],
  "start": 1481497827292,
  "namespace": "whisk.system"
}
{}
```

うごいたーーーー！！！！！！ (*ﾉωﾉ)

うおーーーーー！！！


Epilogue - おわりに
====
ということで、 Ubuntu 16.04 で挑戦して挫折したり、普段は使わない IaaS でしり込みしてましたが、OSSのソース読んだりデバッグするスキルがついてきて、解決することができました！

仮想マシン、思いのほかすんなり使えたので、普段 AWS 触ってる人も似た感覚で使えるんだなーっと感心しました。