Kubernetes Services

A Kubernetes Service object is an abstraction that provides network access to a dynamic set of Pod replicas. Rather than access Pods directly via their IPs, you can use a Service to proxy requests and deal with service discovery and load balancing.

A Service usually uses a selector to decide which Pods will receive traffic. As Pods are dynamically added and removed, the Service will maintain a list of active Pods that are eligible to receive traffic.

Defining a Service

Below is a sample Service definition.

apiVersion: v1
kind: Service
metadata:
  name: my-service
spec:
  type: ClusterIP
  selector:
    app: nginx
  ports:
    - protocol: TCP
      port: 8080
      targetPort: 80

spec.type indicates the type of Service we want to create. In this instance we’ve specified ClusterIP, which is the default and exposes the Service on an IP accessible only within the cluster (hence Cluster IP). Other common service types are

  • NodePort – is accessible on each nodes IP, using a fixed port. This allows a Service to be accessed from outside the cluster using the nodes IP and the node port. For example, Node_IP:Node_Port.
  • LoadBalancer – is used by cloud providers like AWS and Azure to stand up an internet facing load balancer for your cluster.

spec.selector is used in conjunction with Pod selectors to specify which Pods the Service should route traffic to. This Service routes traffic to Pods that have a selector matching app: nginx.

spec.ports specifies the protocol (TCP by default) as well as the port and targetPort. port is the port that the Service receives inbound traffic on, while targetPort is the port on the Pods that the Service sends traffic to.

Testing the Service

To test the Service defined above we’ll need to create some Pod replicas – we’ll do that by creating a Deployment. You can find the Service and Deployment definitions on Github.

After creating the Service we can list it as shown above. You’ll see the Service IP and port 8080 as specified in the manifest. Running kubectl get endpoints my-service will list the Pods that this Service will route traffic to. Remember these are chosen based on the selector defined in the Pod and Service definitions. As expected, these endpoints are accessible on port 80.

To test the Service we can exec into one of the Pods that we created and use the Service to call another Pod. The screenshot below shows us running a curl request against the Service ClusterIP and receiving a response from nginx.

We can also access the Service using its DNS name, my-service as follows.

The sample code for these notes is available on Github.