By using a StatefulSet, each Pod can now be uniquely identified. However, the IP of each Pod is still randomly assigned; we want our Pods to be accessible from a stable IP address. Kubernetes provides the Service Object to achieve this.
The Service Object is very versatile, in that it can be used in many ways. Generally, it is used to provide an IP address to Kuberentes Objects like Pods.
The most common use case for a Service Object is to provide a single, stable, externally-accessible Cluster IP (also known as the Service IP) for a distributed service. When a request is made to this Cluster IP, the request will be proxied to one of the Pods running the service. In this use case, the Service Object is acting as a load balancer.
However, that's not what we need for our Elasticsearch service. Instead of having a single cluster IP for the entire service, we want each Pod to have its own stable subdomain so that each Elasticsearch node can perform Node Discovery.
For this use case, we want to use a special type of Service Object called Headless Service. As with other Kubernetes Objects, we can define a Headless Service using a manifest file. Create a new file at manifests/elasticsearch/service.yaml with the following content:
apiVersion: v1
kind: Service
metadata:
name: elasticsearch
spec:
selector:
app: elasticsearch
clusterIP: None
ports:
- port: 9200
name: rest
- port: 9300
name: transport
Let's go through what some of the fields mean:
- metadata.name: Like other Kuberentes Objects, having a name allows us to identify the Service by name and not ID.
- spec.selector: This specifies the Pods that should be managed by the Service Controller. Specifically for Services, this defines the selector to select all the Pods that constitute a service.
- spec.clusterIP: This specifies the Cluster IP for the Service. Here, we set it to None to indicate that we want a Headless Service.
- spec.ports: A mapping of how requests are mapped from a port to the container's port.
Let's deploy this Service into our Kubernetes cluster:
$ kubectl apply -f manifests/elasticsearch/service.yaml
service "elasticsearch" created
We can run kubectl get service to see a list of running services:
$ kubectl get services
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
elasticsearch ClusterIP None <none> 9200/TCP,9300/TCP 46s
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 4h