Concepts

3 minutes read

A Service is used to expose Pods so that other Pods, or the external world, can access them. It uses labels to group Pods. There are different types of Services:

  • ClusterIP to expose Pods inside the cluster
  • NodePort, LoadBalancer to expose Pods to the outside world

Each time a Service receive a request, this one is load-balanced between the Pods exposed by a Service.

Service

Let’s consider 2 Pods running inside a cluster. The www Pods is running a web interface, how can this Pod access the api Pods running a backend component ? The calling Pod could use the IP address of the Pod it needs to call, but this is not how this should be done.

ClusterIP

Instead, we use a Service which exposes the api Pod. The www Pod calls this new Service to access the api Pod.

ClusterIP

A Service exposes the Pods which labels match its selector.

The following specification defines a Service with selector app: api:

apiVersion: v1
kind: Service
metadata:
  name: api
spec:
  selector:
    app: api
  type: ClusterIP
  ports:
  - port: 80
    targetPort: 5000

The specification below defines a Pod which labels app: api corresponding to the Service’s selector:

apiVersion: v1
kind: Pod
metadata:
  name: api
  labels:             
    app: api
spec:
  containers:
  - name: api
    image: org/api:1.2
    ports:
    - containerPort: 5000

Because the Service’s selector matches the Pod’s labels, the Pod is exposed by the Service, so that other Pods can reach it internally.

A NodePort Service is a ClusterIP Service which also exposes Pods to the outside of the cluster.

NodePort

When specifying a NodePort Service, we need to set the .spec.type property to NodePort. We can also set the port this Service should listen on via the .spec.ports.nodePort property, if it’s not set Kubernetes will automatically select a port on the 30000-32767 range.

The following specification defines a Service of type NodePort exposing the Pods with labels app: ghost. This Service is reachable from any node on port 31000.

apiVersion: v1
kind: Service
metadata:
  name: ghost-np
spec:
  selector:
    app: ghost
  type: NodePort
  ports:
  - port: 80
    targetPort: 2368
    nodePort: 31000

When an application is exposed with a NodePort Service, it’s accessible via the selected port from any cluster’s node.

A LoadBalancer Service is a NodePort Service which also triggers the creation of an external Load Balancer on the cloud provider infrastructure.

LoadBalancer

The following specification defines a Service of type LoadBalancer exposing the Pods with labels app: ghost to the external world.

apiVersion: v1
kind: Service
metadata:
  name: ghost-lb
spec:
  selector:
    app: ghost
  type: LoadBalancer
  ports:
  - port: 80
    targetPort: 2368

When created, this Service creates a LoadBalancer, with a dedicated IP address, in the cloud provider infrastructure.

We can reach the application exposed by the Service (a Pod running the ghost image in this example) using the Service IP address.

LoadBalancer

  • Creating a Service
kubectl apply -f svc.yaml
  • Listing the existing Service
kubectl get svc
  • Getting a Service’s details
kubectl get svc ghost -o yaml
  • Getting the Service main properties
kubectl describe svc ghost
  • Deleting a Service
kubectl delete svc ghost

The previous exercise left the app with the following components:

VotingApp

We will now add Services to the VotingApp to get the first working version of this demo app running fine in Kubernetes.

VotingApp