Kubernetes Pod-to-Pod Communication
In this post, I'll walk through simple scenarios to demonstrate how communication between pods works in Kubernetes.
Assuming you have a Kubernetes cluster (in my case, Minikube deployed locally), you can easily deploy an application:
$ kubectl run demo-app --image nginx
pod/demo-app created
$ kubectl get po
NAME READY STATUS RESTARTS AGE
demo-app 1/1 Running 0 5s
Now, check if the application is running by executing curl localhost
inside the container to see the response from the Nginx web server:
$ kubectl exec -it demo-app -- curl localhost
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
...
</body>
</html>
Cool, now we know demo-app
is up and running on the default port 80.
Next, let's deploy another application, demo-app-2
:
$ kubectl run demo-app-2 --image nginx
pod/demo-app-2 created
$ kubectl get po
NAME READY STATUS RESTARTS AGE
demo-app 1/1 Running 0 6m45s
demo-app-2 1/1 Running 0 5s
Querying demo-app-2
from inside its container should give the same result:
$ kubectl exec -it demo-app-2 -- curl localhost
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
...
</html>
Now, let's see how to query demo-app
from demo-app-2
and vice versa.
Using Pod IP Address
First, the easiest way is to use the Pod IP address. Get detailed output with -o wide
:
$ kubectl get po -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
demo-app 1/1 Running 0 18m 172.17.0.2 minikube <none> <none>
demo-app-2 1/1 Running 0 11m 172.17.0.8 minikube <none> <none>
Here, you can see the IP addresses assigned to each pod. These IPs come from the same pool, regardless of which node the pods are running on.
Using the IP address of demo-app
, query it from inside demo-app-2
:
$ kubectl exec -it demo-app-2 -- curl 172.17.0.2
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
...
</body>
</html>
This works, but Pod IPs are transient—they change every time a pod is restarted. Also, when scaling the number of pods, you want traffic balanced across all pods, not just one.
Using a Kubernetes Service
Let's expose our pod to the cluster using a Kubernetes Service. A Service is an abstraction that enables network traffic balancing and routing to your application.
$ kubectl expose pod demo-app --port 80
service/demo-app exposed
$ kubectl get services
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
demo-app ClusterIP 10.101.54.82 <none> 80/TCP 18s
Now, Kubernetes has created a Service named demo-app
with its own CLUSTER-IP
. Use this IP to query demo-app
from inside demo-app-2
:
$ kubectl exec -it demo-app-2 -- curl 10.101.54.82
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
...
</html>
It works! Now, you don't have to rely on the pod's IP address. If it changes, you still have access to the application through the Service.
However, the Service's IP is also transient—it changes if the Service is recreated.
Using DNS
Kubernetes creates DNS records for Services and Pods. You can contact Services using consistent DNS names instead of IP addresses.
Let's call our demo-app
through the Service using its DNS name:
$ kubectl exec -it demo-app-2 -- curl demo-app
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
...
</html>
Here, demo-app
is the Service name. If your pods are in different namespaces, add .namespace-name
to the Service name, e.g., demo-app.default
:
$ kubectl exec -it demo-app-2 -- curl demo-app.default
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
...
</html>
It works as well! In the example above, we call the demo-app
Service in the default
namespace using curl
from inside the demo-app-2
pod.
Now, you can rely on the DNS name of the Service and be confident that nothing breaks if either the pods or the Service are recreated.