Unable to expose gRPC server with istio

I am not good at English so I apologize if I say something strange.

Now I am developing a gRPC server on GKE with istio and my server works correctly when I call from another pod inside my cluster with DNS. However, calls from outside the cluster always return “context deadline exceeded”.

I implemented the deployment named ms-user that has the pods that my grpc servers are running on with port 5000 and following resources in the namespace “default”.

apiVersion: v1
kind: Service
metadata:
  name: ms-user
spec:
  selector:
    app: ms-user
  ports:
  - name: grpc
    protocol: TCP
    port: 5000
    targetPort: 5000
---
apiVersion: networking.istio.io/v1alpha3
kind: Gateway
metadata:
  name: gateway-dev
spec:
  selector:
    istio: ingressgateway
  servers:
  - hosts:
    - '*'
    port:
      name: grpc
      number: 5000
      protocol: GRPC
---
apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
  name: ms-user-rule-dev
spec:
  host: ms-user
  trafficPolicy:
    loadBalancer:
      simple: ROUND_ROBIN
---
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: vs-dev
spec:
  hosts:
  - "*"
  gateways:
  - gateway-dev
  grpc:
  - match:
    - port: 5000
    route:
    - destination:
        host: ms-user
        port:
          number: 5000

And I deployed following manifests to namespace “istio-system”:

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: gke-ingress
  namespace: istio-system
  annotations:
    kubernetes.io/ingress.global-static-ip-name: "istio-endpoint-dev"
spec:
  rules:
  - http:
      paths:
      - backend:
          serviceName: istio-ingressgateway
          servicePort: 5000
---
apiVersion: v1
kind: Service
metadata:
  name: istio-ingressgateway
  namespace: istio-system
  ...

spec:
  ...
  ports:
  ...
  - name: grpc
    nodePort: 30001
    port: 5000
    protocol: TCP
    targetPort: 5000
  
  selector:
    app: istio-ingressgateway
    istio: ingressgateway
    release: istio
  sessionAffinity: None
  type: LoadBalancer
...

Then, I am testing with grpcurl.

$ grpcurl -plaintext -proto=PATH_TO_PROTO MY_gke_ingress_STATIC_IP:5000 foo.FooService.Foo
Failed to dial target host "IPADRESS:5000": context deadline exceeded

I can call it from some pods.

$ kubectl exec -it foo-pod -- bash
> grpcurl -plaintext -proto=PATH_TO_PROTO ms-user:5000 foo.FooService.Foo
{"result": "OK"}

How can i fix it…?
Thanks a lot