🚧

Istio のサービスへの接続でプロトコルエラーになる

2022/10/04に公開

現象

Istio サービスメッシュを有効にした Kubernetes クラスタ内に立てた Service に接続しようとするも,upstream connect error or disconnect/reset before headers. reset reason: protocol error が出て到達できない。

例えば,以下のような Service に gRPC で接続しようとしても失敗する。

apiVersion: v1
kind: Service
metadata:
  name: my-service
spec:
  selector:
    app.kubernetes.io/name: MyApp
  ports:
    - name: http-port
      protocol: TCP
      port: 80
      targetPort: 8080

原因

Istio では Service で定義したポート名で明示的にプロトコルを判定しており,実際に使用するプロトコルと齟齬があれば通信できなくなる。

Explicit Protocol Selection

上記の例では,gRPC(HTTP/2)でアプリが構成され,接続元も gRPC で接続していたとしても,接続先ポート名が http で始まっているので,Istio に HTTP/1.1 と解釈されてしまい,到達できない。

ただのポート名だと思って自由に命名していたら,プロトコルを判定されて通信に影響してしまうことがあるので,あまり目立たない仕様には注意が必要である。

対処方法

ポート名を規則に従ってプロトコル名で開始するものにする。

  ports:
    - name: grpc-port
      protocol: TCP
      port: 80
      targetPort: 8080

または,Kubernetes 1.18 以降の場合,appProtocol で明示的にプロトコルを指定する。

  ports:
    - name: api-port
      protocol: TCP
      appProtocol: grpc
      port: 80
      targetPort: 8080

Discussion