This page is under regular updates. Please check back later for more content.
Services Object

Services

There is a possibility of pod crash so that the ip address will not be consistent and it will be changed dynamically from time to time in the case of pod failure. In order to make it accessible all the time via application without worrying about the change in pod IP.

Why we need?

Let's say we have two replicaset that create pods in node (may vary or differ)

We have two application one is running backend and the other one running frontend. Frontend is using the IP address and the port to access the backend application.

But there is a possibility that the pod might be crashed due to some reason and if that happens the IP address will change dynamically. So, it will be problem to fetch the data from the backend using the same IP address.

In order to avoid this problem and keep the IP static we use this object called services.

image

Here the replicaset get the Virtual IP address and it is mapped with pods in such a way that if the IP address of an individual pod will change it won't affect the application that was using the application in the pod because the application will be using the VIP.

Replication Controller or Replica Set get virtual IP address

About Service object

  • When using Replication Controller or Replica Set, Ports are terminated and created during scaling or application operation
  • When using deployments, while updating the image version the pods are terminated and new pods take the place of the other pods.
  • Pods are very dynamic i.e., they come and go on the K8s cluster and on any of the available nodes and it would be difficult to access the pods as the pods IP change once its recreate
  • Service object is a logical bridge between pods and end user, which provides virtual IP address (VIP)
  • Service allows client to reliably connect to the containers running in the pod using the VIP
  • The VIP is not an actual IP connected to a network interface but its purpose is purely to forward traffic to one or more pods
  • Kube-proxy is the one which keeps the mapping between the VIP and the pods upto date, which queries the api-server to learn about new services in the cluster
  • Although each pod has a unique IP address those IPs are not exposed outside the cluster
  • Service object helps to expose the VIP map to the force and allow application to receive traffic
  • Labels are used to select which are the ports to be put under service
  • Creating a service will create an endpoint to access the nodes/application in it
  • Services can be exposed in different ways by specifying a type in the service specification -
    1. Cluster IP (default)
    2. NodePort
    3. Load Balancer - Created by cloud providers that will route external traffic to every node on the NodePort (Example ELB on AWS)
    4. Headless - Create several endpoints that are used to produce DNS records each DNS record is bound to a pod
  • Invite fault to skin run only between ports 30,000 to 32,767 the set of pods targeted by service ususlly determined by a selector.

Replicaset get Cluster IP (Virtual IP Address), and a Cluster IP Address get NodePort and Load Balancer is applied on Node Port (for more refer to image)_

Cluster IP

  • Expose VIP only reachable within the cluster
  • Mainly used to communicate between components of Microservices

Example - Cluster IP


Manifest file k8s_example_12.yml

k8s_example_12.yml
kind: Deployment
apiVersion: apps/v1
metadata:
  name: example-12
spec:
  replicas: 2
  selector:
    matchLabels:
      name: xander
  template:
    metadata:
      name: container0
      labels:
        name: xander
    spec:
      containers:
        - name: c00
          image: httpd
          ports: 
          - containerPort: 80

Manifest file service.yml

service.yml
kind: Service
apiVersion: v1
metadata:
  name: my-service
spec:
  ports:
    - port: 80
      targetPort: 80
  selector:
    name: xander
  type: ClusterIP

Create a replica set using manifest

kubectl apply -f k8s_example_12.yml
Output
controlplane $ kubectl apply -f k8s_example_12.yml 
replicaset.apps/example-12 created

Verify the rs and pods

kubectl get rs
kubectl get pods -o wide
Output
controlplane $ kubectl get rs
NAME                    DESIRED   CURRENT   READY   AGE
example-12-7f6f6c744d   2         2         2       14s
controlplane $ kubectl get pods -o wide
NAME                          READY   STATUS    RESTARTS   AGE   IP            NODE           NOMINATED NODE   READINESS GATES
example-12-7f6f6c744d-2f567   1/1     Running   0          16s   192.168.0.4   controlplane   <none>           <none>
example-12-7f6f6c744d-cwhzk   1/1     Running   0          16s   192.168.1.4   node01         <none>           <none>

Try to access the pod using IP_ADDRESS:PORT

curl 192.168.0.4:80
Output
controlplane $ curl 192.168.0.4:80
<html><body><h1>It works!</h1></body></html>

Now let's say if we delete the pod we need to use new IP address to use the httpd service running in the container. Create a service to get a virtual IP address.

kubectl apply -f service.yml
Output
controlplane $ kubectl apply -f service.yml 
service/my-service created

To get the details of the service using service name (Cluster IP)

kubectl get services
Output
controlplane $ kubectl get services
NAME         TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)   AGE
kubernetes   ClusterIP   10.96.0.1       <none>        443/TCP   9d
my-service   ClusterIP   10.108.184.82   <none>        80/TCP    71s

This is the service (my-service) that we have created using manifest.

kubectl describe services my-service
Output
controlplane $ kubectl describe services my-service
Name:                     my-service
Namespace:                default
Labels:                   <none>
Annotations:              <none>
Selector:                 name=xander
Type:                     ClusterIP
IP Family Policy:         SingleStack
IP Families:              IPv4
IP:                       10.108.184.82
IPs:                      10.108.184.82
Port:                     <unset>  80/TCP
TargetPort:               80/TCP
Endpoints:                192.168.1.4:80,192.168.0.4:80
Session Affinity:         None
Internal Traffic Policy:  Cluster
Events:                   <none>

So we get the Virtual IP Address i.e., 10.108.184.82

Try to access the pod using VIRTUAL_IP_ADDRESS:PORT

curl 10.108.184.82:80
Output
controlplane $ curl 10.108.184.82:80
<html><body><h1>It works!</h1></body></html>

Now even if the pod get deleted it won't affect the service.

NodePort

  • It is applied over the cluster.
  • Make a service accessible from outside the cluster that is from Internet using the exposed port.
  • Expose the service on the same port of each selected node on the cluster using NAT gateway.

Example - NodePort


Manifest file k8s_example_12.yml

k8s_example_12.yml
kind: Deployment
apiVersion: apps/v1
metadata:
  name: example-12
spec:
  replicas: 2
  selector:
    matchLabels:
      name: xander
  template:
    metadata:
      name: container0
      labels:
        name: xander
    spec:
      containers:
        - name: c00
          image: httpd
          ports: 
          - containerPort: 80

Manifest file service.yml

service.yml
kind: Service
apiVersion: v1
metadata:
  name: my-service
spec:
  ports:
    - port: 80
      targetPort: 80
  selector:
    name: xander
  type: NodePort

Create a replica set using manifest

kubectl apply -f k8s_example_12.yml
Output
controlplane $ kubectl apply -f k8s_example_12.yml 
replicaset.apps/example-12 created

Verify the rs and pods

kubectl get rs
kubectl get pods -o wide
Output
controlplane $ kubectl get rs
NAME                    DESIRED   CURRENT   READY   AGE
example-12-7f6f6c744d   2         2         2       14s
controlplane $ kubectl get pods -o wide
NAME                          READY   STATUS    RESTARTS   AGE   IP            NODE           NOMINATED NODE   READINESS GATES
example-12-7f6f6c744d-2f567   1/1     Running   0          16s   192.168.0.4   controlplane   <none>           <none>
example-12-7f6f6c744d-cwhzk   1/1     Running   0          16s   192.168.1.4   node01         <none>           <none>

Try to access the pod using IP_ADDRESS:PORT

curl 192.168.0.4:80
Output
controlplane $ curl 192.168.0.4:80
<html><body><h1>It works!</h1></body></html>

Now let's say if we delete the pod we need to use new IP address to use the httpd service running in the container. Create a service to get a virtual IP address.

kubectl apply -f service.yml
Output
controlplane $ kubectl apply -f service.yml 
service/my-service created

To get the details of the service using service name (Cluster IP)

kubectl get services
Output
controlplane $ kubectl get services
NAME         TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)        AGE
kubernetes   ClusterIP   10.96.0.1       <none>        443/TCP        9d
my-service   NodePort    10.108.184.82   <none>        80:32214/TCP   27m

This is the service (my-service) that we have created using manifest.

kubectl describe services my-service
Output
controlplane $ kubectl describe services my-service
Name:                     my-service
Namespace:                default
Labels:                   <none>
Annotations:              <none>
Selector:                 name=xander
Type:                     NodePort
IP Family Policy:         SingleStack
IP Families:              IPv4
IP:                       10.108.184.82
IPs:                      10.108.184.82
Port:                     <unset>  80/TCP
TargetPort:               80/TCP
NodePort:                 <unset>  32214/TCP
Endpoints:                192.168.1.4:80,192.168.0.4:80
Session Affinity:         None
External Traffic Policy:  Cluster
Internal Traffic Policy:  Cluster
Events:                   <none>

So we get the Virtual IP Address i.e., 10.108.184.82

Try to access the pod using VIRTUAL_IP_ADDRESS:NODE_PORT

curl 52.65.226.21:80
Output
localhost $ curl 52.65.226.21:80
<html><body><h1>It works!</h1></body></html>

Now even if the pod get deleted it won't affect the service.