tmp dev
tmp dev

Reputation: 9183

k8s communicate from one service to another

I have two services deployed on the same k8s (minikube cluster). What is the url/approach I should use for one service to communicate with another service. I tried searching a bit on the web but most of them are communicating with an external db which is not what I'm after. This is what my deployments look like. I am looking for the goclient to be able to communicate with goserver. I know I need to go through the service but not sure what the url should look like. And is this dynamically discoverable? In addition to this if I expose goserver though ingress will this change ?

apiVersion: apps/v1
kind: Deployment
metadata:
  name: goserver
  namespace: golang-ns
  labels:
    app: goserver
spec:
  replicas: 1
  selector:
    matchLabels:
      app: goserver
  template:
    metadata:
      labels:
        app: goserver
    spec:
      containers:
      - name: goserver
        image: goserver:1.0.0
        imagePullPolicy: Never
        ports:
        - containerPort: 8080

---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: goclient
  namespace: golang-ns
  labels:
    app: goclient
spec:
  replicas: 1
  selector:
    matchLabels:
      app: goclient
  template:
    metadata:
      labels:
        app: goclient
    spec:
      containers:
      - name: goclient
        image: goclient:1.0.0
        imagePullPolicy: Never
        ports:
        - containerPort: 8081

---

apiVersion: v1
kind: Service
metadata:
  name: goserver-service
  namespace: golang-ns
spec:
  selector:
    app: goserver  
  ports:
    - protocol: TCP
      port: 8080
      targetPort: 8080
  type: LoadBalancer

---

apiVersion: v1
kind: Service
metadata:
  name: goclient-service
  namespace: golang-ns
spec:
  selector:
    app: goclient
  ports:
    - protocol: TCP
      port: 8081
      targetPort: 8081
  type: LoadBalancer

Upvotes: 0

Views: 3353

Answers (1)

mario
mario

Reputation: 11098

Note that the term Service can be quite ambiguous when used in the context of kubernetes.

Service in your question is used to denote one of your microservices, deployed as containerized applications, running in Pods, managed by 2 separate Deployments.

Service, that was mentioned in David Maze's comment, refers to a specific resource type which is used for exposing your apps/microservices both inside and outside your kubernetes cluster. This resource type is called a Service. But I assume you know that as such Services are also added in your examples.

This is the reason why I prefer to use a term microservice if I really want to call "a service" one of the apps (clients, servers, whatever... ) deployed on my kubernetes cluster. And yes, this is really important distinction as talking about communication from one Service to another Service (kubernetes resource type) doesn't make any sense at all. Your Pod can communicate with a different Pod via a Service that exposes this second Pod, but Services don't communicate with each other at all. I hope this is clear.

So in order to expose one of your microservices within your cluster and make it easily accessible for other microservices, running on the same cluster, use a Service. But what you really need in your case is it's simplest form. ❗There is no need for using LoadBalancer type here. In your case you want to expose your Deployment named goserver to make it accessible by Pods from second Deployment, named goclient, not by external clients, sending requests from the public Internet.

Note that LoadBalancer type that you used in your Service's yaml manifests has completely different purpose - it is used for exposing your app for clients reaching to it from outside your kubernetes cluster and is mainly applicable in cloud environments.

So again, what you need in your case is the simplest Service (often called ClusterIP as it is the default Service type) which exposes a Deployment within the cluster. ⚠️ Remember that ClusterIP Service also has loadbalancing capabilities.

OK, enough of explanations, let's move on to the practical part. As I said, it's really simple and it can be done with one command:

kubectl expose deployment goserver --port 8080 --namespace golang-ns

Yes! That's all! It will create a Service named goserver (there is no reason to name it differently than the Deployment it exposes) which will expose Pods belonging to goserver Deployment within your kubernetes cluster, making it easily accessible (and discoverable) via it's DNS name.

If you prefer declarative Service definition, here it is as well:

apiVersion: v1
kind: Service
metadata:
  name: goserver
  namespace: golang-ns
spec:
  selector:
    app: goserver  
  ports:
    - port: 8080

Your golang-client Pods need only the Service name i.e. goserver to access goserver Pods as they are deployed in the same namespace (golang-ns). If you need to access them from a Pod deployed to a different namespace, you need to use <servicename>.<namespace> i.e. goserver.golang-ns. You can also use fully quallified domain name (FQDN) (see the official docs here):

my-svc.my-namespace.svc.cluster-domain.example

which in your case may look as follows:

goserver.golang-ns.svc.cluster.local

As to:

In addition to this if I expose goserver though ingress will this change ?

❗Unless you want to expose your goserver to the external world, don't use Ingress, you don't need it.

Upvotes: 6

Related Questions