Istio gRPC-Web configuration

7/28/2019

I'm trying to expose a gRPC backend service written in .NETCORE3.0 and packaged as a linux docker image. I tested the service in localhost and all works as expected. However, I am unable to access in from GKE using istio (I've updated my GKE cluster to the latest versions as to 7/27/2019). I'm consuming the service using gRPC-Web with react.js. I'm getting a 503 error everytime I try to access. Looking at the istioingress logs, I see this line associated with the 503:

[2019-07-28 15:18:57.131][22][warning][upstream] [external/envoy/source/common/upstream/original_dst_cluster.cc:110] original_dst_load_balancer: No downstream connection or no original_dst.

Is there anything wrong with my configurations below.

apiVersion: networking.istio.io/v1alpha3
kind: EnvoyFilter
metadata:
  name: grpc-web-filter
spec:
  workloadLabels:
    app: users
  filters:
  - listenerMatch:
      listenerType: SIDECAR_INBOUND
      listenerProtocol: HTTP
    insertPosition:
      index: FIRST
    filterType: HTTP
    filterName: "envoy.grpc_web"
    filterConfig: {}

apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
  name: users
spec:
  host: users
  subsets:
  - name: v1
    labels:
      version: v1
---
###########################################################################
# Ingress resource (gateway)
##########################################################################
apiVersion: networking.istio.io/v1alpha3
kind: Gateway
metadata:
  name: sf-gateway
spec:
  selector:
    istio: ingressgateway
  servers:
  - port:
      number: 80
      name: http
      protocol: HTTP
    hosts:
    - "*"
---
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: usersvs
spec:
  hosts:
  - "*"
  gateways:
  - sf-gateway
  http:
  - match:
    - uri:
        prefix: /xxx.common.users.UserService
    - port: 80
    route:
    - destination:
        host: users.default.svc.cluster.local
        port:
          number: 80
        subset: v1
    corsPolicy:
      allowOrigin:
        - "*"
      allowMethods:
        - POST
        - GET
        - OPTIONS
        - PUT
        - DELETE
      allowHeaders:
        - grpc-timeout
        - content-type
        - keep-alive
        - user-agent
        - cache-control
        - content-type
        - content-transfer-encoding
        - custom-header-1
        - x-accept-content-transfer-encoding
        - x-accept-response-streaming
        - x-user-agent
        - x-grpc-web
      maxAge: 1728s
      exposeHeaders:
        - custom-header-1
        - grpc-status
        - grpc-message
      allowCredentials: true
---

##################################################################################################
# users service
##################################################################################################
apiVersion: v1
kind: Service
metadata:
  name: users
  labels:
    app: users
spec:
  ports:
  - name: grpc-port
    port: 80
  selector:
    app: users
---
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: users
spec:
  replicas: 1
  template:
    metadata:
      labels:
        app: users
        version: v1
    spec:
      containers:
      - name: users
        image: ***
        imagePullPolicy: IfNotPresent
        ports:
        - containerPort: 80
---

Here is the Dockerfile FROM mcr.microsoft.com/dotnet/core/aspnet:3.0-buster-slim AS base WORKDIR /app EXPOSE 80 EXPOSE 443

FROM mcr.microsoft.com/dotnet/core/sdk:3.0-buster AS build
WORKDIR /src
COPY ["UserService/XXX.Users.csproj", "UserService/"]
COPY ["ShowFam.Common/ShowFam.Common.csproj", "ShowFam.Common/"]
RUN dotnet restore "UserService/XXX.Users.csproj"
COPY . .
WORKDIR "/src/UserService"
RUN dotnet build "XXX.Users.csproj" -c Release -o /app

FROM build AS publish
RUN dotnet publish "XXX.Users.csproj" -c Release -o /app

FROM base AS final
WORKDIR /app
COPY --from=publish /app .
ENTRYPOINT ["dotnet", "XXX.Users.dll"]
-- nkigen
google-kubernetes-engine
grpc-web
istio

1 Answer

3/22/2020

You can write “grpc-web” in the service port name like this.

apiVersion: v1
kind: Service
metadata:
  name: echo-service
spec:
  type: ClusterIP
  ports:
    - name: grpc-web # istio refers this value as protocol
      port: 80
      targetPort: 9090
  selector:
    app: echo-service-worker

Istio/Protocol Selection: https://istio.io/docs/ops/configuration/traffic-management/protocol-selection/

-- Masayuki Ito
Source: StackOverflow