sitateru tech blog: Cloud Endpoints

sitateru tech blog

シタテルの技術やエンジニアの取り組みを紹介するテックブログです。

ラベル Cloud Endpoints の投稿を表示しています。 すべての投稿を表示
ラベル Cloud Endpoints の投稿を表示しています。 すべての投稿を表示

2018年11月2日金曜日

Google Cloud EndpointsとAWS上のAPIサーバをつないでみる

11月 02, 2018

こんにちは、シタテルの茨木です。

シタテルではSCS(Sitateru-Control-System)という生産管理システムをRuby on Railsで実装し、AWSでホスティングしています。

SCS自体もViewを持っているのですが、徐々にAPI化とフロントエンドの分離を進めており、一部のフロントエンドは既にSPAで分離されていたりします。

今後はシステムをAPI仕様ベースで分離&疎結合化していきたいねーという流れで、API-Gateway系のプロダクト、今回は特にGoogle Cloud Endpointsに触ってみました。

やること

既にあるAWS上のOpenAPI仕様で実装されたAPIサーバと、Google Cloud Endpointsを接続して、APIアクセスを管理できるか見てみる。

とりあえずトラフィックが見えるところまでで、認証系とかはやりません。

構成イメージ

API-Server ---- ESP ---- Client App
                 |
                 |
          Cloud Endpoints

ESP(Extensible Service Proxy)

ESPはEndpoints固有の要素で、リバースプロキシとしてAPIリクエストを一次受けし、Cloud Endpointsと連携しつつ、通していいリクエストだけバックエンド(API-Server)に流してくれます

  • API-Serverの手前でESPを動作させるのが必須
  • ESPはdockerで稼働が必要、ESPの稼働プラットフォームは任意
  • ESPを間に噛ませさえすれば、API Serverのプラットフォームも任意

手順

身も蓋もないですが公式ガイドに書いてあるのを読むのが確実です

ESP をローカルまたは別のプラットフォームで実行する

ざっと流れを書いておきます

  • GCPにプロジェクト作る

  • プロジェクトにサービスアカウント作って秘密鍵を払い出す

    • サービスアカウントはESPがendpointにアクセスする際に使われます
  • OpenAPIの定義ファイル(いわゆるswagger)をAPIサーバから持ってくる

    • 今回はgrape-swaggerで生成したものを使いました
    • ガイドだとyamlになってますが、jsonでも読んでくれます
  • APIサーバのドメイン所有権の証明を行う

  • gcloud endpoints services deploy [API定義ファイル]でendpoint構成をデプロイする

    • デプロイが通ると、下図の様にGCPのポータル上で見えるようになります
    • あくまでendpoint構成をデプロイしただけで、ESPと繋いでないので何も起きません
  • ESP用のインスタンスをAWS上に作って、dockerでESPを稼働させる

    • docker導入は一般的な手順なので割愛
    • ESP稼働させるdocker runは下記の様になります(サンプル)
sudo docker run \
    --detach \
    --name="esp" \
    --net="host" \
    --volume=$HOME/esp:/esp \
    --publish=8082 \
    gcr.io/endpoints-release/endpoints-runtime:1 \
    --service=hogehoge.sitateru.com \
    --rollout_strategy=managed \
    --http_port=8082 \
    --backend=https://hogehoge.sitateru.com \
    --service_account_key=/esp/key.json

ざっとオプション説明

--service
endpoint構成のサービス名(≒APIサーバのドメイン名≒swaggerのhostエントリ)と一致させる

--backend
ESPのプロキシ先。APIサーバを指定する

--service_account
サービスアカウントの鍵ファイルを指定する

  • ここまでやるとESP経由でリクエストが通るようになります
    • curl等で試してみましょう
curl --request POST \
    --header "Content-Type:application/json" \
    --header "APIサーバ固有で必要なヘッダ等あれば" \
    --data '{"email":"hogehoge", "password":"fugafuga"}' \
    http://(ESPインスタンスのIP):8082/path/to/api
  • ESP経由でのアクセスは、GCPポータルからログが確認できます

ハマった点

上記手順ではすんなりswaggerを読ませていますが、実際は結構エラーと戦いました。

ちゃんと読むとガイドにも書いてありますが、endpoint構成はOpenAPI仕様を完全にはサポートしていないようです。

例1. type: fileはダメっぽい

"/definitions/putApiV2Topics/properties/files/items/type": domain: validation; keyword: enum; message: value not found in enum; enum: ["array","boolean","integer","null","number","object","string"]; value: "file"

type: fileはサポートしてない。
仕様的にはstringに置換してよさそう?

例2. request-paramの渡し方に制限がある

 ERROR: unknown location: http: body field path 'ids' must be a non-repeated message.
 ERROR: unknown location: http: body field path 'api_v2_files' must be a non-repeated message.
 ERROR: unknown location: http: body field path 'api_v2_items_id_files' must be a non-repeated message.
 ERROR: unknown location: http: body field path 'emails' must be a non-repeated message.'

request-parameterのbody直下にarrayはサポートしない模様。
API側のパラメタ受け取り仕様で、arrayはobjectでくるむように作る必要がある?

まとめ

ESPまわりの構成は実際に組むまでイメージ湧かなかったので、その辺の助けになれば幸いです。

OpenAPIはほぼデファクトだと思っていたので、制約がいくつか出てきたのは意外でした。gRPC推しなんですかね?