双方向ストリーミングなgRPCサーバーをGKEにデプロイしてみる
どうもMAD事業部の新井です。
本エントリは クラスメソッド Google Cloud Advent Calendar 2021 の14日目の記事です。
あまりいいネタも思いつかなかったので、前回作成したojichat-streamをGoogle Kubernetes Engine(GKE)にデプロイしてみようと思います。
正直GKEは触ったことないので、初歩的な内容になるかと思います。
概要
こちらのESPを使用したGKE用Endpointsのスタートガイドを参考に進めていきます。
GKE上のgRPCサーバーと通信するためにCloud EndpointsのESPv1を利用します。ESPv1はNginxベースのリバースプロキシとして動作し、サイドカーコンテナとしてアプリケーションと一緒にデプロイすることで、認証、モニタリング、ロギングなどのCloud Endpointsの機能が利用可能です。
ちなみにESPv2はEnvoyベースのプロキシです。 機会があればこちらも試してみたいです。
Endpoints の設定
サンプルプロジェクトのクローン
以前作った、ojichat-streamをそのまま使います。
git clone https://github.com/seiichi1101/ojichat-stream
※以降はこのリポジトリ内で作業を進めます
コードの自動生成
protoc -I proto \ --go_out proto/gen \ --go_opt paths=source_relative \ --go-grpc_out proto/gen \ --go-grpc_opt paths=source_relative \ --descriptor_set_out=api_descriptor.pb \ proto/ojichat.proto
Cloud EndpointのデプロイにFileDescriptorSet
が必要なので、protocコマンドに--descriptor_set_out
を追加しています。
APIの設定ファイル
type: google.api.Service config_version: 3 name: ojichat-stream.endpoints.<your-accont-id>.cloud.goog title: Ojichat Strem gRPC API apis: - name: ojichat.Ojichat usage: rules: - selector: ojichat.Ojichat.Chat allow_unregistered_calls: true
selector
にはProtocol Bufferの「パッケージ名+サービス名」の組み合わせになっている必要があります。
Endopiontのデプロイ
gcloud endpoints services deploy api_descriptor.pb api_config.yaml
先にEndpointをデプロイします。後ほどこのEndpointをESPのサイドカーコンテナから参照させます。
サービスの有効化
GKEが利用するサービス
- Service Management API
gcloud services enable servicemanagement.googleapis.com
- Service Control API
gcloud services enable servicecontrol.googleapis.com
- Google Cloud Endpoints
gcloud services enable endpoints.googleapis.com
Endpointsサービスの有効化
gcloud services enable <ENDPOINTS_SERVICE_NAME>
先ほどデプロイしたEndpointsサービスの有効化です。
Kubernetesクラスタの作成
今回は簡略化のため「GKE Standard」をデフォルト設定のまま利用します。
クラスタへkubectlコマンドを実行できるように認証しておきます。
gcloud container clusters get-credentials cluster-1 --zone asia-northeast1-a
※また、今回はデフォルトのサービスアカウントを利用します。特に指定していなければ、Compute Engineサービスアカウントがデフォルトサービスアカウントとして設定されるはずです。
コンテナのbuild&push
- build
docker build -t gcr.io/<your-account-id>/ojichat-stream:latest .
- push
docker push gcr.io/<your-account-id>/ojichat-stream:latest
GCR(Google Container Registry)にPushします。
アプリケーションのデプロイ
マニフェスト
apiVersion: v1 kind: Service metadata: name: esp-grpc-ojichat-stream spec: ports: - port: 80 targetPort: 9000 protocol: TCP name: http2 selector: app: esp-grpc-ojichat-stream type: LoadBalancer --- apiVersion: apps/v1 kind: Deployment metadata: name: esp-grpc-ojichat-stream spec: selector: matchLabels: app: esp-grpc-ojichat-stream replicas: 1 template: metadata: labels: app: esp-grpc-ojichat-stream spec: containers: - name: esp image: gcr.io/endpoints-release/endpoints-runtime:1 args: [ "--http2_port=9000", "--service=ojichat-stream.endpoints.<your-accont-id>.cloud.goog", "--rollout_strategy=managed", "--backend=grpc://127.0.0.1:50051" ] ports: - containerPort: 9000 - name: ojichat-stream image: gcr.io/<your-accont-id>/ojichat-stream:latest ports: - containerPort: 50051
L4 LoadBalancerを追加し、ESPをアプリケーションのサイドカーコンテナとして設定しています。
--service
の部分に、先ほど作成したEndpointのサービス名を割り当てることで、ESPのサイドカーコンテナからCloud Endpointを参照することが可能です。
アプリケーションのデプロイ
kubectl create -f grpc-ojichat-stream.yaml
マニフェストファイルの設定に基づいてデプロイされます。
動作確認
エンドポイントの確認
kubectl get service
表示されるLoad BalancerのEXTERNAL-IP
が外部アクセス用のエンドポイントになります。
確認用コマンド
go run ./cmd/client/main.go --name arai --addr <ip-addr>:80
まとめ
正直GKEを触るのは初めてだったため、Cloud EndpointとESPの関係性の理解に苦しんだり、サービスアカウントまわりでハマったりと、結構時間がかかりました。
次はもうちょっと実践的な環境構築ができれば思います。
明日12/15は西田さんです。よろしくお願いします!