3
votes

I have a gRPC server running on port 9000 with gRPC-gateway running on port 9080. I can make request to my service with postman using the following link: ```http://cluster1.example.com/api/v1/namespaces/default/services/my-service:9080/proxy

How can I connect to my service from gRPC client (on my local machine, which is outside of the cluster) using grpc.Dial()?

Example:

conn, err := grpc.Dial(...?, grpc.WithInsecure())
if err != nil {
    panic(err)
}
2
Have you tried `cluster1.example.com:9000'? (the go gRPC client will communicate with the gRPC server directly). See the naming doc for supported formats. If you want a tool for testing this then try bloomRPC.Brits
@Brits I've tried cluster1.example.com:9000, but got i/o timeout error. I think it was expected behavior. How does it know what grpc service connect to (there are huge amount of services inside k8s cluster)?Klimbo
@Brits Here is a way to connect to k8s service. I made my url with the help of that documentation. But I don't understand how to connect to a specific service inside the cluster from grpc client...Klimbo

2 Answers

2
votes

You should be able to connect to services in your k8s cluster from local with port forwarding:

kubectl port-forward --context <mycontext> -n <mynamespace> svc/my-service 9000:9000

And then you just pass the gRPC target into Dial with localhost and no scheme:

conn, err := grpc.Dial("localhost:9000", grpc.WithInsecure())
if err != nil {
    panic(err)
}

I might state the obvious, but of course the server also must be started in insecure mode (no credentials), otherwise you might get Unavailable response code.

2
votes

Short answer:

This is mostly not a Golang question, it is a Kubernetes question. You have to set up the Kubernetes part and use it like ever before in Golang.

You can refer to @blackgreen's answer for a simple and temporary way.

Details

Kubernetes uses an overlay network, Flannel in most cases, the communication inside the cluster is set up by default, and it is isolated from outside.

Of cause there are some projects like Calico can connect the inside and outside network, but it another story.

There are several solutions if we want to access the pods from outside.

kubectl

https://kubernetes.io/docs/tasks/access-application-cluster/port-forward-access-application-cluster/

Kubectl uses socat to create a tunnel and forward one or more local ports to a pod.

The port forward will end when you stop the command, but it is a good choice if you want to temporarily access the pod for debugging.

kubectl port-forward redis-master-765d459796-258hz 7000:6379

Service

https://kubernetes.io/docs/concepts/services-networking/service/#publishing-services-service-types

Service is an abstract way to expose an application running on a set of Pods as a network service.

when accessing from outside, there are kinds of Service to use, NodePort may be a good choice in most case.

It uses iptables or ipvs to create a Port Forward in all Nodes forwarding network to the target port.

apiVersion: v1
kind: Service
metadata:
  name: my-service
spec:
  type: NodePort
  selector:
    app: MyApp
  ports:
      # By default and for convenience, the `targetPort` is set to the same value as the `port` field.
    - port: 80
      targetPort: 80
      # Optional field
      # By default and for convenience, the Kubernetes control plane will allocate a port from a range (default: 30000-32767)
      nodePort: 30007

Ingress

https://kubernetes.io/docs/concepts/services-networking/ingress/

Ingress is a layer 7 proxy managing external network access to Service, as gRPC is also built on top of HTTP/2, Ingress work perfectly.

Ingress should be the choice if you are exposing a Production Application.