Headless Service in Kubernetes

Headless Service in Kubernetes

In this blog, we will explore the concept of Headless Services in Kubernetes and learn how they enable advanced use cases such as stateful applications, custom load balancing, and more fine-grained control over network traffic within clusters.

What is a Service in Kubernetes?

Pods in Kubernetes are the smallest unit of execution in Kubernetes, and they are ephemeral, meaning they can be created and destroyed at any time. Kubernetes Services provide a way to expose Pods to the outside world and make them more durable.

There are four types of services in Kubernetes:

  • ClusterIP: This is the default type of service. It exposes a service on a cluster-internal IP address, which can only be accessed by other Pods in the cluster.
  • NodePort: This type of service exposes a service on a specific port on each node in the cluster. This allows external clients to access the service by connecting to a node’s IP address and port.
  • LoadBalancer: This type of service exposes a service on a load balancer. This allows external clients to access the service through a single IP address and port.
  • Ingress: This type of service is used to expose multiple services to the outside world through a single URL.

Create Nginx Deployment

Let’s create a deployment using the Nginx image with two replicas.

microk8s kubectl create deployment nginx --image nginx:latest --replicas 2 --dry-run=client -oyaml

The above dry run command will generate a deployment manifest file like below:

apiVersion: apps/v1
kind: Deployment
metadata:
  creationTimestamp: null
  labels:
    app: nginx
  name: nginx
spec:
  replicas: 2
  selector:
    matchLabels:
      app: nginx
  strategy: {}
  template:
    metadata:
      creationTimestamp: null
      labels:
        app: nginx
    spec:
      containers:
      - image: nginx:latest
        name: nginx
        resources: {}
status: {}

Let’s apply the deployment manifest:

deployment

Let’s check the pods in the default namespace:

get pods

Expose deployment as ClusterIP Service

Let’s create a service to expose nginx deployment and check the newly created nginx service:

create service

Because it is ClusterIP service so it can be only accessed from within the cluster.

We will now launch a busybox-based pod and go inside the container. We will use this to explore our Nginx service.

sudo microk8s kubectl run busybox --image busybox:latest -it --restart Never -- sh

A Service in Kubernetes is assigned a stable IP address or DNS name that remains unchanged, even if the underlying Pods are rescheduled or replaced. This allows other services or external clients to reliably access the Pods without needing to keep track of their dynamic IP addresses.

Query our ClusterIP service

Let’s query our standard nginx service using the nslookup command from within busybox container:

nslookup service

Here the nginx cluster ip service hostname and ip address are returned. There are no details of the individual pod ip address. So the traffic is going through the service load balancer. This is the usual behavior when we query a standard Kubernetes Service.

What is a Headless Service in Kubernetes?

A headless service in Kubernetes is a service that does not have a ClusterIP address assigned to it. This is achieved by setting the clusterIP to None in the service definition.

Expose deployment as Headless Service

Let’s modify the Nginx service and create a new ClusterIP service with name: nginx-headless

sudo microk8s kubectl expose deployment/nginx --name nginx-headless --type ClusterIP --port 80 --dry-run=client -oyaml
apiVersion: v1
kind: Service
metadata:
  creationTimestamp: null
  labels:
    app: nginx
  name: nginx-headless
spec:
  ports:
  - port: 80
    protocol: TCP
    targetPort: 80
  selector:
    app: nginx
  type: ClusterIP
status:
  loadBalancer: {}

Edit and add a new attribute clusterIP: None in spec as shown below:

service manifest

Let’s apply this manifest and check the services in the default namespace:

create headless service

Query our ClusterIP service

Let’s query our headless service nginx-headless created above using the nslookup command from our busybox pod:

nslookup headless service

As we see above query to the headless service returned hostname and ip address of individual pods backing the headless service. This is a useful way to allow clients to connect to Pods directly, without having to go through a load balancer. They are also a good way to get the IP addresses of Pods in DNS.

What is the use of headless service?

Headless services are useful for a number of purposes, including:

  • Discovering individual pods: Headless services can be used to discover individual pods by returning a list of the Pod IPs of the pods that are part of the service. This can be useful for applications that need to communicate directly with pods, such as DNS servers or service meshes.
  • Load balancing: Headless services can be used to load balance traffic between pods, but this is not the default behavior. Instead, headless services return a list of the Pod IPs of the pods that are part of the service, and the client is responsible for load balancing the traffic.
  • StatefulSets: Headless services are required for StatefulSets. StatefulSets are a type of Kubernetes workload that is used to deploy stateful applications. Headless services allow StatefulSets to maintain the identity of the pods that are part of the StatefulSet.

Conclusion

Headless service is a powerful concept in Kubernetes. Instead of returning a single DNS A record, the DNS server will return multiple A records for the service, each record pointing to the IP of an individual pod backing the service at that moment. Clients can simply do a DNS A record lookup and get the IPs of all the pods that are part of the service. The client can then use that information to connect to one, many, or all of them. This flexibility enables advanced use cases such as stateful applications and custom load balancing, empowering clients to connect to one, multiple, or all pods associated with the service based on their specific requirements.

FAQs

How is load balancing handled in a Headless Service?

There is no load balancing performed by default and if load balancing is required, it needs to be implemented within the client or application logic. Each client is responsible for selecting and establishing connections to individual pods based on the DNS records provided by the Headless Service.

What are the use cases for a Headless Service?

Headless Services are commonly used for stateful applications that require unique identities or direct pod-to-pod communication. Other use cases include database clusters, distributed messaging systems, peer-to-peer networks, or any scenario where each pod needs to be addressable individually.

Want to know more about the container world?

Please check out our other blogs

Leave a Comment