2022-06-18

Kubernetes Service

What is Service in Kubernetes

In Kubernetes, managing how parts of your application communicate with each other or with external services is crucial. That's where the concept of "Services" comes into play. A Service in Kubernetes is a resource that you use to expose an application running in a set of Pods as a network service.

Services track the IP addresses of the pods using label selectors. Since pods are ephemeral, the set of pods that a service sends traffic to can change dynamically as pods are created and destroyed. A service’s IP address remains the same over time, and other applications can rely on this consistent address despite the turnover of the underlying pods.

A Kubernetes Service acts as an L4 (Layer 4) load balancer. It ensures that traffic is distributed among the available pods.

The following diagram illustrates how Services operate:

  +--------------+     +------------+     +------------+
  |              |     |            |     |            |
  |    Client    +----->  Service   +----->    Pod     |
  |              |     |            |     |            |
  +--------------+     +------------+     +------------+
                           /\ |
                          /   \
                 selector /     \ label
                        /       \
           +------------+       +------------+
           |            |       |            |
           |    Pod     |       |    Pod     |
           |            |       |            |
           +------------+       +------------+
  • Client: Initiates requests.
  • Service: Distributes network traffic.
  • Pods: Processes requests.

Types of Services in Kubernetes

There are three types of Services in Kubernetes:

  • ClusterIP
  • NodePort
  • LoadBalancer

ClusterIP Service

Pods are ephemeral in nature, and it's not feasible to know on which node a Pod is deployed. Even if you were aware, Pods can be frequently restarted, so there's no guarantee of accessing the same Pod consistently.

Using a ClusterIP Service is beneficial as it abstracts the impermanent Pod IPs and places a proxy with a static IP in front of them. This eliminates the need to know the Pod IP and enables load balancing for access to the Pods.

Example: Expose and Load Balance Pod within the Cluster using ClusterIP

Start Minikube:

bash
$ minikube start

Create a helloworld Pod:

bash
$ kubectl run --port 8080 --image gcr.io/google-samples/hello-app:1.0 --restart Never helloworld

pod/helloworld created

Expose the helloworld Pod as a ClusterIP Service helloworld-clusterip:

bash
$ kubectl expose pod helloworld --type ClusterIP --port 8080 --name helloworld-clusterip

Now, test access to the helloworld ClusterIP Service from another Pod within the cluster:

bash
$ kubectl run --restart Never --image curlimages/curl:7.68.0 -it --rm curl sh

/ $ curl helloworld-clusterip:8080
Hello, world!
Version: 1.0.0
Hostname: helloworld

/ $ exit

However, the host OS cannot access the pod.

bash
$ kubectl get pod,svc -o wide

NAME             READY   STATUS    RESTARTS   AGE     IP           NODE       NOMINATED NODE   READINESS GATES
pod/helloworld   1/1     Running   0          3m57s   10.244.0.3   minikube   <none>           <none>

NAME                           TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)    AGE     SELECTOR
service/helloworld-clusterip   ClusterIP   10.99.232.132   <none>        8080/TCP   2m37s   run=helloworld
service/kubernetes             ClusterIP   10.96.0.1       <none>        443/TCP    5m4s    <none>
$ curl 10.99.232.132:8080
curl: (28) Failed to connect to 10.99.232.132 port 8080 after 75007 ms: Operation timed out

NodePort Service

NodePort Services allow exposing Pods to external networks, which is not possible with ClusterIP. It achieves this by making the Pod accessible through the Node IP and a designated port.

Example: Expose Pod Externally using NodePort

Expose the Pod as a NodePort Service:

bash
$ kubectl expose pod helloworld --type NodePort --port 8080 --name helloworld-nodeport

Now, test access to the helloworld NodePort Service from within the cluster:

bash
$ kubectl run --restart Never --image curlimages/curl:7.68.0 -it --rm curl sh

/ $ curl helloworld-nodeport:8080
Hello, world!
Version: 1.0.0
Hostname: helloworld

/ $ exit

You can also access it externally using the Node IP and NodePort:

bash
$ minikube service helloworld-nodeport --url
$ curl $(minikube service helloworld-nodeport --url)

Hello, world!
Version: 1.0.0
Hostname: helloworld

However, the downside of using NodePort is that you need to know both the Node IP and the NodePort, which is typically a high port number above 30000. Additionally, in a multi-host cluster, node IPs may change, making this method of access less stable.

To address these issues, you can use a LoadBalancer service type, which puts a load balancer in front of the nodes and provides it with a static IP and DNS, removing the need to know the node IPs.

LoadBalancer Service

LoadBalancer services are an extension of NodePort services and are primarily used in cloud environments. They facilitate access to the Pods by routing external traffic from the cloud provider's Load Balancer to the nodes on specific ports, and eventually to the Pods.

Example: Expose Pod Externally using LoadBalancer

Expose the Pod as a LoadBalancer Service:

bash
$ kubectl expose pod helloworld --type LoadBalancer --port 8080 --name helloworld-lb

Now, test access to the helloworld LoadBalancer Service from within the cluster:

bash
$ kubectl run --restart Never --image curlimages/curl:7.68.0 -it --rm curl sh

/ $ curl helloworld-lb:8080
Hello, world!
Version: 1.0.0
Hostname: helloworld

/ $ exit

You can also access it externally by fetching the LoadBalancer's URL and using curl:

bash
$ minikube service helloworld-lb --url
$ curl $(minikube service helloworld-lb --url)

Hello, world!
Version: 1.0.0
Hostname: helloworld

When operating a Kubernetes cluster in the cloud, the LoadBalancer service will be assigned a public IP and DNS through which you can access the service.

Issues with LoadBalancer

While the LoadBalancer service provides an excellent way to expose Pods externally and abstract the Node IPs, there are some drawbacks:

  • Each service requires its own LoadBalancer, which can be costly.
  • It operates at L4, meaning it's not aware beyond the TCP/IP stack and cannot handle HTTP host/path-based routing.

For more sophisticated L7 (application layer) load balancing, which enables HTTP host and path-based routing, Kubernetes provides another resource called Ingress.

Ryusei Kakujo

researchgatelinkedingithub

Focusing on data science for mobility

Bench Press 100kg!