Published 2022-05-25

Getting started with Kubernetes Services

Director Devops @ Spectro Cloud

Kubernetes Service is an abstraction that allows pods to be created or destroyed without the underlying client needing to keep track of it, helping resolve complex problems like service discovery.

Choosing the right service type is critical to designing your architecture correctly and saving time during the debugging phase. Getting familiar with the different types of services in Kubernetes is an integral part of mastering Kubernetes and enables the communication between pods, users, and external services. In this blog, we’ll look at how Kubernetes provides different service types and how to expose these services outside the cluster as type LoadBalancer or NodePort.

What is a Kubernetes Service?

A Kubernetes service is a mechanism of grouping pods running on the cluster. Since pods are ephemeral, meaning they’re created and destroyed on a regular basis, we use Kubernetes services to keep track of changes on the pod. Services provide functionality like load balancing, service discovery between apps, and support for zero-downtime app deployments.

So what is a service in Kubernetes? Kubernetes services expose a single endpoint for your application in the form of virtual IP. All the requests made to your service get redirected to appropriate pods, and thus service becomes a single endpoint for application communication.

Meet the three Kubernetes Service types

Kubernetes offers three different service types :

  • ClusterIP: A ClusterIP creates a service inside the Kubernetes on a cluster-internal IP.. ClusterIP is the default service type i.e. when you create a service and don't define the service type, it will automatically create a ClusterIP service.
  • NodePort: The NodePort service, like ClusterIP, is assigned an IP address, but it also exposes the application on a port shared by all nodes in the cluster. Any request for the particular port has been redirected and forwarded to one or more specified nodes.
  • LoadBalancer: The LoadBalancer service is implemented on top of the NodePort and ClusterIP service and exposes services over the internet for external access. Any request to the IP of the loadbalancer forwards to the appropriate node in the cluster. Hosting your Kubernetes cluster on a supported cloud provider, such as AWS, Google Cloud, Azure or Tencent allows you to leverage the Kubernetes loadbalancer.

In brief: how Kubernetes Services work

Kubernetes runs a “node agent” called kubelet that is primarily responsible for creating and managing pods. Each kubelet process on each node watches the changes in the cluster through the kube-apiserver. With every request for pod creation, kubelet comes into play and takes care of it. Kubelet then invokes the Container Network Interface (CNI) plugin to configure networking for that pod.

All the nodes in the cluster have a kube-proxy service that monitors changes in the cluster via the kube-api server. Every time a new service needs to be created, kube-proxy steps in. When creating a service object, it gets an IP address from a predefined range (specified on the kube-api server under service-cluster-ip-range).

The kube-proxy server running on each node gets that IP address and creates forwarding rules, using iptables, as default, but IPVS is also an option. The rule will be similar to: all the requests coming to this Service IP to be forwarded to the Pod IP.

In the rest of this blog, we’ll look at how you can use the three service types, step by step.

Creating a NodePort Service

To create any Kubernetes resource, you need to define the object in the YAML file. Like any other resource definition, the service starts with four mandatory fields:

  • apiVersion: Used to define which version of Kubernetes API you are using to create the object. Make sure that you are using the appropriate apiVersion based on the resource you are creating. The apiVersion for pod is v1. Check the following guide to find more information.
  • kind: Refers to the kind of object that you are trying to set up, in this case, service. Other possible values are POD, ReplicaSet, Deployment, etc.
  • metadata: Data about the object that helps to uniquely identify it. This could be as simple as a name or a label.
  • spec: Defines the desired state of the object, which varies from object to object as it contains nested fields specific to the object that you are creating. For example, it is in the spec field that you define the ports for your service. Further information can be found in the following guide.

Kubernetes provides a service-discovery mechanism natively, which means that you don’t need to modify your application to use an external service-discovery mechanism. Kubernetes provides Pods with IP addresses and a single DNS name for a set of Pods, providing a load-balance capability. To take full advantage of these Kubernetes features the spec field of the service object needs to be set up correctly, so let's dig deeper into the spec.

  • type: Specifies the service: ClusterIP, NodePort, or LoadBalancer.
  • selector: To connect the service to a pod you need to use the selector field. For example, a service with a selector label run:nginx will be attached to any Pod with the run:nginx label.
  • Ports: As shown in Figure 1, three ports are involved in the service creation process.

TargetPort: The target port is the port where your pod is listening, and the service will send the request (targetPort: 80).

Port: Port exposes the Kubernetes service on the specified port in the cluster. Pods within the cluster can use this port to communicate with each port (port: 80).

NodePort: NodePort exposes the service externally to the cluster (NodePort 30008). NodePort can only be between 30000 and 32767

The only mandatory field in the spec is the Port. The TargetPort is assumed to be the same as the Port. If you don't provide the NodePort, a free port in the valid range between 30000–32767 is automatically allocated.

Remember that ports are always an array. You can have multiple such port mappings within a single service

Figure 1: Kubernetes NodePort service Figure1: Kubernetes NodePort service

By combining everything, you can now create a YAML file. Your YAML file can have any name but should end with a .yaml extension (for example, myservice.yaml)

apiVersion: v1 kind: Service metadata: name: my-demo-service spec: type: NodePort selector: run: nginx ports: - port: 80 targetPort: 80 nodePort: 30007

To create a service use the kubectl create command and specify the file name (myservice.yaml) created in the above step.

kubectl create -f myservice.yaml service/my-demo-service created

To verify that the service is set up correctly, run kubectl get services. You should see that the service TYPE is NodePort.

kubectl get services NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE my-demo-service NodePort 10.43.189.153 <none> 80:30007/TCP 5s

Use the kubectl describe service command with the service name to retrieve detailed information.

kubectl describe service my-demo-service Name: my-demo-service Namespace: default Labels: <none> Annotations: <none> Selector: run=nginx Type: NodePort IP Family Policy: SingleStack IP Families: IPv4 IP: 10.43.189.153 IPs: 10.43.189.153 Port: <unset> 80/TCP TargetPort: 80/TCP NodePort: <unset> 30007/TCP Endpoints: 10.42.0.13:80 Session Affinity: None External Traffic Policy: Cluster Events: <none>

Run the curl command, followed by the Node IP and port number we specified at NodePort, to access the service.

curl http://172.25.0.15:30007 <!DOCTYPE html> <html> <head> <title>Welcome to nginx!</title> <style> html { color-scheme: light dark; } body { width: 35em; margin: 0 auto; font-family: Tahoma, Verdana, Arial, sans-serif; } </style> </head> <body> <h1>Welcome to nginx!</h1> <p> If you see this page, the nginx web server is successfully installed and working. Further configuration is required. </p> <p> For online documentation and support please refer to <a href="http://nginx.org/">nginx.org</a>.<br /> Commercial support is available at <a href="http://nginx.com/">nginx.com</a>. </p> <p><em>Thank you for using nginx.</em></p> </body> </html>

Creating a ClusterIP Service

Figure2: Kubernetes ClusterIP service Figure 2: Kubernetes ClusterIP service

Creating a ClusterIP service is similar to NodePort, the only difference is the type is ClusterIP. By default, when creating a service, if you omit this field, Kubernetes will create the service of type ClusterIP.

apiVersion: v1 kind: Service metadata: name: my-clusterip-service spec: selector: run: nginx ports: - protocol: TCP port: 80 targetPort: 80

Use the kubectl create command, specifying the file name, myservice1.yaml, prepared in the previous step as the argument, to create the service.

kubectl create -f service1.yaml service/my-clusterip-service created

Verify the service was successfully formed by using the kubectl get svc command. As you can see the TYPE is ClusterIP.

kubectl get services NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE my-clusterip-service ClusterIP 10.43.126.215 <none> 80/TCP 4s

This service can be accessed by other pods in the cluster using ClusterIP (10.43.126.215) or service name (my-clusterip-service).

Creating a LoadBalancer Service

Figure3: Kubernetes LoadBalancer service Figure 3: Kubernetes LoadBalancer service

Creating a LoadBalancer service is similar to other services, the only difference is the type is LoadBalancer and your cloud provider must support it. Following is the list of CloudProviders which support loadbalancer service.

apiVersion: v1 kind: Service metadata: name: my-lb-service spec: selector: run: nginx ports: - protocol: TCP port: 80 targetPort: 80 type: LoadBalancer

Create the service by using the kubectl create command and specify the file name (loadbalancerservice.yaml) generated in the above step.

kubectl create -f loadbalancerservice.yaml service/my-lb-service created

Verify that the service was successfully created by using the kubectl get service command. As you can see the service TYPE is LoadBalancer. Also, under the EXTERNAL-IP field, you will see а loadbalancer is created, which can be accessed using (aedc2001d600d460e96052efaad6ed63-486058819.us-east-1.elb.amazonaws.com) url.

# kubectl get services NAME TYPE CLUSTER-IP EXTERNAL-IP my-lb-service LoadBalancer 10.100.4.110 aedc2001d600d460e96052efaad6ed63-486058819.us-east-1.elb.amazonaws.com 80:30951/TCP 4s

Next steps

Want to read more about Kubernetes services and how to use them? There’s plenty out there, starting with the official Kubernetes docs, and how Google defines the concept in its GKE docs. As always, get in touch if you have any questions — we love engaging on technical topics at developers@spectrocloud.com.

Related Articles

Blog Posts

Enterprise challenges for containers and Kubernetes

Read our article
Be the first to receive the latest on
K8s, Palette, our upcoming webinar, events, and much more!

We are using the information you provide to us to send you our montly newsletter. You may unsubscribe at any time.
For more information, please see our Privacy Policy.

Spectro Cloud uniquely enables organizations to manage Kubernetes in production, at scale. Our Palette management platform gives effortless control of the full Kubernetes lifecycle, across clouds, data centers, bare metal and edge environments.
Follow us
Follow us

© 2022 Spectro Cloud®. All rights reserved.