Docker マルチコンテナによる gRPC 検証

#概要
　本記事では、高速な RPC (Remote Procedure Call) 機能を提供する [gRPC プロトコル](https://qiita.com/oohira/items/63b5ccb2bf1a913659d6)の動作検証について記載しています。動作検証には Azure PaaS サービスとして Docker のマルチコンテナ環境をサポートしている [WebApp for Container](https://azure.microsoft.com/ja-jp/services/app-service/containers/) 及び [Azure Kubernetes Service (AKS)](https://azure.microsoft.com/ja-jp/services/kubernetes-service/) を利用しました。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/166732/675dd53f-f2a4-7ec6-e776-1345afe58544.png)

#検証用プログラム
　プラットフォーム主体の検証という事で、クライアント、サーバーのサンプルコードは、GitHub に公開されている [grpc](https://github.com/grpc) サンプルから Go 言語 (golang) で書かれた [helloworld](https://github.com/grpc/grpc-go/tree/master/examples) をベースにしています。今回クライアント側は Web App として動作させるため、既存クライアントを次の [webclient.go](https://github.com/Yuichi-Ikeda/webclient-go/blob/master/webclient.go) に置き換えています。

#開発環境の準備とイメージ作成手順
　この章では Web App for Container へデプロイするための gRPC Docker イメージを作成します。作成したイメージは DockerHub に公開しているので、本章をスキップして公開済みイメージを利用した Web App for Container への展開作業を実施する事も可能です。

本章を実施する場合には、Azure VM として CentOS をデプロイします。

[**１. CentOS に Docker をインストール**](https://qiita.com/uhooi/items/f8c67a9e716a226e28cd)
[**２. CentOS に Go 言語をインストール**](https://qiita.com/estaro/items/23c10fe7e43a2a70e689)

```bash:.bash_profile（環境変数の設定例）
GOPATH=$HOME/go
export GOPATH

PATH=$PATH:$HOME/.local/bin:$HOME/bin:/usr/local/go/bin:$GOPATH/bin
export PATH
```

[**３. GitHub より gRPC サンプルをダウンロード**](https://github.com/grpc/grpc-go/tree/master/examples)

```bash:コマンド例
# 事前に Git をインストール
sudo yum install git

# gRPC サンプルのインストール
go get -u google.golang.org/grpc/examples/helloworld/greeter_client
go get -u google.golang.org/grpc/examples/helloworld/greeter_server

# gRPC のサンプル実行（ $HOME/go/bin にある）
greeter_server &
greeter_client

# greeter_server のソースコードの確認
cat go/src/google.golang.org/grpc/examples/helloworld/greeter_server/main.go

# greeter_client のソースコードの確認
cat go/src/google.golang.org/grpc/examples/helloworld/greeter_client/main.go
```

**４. gRPC サンプルのカスタマイズ**

```bash:コマンド例
# gRPC Server
mkdir grpc-server
cp go/bin/greeter_server grpc-server/goserver

#サーバー実行
grpc-server/goserver &

# gRPC Client
mkdir grpc-client
git clone https://github.com/Yuichi-Ikeda/webclient-go.git grpc-client/

# ソースから webclient をビルド
cd grpc-client
go build webclient.go

#クライアント実行
./webclient
```

　上記のコマンドを実行状態で、ブラウザで http://dockerhost:8080 へアクセスしサンプルが動作する事を確認します。NSG の受信ポート 8080 を空ける事を忘れずに。 

**５. gRPC サーバーと gRPC クライアントのコンテナイメージを作成**

　DockerHub より golang の docker image をそのまま利用する事で GO 環境構築の手間を削減しています。この辺は docker のエコシステムの恩恵を見事に受けていると感じられます。

**① gRPC サーバーの docker イメージ**

```dockerfile:Dockerfile
FROM golang
MAINTAINER yuichii
ADD . /go
EXPOSE 50051
CMD ["/go/goserver"]
```
上記 Dockerfile を **grpc-server** ディレクトリに配置成し、docker イメージをビルドします。

```bash:コマンド例
cd grpc-server
docker build -t goserver .
```

**② gRPC クライアントの docker イメージ**

```dockerfile:Dockerfile
FROM golang
MAINTAINER yuichii
ADD . /go
EXPOSE 8080
CMD ["/go/webclient"]
```
上記 Dockerfile を **grpc-client** ディレクトリに配置し、docker イメージをビルドします。

```bash:コマンド例
cd grpc-client
docker build -t goclient .
```

**③ 動作確認**

```bash:コマンド例
# gRPC Server コンテナを先に実行
docker run -d -p 50051:50051 --name goserver goserver
# gRPC Cleint コンテナをサーバにリンクして実行
docker run -d -p 8080:8080 --name goclient --link goserver:localhost goclient
```

　ブラウザで http://dockerhost:8080 へアクセスしサンプルが動作する事を確認します。結果は手順4と同じですが、今回は Docker ホスト上のマルチコンテナ環境でサンプルが実行されています。

**６. 作成したコンテナイメージを DockerHub に公開**

　手順５で作成したコンテナイメージを DockerHub へ push します。この手順は割愛しますが、下記リポジトリで公開しているので、後続の手順ではこちらの公開イメージをご利用頂いても構いません。

　　[yuichii1971/goserver](https://hub.docker.com/r/yuichii1971/goserver/)
　　[yuichii1971/goclient](https://hub.docker.com/r/yuichii1971/goclient/)

#Azure Web App for Container へのデプロイ

　前章で公開した Docker イメージを Web App for Container へ展開します。マルチコンテナの展開は Docker Compose もしくは Kubernetes の定義 (.yml ファイル) を用いてデプロイします。

**１. Kubernetes Pod 定義ファイルの作成**

```yml:kubernetes-go.yml
apiVersion: v1
kind: Pod
metadata:
  name: go
  labels:
    name: go
spec:
  containers:

   - image: yuichii1971/goserver
     name: goserver

   - image: yuichii1971/goclient
     name: goclient
     ports:
     - containerPort: 8080
       name: goclient
```

**２. Web App for Container のデプロイ**

　[Azure Web App 3種類のタイプ (Windows, Linux, Docker)](https://qiita.com/Aida1971/items/7e6562e0ee3cd7c4b84e) から **Docker** を選択します。**Kubernetes（プレビュー）** を選択し、上記の kubernetes-go.yml ファイルをローカルのデスクトップなどに用意しておき、**ファイルの選択**からアップロードします。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/166732/29067f5d-450a-8cce-15fb-6365ec099532.png)

**３. 動作確認**

　上記画面で [作成] を実行してデプロイが完了したら、ブラウザにて Web サイト（例）https://grpcdemo.azurewebsites.net/ へアクセスします。初回アクセス時は応答に時間がかかりますが、成功すると gRPC サーバーからのメッセージがブラウザ画面に表示されます。

　※１　Web App for Container は 80 もしくは 8080 ポートを expose しているコンテナを WEB コンテナ―として自動判別し、ホストの 80/443 ポートを自動マッピングします。このためブラウザからの http/https でのアクセスが自動的に goclient コンテナへ着信します。

　※２　Web App for Container のマルチコンテナサポートでは、現在（プレビュー中）、TCP ポートを expose できるコンテナは 1 つだけとなります。

**補足**
　正常に動作した場合、Web App の [コンテナ―の設定] 画面のログに、次のような出力がされます。動作しない場合には、このログにエラーの内容が出力されるので、それを確認して対処を行う必要があります。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/166732/976f4394-d7d8-1005-ad94-a64bfb12dd98.png)

#Azure Kubernetes Service (AKS)へのデプロイ

　[次回](https://qiita.com/Aida1971/items/d4f6e13f123a1d6fb233)は Azure Kubernetes Service (AKS) へのデプロイ手順を掲載します。