I.Tyger
I.Tyger

Reputation: 805

How to access a service in a kubernetes cluster using the service name .

I am pretty new to kubernetes and I have successfully setup a cluster on google container engine . In my cluster I have a backend api developed with dropwizard, front end developed with node js and a mysql database. All have been deployed to the cluster and are working .However my challenge is this after setting up an external ip for my node containers and backend I can access them remotely but I can't access my backed from my front end using the service name e.g my backend is called backendapi within the cluster. I can't do this http://backendapi:8080 to call my rest services when deployed to the cluster . The catch for me is when I deploy to the cluster I don't want my front end to hit my back end using the external ip, I want them to connect within the cluster without going via the external ip address. When I connect to a pod and ping backendapi it returns a result but when I deploy my front end and use the label name it doesn't work .What could I be doing wrong ?.

Upvotes: 26

Views: 49185

Answers (2)

so-random-dude
so-random-dude

Reputation: 16555

But the problem still persists when I change to this backendapi.default.svc.cluster.local:8080. I even tried using the other port that it is mapped to internally and my frontend web page keeps saying backendapi.default.svc.cluster.local:32208/api/v1/auth/login net::ERR_NAME_NOT_RESOLVED. The funny thing is when I curl from my frontend pod it works . But when I'm accessing it using my web browser it doesn't

Because it is resolvable only within the cluster. (Because only the K8s cluster with kube-dns add-on can translate the domain name backendapi.default.svc.cluster.local to it's corresponding IP address)

Could this be because i exposed an external ip for the service as well . The external ip works though

No, It is because domain name backendapi.default.svc.cluster.local is resolvable only within the cluster, not from a random browser in a random machine.

Solution

What you did is one of the solutions, exposing an external IP for the service. If you don't want to use a cryptic IP address, you can create an ingress (and use an ingress controller in your cluster) and expose your Microservice. Since you are on GCP, you can make use of their API gateway rather than exposing a IP address.

Note: Remember to add the authentication/Authorization to lock down your microservice as needed as it's getting exposed to the user.

Another Solution

Proxy all the backend calls through the server which serves your web app (nginx/nodejs etc)

Advantage of this approach is, you will avoid all the Same Origin Policy/CORS headaches, your microservice (express) authentication details will be abstracted away from user's browser.

Disadvantage of this approach is, 1) your backend microservice will have a tight coupling with frontend (or vice-versa depending on how you look at it), This will make the scaling of backend dependent on frontend. 2) Your Backend is not exposed. So, if you have another consumer (let's just say an android app) it will not be able to access your service.

Kind of similar question: https://stackoverflow.com/a/47043871/6785908

Upvotes: 9

mdaniel
mdaniel

Reputation: 33231

As long as kube-dns is running (which I believe is "always unless you disable it"), all Service objects have an in cluster DNS name of service_name +"."+ service_namespace + ".svc.cluster.local" so all other things would address your backendapi in the default namespace as (to use your port numbered example) http://backendapi.default.svc.cluster.local:8080. That fact is the very reason Kubernetes forces all identifiers to be a "dns compatible" name (no underscores or other goofy characters).

Even if you are not running kube-dns, all Service names and ports are also injected into the environment of Pods just like docker would do, so the environment variables ${BACKENDAPI_SERVICE_HOST}:${BACKENDAPI_SERVICE_PORT} would contain the Service's in-cluster IP (even though the env-var is named "host") and the "default" Service port (8080 in your example) if there is only one.

Whether you choose to use the DNS name or the environment-variable-ip is a matter of whether you like having the "readable" names for things in log output or error messages, versus whether you prefer to skip the DNS lookup and use the Service IP address for speed but less legibility. They behave the same.

The whole story lives in the services-networking concept documentation

Upvotes: 44

Related Questions