The default Kubernetes service provides a stable IP address that allows clients to connect to pods.
However, you don’t control which pod you are connecting to. The service forwards the connection to a randomly selected backing pod.
Such a service is known as the Cluster IP service.
But what if the client has a need to connect to all the pods?
Maybe, each individual pod needs to connect to all the other pods behind a service?
This is made possible using the Kubernetes Headless Service.
1 – Uses of Kubernetes Headless Service
Here are a few use-cases of the Kubernetes Headless Service:
- Stateful services that preserve the state of a request and it’s important for subsequent connections to connect to the same pod
- Deploying relational databases with replicas that need to talk with each other
- Deploying message brokers like RabbitMQ
- Implementing custom load balancing logic based on individual pod capacity
- Setting up advanced health checks
By the way, if you are interested in Kubernetes & Cloud Native concepts, you’d love the Progressive Coder newsletter where I explain such topic in a fun & interesting manner.
Subscribe now to join along.
2 – Create a Headless Service in Kubernetes
A typical service (ClusterIP) looks like this:
apiVersion: v1
kind: Service
metadata:
name: demo
spec:
ports:
- port: 80
targetPort: 3000
selector:
app: hello-service
Even if you don’t mention a service type value, Kubernetes defaults to ClusterIP.
To create a headless service in Kubernetes, you can simply specify the clusterIP
as None.
See the below example:
apiVersion: v1
kind: Service
metadata:
name: demo-headless
spec:
clusterIP: None
ports:
- port: 80
targetPort: 3000
selector:
app: hello-service
This makes the service headless.
You can apply the service using the below command:
$ kubectl apply -f demo-headless.yaml
After it is successfully applied, you can check the details of the service.
saurabhdashora@Saurabhs-MacBook-Air basic-pod-demo % kubectl describe svc demo-headless
Name: demo-headless
Namespace: default
Labels: <none>
Annotations: <none>
Selector: app=hello-service
Type: ClusterIP
IP Family Policy: SingleStack
IP Families: IPv4
IP: None
IPs: None
Port: <unset> 80/TCP
TargetPort: 3000/TCP
Endpoints: 10.1.0.124:3000,10.1.0.128:3000,10.1.0.131:3000
Session Affinity: None
Events: <none>
As you can notice, the IP address is None. The Endpoints field shows the IP addresses of the backing pods. If interested, you can read more about the concept of endpoints in Kubernetes.
In contrast, if you describe the properties of a ClusterIP service, you see the below output.
saurabhdashora@Saurabhs-MacBook-Air basic-pod-demo % kubectl describe svc demo
Name: demo
Namespace: default
Labels: <none>
Annotations: <none>
Selector: app=hello-service
Type: ClusterIP
IP Family Policy: SingleStack
IP Families: IPv4
IP: 10.100.68.216
IPs: 10.100.68.216
Port: <unset> 80/TCP
TargetPort: 3000/TCP
Endpoints: 10.1.0.124:3000,10.1.0.128:3000,10.1.0.131:3000
Session Affinity: None
Events: <none>
In this case, the IP address field has a specific value.
3 – Testing the Kubernetes Headless Service
For testing purpose, you can perform a DNS lookup. For that, you can use the nslookup
command.
Since we want to do the testing within the context of our Kubernetes cluster, we can create a pod with the necessary binaries.
See the below YAML:
apiVersion: v1
kind: Pod
metadata:
name: dnsutils
namespace: default
spec:
containers:
- name: dnsutils
image: registry.k8s.io/e2e-test-images/jessie-dnsutils:1.3
command:
- sleep
- "infinity"
imagePullPolicy: IfNotPresent
restartPolicy: Always
Basically, when you apply this YAML, you get a pod that runs the jessie-dnsutils
image that contains the necessary binaries to run the nslookup
command.
You can now execute the nslookup
command for the demo-headless
service as below:
saurabhdashora@Saurabhs-MacBook-Air basic-pod-demo % kubectl exec dnsutils -- nslookup demo-headless
Server: 10.96.0.10
Address: 10.96.0.10#53
Name: demo-headless.default.svc.cluster.local
Address: 10.1.0.124
Name: demo-headless.default.svc.cluster.local
Address: 10.1.0.131
Name: demo-headless.default.svc.cluster.local
Address: 10.1.0.128
As you can see, the output contains a list of the IP address of 3 different pods.
In contrast, if you execute the same command for the normal ClusterIP service, you get only one IP address.
saurabhdashora@Saurabhs-MacBook-Air basic-pod-demo % kubectl exec dnsutils -- nslookup demo
Server: 10.96.0.10
Address: 10.96.0.10#53
Name: demo.default.svc.cluster.local
Address: 10.100.68.216
Note that Kubernetes headless service isn’t so different from a regular service. Clients can still connect to the pods using the service’s DNS name.
However, they can also connect to individual pods.
Conclusion
That’s all for this post.
Kubernetes Headless Service is a great tool for some specific requirements with regards to connecting directly with pods sitting behind a service.
In this post, you learned how to setup such a service and test it.
If you have any comments or queries, please mention them in the comments section below.
Anyways, before we end this post, a quick reminder about the Progressive Code Newsletter where I explain software concepts using a storytelling approach so that you never forget what you’ve learned. I’m 100% sure you’d love it.
Subscribe now and see you over there.
0 Comments