Services in Kubernetes
Without Services in Kubernetes
Before getting started with Services in Kubernetes, the first question comes in our mind is “Why do we need Services?”. Suppose we have a website where we have 3 pod replicas of front-end and 3 pod replicas of backend. These are the following scenarios we have to tackle:
- How would the front-end pods be able to access the backend pods?
- If the front-end pod wants to access the backend pod to which replica of the backend pod will the requests be redirected. Who makes this decision?
- As the IP address of the pods can change, who keeps the track of the new IP addresses and inform this to the front-end pods?
- As the containers inside the pods are deployed in a private internal network, which IP address will the users use to access the front-end pods?
With Services in Kubernetes:
To overcome the above mentioned cases the services object is created. Services enables loose coupling between microservices in our application. It enables communication between various components within and outside of the application.
Lets try to solve the scenarios we discussed earlier by using Services.
- Services allow the frontend pods to connect with the backend pods on a specific port.
- The Service created for the backend pods will help to group all the replicas of backend pods together and provide a single interface for the front-end pods to access the service. The request from the front-end pod is forwarded to one of the pod replicas under the service randomly.
- Each service gets an IP address and name assigned to it inside the cluster and that is the name used by other pods to access the service. So, even if the pod’s IP address changes other pods can reach the service using the name of the service.
- The Services can be used to listen to a port on a node and forward the requests to the port of the pod present inside the pod. So, the user will be able to access the application using the NodeIP:NodePort.
Types of Services in Kubernetes:
Depending on how and what component we want to expose from the service to the network, the Services can be categorised into 4 types:
- ClusterIP: It is a service in which a virtual IP is created inside the cluster to enable communication between different services. This is the default value of the services.
- NodePort: It is a type of service which makes an internal pod accessible on a port of the node. Kubernetes control plane allocates a port from a range (30000-32767) for the nodeport service. We can access the application by using NodeIP:NodePort.
- LoadBalancer: It is a type of service which provisions a Load Balancer for our services in a supported cloud providers like GCP, AWS, Azure. We can use this service when we want to distribute load across different web servers in our front-end tier. The LoadBalancer of the cloud provider will provide us with an IP address by using which users will be able to access our application front-end.
- ExternalName: This type of service is used to Map the Service to the contents of the externalName field (like my.database.example.com), by returning a CNAME record with its value. For this type of service no proxying or forwarding is set up. For using ExternalName service, we require either kube-dns version 1.7 or CoreDNS version 0.0.8 or higher.
Creating a service in Kubernetes:
We can create services in two ways: Imperative way and Declarative way.
- Imperative way: In this method we create a service by using one-line commands. For example,
- If we have a kubernetes deployment named “k8s-demo”, we can use this command to create a LoadBalancer type service for the deployment: kubectl expose deployments k8s-demo –port 8080 –type LoadBalancer
- If we want to create a clusterip service with name demo, we can use this command: kubectl create service clusterip demo –tcp=80:80
- Declarative way: In this method we will use the definition file to create a service. This method is preferred in the corporate world as we will be able to reuse these definition files. Here is an example were we are creating a service with “service-definition.yaml” definition file:
apiVersion: v1 kind: Service metadata: name: myapp-service spec: selector: app: front-end ports: - protocol: TCP port: 80 nodePort: 30008 targetPort: 8080
After saving the above file execute the following command to create the service: Kubectl create -f service-definition.yaml. We can view the status of service by executing this command: Kubectl get services.
As we have not provided any value for the type of the cluster, the service will be a clusterIP service (default).
In the definition file port field is mandatory, if targetPort value is not set then kubernetes will take the same value of targetPort as port and if no value for nodePort is specified then it will take any free port value from “30000-32767” range.
To summarize in any case whether it be a single pod on single node, multiple pod on a single node or multiple pod on multiple node the services is required to enable communication between the different components. When the pods are removed or added, the service is automatically updated making it highly flexible and adaptive. Once created we won’t have to make any additional configuration changes.