前回 はIstioでHTTPのリクエストを振り分けていたので,今度はgRPCを扱ってみようと思う. といっても基本的な構成はそんなに変わらない.
前回とほとんど同じような環境を使うので,
- Helm
- Istio
- Auto injection
あたりの設定は終わっているものとする. また,今回も基本的にクラスタ内でマイクロサービス間通信を扱うことを前提にするため,外部との接続は行わない.
gRPCサーバを立てる
gRPCはいつも使っているexampleのサーバを使うことにする.
まず,バックエンドとなるgRPCサーバを立てる.
apiVersion: apps/v1 kind: Deployment metadata: name: backend-0 namespace: istio-grpc-example labels: app: backend-0 spec: replicas: 1 selector: matchLabels: app: backend version: "0" template: metadata: labels: app: backend version: "0" spec: containers: - name: python image: h3poteto/grpc_example-server-python:master imagePullPolicy: Always ports: - name: grpc containerPort: 9090 protocol: TCP env: - name: SERVER_IP value: 0.0.0.0 - name: SERVER_PORT value: "9090"
前回同様,あとでバージョンによる分岐をさせるために,version: "0"
を付与しておくが,とりあえず今の段階では使わない.
次にこのサーバにアクセスできるようにServiceを作る.
apiVersion: v1 kind: Service metadata: name: backend namespace: istio-grpc-example labels: app: backend spec: ports: - port: 50051 targetPort: 9090 protocol: TCP #ポートの名前に注意 name: grpc-backend selector: app: backend
ここで,ポートの名前が非常に重要になるのだが,これについてはIstioのVirtualServiceの仕様によるものなので,VirtualServiceの章で説明する.
ひとまずこれでgRPCサーバが立ち上がるはずだ. gRPCサーバは9090ポートで立ち上がり,Service経由だと50051ポートでアクセスできるようになっている.
Istioによるロードバランスをせずにアクセスする
とりあえず今作ったサーバに,Istioを通しつつも特にアクセスコントロールをせずにアクセスしてみる.
クライアントとなるPodを立てる・
apiVersion: apps/v1 kind: Deployment metadata: name: client-0 namespace: istio-grpc-example labels: app: client-0 spec: replicas: 1 selector: matchLabels: app: client version: "0" template: metadata: labels: app: client version: "0" spec: containers: - name: python image: h3poteto/grpc_example-client-python:master imagePullPolicy: Always env: - name: SERVER_IP value: "backend" - name: SERVER_PORT value: "50051"
こいつは, SERVER_IP:SERVER_PORT
にあるgRPCサーバにアクセスをし続ける.
Istioによりアクセスを振り分ける
バックエンドのgRPCサーバとして, version: 0
と version: 1
を作ろう.
apiVersion: apps/v1 kind: Deployment metadata: name: backend-0 namespace: istio-grpc-example labels: app: backend-0 spec: replicas: 1 selector: matchLabels: app: backend version: "0" template: metadata: labels: app: backend version: "0" spec: containers: - name: python image: h3poteto/grpc_example-server-python:master imagePullPolicy: Always ports: - name: grpc containerPort: 9090 protocol: TCP env: - name: SERVER_IP value: 0.0.0.0 - name: SERVER_PORT value: "9090" --- apiVersion: apps/v1 kind: Deployment metadata: name: backend-1 namespace: istio-grpc-example labels: app: backend-1 spec: replicas: 1 selector: matchLabels: app: backend version: "1" template: metadata: labels: app: backend version: "1" spec: containers: - name: python image: h3poteto/grpc_example-server-python:master imagePullPolicy: Always ports: - name: grpc containerPort: 9090 protocol: TCP env: - name: SERVER_IP value: 0.0.0.0 - name: SERVER_PORT value: "9090"
この段階では, version: 0
と version: 1
の両方にアクセスが飛んできているはずである.
version: 0にだけアクセスさせる
これはHTTPのときとあまり変わらないVirtualServiceを定義する.
apiVersion: networking.istio.io/v1alpha3 kind: VirtualService metadata: name: backend namespace: istio-grpc-example spec: hosts: - "backend" http: - match: - port: 50051 route: - destination: host: backend subset: v0 --- apiVersion: networking.istio.io/v1alpha3 kind: DestinationRule metadata: name: backend namespace: istio-grpc-example spec: host: backend trafficPolicy: loadBalancer: simple: RANDOM subsets: - name: v0 labels: version: "0" - name: v1 labels: version: "1"
これで version: 0
にのみアクセスが飛ぶようになるはずだ.
Portの名前マジ大事
Serviceを定義する際に少し書いたが,これをやる上でServiceのポート名が大事になってくる.
IstioのVirtualServiceのドキュメントを読むと,
httpとtcpというのが定義されている.gRPCなのでうっかりtcpにしそうだが,httpの項目を読むと
service entry ports using HTTP/HTTP2/GRPC protocols
普通にhttpでHTTP2やgRPCをさばける.
ただしすごく重要なことが書いてあって,
HTTP routes will be applied to platform service ports named ‘http-’/‘http2-’/‘grpc-*’, gateway ports with protocol HTTP/HTTP2/GRPC/ TLS-terminated-HTTPS
そう,
- httpなら
http-*
- http2なら
http2-*
- gRPCなら
grpc-*
という名前のポートにしておかないと,VirtualServiceが拾ってくれない.
最初,適当に, backend-port
とか名前をつけていたら,疎通はしてくれるんだけどVirtualServiceが全然振り分けてくれなくて,困った.
ポート名をちゃんと grpc-*
にすることでしっかりVirtualServiceによる振り分けが可能となった.
その他の振り分けパターン
前回とあまり変わらないので,振り分けパターンは1パターンしか紹介しなかったが,まぁだいたい前回と同じようなVirtualServiceでできる.
詳しくはソースを参考にしてほしい.
前回作ったHTTPの方も置いておく.
まとめ
ひとまずIstioでやりたかったことはできた.これでgRPCサーバの前段に楽にEnvoyを仕込んでロードバランスできるようになる.
いよいよIstioも1.0になり,GKEにも入ろうとしているので(まだベータ版),俺も本番に入れたい.