How to make multiple pods communicate with each other on kubernetes
For internal communication between different microservices in Kubernetes you should use Service
of a type ClusterIP. It is actually the default type so even if you don't specify it in your Service
yaml definition file, Kubernetes assumes you want to create ClusterIP
. It creates virtual internal IP (accessible within your Kubernetes cluster) and exposes your cluster component (microservice) as a single entry point even if it is backed up by many pods.
Let's assume you have front-end app which needs to communicate with back-end component which is run in 3 different pods. ClusterIP
service provides single entry point and handles load-balancing between different pods, distributing requests evenly among them.
You can access your ClusterIP
service by providing its IP address and port that your application component is exposed on. Note that you may define a different port (referred to as port
in Service
definition) for the Service
to listen on than the actual port used by your application (referred to as targetPort
in your Service
definition). Although it is possible to access the Service
using its ClusterIP
address, all components that communicate with pods internally exposed by it should use its DNS name. It is simply a Service
name that you created if all application components are placed in the same namespace. If some components are in a different namespaces you need to use fully qualified domain name so they can communicate across the namespaces.
Your Service
definition files may look like this:
apiVersion: v1kind: Servicemetadata: name: angular-servicespec: type: ClusterIP ### may be ommited as it is a default type selector: name: angular ### should match your labels defined for your angular pods ports: - protocol: TCP targetPort: 4200 ### port your angular app listens on port: 4200 ### port on which you want to expose it within your clusterapiVersion: v1kind: Servicemetadata: name: backend-servicespec: type: ClusterIP ### may be ommited as it is a default type selector: name: backend ### should match your labels defined for your backend pods ports: - protocol: TCP targetPort: 5000 ### port your backend app listens on port: 5000 ### port on which you want to expose it within your cluster
You can find a detailed description of this topic in official Kubernetes documentation.
NodePort
has totally different function. It may be used e.g. to expose your front-end app on a specific port on your node's IP. Note that if you have Kubernetes cluster consisting of many nodes and your front-end pods are placed on different nodes, in order to access your application you need to use 3 different IP addresses. In such case you need an additional load balancer. If you use some cloud platform solution and you want to expose front-end part of your application to external world, Service type LoadBalancer is the way to go (instead of using NodePort
).
You can implement ingress rule for this like follows -
apiVersion: extensions/v1beta1kind: Ingressmetadata: annotations: nginx.ingress.kubernetes.io/rewrite-target: /$1 kubernetes.io/ingress.class: nginx name: ingress-rulespec: rules: - host: test.example.io http: paths: - path: /(.*) backend: serviceName: angular-service servicePort: port-number - path: /api/(.*) backend: serviceName: backend-service servicePort: port-number
In your front-end app, you can add the URL of the backend service as
host/api/{your_uri}
This shall help you out. The host represents DNS mentioned in the ingress rule file