本文へ移動

gRPCゲートウェイを使う理由

gRPCゲートウェイの使用を検討する理由

etcd v3は、メッセージングプロトコルにgRPC を使用します。etcdプロジェクトは、gRPCでetcdクラスターと通信するための、gRPCベースのGoクライアント とコマンドラインユーティリティーetcdctl を提供しています。gRPCをサポートしない言語向けには、JSONのgRPCゲートウェイ を提供しています。このゲートウェイはRESTfulなプロキシとして動作し、HTTP/JSONリクエストをgRPCメッセージに変換します。

gRPCゲートウェイの使用

ゲートウェイは、etcdのProtocol Buffers メッセージ定義のJSONマッピング を受け付けます。keyとvalueフィールドはバイト配列として定義されているため、JSONではbase64でエンコードする必要があります。以下の例ではcurlを使いますが、どのHTTP/JSONクライアントでも同様に動作するはずです。

注意事項

gRPCゲートウェイのエンドポイントは、etcd v3.3以降で変更されています。

  • etcd v3.2以前は、[CLIENT-URL]/v3alpha/*だけを使用します。
  • etcd v3.3は、[CLIENT-URL]/v3alpha/*を維持しつつ、[CLIENT-URL]/v3beta/*を使用します。
  • etcd v3.4は、[CLIENT-URL]/v3beta/*を維持しつつ、[CLIENT-URL]/v3/*を使用します。
    • [CLIENT-URL]/v3alpha/*は非推奨です。
  • etcd v3.5以降は、[CLIENT-URL]/v3/*だけを使用します。
    • [CLIENT-URL]/v3beta/*は非推奨です。

gRPC-gatewayは、TLSのCommon Nameを使った認証をサポートしていません。

キーの書き込みと取得

/v3/kv/rangeと/v3/kv/putサービスで、キーを読み書きします。

<<COMMENT
https://www.base64encode.org/
foo is 'Zm9v' in Base64
bar is 'YmFy'
COMMENT

curl -L http://localhost:2379/v3/kv/put \
  -X POST -d '{"key": "Zm9v", "value": "YmFy"}'
# {"header":{"cluster_id":"12585971608760269493","member_id":"13847567121247652255","revision":"2","raft_term":"3"}}

curl -L http://localhost:2379/v3/kv/range \
  -X POST -d '{"key": "Zm9v"}'
# {"header":{"cluster_id":"12585971608760269493","member_id":"13847567121247652255","revision":"2","raft_term":"3"},"kvs":[{"key":"Zm9v","create_revision":"2","mod_revision":"2","version":"1","value":"YmFy"}],"count":"1"}

# get all keys prefixed with "foo"
curl -L http://localhost:2379/v3/kv/range \
  -X POST -d '{"key": "Zm9v", "range_end": "Zm9w"}'
# {"header":{"cluster_id":"12585971608760269493","member_id":"13847567121247652255","revision":"2","raft_term":"3"},"kvs":[{"key":"Zm9v","create_revision":"2","mod_revision":"2","version":"1","value":"YmFy"}],"count":"1"}

キーの監視

/v3/watchサービスで、キーを監視します。

curl -N http://localhost:2379/v3/watch \
  -X POST -d '{"create_request": {"key":"Zm9v"} }' &
# {"result":{"header":{"cluster_id":"12585971608760269493","member_id":"13847567121247652255","revision":"1","raft_term":"2"},"created":true}}

curl -L http://localhost:2379/v3/kv/put \
  -X POST -d '{"key": "Zm9v", "value": "YmFy"}' >/dev/null 2>&1
# {"result":{"header":{"cluster_id":"12585971608760269493","member_id":"13847567121247652255","revision":"2","raft_term":"2"},"events":[{"kv":{"key":"Zm9v","create_revision":"2","mod_revision":"2","version":"1","value":"YmFy"}}]}}

トランザクション

/v3/kv/txnで、トランザクションを発行します。

# target CREATE
curl -L http://localhost:2379/v3/kv/txn \
  -X POST \
  -d '{"compare":[{"target":"CREATE","key":"Zm9v","createRevision":"2"}],"success":[{"requestPut":{"key":"Zm9v","value":"YmFy"}}]}'
# {"header":{"cluster_id":"12585971608760269493","member_id":"13847567121247652255","revision":"3","raft_term":"2"},"succeeded":true,"responses":[{"response_put":{"header":{"revision":"3"}}}]}
# target VERSION
curl -L http://localhost:2379/v3/kv/txn \
  -X POST \
  -d '{"compare":[{"version":"4","result":"EQUAL","target":"VERSION","key":"Zm9v"}],"success":[{"requestRange":{"key":"Zm9v"}}]}'
# {"header":{"cluster_id":"14841639068965178418","member_id":"10276657743932975437","revision":"6","raft_term":"3"},"succeeded":true,"responses":[{"response_range":{"header":{"revision":"6"},"kvs":[{"key":"Zm9v","create_revision":"2","mod_revision":"6","version":"4","value":"YmF6"}],"count":"1"}}]}

認証

/v3/authサービスで、認証を設定します。

# create root user
curl -L http://localhost:2379/v3/auth/user/add \
  -X POST -d '{"name": "root", "password": "pass"}'
# {"header":{"cluster_id":"14841639068965178418","member_id":"10276657743932975437","revision":"1","raft_term":"2"}}

# create root role
curl -L http://localhost:2379/v3/auth/role/add \
  -X POST -d '{"name": "root"}'
# {"header":{"cluster_id":"14841639068965178418","member_id":"10276657743932975437","revision":"1","raft_term":"2"}}

# grant root role
curl -L http://localhost:2379/v3/auth/user/grant \
  -X POST -d '{"user": "root", "role": "root"}'
# {"header":{"cluster_id":"14841639068965178418","member_id":"10276657743932975437","revision":"1","raft_term":"2"}}

# enable auth
curl -L http://localhost:2379/v3/auth/enable -X POST -d '{}'
# {"header":{"cluster_id":"14841639068965178418","member_id":"10276657743932975437","revision":"1","raft_term":"2"}}

/v3/auth/authenticateでetcdの認証を行い、認証トークンを取得します。

# get the auth token for the root user
curl -L http://localhost:2379/v3/auth/authenticate \
  -X POST -d '{"name": "root", "password": "pass"}'
# {"header":{"cluster_id":"14841639068965178418","member_id":"10276657743932975437","revision":"1","raft_term":"2"},"token":"sssvIpwfnLAcWAQH.9"}

認証情報を使ってキーを取得するには、Authorizationヘッダーに認証トークンを設定します。

curl -L http://localhost:2379/v3/kv/put \
  -H 'Authorization: sssvIpwfnLAcWAQH.9' \
  -X POST -d '{"key": "Zm9v", "value": "YmFy"}'
# {"header":{"cluster_id":"14841639068965178418","member_id":"10276657743932975437","revision":"2","raft_term":"2"}}

エラーレスポンス

gRPCゲートウェイは、gRPCのステータスをHTTPステータスコードとJSONのエラー本文に変換します。 etcd v3.6以降は、grpc-gateway v2へのアップグレードによってエラー処理が変わりました (v2移行ガイドのエラー処理に関する注意事項 を参照)。 現在のゲートウェイの動作は、GoogleのAPIエラーモデル で説明されている google.rpc.Status(code、message、details)に沿っています。 以前のgrpc-gatewayにはトップレベルのerrorフィールドも含まれていましたが、 etcd v3.6以降では、このフィールドはサポートされていません。

クライアントは、HTTPステータスコードを成功・失敗の主な判断材料として扱ってください。 リクエストが失敗した場合は、messageフィールドをエラー情報の主な情報源とし、 追加の詳細情報から、さらに詳しい状況を読み取ることを推奨します。

Swagger

生成されたSwagger API定義は、rpc.swagger.json にあります。