# Create a NodePort service

In 
Published 2022-12-03

This tutorial explains how we can create a NodePort service in Kubernetes.

# Services - introduction

The pods don't have stable IPs and this is a problem for an external service to call the services inside pods.

A Kubernetes service group the pods (by using labels and selectors) and give them a fix

  • IP
  • DNS name
  • port

We can access the services inside these pods through this service, which acts as a load balancer as well. Each Service that is created, automatically gets an associated Endpoint object. This Endpoint object is a dynamic list of all the healthy Pods on the cluster that match the Service’s label selector.

The services could be of several types:

  • ClusterIP
  • NodePort
  • LoadBalancer

ClusterIP service type (the default service type)

All the services inside cluster can communicate by using the Cluster IP (or the name of the cluster which is resolved to the Cluster IP). This IP address is accessible only inside Kubernetes cluster.

# NodePort Service - introduction

NodePort service type

The NodePort Service type add a new layer over the ClusterIP Service type. This layer let you access the service on each node on a particular port (defined during the NodePort service definition).

With this type of service, you can access the services we have in pods by using node_ip:nodePort, where node_ip is the IP of any node, and nodePort is a port defined during the service definition. If there are multiple nodes, then multiple IP addresses with the same port will be exposed.

# Create a NodePort service

The following example is has a prerequisite the Deployment from Create, View and Destroy a Deployment

Now we can create the yaml file for creating the new service:

kind: Service 
apiVersion: v1 
metadata:
  name: http-server-service 
spec:
  # Expose the service on a static port on each node of the cluster
  # Each "node-ip:NodePort" will be accessible from outside the cluster 
  type: NodePort

  # This service works only with pods labeled as below
  selector:
    app: app1

  ports:
    - nodePort: 30001 #Accessible from outside the cluster
      port: 8080 # On the clusterIP level (for inter-pods communication)
      targetPort: 80 #On the pod level

The following command will create the new service:

kubectl apply -f my-first-service.yml

We can run the following command in order to see if the new service is created:

kubectl get service

Here is the result:

http-server-service   NodePort    10.100.99.160   <none>        8080:30001/TCP   22s
kubernetes            ClusterIP   10.96.0.1       <none>        443/TCP          3d15h

If you want to get more information on "http-server-service" service you can run:

kubectl describe service http-server-service

Here is the result:

Name:                     http-server-service
Namespace:                default
Labels:                   <none>
Annotations:              <none>
Selector:                 app=app1
Type:                     NodePort
IP Family Policy:         SingleStack
IP Families:              IPv4
IP:                       10.100.99.160
IPs:                      10.100.99.160
Port:                     <unset>  8080/TCP
TargetPort:               80/TCP
NodePort:                 <unset>  30001/TCP
Endpoints:                10.244.0.26:80,10.244.0.27:80,10.244.0.30:80 + 1 more...
Session Affinity:         None
External Traffic Policy:  Cluster
Events:                   <none>

If you want to test that the service is accessible, you can go to the node, or to a machine which has access to that node and run the command curl 192.168.49.2:30001 :

curl 192.168.49.2:30001

<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
    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>

IF you want to see the nodes IPs, you can run the following command:

kubectl get nodes -o wide

Here is the result in my case:

NAME       STATUS   ROLES           AGE    VERSION   INTERNAL-IP    EXTERNAL-IP   OS-IMAGE             KERNEL-VERSION                      CONTAINER-RUNTIME
minikube   Ready    control-plane   4d4h   v1.26.1   192.168.49.2   <none>        Ubuntu 20.04.5 LTS   5.10.16.3-microsoft-standard-WSL2   docker://20.10.23

# Delete a Service in Kubernetes

Delete the service created above:

kubectl delete service http-server-service