Istio シリーズ 第9回です。
Istio by Example に gRPC というのがあった。 gRPC に delay が挿入されている。できるんだねそれも。
ということで試してみます。gRPC については全然分かってないのだけれど。。。
テスト用の gRPC サーバーとクライアントは github.com/yteraoka/grpc-helloworld に用意しました。Docker Image も yteraoka/grpc-helloworld:latest にあります。
非 TLS の場合
Deployment と Service を作る Manifest です。サーバーに -tls
オプションをつけずに実行して、Service の port name は grpc にしてあります。
apiVersion: apps/v1 kind: Deployment metadata: name: grpc-helloworld-deployment labels: app: grpc-helloworld spec: replicas: 1 selector: matchLabels: app: grpc-helloworld template: metadata: labels: app: grpc-helloworld spec: containers: - name: helloworld image: yteraoka/grpc-helloworld:latest imagePullPolicy: IfNotPresent command: - "/server" ports: - containerPort: 10000 readinessProbe: exec: command: - "/client" initialDelaySeconds: 10 periodSeconds: 5 livenessProbe: exec: command: - "/client" initialDelaySeconds: 15 periodSeconds: 5 --- apiVersion: v1 kind: Service metadata: name: grpc-helloworld-service spec: selector: app: grpc-helloworld type: ClusterIP ports: - name: grpc protocol: TCP port: 10000
クライアントに使う Pod 用の Deployment はこちら。ここから作られる Pod 内から /client コマンドを実行します。
apiVersion: apps/v1 kind: Deployment metadata: name: grpc-client-deployment labels: app: grpc-client spec: replicas: 1 selector: matchLabels: app: grpc-client template: metadata: labels: app: grpc-client spec: containers: - name: grpc-client image: yteraoka/grpc-helloworld:latest imagePullPolicy: IfNotPresent command: - sleep - infinity
クライアントからの接続テストは次のようにします。grpc-go って接続に成功するまでずっとリトライするんですね。間隔が開いていくんで Retry with Exponential Backoff and jitter ってやつかな。
$ /client -server_addr grpc-helloworld-service.default.svc.cluster.local:10000 -timeout 10
VirtualService 無しの状態でのアクセス
Envoy は protocol を理解していますね。
{ "authority": "grpc-helloworld-service.default.svc.cluster.local:10000", "bytes_received": "12", "bytes_sent": "18", "downstream_local_address": "10.98.145.150:10000", "downstream_remote_address": "172.17.0.16:38298", "duration": "1", "istio_policy_status": "-", "method": "POST", "path": "/helloworld.Greeter/SayHello", "protocol": "HTTP/2", "request_id": "132f13ce-9503-4b4e-aaa9-ea9caf34d9a0", "requested_server_name": "-", "response_code": "200", "response_flags": "-", "route_name": "default", "start_time": "2020-03-14T15:36:25.619Z", "upstream_cluster": "outbound|10000||grpc-helloworld-service.default.svc.cluster.local", "upstream_host": "172.17.0.17:10000", "upstream_local_address": "172.17.0.16:56496", "upstream_service_time": "1", "upstream_transport_failure_reason": "-", "user_agent": "grpc-go/1.28.0", "x_forwarded_for": "-" }
VirtualService で Delay を挿入する
Fault Injection のために VirtualService を作成します。
VirtualService の Manifest。常に 3 秒の delay を入れます。
apiVersion: networking.istio.io/v1beta1 kind: VirtualService metadata: name: grpc-helloworld-virtual-service spec: hosts: - grpc-helloworld-service http: - fault: delay: percentage: value: 100.0 fixedDelay: 3s route: - destination: host: grpc-helloworld-service
delay を挿入した場合のログです。
{ "authority": "grpc-helloworld-service.default.svc.cluster.local:10000", "bytes_received": "12", "bytes_sent": "18", "downstream_local_address": "10.98.145.150:10000", "downstream_remote_address": "172.17.0.16:51828", "duration": "3004", "istio_policy_status": "-", "method": "POST", "path": "/helloworld.Greeter/SayHello", "protocol": "HTTP/2", "request_id": "5340f5d7-f6a8-45e5-897f-ceeb3526dfd5", "requested_server_name": "-", "response_code": "200", "response_flags": "DI", "route_name": "-", "start_time": "2020-03-14T12:31:59.995Z", "upstream_cluster": "outbound|10000||grpc-helloworld-service.default.svc.cluster.local", "upstream_host": "172.17.0.17:10000", "upstream_local_address": "172.17.0.16:41198", "upstream_service_time": "2", "upstream_transport_failure_reason": "-", "user_agent": "grpc-go/1.28.0", "x_forwarded_for": "-" }
TLS 有効な場合
次に TLS を有効にした gRPC サーバーとの通信で試します。サーバーとヘルスチェック用のコマンドに -tls オプションをつけます。Service は port name を tls にします。TLS を有効にしているのに port name を grpc にしてしまうと通信できません。
apiVersion: apps/v1 kind: Deployment metadata: name: grpc-helloworld-deployment labels: app: grpc-helloworld spec: replicas: 1 selector: matchLabels: app: grpc-helloworld template: metadata: labels: app: grpc-helloworld spec: containers: - name: helloworld image: yteraoka/grpc-helloworld:latest imagePullPolicy: IfNotPresent command: - "/server" - "-tls" ports: - containerPort: 10000 readinessProbe: exec: command: - "/client" - "-tls" initialDelaySeconds: 10 periodSeconds: 5 livenessProbe: exec: command: - "/client" - "-tls" initialDelaySeconds: 15 periodSeconds: 5 --- apiVersion: v1 kind: Service metadata: name: grpc-helloworld-service spec: selector: app: grpc-helloworld type: ClusterIP ports: - name: tls protocol: TCP port: 10000
アクセスした場合のログ。TLS の中は見れません。よって delay を入れることもできません。
{ "authority": "-", "bytes_received": "688", "bytes_sent": "1359", "downstream_local_address": "10.98.145.150:10000", "downstream_remote_address": "172.17.0.16:46948", "duration": "11", "istio_policy_status": "-", "method": "-", "path": "-", "protocol": "-", "request_id": "-", "requested_server_name": "-", "response_code": "0", "response_flags": "-", "route_name": "-", "start_time": "2020-03-14T15:43:52.547Z", "upstream_cluster": "outbound|10000||grpc-helloworld-service.default.svc.cluster.local", "upstream_host": "172.17.0.7:10000", "upstream_local_address": "172.17.0.16:55454", "upstream_service_time": "-", "upstream_transport_failure_reason": "-", "user_agent": "-", "x_forwarded_for": "-" }
まとめ
考えてみれば「そりゃそうだよな」なんだけど TLS が有効では Fault Injection できませんでした。mesh 内の通信は非TLSでも良さそうですが、gRPC (HTTP2) で非TLSっていうのがどの程度一般的なのかが良くわからない。Envoy で gRPC の TLS 終端と負荷分散っていうのをちょいちょい見かけるので結構使われているのかな?
Istio 使うなら mTLS もあるし、通信の暗号化という意味では問題なさそう。TLS 無しであればリクエスト単位でアクセスが分散されるのでこちらの方が良いですね。
Chaos Engineering 系ツールで delay 入れられたりするんだけどあれは API サーバーのレスポンスが遅い的な再現には使いづらいんですよね。
Istio 導入への道シリーズ
- Istio 導入への道 (1) – インストール編
- Istio 導入への道 (2) – サービス間通信編
- Istio 導入への道 (3) – VirtualService 編
- Istio 導入への道 (4) – Fault Injection 編
- Istio 導入への道 (5) – OutlierDetection と Retry 編
- Istio 導入への道 (6) – Ingress Gatway 編
- Istio 導入への道 (7) – 外部へのアクセス / ServiceEntry 編
- Istio 導入への道 (8) – 外部へのアクセスでも Fault Injection 編
- Istio 導入への道 (9) – gRPC でも Fault Injection 編
- Istio 導入への道 (10) – 図解
- Istio 導入への道 (11) – Ingress Gateway で TLS Termination 編