【2019/8月更新】Watsonと電話で会話しよう！ IBM Voice Gateway を使ってみた(Containers in Kubernetes Cluster編) 


![image](https://qiita-image-store.s3.amazonaws.com/0/108535/d3cd8f63-0217-ebd3-a676-40427ec94176.png)

## 更新履歴
(2018/07)　    [Voice Agent with Watson](#201807追記voice-agent-with-watsonのサービスも出ました)につき追記
(2019/08/26)  新しい価格体系[Watson Assistant for Voice Interaction](#201908追記新しい価格体系watson-assistant-for-voice-interaction-が出ました)を追記

## <i class="fa fa-newspaper-o" style="font-size:1em;"></i> 始めに

2017年4月に「[Watsonと電話で会話しよう！ IBM Voice Gateway を使ってみた](https://qiita.com/ishida330/items/f64d5d7fe87e2b247b57#comment-3bcd3c99515b8e43cb94)」という記事を書きました。当時はIBM Cloud(旧Bluemix)のコンテナ・サービスはDockerベースだったのですが、その後**Kubernetesベースのものに変わって**しまったので記事が古くなってしまいました。またVoice Gateway自体もかなり機能強化されています。そこで、改めて2018年3月時点でIBM Cloud上のContainers in Kubernetes ClusterにIBM Voice Gatewayをデプロイしてみたので、注意点含めアップデート記事を書きます。( IBM Voice Gatewayって何？というお話は上記の記事を参照ください)


## (2018/07追記)　Voice Agent with Watsonのサービスも出ました!
新たにIBM CloudのサービスアイコンとしてVoice Agent with Watsonが出ました！クラウド環境でTwilio等と連携するならこちらのほうが簡単だと思います。オンプレミス/プライベートなら従来通りVoice Gatewayでどうぞ～。
![image](https://qiita-image-store.s3.amazonaws.com/0/108535/2b76f759-7ba3-2090-370d-e4c3e5410d16.png)

:blue_book: [IBM Voice Agent with Watson - Document](https://console.bluemix.net/docs/services/voice-agent/getting-started.html#-)

## (2019/08追記)　新しい価格体系　Watson Assistant for Voice Interaction が出ました!

従来、Watsonのテレフォニー連携を使う場合には① IBM  Voice Agent　② Watson Assistant　③ Watson Text to Speech　④ Watson Speech to Textの４つを別々に用意する必要がありました。これら４つのサービスは課金の単位が異なるため、費用見積もりが面倒になりがちだという課題がありました。2019/8月に新しいライセンス体系として[Watson Assistant for Voice Interaction](https://www.ibm.com/cloud/watson-assistant/pricing/) [^1]が出て、この辺が便利になりました。

![image](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/108535/f7086d2a-c011-7a69-8622-6e7f5caca87c.png)

- １つの契約で４つのサービスを全部使えます
- **課金単位は「通話時間（分）」に統一**されています
- 2019/8月時点ではPlusプランのみ
    - $0.065/call minuteですが最低利用単位が1万分/月なので実質$650/1万分・月が最低料金になります
    - 1万分を超えた場合は$325/5,000分単位で追加課金が発生
- 他にもいくつか上限や制限があるので[Pricingのページ](https://www.ibm.com/cloud/watson-assistant/pricing/) [^1]をご確認ください





[^1]: WatsonAssistantのプランを説明するページですが、「Phone」のタブをクリックすると費用など詳細が見られます。

## この一年余りで変わったこと

IBM CloudのコンテナがKubernetesベースのものになり、IBM Voice Gatewayもかなり機能強化されました。 Knowledge Centerの[新機能](https://www.ibm.com/support/knowledgecenter/ja/SS4U29/whatsnew.html)に詳細がありますが、目立ったところを抜粋します。

- Watson Conversation サービスの動的構成により、通話の途中で異なる Conversation ワークスペースに切り替え可能
- アタック防止のために特定の IP アドレスや電話番号をホワイトリストに登録可能
- 会話のやりとりを「録音」可能（ステレオ録音も可能)
- (日本語は未対応なので関係ないが) Watson Virtual Agent と統合可能
- アクション・タグでConversation サービスから Voice Gateway 内の 1 つのアクションまたはアクションのシーケンスを起動可能
- マルチテナントの Voice Gateway 環境(１インスタンスで複数の電話番号をホスト可能)
- (ベータ) IBMのSpeech to Text サービスの代わりに Google Cloud Speech API を使用可能(但し日本語は未サポート)
- (ベータ) SMS GatewayでSMS メッセージを介しての対話が可能
- Docker Engine / IBM Cloud Private / IBM Cloud Container Service 内の Kubernetes の３つをデプロイ先をサポート

他にも電話周りで細かい改善が多数あるようですが、割愛します。

## 当記事の内容を試される方へのご注意点

◆今回はIBM Cloud上のKubernetes環境にIBM Voice Gatewayをデプロイしますが、残念ながらContainers for Kubernetes Clusterのサービスは**無償のライト・アカウントやトライアル・アカウントでは使えません。** クレジットカードを登録済のPAYGアカウントや企業のサブスクリプション・アカウントを使っていただく必要があります。(それらのアカウントであれば**Freeプランがある**ので課金されずにお試しいただけます。) (ちなみにIBM社員の方でトライアルのIDをお持ちの場合は、w3のSSOを経由することでFreeプランを使えます）

![image](https://qiita-image-store.s3.amazonaws.com/0/108535/cc9b3eaf-f2ce-08b9-0d40-9d0c6fe60c66.png)

◆ IBM Voice Gatewayの[マニュアル(Knowledge Center)](https://www.ibm.com/support/knowledgecenter/ja/SS4U29/welcome_voicegateway.html)が日本語化されましたので、読むのがとっても楽になりました。ただ、一部の手順が英語版に書いてあって日本語版に書いてない、てな事態があったので、「ん？」と思ったら英語版をチェックください（ブラウザーの言語設定によりデフォルト言語で表示されますが、下部から言語を選べます）
![image](https://qiita-image-store.s3.amazonaws.com/0/108535/50f18115-7821-9d67-c747-f5877aba499f.png)

◆「Kubernetesなんて、よく知らねーよ！:worried:」という方(つまり、私:smile:)でも地道にマニュアル通りコピペで進めば大丈夫です。当記事ではコピペしやすいように`hogeコマンド`のような形で主なコマンドを書いておきます。当記事はマニュアルの[Deploying Voice Gateway to Kubernetes in IBM Cloud Container Service](https://www.ibm.com/support/knowledgecenter/SS4U29/deploybmix.html)の章のサマリーです。
◆以下、Watson Conversation/Speech to Text(STT) /Text to Speech(TTS)などのサービスは構成済との前提で話を進めます。

## 全体感とおおまかな作業の流れ
### 全体の印象
以下、以前の記事同様に最も基本的なユースケースである「セルフサービス・エージェント」の環境を作ります。

Dockerを用いていた前の方法も簡単でしたが、IBM Voice GatewayをContainers in Kubernetes Cluster環境にデプロイするのは、さらに簡単です。以前は作業用のクライアントにDocker環境を準備してからDocker イメージを自分でpullして編集してIBM Cloudにpushして開始して、、、という流れでしたが、今回はgithubからリソース一式クローンして定義ファイル編集して、kubectl createコマンド一発で終わり！です。**当ケースでは作業用のクライアントにDocker環境を用意する必要はありません。** 内部的にはIBM Voice Gatewayは2つのDockerイメージを使いますが、イメージはIBM Cloud上で自動的にpullしてくれますので、起動も速いです。ただ、そのためにはクライアント上でkubernetesのコマンド環境を色々と準備する必要がありまして、こっちのほうが余程面倒くさい。。。まあこれはKubernetes環境を触るための準備であり、１回だけで済むのでご辛抱ください。なお、当ケースでは**要はbxコマンドやkubectlコマンドとエディターが使えればいい**ので、クライアントはWindowsでもLinuxでもMacでもオーケーです。(筆者はUbuntu 16.4を使いました）

### おおまかな環境構築作業の流れ
大きい流れは以下になります。

1. GithubからIBM Voice Gatewayのリソース一式をクローン
2. Kubernetesのクラスターを作成( UIが楽。お試しならFree Planでよいです )
3. クライアントでKubernetesのコマンド(kubectl等）環境を準備
4. 定義ファイル(deploy.json)の編集
5. Kubernetesクラスターにデプロイ( kubectl create )
6. Twilioのアカウントを取得し、セットアップ
7. 電話してみる

![image](https://qiita-image-store.s3.amazonaws.com/0/108535/f1c8a7d1-03fc-60da-c167-7a7789d50c38.png)

## やってみる
以下、何もない状態からIBM CloudにIBM　Voice Gatewayをデプロイするまでの手順をお示しします。

### 1. GithubからIBM Voice Gatewayのリソース一式をクローン

Windows/Linux/Macの任意のクライアント上で、普通に[sample.voice.gateway](https://github.com/WASdev/sample.voice.gateway)をクローンします。（またはダウンロードして適当なディレクトリーにunzipします。）

`git clone https://github.com/WASdev/sample.voice.gateway`

```bash:git_clone
root@ubuntu:~# git clone https://github.com/WASdev/sample.voice.gateway
Cloning into 'sample.voice.gateway'...
remote: Counting objects: 1214, done.
remote: Compressing objects: 100% (12/12), done.
remote: Total 1214 (delta 1), reused 9 (delta 1), pack-reused 1199
Receiving objects: 100% (1214/1214), 9.79 MiB | 400.00 KiB/s, done.
Resolving deltas: 100% (454/454), done.
Checking connectivity... done.
root@ubuntu:~#
```

### 2. KubernetesクラスターをUIで作成

:triangular_flag_on_post: [bx cs cluster-create](https://console.bluemix.net/docs/containers/cs_cli_reference.html#cs_cluster_create)コマンドでも操作可能ですがUIのほうが簡単なので、UIでやります。


IBM Cloudに有効な(≒PAYGまたはサブスクリプション)アカウントでログインし、カタログの「インフラスチラクチャー」-「コンテナ」で下記を選択
![image](https://qiita-image-store.s3.amazonaws.com/0/108535/edea55b4-8f49-d5b3-8fae-05077c1fb227.png)

右下の「作成」ボタン
![image](https://qiita-image-store.s3.amazonaws.com/0/108535/1c0e1fed-c955-ce1c-574c-b056c442da55.png)

Regionは無難に米国南部、「無料」、クラスター名はお好みで（今はデフォルトのmycluster)指定して、「クラスターの作成」

![image](https://qiita-image-store.s3.amazonaws.com/0/108535/da1f4792-a55e-d3cf-d8ff-315ecbac1019.png)

:triangular_flag_on_post: 無料プランの場合、workerは１つですがIBM Voice Gatewayの２つのコンテナを同じPodにデプロイできます

「デプロイ中」の状況が「準備完了」に変わるまで、しばらくお待ちください

![image](https://qiita-image-store.s3.amazonaws.com/0/108535/8b299357-8048-4ff5-7aca-f7b83586559d.png)

完了すると、「概要」タブで様子を見られます

![image](https://qiita-image-store.s3.amazonaws.com/0/108535/ea885e74-e84c-c017-8bd6-c0adf06310ef.png)

「ワーカーノード」タブでパブリックなIPアドレスも見られます

![image](https://qiita-image-store.s3.amazonaws.com/0/108535/d5241028-04fb-aa7a-3fbc-da1b67b0c506.png)


### 3. クライアントでKubernetesのコマンド(kubectl等）環境を準備

ここはIBM Voice GatewayというよりKubernetesクラスターを作業用のクライアントから操作するための環境整備です。色々あってちょっと面倒くさいんですが、一回だけなのでご辛抱ください。（コマンド類は、ほとんど下記のコピペでいけると思います）

#### 3.1  CLIのインストール
Windows/Linux/Macの任意のクライアントに
① IBM Cloud CLI( bxコマンド)
② Kubernetes CLI( kubectlコマンド)
③ (IBM Cloud CLIの) Container Service Plugin
の３つをインストールします。

下記の「アクセス」タブにCLIのダウンロードリンクがありますのでご自身のプラットフォームに合ったものをインストールしてください。

![image](https://qiita-image-store.s3.amazonaws.com/0/108535/f1bdac84-1608-fa7e-74dc-74d84d26746a.png)

下記は私のubuntu16.4環境での例です(ダウンロード後)

① IBM Cloud CLI 
ダウンロード＆解凍してからインストーラーを起動
`tar zxvf IBM_Cloud_CLI_0.6.5_amd64.tar.gz`
` ./install_bluemix_cli`
`bx --version`

```bash:IBM_Cloud_CLI
root@ubuntu:~# tar zxvf IBM_Cloud_CLI_0.6.5_amd64.tar.gz
Bluemix_CLI/
Bluemix_CLI/bx/
Bluemix_CLI/bx/zsh_autocomplete
Bluemix_CLI/bx/bash_autocomplete
Bluemix_CLI/bin/
Bluemix_CLI/bin/NOTICE
Bluemix_CLI/bin/cfcli/
Bluemix_CLI/bin/cfcli/cf
Bluemix_CLI/bin/LICENSE
Bluemix_CLI/bin/bluemix
Bluemix_CLI/bin/bluemix-analytics
Bluemix_CLI/install_bluemix_cli
root@ubuntu:~#

root@ubuntu:~# cd Bluemix_CLI/
root@ubuntu:~/Bluemix_CLI# ls
bin  bx  install_bluemix_cli
root@ubuntu:~/Bluemix_CLI# ./install_bluemix_cli
Copying files ...
IBM Cloud Command Line Interface(IBM Cloud CLI) is installed successfully.
To get started, open a new Linux terminal and enter "bluemix help", or enter "bx help" as short name.

With IBM Cloud CLI 0.4.0 or later, the CLI can automatically collect diagnostic and usage information and send it to cloud platform for analysis.
This information will help us better understand current client usage and plan for future use. No personally identifiable data is collected.

To stop collecting information, you can run the following command:
        'bluemix config --usage-stats-collect false'
root@ubuntu:~/Bluemix_CLI#
root@ubuntu:~# bx --version
bx version 0.6.5+0183260-2018-02-05T06:56:08+00:00
root@ubuntu:~#
```

② Kubernetes CLI (kubectl)
直にwgetして実行権限を付与の上、/usr/local/binなどPATHの通った場所へ移動
`wget https://storage.googleapis.com/kubernetes-release/release/v1.8.6/bin/linux/amd64/kubectl`

```bash:Kubernetes_CLI
root@ubuntu:~# wget https://storage.googleapis.com/kubernetes-release/release/v1.8.6/bin/linux/amd64/kubectl
--2018-02-26 01:23:22--  https://storage.googleapis.com/kubernetes-release/release/v1.8.6/bin/linux/amd64/kubectl
Resolving storage.googleapis.com (storage.googleapis.com)... 216.58.197.144
Connecting to storage.googleapis.com (storage.googleapis.com)|216.58.197.144|:443... connected.
HTTP request sent, awaiting response... 200 OK
Length: 52334123 (50M) [application/octet-stream]
Saving to: ‘kubectl’

kubectl                      100%[===========================================>]  49.91M   635KB/s    in 1m 42s

2018-02-26 01:25:05 (500 KB/s) - ‘kubectl’ saved [52334123/52334123]

root@ubuntu:~# ls -al kube*
-rw-r--r-- 1 root root 52334123 Dec 21 09:51 kubectl
root@ubuntu:~# chmod 755 kube*
root@ubuntu:~# ls -al kube*
-rwxr-xr-x 1 root root 52334123 Dec 21 09:51 kubectl
root@ubuntu:~# mv kubectl /usr/local/bin/.
root@ubuntu:~# ls -al /usr/local/bin/kubectl
-rwxr-xr-x 1 root root 52334123 Dec 21 09:51 /usr/local/bin/kubectl
root@ubuntu:~#
root@ubuntu:~# echo $PATH
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games
root@ubuntu:~#
```

③ (IBM Cloud CLIの) Container Service Plugin
`bx plugin install container-registry -r Bluemix`
`bx plugin list`

```bash:Container_Service_Plugin
root@ubuntu:~# bx plugin install container-registry -r Bluemix
Looking up 'container-registry' from repository 'Bluemix'...
Plug-in 'container-registry 0.1.292' found in repository 'Bluemix'
Attempting to download the binary file...
 21.50 MiB / 21.50 MiB [==========================================================================] 100.00% 1m18s
22546728 bytes downloaded
Installing binary...
OK
Plug-in 'container-registry 0.1.292' was successfully installed into /root/.bluemix/plugins/container-registry. Use 'bx plugin show container-registry' to show its details.
root@ubuntu:~#

root@ubuntu:~# bx plugin list
Listing installed plug-ins...

Plugin Name          Version
container-registry   0.1.292
container-service    0.1.440
```

#### 3.2 IBM Cloudへのログイン

**bx login**と打てばあとは対話式にログインできます。( 私はsingle sign-onを使っているので bx login -ssoとしましたが、通常はbx loginだけでOKです）クラスターは米国南部(Dallas)に作ったので、もしAPI Endpointなどのリージョンが違っていたら　**bx target -r us-south**で再設定します。マニュアルは[kubectl を実行するように CLI を構成する](https://console.bluemix.net/docs/containers/cs_cli_install.html#cs_cli_configure)です

`bx login` または　`bx login -sso`
`bx target -r us-south`
`bx cs locations`

```bash:bx_login
root@ubuntu:~# bx login -sso
API endpoint: https://api.eu-gb.bluemix.net

One Time Code (Get one at https://iam-id-1.au-syd.bluemix.net/identity/passcode)>
Authenticating...
OK

Select an account (or press enter to skip):
1. ishida's Account (xxxxxxxxxxxxxxxxxxxxxxxxxxxxx)
Enter a number> 1
Targeted account ishida's Account (xxxxxxxxxxxxxxxxxxxxxxxxxxxxx)

Targeted resource group default


API endpoint:     https://api.eu-gb.bluemix.net (API version: 2.92.0)
Region:           eu-gb
User:            xxxxx@xx.xx.xxx
Account:          ishida's Account (xxxxxxxxxxxxxxxxxxxxxxxxxxxxx)
Resource group:   default
Org:
Space:

Tip: If you are managing Cloud Foundry applications and services
- Use 'bx target --cf' to target Cloud Foundry org/space interactively, or use 'bx target -o ORG -s SPACE' to target the org/space.
- Use 'bx cf' if you want to run the Cloud Foundry CLI with current Bluemix CLI context.

root@ubuntu:~# bx target -r us-south
Switched to region us-south



API endpoint:     https://api.ng.bluemix.net (API version: 2.92.0)
Region:           us-south
User:            xxxxx@xx.xx.xxx
Account:          ishida's Account (xxxxxxxxxxxxxxxxxxxxxxxxxxxxx)
Resource group:   default
Org:
Space:

Tip: If you are managing Cloud Foundry applications and services
- Use 'bx target --cf' to target Cloud Foundry org/space interactively, or use 'bx target -o ORG -s SPACE' to target the org/space.
- Use 'bx cf' if you want to run the Cloud Foundry CLI with current Bluemix CLI context.

root@ubuntu:~# bx cs locations
OK
Location
dal10
dal12
dal13
root@ubuntu:~#
```

#### 3.3 kubectl を実行するように CLI を構成する

環境変数 KUBECONFIGを設定して Kubernetes 構成ファイルをダウンロードするためのコマンドを取得し、環境変数をセットします。具体的には、**bx cs cluster-config mycluster --admin**でexport KUBECONFIG=~の一行のテキストが表示されるので、その通り環境変数　KUBECONFIGをセットします。(私は.profileに書きました。Windowsならexportではなくsetですね、もちろん）

:triangular_flag_on_post: マニュアルでは --adminが書いてませんが、次のcalicoctlで必要になるので、付けて実行します。

`bx cs cluster-config mycluster --admin`
`echo $KUBECONFIG`

```bash:bx_cs_cluster-config_mycluster_--admin
root@ubuntu:~# bx cs cluster-config mycluster --admin
OK
The configuration for mycluster was downloaded successfully. Export environment variables to start using Kubernetes.

export KUBECONFIG=/root/.bluemix/plugins/container-service/clusters/mycluster-admin/kube-config-hou02-mycluster.yml
root@ubuntu:~# vi .profile
root@ubuntu:~# su - root
root@ubuntu:~# echo $KUBECONFIG
/root/.bluemix/plugins/container-service/clusters/mycluster-admin/kube-config-hou02-mycluster.yml
root@ubuntu:~#

```
ここまでがIBM Cloud上のKubernetesクラスターを操作するための準備です。

#### 3.4 calicoctlのインストールと設定

KubertenetesクラスターがTwilioなど外部からの電話発呼を受け取る際のポート番号などを設定するために、デフォルトのネットワーク構成を一部変更する必要があります。そのためにcalicoctlコマンドをインストールします。マニュアル該当箇所は「[ネットワーク・ポリシーによるトラフィックの制御](https://console.bluemix.net/docs/containers/cs_network_policy.html#network_policies)」です。

[calicoctl](https://github.com/projectcalico/calicoctl/releases/tag/v1.6.1)コマンドをダウンロードして実行権限を付与後、/usr/local/bin/などPATHの通った場所に移動します。私はubuntuなので下記を落としました。

![image](https://qiita-image-store.s3.amazonaws.com/0/108535/7a4022ce-6142-840c-b196-c5015ca6698a.png)
`chmod 775 calicoctl`
`mv calicoctl /usr/local/bin/calicoctl`
`calicoctl version`

```bash:calicoctl
root@ubuntu:~# ls cali*	
calicoctl	
root@ubuntu:~# chmod 775 cali*	
root@ubuntu:~# ls cali*	
calicoctl	
root@ubuntu:~# mv calicoctl /usr/local/bin/calicoctl	
root@ubuntu:~# ls -al /usr/local/bin/calicoctl	
-rwxrwxr-x 1 root root 32285568 Feb 27 17:14 /usr/local/bin/calicoctl	
root@ubuntu:~# calicoctl version	
Client Version:    v1.6.1	
Build date:        2017-09-28T01:12:35+0000	
Git commit:        1724e011	
Cluster Version:   unknown (client: etcd cluster is unavailable or misconfigured; error #0: dial tcp 127.0.0.1:2379: getsockopt: connection refused	
)	
Cluster Type:      unknown (client: etcd cluster is unavailable or misconfigured; error #0: dial tcp 127.0.0.1:2379: getsockopt: connection refused	
)	
root@ubuntu:~#	
```
コマンドがダウンロードできたら、お好きなエディターで/etc/calico/calicoctl.cfgを以下の内容で作成します

```text:calicoctl.cfg(編集前)
apiVersion: v1
kind: calicoApiConfig
metadata:
spec:
  etcdEndpoints: <ETCD_URL>
  etcdKeyFile: <CERTS_DIR>/admin-key.pem
  etcdCertFile: <CERTS_DIR>/admin.pem
  etcdCACertFile: <CERTS_DIR>/<ca-*pem_file>
```

上記のETCD_URLなどの値は各々、コマンドで照会・取得の上セットします(面倒くせー。まあもう少しなんで）

`kubectl get cm -n kube-system calico-config -o yaml | grep "etcd_endpoints:" | awk '{ print $2 }'`

```bash:**ETCD_URL**にセットする値の入手
root@ubuntu:~# kubectl get cm -n kube-system calico-config -o yaml | grep "etcd_endpoints:" | awk '{ print $2 }'

https://184.173.44.62:22497
root@ubuntu:~#
```
`dirname $KUBECONFIG`

```bash:**CERTS_DIR**にセットする値の入手
root@ubuntu:~# dirname $KUBECONFIG
/root/.bluemix/plugins/container-service/clusters/mycluster-admin
root@ubuntu:~#
```
`ls `dirname $KUBECONFIG` | grep "ca-"` <- うまくescapeできないので下からコピペお願いします

```bash:**ca-*pem_file**にセットする値の入手
root@ubuntu:~# ls `dirname $KUBECONFIG` | grep "ca-"
ca-hou02-mycluster.pem
root@ubuntu:~#
```

結果、以下のようになります

```text:calicoctl.cfg(編集後)
root@ubuntu:~# vi /etc/calico/calicoctl.cfg
root@ubuntu:~# cat /etc/calico/calicoctl.cfg
apiVersion: v1
kind: calicoApiConfig
metadata:
spec:
  etcdEndpoints: https://184.173.44.62:22497
  etcdKeyFile: /root/.bluemix/plugins/container-service/clusters/mycluster-admin/admin-key.pem
  etcdCertFile: /root/.bluemix/plugins/container-service/clusters/mycluster-admin/admin.pem
  etcdCACertFile: /root/.bluemix/plugins/container-service/clusters/mycluster-admin/ca-hou02-mycluster.pem
root@ubuntu:~#
```


**calicoctl get nodes**コマンドでノードの情報が取れれば設定はOKです。
`calicoctl get nodes`

```bash:calicoctl_get_nodes
root@ubuntu:~# calicoctl get nodes
NAME
kube-hou02-pa9e47ba84865b4bfca0c8fbc150a5efc4-w1.cloud.ibm

root@ubuntu:~#
```
calicoctlコマンドが使えるようになったら、サンプルで提供されているCalico ネットワーク・ポリシーをそのまま適用します。クローンした雛形には色々なリソースがありますが、今回はKubernetes上のSingleテナント環境(電話番号が一つ)で実施するので、**/sample.voice.gateway/kubernetes/bluemix/single-tenant**にある雛形を使います。似たようなディレクトリーがあるのでお間違えなきよう！

![image](https://qiita-image-store.s3.amazonaws.com/0/108535/beba1b47-0233-7662-b3d5-a56bcc91897b.png)

**/sample.voice.gateway/kubernetes/bluemix/single-tenant**に移動して下記を実行します

`calicoctl apply -f calico.yaml`

```bash:calicoctlでKubernetesのネットワーク構成を変更
root@ubuntu:~/sample.voice.gateway/kubernetes/bluemix/single-tenant# ls
calico.yaml  deploy.json  README.md
root@ubuntu:~/sample.voice.gateway/kubernetes/bluemix/single-tenant# calicoctl apply -f calico.yaml
Successfully applied 1 'policy' resource(s)
root@ubuntu:~/sample.voice.gateway/kubernetes/bluemix/single-tenant#
```

これで一段落です。お疲れ様でした！（ここまでやれば、あとは楽ですよ！）

### 4. 定義ファイル(deploy.json)の編集(&パスワードのセット)

#### 4-1. deploy.jsonの編集
Githubからクローンした**/sample.voice.gateway/kubernetes/bluemix/single-tenant**の下のdeploy.jsonのエントリーWatson Conversation/STT/TTSのユーザーIDやワークスペースIDを設定します。以下の6エントリーの値を編集してください。それ以外は雛形のデフォルト設定でOKです。

:warning: JSON中にはWATSON_STT_PASSWORDなど、サービスのパスワードのエントリーもありますが、<font color="DeepPink">パスワードは次にコマンドで設定するので、ここでは触らないでください！</font>

![image](https://qiita-image-store.s3.amazonaws.com/0/108535/112b0585-7cea-1d30-ae2a-74d852547409.png)

| キー | 設定値 | 備考 |
|:------------|:------------|:------------|
| WATSON_STT_USERNAME | サービス資格情報からコピペ |  |
| WATSON_STT_MODEL | ja-JP_NarrowbandModel | **エントリー追加** |
| WATSON_TTS_USERNAME | サービス資格情報からコピペ |  |
| WATSON_TTS_VOICE | ja-JP_EmiVoice | 日本語音声を設定 |
| WATSON_CONVERSATION_WORKSPACE_ID | サービス資格情報からコピペ |  |
| WATSON_CONVERSATION_USERNAME | サービス資格情報からコピペ |  |

:warning: **WATSON_STT_MODEL**は雛形にエントリーが無いので、vgw-media-relayに属するエントリーとして70行目前後に追加します。( これが無いと発話(STT)が英語と解釈されてしまいます。)

![image](https://qiita-image-store.s3.amazonaws.com/0/108535/e32c350d-3e3c-2d6e-46ba-c272c8ab58b5.png)

#### 4-2. Watsonサービスのパスワードのセット

:warning: この記述が[英語版のマニュアル](https://www.ibm.com/support/knowledgecenter/en/SS4U29/deploybmix.html)にはあるのですが、[日本語版のマニュアル](https://www.ibm.com/support/knowledgecenter/ja/SS4U29/deploybmix.html)から漏れていました。

Watsonサービスのパスワードは以前はファイルにベタで書いていましたが、セキュリティ改善としてsecret-credentialに格納するようになっています。以下のようにWatsonサービスのパスワードを設定します。

`kubectl create secret generic secret-creds --from-literal=WATSON_STT_PASSWORD='xxxxxxxx' --from-literal=WATSON_TTS_PASSWORD='xxxxxxxx' --from-literal=WATSON_CONVERSATION_PASSWORD='xxxxxxxx'`

```bash:Watsonサービスのパスワードをセット
root@ubuntu:~# kubectl create secret generic secret-creds --from-literal=WATSON_STT_PASSWORD='xxxxxxxx' --from-literal=WATSON_TTS_PASSWORD='xxxxxxxx' --from-literal=WATSON_CONVERSATION_PASSWORD='xxxxxxxx'
secret "secret-creds" created
```

### 5. Kubernetesクラスターへのデプロイ

これで準備完了です！ではデプロイしましょう。ディレクトリー**sample.voice.gateway/kubernetes/bluemix/single-tenant**上で`kubectl create -f deploy.json`でIBM Voice Gatewayの定義をkubernetesクラスターにデプロイします。`kubectl get pods`で状況を見られます。コンテナが２つデプロイされ、Runningになれば成功です。なんらかのエラーの場合は、ここで表示されるpodの名前から`kubectl describe pod <podの名前>`で詳細が表示されますが、末尾のeventsの箇所からエラーメッセージが見られます。

`kubectl create -f deploy.json`
`kubectl get pods`
`kubectl describe pod <podの名前>`

```bash:Kubernetesクラスターへのデプロイ
root@ubuntu:~/sample.voice.gateway/kubernetes/bluemix/single-tenant# kubectl create -f deploy.json
deployment "vgw" created
root@ubuntu:~/sample.voice.gateway/kubernetes/bluemix/single-tenant# kubectl get pods
NAME                  READY     STATUS    RESTARTS   AGE
vgw-ccb8bf55b-ww4p9   2/2       Running   0          11s
root@ubuntu:~/sample.voice.gateway/kubernetes/bluemix/single-tenant# kubectl describe pod vgw-ccb8bf55b-ww4p9
Name:           vgw-ccb8bf55b-ww4p9
Namespace:      default
Node:           10.76.xxx.xxx/10.76.xxx.xxx
(長いので途中省略)
Tolerations:     node.alpha.kubernetes.io/notReady:NoExecute for 300s
                 node.alpha.kubernetes.io/unreachable:NoExecute for 300s
Events:
  Type    Reason                 Age   From                    Message
  ----    ------                 ----  ----                    -------
  Normal  Scheduled              28s   default-scheduler       Successfully assigned vgw-ccb8bf55b-ww4p9 to 10.76.xxx.xxx
  Normal  SuccessfulMountVolume  28s   kubelet, 10.76.xxx.xxx  MountVolume.SetUp succeeded for volume "recordings"
  Normal  SuccessfulMountVolume  28s   kubelet, 10.76.xxx.xxx  MountVolume.SetUp succeeded for volume "default-token-jv8sx"
  Normal  Pulling                27s   kubelet, 10.76.xxx.xxx  pulling image "ibmcom/voice-gateway-mr:latest"
  Normal  Pulled                 27s   kubelet, 10.76.xxx.xxx  Successfully pulled image "ibmcom/voice-gateway-mr:latest"
  Normal  Created                27s   kubelet, 10.76.xxx.xxx  Created container
  Normal  Started                27s   kubelet, 10.76.xxx.xxx  Started container
  Normal  Pulling                27s   kubelet, 10.76.xxx.xxx  pulling image "ibmcom/voice-gateway-so:latest"
  Normal  Pulled                 26s   kubelet, 10.76.xxx.xxx  Successfully pulled image "ibmcom/voice-gateway-so:latest"
  Normal  Created                26s   kubelet, 10.76.xxx.xxx  Created container
  Normal  Started                26s   kubelet, 10.76.xxx.xxx  Started container
root@ubuntu:~/sample.voice.gateway/kubernetes/bluemix/single-tenant#
```

### 6. Twilioのアカウントを取得し、セットアップ

Twilioの画面が少し変わっていたので、2018/3月時点での手順を掲載します。要は電話番号を取得して、SIPトランクを構成します。

① もしTwilioのアカウントをお持ちでなければ、[Twilioのトライアル・アカウントを入手](http://twilio.kddi-web.com/)します。( Twilioのサインアップ方法はネットに様々な情報があるので割愛します。) 
![image](https://qiita-image-store.s3.amazonaws.com/0/108535/02fe77bb-5eb6-602b-d5b3-e061ce41df70.png)

② 有効なアカウントでコンソールにログインすると、初回はプロジェクト名を聞かれるのでお好きな名前で「Create Project」

![image](https://qiita-image-store.s3.amazonaws.com/0/108535/35adb63a-6f1e-fea8-f2d0-c92355c0d646.png)

③以下の画面に遷移するので、「はじめる」

![image](https://qiita-image-store.s3.amazonaws.com/0/108535/af49a597-26e3-0993-d895-f713b3f4586f.png)

③ まずは自分の電話番号をゲットしましょう。( Twilioではトライアル中も電話番号を１つ無料でもらえます。) 「Get your first twilio number」

![image](https://qiita-image-store.s3.amazonaws.com/0/108535/475169ca-0333-41e2-d228-8b17135e7caa.png)

↓パネルがポップアップするので「この番号を選択」
![image](https://qiita-image-store.s3.amazonaws.com/0/108535/99cc074a-159d-d312-be27-97ca92485c7a.png)

↓電話番号がゲットできました。(+81503196xxxx→国内の電話では050-3196-xxxxになります）「終了」
![image](https://qiita-image-store.s3.amazonaws.com/0/108535/4d411b0c-da05-7705-3030-fe702935d399.png)


④ 次はSIPトランクです。左側のアコーディオン・メニューを開き、「Elastic SIP Trunking」

![image](https://qiita-image-store.s3.amazonaws.com/0/108535/9987f7c8-5be9-6975-a79a-3b928a3f3b90.png)

↓　「はじめる」
![image](https://qiita-image-store.s3.amazonaws.com/0/108535/f9afeefe-7046-97b1-90c5-e8d45e6f8fed.png)


↓　「SIPトランクを作成する」 
![image](https://qiita-image-store.s3.amazonaws.com/0/108535/8e30686f-091a-21a3-4059-d7f4437f9bd4.png)

↓　お好きな名前で「作成」
![image](https://qiita-image-store.s3.amazonaws.com/0/108535/3d336bb7-4bb4-ba3e-5455-c0f637d0a81e.png)

↓　できました
![image](https://qiita-image-store.s3.amazonaws.com/0/108535/f8f10479-5e5a-e193-f1f9-47389654dc04.png)

↓　「オリジネーション」- 「Add new Origination URI」
![image](https://qiita-image-store.s3.amazonaws.com/0/108535/b89fa6ad-bdb1-bd87-6365-d7b3a02925e4.png)

ブラウザを離れ、`bx cs workers mycluster`コマンドで表示されるパブリックIPアドレスを入手します

```bash:パブリックIPアドレスを入手
root@ubuntu:~/sample.voice.gateway/kubernetes/bluemix/single-tenant# bx cs workers mycluster
OK
ID                                                 Public IP        Private IP      Machine Type   State    Status   Zone    Version
kube-hou02-pa9e47ba84865b4bfca0c8fbc150a5efc4-w1   173.193.XX.XX   10.76.195.107   free           normal   Ready    hou02   1.8.8_1507
root@ubuntu:~/sample.voice.gateway/kubernetes/bluemix/single-tenant#
```


↓ 上記のIPアドレス：ポート番号(デフォルトの5060でいいです）を以下の形式でパネルの「オリジネーションSIP URI」欄に記入して「追加」

```
sip:<address:port>;transport=tcp
```

![image](https://qiita-image-store.s3.amazonaws.com/0/108535/190db79d-a7c1-0c7e-e2eb-54b40cbffd64.png)

↓　追加されました。
![image](https://qiita-image-store.s3.amazonaws.com/0/108535/16d115fd-702c-ed78-0adc-c1f85754af7f.png)

↓ このSIPトランクに先ほどの電話番号を関連付けます。「電話番号」－「Add a Number to this Trunk」
![image](https://qiita-image-store.s3.amazonaws.com/0/108535/b36bab3d-812f-2458-11af-0f73f25acec9.png)

↓　電話番号にチェックを入れ「Add Selected」
![image](https://qiita-image-store.s3.amazonaws.com/0/108535/72ade2de-93b4-5bbc-20d6-c57902cd2b30.png)

↓　関連付けができました。
![image](https://qiita-image-store.s3.amazonaws.com/0/108535/8e1281c4-6784-76b0-9797-9b5df585b87e.png)

以上で環境設定は終了です。

### 7. お疲れ様でした！では電話してみましょう！

では先ほどTwilioで設定した電話番号 050-XXXX-XXXXにお手持ちのスマホか手元のお電話から電話を架けてみてください。Watsonからの挨拶が聞こえてきましたか? こちらの話声はきちんと認識されましたか?

## Tips
いくつか、知っておくとよい情報を書いておきますね。
### WHITE_LIST
外部ソースからの望まないセッションを防止するために、着信を許可する電話番号をWHITE LISTに登録しておくことが推奨されています。マニュアル：[発信者および着信者のホワイトリスト登録](https://www.ibm.com/support/knowledgecenter/ja/SS4U29/security.html#whitelisting-callers-and-callees)

deploy.jsonのsip-orchestratorの環境変数として`WHITELIST_TO_URI`を定義し、valueはTwilioから割り当てられた電話番号の**国コード(81)を除いた部分をそのまま**記載します。

![image](https://qiita-image-store.s3.amazonaws.com/0/108535/d1aa49bb-744e-766a-594a-54ef656d7f69.png)
なお、deploy.jsonを変更した場合は環境を再度デプロイする必要があります。
現在の環境の削除　`kubectl delete -f deploy.json`
再度デプロイ　　　`kubectl create -f deploy.json`    

### 問題判別のためのログ入手
以前と同様にコンテナのログを入手できます。(${pod}はPOD名)

`kubectl cp default/${pod}:logs -c vgw-sip-orchestrator . `
`kubectl cp default/${pod}:logs -c vgw-media-relay . `

以下のようにシェル化すると便利です

```bash:ログをカレントディレクトリーに取り込むシェルの例(ubuntu)
#!/bin/bash
pod=$(kubectl get pods|grep vgw| awk '{print $1}')
echo $pod
kubectl cp default/${pod}:logs -c vgw-sip-orchestrator .
kubectl cp default/${pod}:logs -c vgw-media-relay .
```

```bash:実行例
root@ubuntu:~/log# cat get_log.sh
#!/bin/bash
pod=$(kubectl get pods|grep vgw| awk '{print $1}')
echo $pod
kubectl cp default/${pod}:logs -c vgw-sip-orchestrator .
kubectl cp default/${pod}:logs -c vgw-media-relay .
root@ubuntu:~/log# ./get_log.sh
vgw-7dfd9d89b7-cx46p
root@ubuntu:~/log# ls -al
total 164
drwxr-xr-x 2 root root  4096 Feb 28 23:32 .
drwx------ 9 root root  4096 Feb 28 23:31 ..
-rwxr-xr-x 1 root root   182 Feb 28 23:31 get_log.sh
-rw-r--r-- 1 root root 18016 Feb 28 23:32 messages.log
-rw-r--r-- 1 root root 85342 Feb 28 23:32 trace.log
-rw-r--r-- 1 root root 21614 Feb 28 23:32 trace-mr.log
-rw-r--r-- 1 root root 22840 Feb 28 23:32 verbosegc.1.001.log
```

以下はmessages.logの例です。対話内容なども記録されています。

```text:messages.log
[2/28/18 4:56:16:688 UTC] 00000052 com.ibm.ws.webcontainer I SRVE0250I: Web Module cgw.sip.orchestrator has been bound to default_host.
[2/28/18 4:56:16:688 UTC] 00000052 com.ibm.ws.http.internal.VirtualHostImpl A CWWKT0016I: Web application available (default_host): http://172.30.XX.XX:9080/com.ibm.ws.cgw.sip/
[2/28/18 4:56:16:712 UTC] 000000bd com.ibm.ws.webcontainer.osgi.mbeans.PluginGenerator I SRVE9103I: A configuration file for a web server plugin was automatically generated for this server at /opt/ibm/wlp/output/defaultServer/logs/state/plugin-cfg.xml.
[2/28/18 4:56:16:781 UTC] 00000021 com.ibm.ws.kernel.feature.internal.FeatureManager A CWWKF0012I: The server installed the following features: [servlet-3.1, ssl-1.0, jndi-1.0, localConnector-1.0, appSecurity-2.0, jaxrs-2.0, jaxrsClient-2.0, blueprint-1.0, usr:cgwSipOrchestrator-1.0, productInsights-1.0, json-1.0, distributedMap-1.0, wab-1.0, websocket-1.1, sipServlet-1.1].
[2/28/18 4:56:16:783 UTC] 00000021 com.ibm.ws.kernel.feature.internal.FeatureManager I CWWKF0008I: Feature update completed in 13.932 seconds.
[2/28/18 4:56:16:784 UTC] 00000021 com.ibm.ws.kernel.feature.internal.FeatureManager A CWWKF0011I: The server defaultServer is ready to run a smarter planet.
[2/28/18 4:56:16:784 UTC] 00000052 com.ibm.ws.session.WASSessionCore I SESN0176I: A new session context will be created for application key default_host/com.ibm.ws.cgw.sip
[2/28/18 4:56:16:785 UTC] 00000052 com.ibm.ws.util I SESN0172I: The session manager is using the Java default SecureRandom implementation for session ID generation.
[2/28/18 4:56:16:869 UTC] 00000052 com.ibm.ws.sip.container.appqueue.MessageDispatcher I CWSCT0433I: SIP Container queues stats print mode= 0 . 1 = only when overloaded, 2 = always. once every 1,000 msec.
[2/28/18 4:56:17:103 UTC] 00000052 com.ibm.ws.cgw.sip.MediaRelayHealthMonitorTask A CWSGW0084I: The health monitor task for the Media Relay was initialized.
[2/28/18 4:56:17:303 UTC] 00000052 com.ibm.ws.webcontainer.servlet I SRVE0242I: [cgw.sip.orchestrator] [/com.ibm.ws.cgw.sip] [CGWSipServlet]: Initialization successful.
[2/28/18 4:56:48:588 UTC] 00000059 com.ibm.ws.sip.dar.ApplicationRepositoryFactory I CWSCT0405I: The application router is configured to select applications by its start.
[2/28/18 4:56:48:598 UTC] 00000059 com.ibm.ws.sip.dar.ApplicationRepositoryFactory I CWSCT0424I: Loading default application router, start order strategy.
[2/28/18 4:56:48:602 UTC] 00000059 com.ibm.ws.sip.dar.DefaultApplicationRouter I CWSCT0401I: Default application router has been initialized.
[2/28/18 4:56:48:860 UTC] 00000079 com.ibm.ws.cgw.session.FullDuplexSession A CWSGW0011I: A call to the Voice Gateway is starting ... SIP Call-ID = fad3cc41e1efac16dc4b210ee32e29b7@0.0.0.0 sessionID = fad3cc41e1efac16dc4b210ee32e29b7@0.0.0.0 SIP To URI = sip:+8150XXXXXXXX@XX.XX.XX.XX;user=phone SIP From URI = sip:+8180XXXXXXXX@pstn.twilio.com tenantID = sip:+8150XXXXXXXX@XX.XX.XX.XX;user=phone
[2/28/18 4:56:51:284 UTC] 000000e6 com.ibm.ws.cgw.utils.LatencyMonitor A CWSGW0004I: A request to the Watson Conversation service took 2,297 ms to complete, which exceeds the latency threshold of 1,000 ms. Method = com.ibm.ws.cgw.conversation.conv.v1.ConversationConvImpl.start() sessionID = fad3cc41e1efac16dc4b210ee32e29b7@0.0.0.0
[2/28/18 4:56:51:724 UTC] 00000078 com.ibm.ws.cgw.session.FullDuplexSession A CWSGW0002I: The call to the Voice Gateway was established. sessionID = fad3cc41e1efac16dc4b210ee32e29b7@0.0.0.0 SIP Call-ID = fad3cc41e1efac16dc4b210ee32e29b7@0.0.0.0 Conversation ID = b9f02cab-650c-4d3b-8eee-d4dd1561b6d6 tenantID = sip:+8150XXXXXXXX@XX.XX.XX.XX;user=phone
[2/28/18 4:56:51:742 UTC] 00000078 com.ibm.ws.cgw.session.FullDuplexSession A CWSGW0008I: Transcription to the caller. sessionID = fad3cc41e1efac16dc4b210ee32e29b7@0.0.0.0 Transcription = こんにちは、 様。前回のお問い合わせは でしたね。本日はどのようなご相談でしょうか？ tenantID = sip:+8150XXXXXXXX@XX.XX.XX.XX;user=phone
[2/28/18 4:56:59:409 UTC] 00000055 com.ibm.ws.cgw.session.FullDuplexSession A CWSGW0012I: The transaction to play text as audio completed. sessionID = fad3cc41e1efac16dc4b210ee32e29b7@0.0.0.0 transactionID = 4b0150f7-8db5-42c7-9296-0964854ea8a6 Barge-in occurred = No tenantID = sip:+8150XXXXXXXX07@XX.XX.XX.XX;user=phone
[2/28/18 4:57:05:469 UTC] 00000033 com.ibm.ws.cgw.session.FullDuplexSession A CWSGW0010I: Transcription from the caller. sessionID = fad3cc41e1efac16dc4b210ee32e29b7@0.0.0.0 Transcription = D_ア パソコン の 調子 が 悪い ので 修理 して 欲しい ん です けど tenantID = sip:+8150XXXXXXXX@XX.XX.XX.XX;user=phone
```

以上です。お疲れ様でした。ではWatsonとの会話をお楽しみください！:smiley: