🚧
Istio のサービスへの接続でプロトコルエラーになる
現象
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 で定義したポート名で明示的にプロトコルを判定しており,実際に使用するプロトコルと齟齬があれば通信できなくなる。
上記の例では,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