Services in Kubernetes are the communication channels between different components and entities in and outside of your cluster. They are like the gateways of your Kubernetes cluster. A service, being like a mini gateway/server running in your cluster, has its own internal cluster IP address.
There are three types of services;
- NodePort –> Creates a connection between a port on the node and a port on a pod inside it.
- ClusterIP –> Creates IPs to connect different nodes in a cluster.
- LoadBalancer –> Creates a load balancer for connections into your cluster
NodePorts creates connections between the following ports;
- TargetPort –> The port on a Pod
- Port –> The port on the NodePort service
- NodePort –> The port on the node. They are limited to port numbers 30,000 - 32,000.
As with other objects, we create a NodePort service with a YAML file.
// nodeport.yml apiVersion: v1 kind: Service metadata: name: nodeport-service-example spec: type: NodePort ports: - targetPort: 80 port: 80 nodePort: 30000 selector: // <- Add pods applicable app: front-end-app type: front-end
You don't need to add all 3 ports, if you leave out targetPort it defaults to the same value as port, and if you leave out nodePort Kubernetes will select a random port between 30,000 and 32,000.
You then create it as per usual with kubectl, and voila! Now you can access the pod on the nodes IP address on port 30,000.
Another thing to note is that the selector will look for all pods with the name front-end-app and of type front-end. If you have 4 pods created with those names, the selector will connect all 4 of them for you, and also load balance requests between them for you.
But it goes further than that, it will select Pods across different nodes as well, as long as the names and types match. You could then access the same service on any of the connected nodes' IP addresses, on port 30,000.
ClusterIP's enable you to create a micro-services architecture on your cluster by creating a single point of contact on a service for multiple pods of a kind. For instance, if you have a traditional front-end, api-backend and caching servers deployment, you can connect all the instances of front-end Pods under one front-end service with a single IP, a single back-end service for multiple back-end Pods with its own IP address, and so on.
These services will each have their own IP address and name on the cluster. Other Pods will then be able to access this service with that address.
Lets create api.yml;
// api.yml apiVersion: v1 kind: Service metadata: name: api-service spec: type: ClusterIP ports: - targetPort: 80 port: 80 selector: // <- Add pods applicable app: main-api type: back-end-api
Create it with kubectl and then view the service - you should see it is created and now has a clusterIP and name, both of which can be used by other entities in your cluster to connect to.
If your cluster runs in a cloud provider that supports load-balancing, you can create a LoadBalancer service. This allows external access to your cluster through an IP address and port.
The LoadBalancer service essentially creates an internal ClusterIP service, connecting the pods in the cluster to an external load-balancing service provided by your cloud provider.
// loadbalancer.yml apiVersion: v1 kind: Service metadata: name: loadbalancing-service spec: type: LoadBalancer ports: - targetPort: 80 port: 80
You can also do it CLI with
kubectl expose rc loadbalancerExample --port:80 --targetPort=80 --name=loadbalancing-service --type=LoadBalancer
Ok cool. So you might have noticed that we don't know something quite crucial.
What is the IP address then?
Well, let's interrogate our newly created loadbalancer;
kubectl describe service loadbalancing-service
Now look for the line LoadBalancer Ingress - that is your load-balancer IP address. LoadBalancers can get a little bit more technical, so we'll have a deeper look at them in some later post.
We're done with Service! We've learned quite a bit. Now we're going to get more hard core and look at Scheduling next.
Thanks for reading!