Reputation: 3626
I've read a couple of passages from some books written on Kubernetes as well as the page on headless services in the docs. But I'm still unsure what it really actually does and why someone would use it. Does anyone have a good understanding of it, what it accomplishes, and why someone would use it?
Upvotes: 241
Views: 129150
Reputation: 7618
Well, I think you need some theory. There are many explanations (including the official docs) across the whole internet, but I think Marco Luksa did it the best:
Each connection to the service is forwarded to one randomly selected backing pod. But what if the client needs to connect to all of those pods? What if the backing pods themselves need to each connect to all the other backing pods. Connecting through the service clearly isn’t the way to do this. What is?
For a client to connect to all pods, it needs to figure out the IP of each individual pod. One option is to have the client call the Kubernetes API server and get the list of pods and their IP addresses through an API call, but because you should always strive to keep your apps Kubernetes-agnostic, using the API server isn’t ideal
Luckily, Kubernetes allows clients to discover pod IPs through DNS lookups. Usually, when you perform a DNS lookup for a service, the DNS server returns a single IP — the service’s cluster IP. But if you tell Kubernetes you don’t need a cluster IP for your service (you do this by setting the clusterIP field to None in the service specification ), the DNS server will return the pod IPs instead of the single service IP. Instead of returning a single DNS A record, the DNS server will return multiple A records for the service, each pointing to the IP of an individual pod backing the service at that moment. Clients can therefore do a simple 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.
Setting the clusterIP field in a service spec to None makes the service headless, as Kubernetes won’t assign it a cluster IP through which clients could connect to the pods backing it.
"Kubernetes in Action" by Marco Luksa
Upvotes: 476
Reputation: 527
A Headless service is a service that doesn't have the clusterIP
address allocated. This is achieved by setting the clusterIP
to None
.
What does this mean?: The kube-proxy
won't handle these type of services, and therefore no load-balancing or proxying will be provided for a headless service, instead, the DNS response will contain a list of all IP addresses of each endpoint (podIP) that is part of the service.
When do you use it:
Upvotes: 31
Reputation: 10368
Let me break this question into each sub-parts the way we do in agile.
What exactly is a headless service.
It is used for discovering individual pods(especially IPs) which allows another service to interact directly with the Pods instead of a proxy. With NodePort, LoadBalancer, ExternalName, and ClusterIP clients usually connect to the pods through a Service (Kubernetes Services simply visually explained) rather than connecting directly.
What does it accomplish?
The requirement is not to make single IP like in the case of other service types. We need all the pod's IP sitting behind the service.
What are some legitimate use cases for it?
Create Stateful service.
Deploying RabbitMQ or Kafka (or any message broker service) to Kubernetes requires a stateful set for RabbitMQ cluster nodes.
Deployment of Relational databases
and many more
Some Practical in Action
Deployment config
apiVersion: apps/v1
kind: Deployment
metadata:
name: app
labels:
app: server
spec:
replicas: 3
selector:
matchLabels:
app: web
template:
metadata:
labels:
app: web
spec:
containers:
- name: nginx
image: nginx:alpine
ports:
- containerPort: 80
Regular Service
apiVersion: v1
kind: Service
metadata:
name: regular-svc
spec:
selector:
app: web
ports:
- protocol: TCP
port: 80
targetPort: 8080
Headless Service
apiVersion: v1
kind: Service
metadata:
name: headless-svc
spec:
clusterIP: None # <= Don't forget!!
selector:
app: web
ports:
- protocol: TCP
port: 80
targetPort: 8080
Create all resources and run tmp pod.
k run tmp01 --image=tutum/dnsutils -- sleep infinity
k exec tmp01 -it -- /bin/sh
#=> nslookup regular-svc
Server: 10.96.0.10
Address: 10.96.0.10#53
Name: regular-svc.moon.svc.cluster.local
Address: 10.109.150.46
#=> nslookup headless-svc
Server: 10.96.0.10
Address: 10.96.0.10#53
Name: headless-svc.moon.svc.cluster.local
Address: 172.17.0.31
Name: headless-svc.moon.svc.cluster.local
Address: 172.17.0.30
Name: headless-svc.moon.svc.cluster.local
Address: 172.17.0.32
The DNS server returns three different IPs
for the headless-svc.moon.svc.cluster.local
FQDN
.
Note 1: with a headless service, clients can connect to its pods by connecting to the service’s DNS name, as they can with regular services. But with headless services, because DNS returns the pods’ IPs, clients connect directly to the pods, instead of through the service proxy.
Note 2: Headless services still provide load balancing across pods but through the DNS round-robin mechanism instead of through the service proxy.
Upvotes: 104