This is the first article in what I intend to be an X? part series on various kubernetes[k8s] concepts. This article/series is aimed at folks new to the world of k8s, looking to gain a simplified knowledge of some of the fundamental concepts of Kubernetes.
The Need For Services
According to the official k8s documentation, Kubernetes services are an abstract way to expose an application running on a set of Pods as a network service. This is as simple as the definition of a k8s service can get. In the rest of this section, we would discuss and get to understand this definition in detail. I like to think of Pods as the atoms of k8s. They are the basic, building block on which every other advanced k8s feature is based. However, Pods are highly volatile. They have a short life span and are created/destroyed as often as possible to match the state of your cluster as declared by the replicaset or deployment. Every Pod gets its own IP address. That’s great, Now you want to configure two pods to communicate with each other through the addresses? No! That will be a disaster. Remember, that pods are volatile. If a new Pod fails, the replicaset will attempt to create a new one with an entirely new address. This new address is not configured to communicate with the second pod. We need a constant address that does not change through pod creation or destruction. This is where services come In. Services provide a non-changing address that pods can use to communicate with each other. Services ensure a sort of decoupling between pods. Pod A does not need to keep track of Pod B’s possibly changing IP address. You could check out the motivation behind services on the official website
A closer look at services
Great! Now you know why we need services. We will look into creating services in this section. You create a service by exposing a port. This port is what other pods in the cluster can use to access it. Say pod A has its port 80 exposed and port B needs to connect to it, It uses that port. Services can be created imperatively using the kubectl expose command. This command creates a service by exposing a resource and is based on the name, target port and type of service specified alongside the command.
This is the general format for using the kubectl expose command.
$ kubectl expose (-f FILENAME | TYPE NAME) [--port=port] [--protocol=TCP|UDP|SCTP] [--target-port=number-or-name] [--name=name] [--external-ip=external-ip-of-service] [--type=type]
It can be used like this
kubectl expose rs nginx \ --name=nginx-service\ --target-port=8000 \ --type=NodePort
- The name field is used to specify the name of the service. When the above command is executed, It creates a service named Nginx-service. When specifying a name for your service, It is important to ensure it follows the DNS Label Name standard.
- The target-port field represents the actual port on which your application is running inside the container.
The type field specifies the type of service. There are four types of k8s services.
- The ClusterIP - This service is only accessible within the cluster. It is useful for communicating between pods while preventing external access.
- The NodePort - This service exposes the targetPort on every node in the cluster, making it accessible to the outside world. The NodePort service type automatically creates a ClusterIP type for internal communication between pods
- The LoadBalancer - This service type combines with your cloud providers load balancer and exposes the service externally. It routes to the NodePort ad ClusterIP which are created on the fly when this service type is selected.
- The ExternalName - This service type maps to an external address.
We can also take a declarative approach when creating K8s services. we can create a YAML file and declare all the necessary properties of a service and create it using kubectl create -f [Name of the YAML file].
apiVersion: v1 kind: Service metadata: name: hello-world spec: type: NodePort selector: app: hello-world ports:
- protocol: TCP port: 8080 targetPort: 80 nodePort: 30036
You should be a little familiar with the definition above. It is similar to the definition of a replica set. However, The Kind property is different, It is set to Service. This is to let the API Server know that we intend to create a Service object. The specification above creates a hello-world service. It targets any pods with TCP port 80 that has a label that matches the one specified in the selector section[app=hello-world in our case]. The nodePort value in the service we created imperatively above was automatically generated for us. In this case, we can expose it to be used externally. You can access the hello-world service outside the cluster by visiting http://$IP:nodePort on your browser. In Conclusion So far, We have discussed quite a bit about k8s services which I hope at this point has become a little less [k8s service-ish] complex. This post is by no means an exhaustive tutorial on k8s service, I do recommend checking out the official documentation for a full guide to k8s services. You can connect with me on twitter!