Understanding Services — Kubernetes
In order to understand how Kubernetes Services work, you need to have some understanding of how pods and labels work. Click the following links to have a refresher on pods and labels.
https://medium.com/@ngugijoan/understanding-pods-kubernetes-8fe3717046d4
What is a Kubernetes Service?
A service provides a single entry for accessing one or more Pods. From our diagram above, if you wanted to access a Pod, either from within you cluster or externally you would use a Service.
Why use a Kubernetes Service?
Let’s briefly go back to Pods. Pods usually have their default IP as below.
You might be tempted to use a pod’s IP address to handle requests. In Kubernetes however, we don’t specify a pod’s IP due to the following reasons.
- Pods are mortal — They are born and can die. This means that the IP address of a pod will change.
- Kubernetes assigns an IP address to a pod after the pod has been scheduled to a node and before it’s started. Your client, therefore, cannot know the IP address of the server pod upfront.
- Horizontal scaling means multiple pods may provide the same service — No matter how many pods you have, your client should be able to access all your pods through a single IP address.
Kubernetes uses services to abstract Pod’s IPs from clients since a Kubernetes Service IP is static.
Creating Kubernetes Services.
When you are creating a Kubernetes service, you are essentially creating endpoints that sit between a Service and Pod. Kubernetes Services rely on labels to associate a Service with a Pod.
Explaining the above diagram
- We have an external request to our Kubernetes cluster through our frontend service.
- Our frontend service knows all the pods that are behind it, which are all the pods with the label frontend.
- Our frontend pods are talking to another pod labeled backend through service also labeled as backend.
It is even therefore very easy to do Pod Load Balancing through Services.
Kubernetes allows you to extend your service by going further to specify the type of service you want. For instance, from our diagram above, our frontend application has been exposed outside our cluster, we would therefore exclusively use a service that allows outside requests. Our backend application is being exposed from within our cluster, we would therefore exclusively use a service that is only reachable from within our cluster.
Service Types
- ClusterIP — This is the default service type of one is not specified. It exposes your service on an IP that is available within the cluster. In a real-world application, you would most likely use this during development and not on production. Only pods within the cluster can talk to the service
- NodePort — A nodePort makes your service visible outside the Kubernetes Cluster by using the node’s IP address and the port number declared in the property. A node port can be statically assigned or explicitly defined in the service specification.[30000–32767]
- LoadBalance — Provision an external IP to act as a load balancer for the service
- ExternalName — Maps a service to a DNS name.
Like all other Kubernetes resources,
- We can create our service with kubectl.
- We can also create our service with YAML
YAML structure for a service.
apiVersion: v1
kind: Service
metadata:
name: my-service 1
spec:
selector:
tier: frontend 2
ports:
- protocol: TCP 3
port: 80 4
targetPort:9376 5
This specification means:
- 1 — The name of our service
- 2 — All pods with the label tier: frontend will be part of this service
- 3 — Protocol being used. The default protocol for Services is TCP but any other supported protocol can be used.
- 4 — The port this service will be available on.
- 5 — The container port the service will forward to
You can also create your service by creating a deploying then exposing the deployment so that the deployment’s pods can be accessed through a service.
Challenge
- Create a deployment named mydeployment that creates 2 replicas for Pods with the image nginx. Expose the container port 80.
# Lets view if our deployment has been created
kubectl get deployments
Remember that creating deployments is essentially creating our pods which are being managed through the deployment.
# Let's also see if we have two pods being managed by the deployment
Kubectl get pods
Our two replica pods are running.
2. Expose the Pods so that requests can be made against the service from inside of the cluster. ( We will expose the pods but using our deployment).
What do you think the above kubectl command has done? The command has essentially created a service for our pods. Remember that if you don’t specify the service a clusterIP is created by default. The cluster IP will expose our service inside our cluster.
The above kubectl get service command is displaying all my services available. Our latest created service is the last one here. The name is mydeployment, we can see our clusterIP(10.12.15.203). We don’t have an external IP yet meaning we cannot access our pods outside the cluster. The service is also running on the TCP protocol on port 80.
You now have your service running on a clusterIP. How would another pod inside this cluster interact with that other pod?
3. Create a temporary Pod using the image alpine and run a wget command against the IP of the service.
kubectl run alpine --image=alpine --restart=Never --rm -it --wget -O- [clusterIP:port]#As shown below we will have our alpine image run using "mydeployment" cluster IP
- 0ur pod name is alpine.
- We are using the alpine base image.
- We are using a restartPolicy of Never. Which means our pod will not be restarted regardless of how it exited.
- We are then using our previous service IP together with its port.
( The wget command is a Linux command that helps us download files from the web).
We will now change our service type so that the pods can be reached from outside the cluster.
4. Change the service type so that the Pods can be reached from outside of the cluster.
kubect edit service mydeployment
Let’s change the service type from ClusterIP to a NodePort.
Save the edit and run the get service command.
Our mydeployment service type has now changed to NodePort and in addition, we have our static IP 31205.
5. If we change the type to a LoadBalancer, we will get an External IP which we would then run on a web browser.
For instance, I have changed the service type below to be a Load Balancer.
You can see TYPE= LoadBalancer and External-IP=35.193.25.184. I can, therefore, run this LoadBalancer on my web browser.
Note: In a real ecosystem you would also use Network Policies to control traffic to and from Pods. In my next article, I am going to help you understand how you can use Network Policies.