A pod is the smallest unit of deployment in Kubernetes and each one gets its IP address when deployed in a Kubernetes cluster. Pods are ephemeral i.e they are destroyed frequently. When the old pod dies and new ones are created in their place, new IP addresses are assigned. Therefore it doesn't make sense to use pod IP addresses to access your application directly as you will have to keep up with the constantly changing IPs when the pods get recreated. This is where Services comes in
A Service is an abstraction that defines a set of Pods and a policy to access them. Services usually have a stable IP address and provide a consistent way of accessing Kubernetes Pods. Services also provide load balancing, loose coupling, and communication within and outside the cluster
In this article, you will learn what a Kubernetes Service is, why they are needed, different types of services, and their use cases
An example of what a service definition looks like.
apiVersion: v1 kind: Service metadata: name: my-service spec: selector: app: MyApp ports: - protocol: TCP port: 80 targetPort: 9376
The name of the service is
my-service as seen above. The selector flag is used to identify the pods to forward the request to. They are usually defined as labels on the Pod. Under the ports section, the
port is the service port while the
targetPort is used to identify the container port to forward requests to on the Pod.
You might be wondering
- How does a service know which
podto direct traffic to?
- How does the service know the
portto also forward requests to in the case of a multi-container pod?
Services identify the pod to direct traffic using
selectors. The selectors are usually defined as key-value pairs under the
spec section of the service definition file(YAML).
There are also instances where you have a multi-container pod with each container listening on a different port. The Service would be able to identify the container to forward the request to with the
When you create a service, Kubernetes creates an Endpoint object that has the same name as the service itself. It is used to keep track of the pods that are endpoints of that service.
As seen above, service endpoints keep track of the pods that are endpoints of the service. Services use the endpoint to dynamically forward the request to any of the pods with the right label. But sometimes, you want to communicate directly with a Pod especially when working with stateful applications like a database. Kubernetes allows you to define a headless. When you create a Headless service, there is no load balancing or proxying done by the platform for them, this way you can make a request to a specific pod as opposed to randomly forwarding requests to Pods
To define a Headless Service, set the
clusterIP under the
spec section to
apiVersion: v1 kind: Service metadata: name: headless-svc spec: clusterIP: None selector: app: web ports: - protocol: TCP port: 80 targetPort: 8080
There are scenarios where you need to expose more than one port in your service. i.e You can expose one port to handle client requests and the other port to perform another operation like logging or monitoring. Services allow you to do that by defining the ports as a list. When defining multi-port services, it's advisable to give it a name to differentiate each port
apiVersion: v1 kind: Service metadata: name: multi-port-svc spec: selector: app: MyApp ports: - name: http protocol: TCP port: 80 targetPort: 9376 - name: https protocol: TCP port: 443 targetPort: 9377
Types of Services
- ClusterIP: This is the default service type in Kubernetes. When you create a service without specifying the type, it automatically becomes a Cluster IP. Cluster IP exposes the service on an internal IP in the cluster. Services of type ClusterIP are only reachable from within the cluster. An example of a service with the type
ClusterIPis given below
apiVersion: v1 kind: Service metadata: name: cluster-ip-svc spec: selector: app: MyApp ports: - protocol: TCP port: 80 targetPort: 9376
- NodePort: This is a type of service that is accessible on a static port on each worker node in a Kubernetes cluster. While a clusterIP only allows traffic from within the cluster, NodePort on the other hand allows External Traffic through the fixed port on the worker nodes. So instead of using Ingress, the client can hit the cluster directly via the static port. When you create a Service of type NodePort, a ClusterIP service is automatically created. The NodePort uses the ClusterIP to route the request through the cluster internally.
This type of Service definition is not secure, as you are opening the port to directly talk to the services on the worker nodes. The
NodePorttype is mainly used for testing purposes and not used in a production environment. The NodePort is an extension of the ClusterIP service
apiVersion: v1 kind: Service metadata: name: node-port-svc spec: type: NodePort selector: app: MyApp ports: - protocol: TCP port: 80 targetPort: 9376 nodePort: 30021
It is important to note that, the
nodePort attribute under the service definition can only have a value within the range of 30000 - 32767
- Load Balancer: This type of Service definition allows the service to become accessible externally through cloud provider's load balancer functionality. Cloud providers have their native implementation of a load balancer which is used whenever you create a service type of Load balancer. When you create a Load balancer service, NodePort and ClusterIP Services are created automatically by Kubernetes to which the external load balancer of the cloud platform will route traffic. LoadBalancer Service is an extension of the NodePort Service
apiVersion: v1 kind: Service metadata: name: load-balancer-svc spec: type: LoadBalancer selector: app: MyApp ports: - protocol: TCP port: 80 targetPort: 9376 nodePort: 30021
ClusterIP, NodePort and LoadBalancers
It is important to note that
ClusterIPService is only reachable from within the cluster
NodePortis an Extension of the
LoadBalanceris an Extension of the
In a real Kubernetes setup in production, you will not use the
NodePort Service for external connection. You can use it to test your application but not for a production use case. If you have an application you want to expose to the client from the Kubernetes cluster, you can consider using an Ingress or use a Service type of
LoadBalancer that uses the cloud provider's load balancer implementation. You can read more about Kubernetes Services here