NodePort Service
Creating a NodePort Service
A NodePort Service exposes a specified port on all the nodes in the cluster. Any traffic that comes to the Node on that port is routed to the selected Pods.
To Create a NodePort Service, update the service.yaml
file to have the following configuration:
apiVersion: v1
kind: Service
metadata:
name: backend-service
spec:
type: NodePort
selector:
app: simple-deployment
ports:
- protocol: TCP
port: 8000
targetPort: 8000
nodePort: 30001
Apply the changes to the Service:
kubectl apply -f service.yaml
Now, we'll send a request to the Node directly. First, get the nodes where the Pods are running:
$ kubectl get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
simple-deployment-794f78c89-cpwdd 1/1 Running 0 7m4s 192.168.189.66 worker2 <none> <none>
simple-deployment-794f78c89-gq7ts 1/1 Running 0 7m4s 192.168.235.130 worker1 <none> <none>
simple-deployment-794f78c89-nfzzk 1/1 Running 0 7m4s 192.168.219.71 master <none> <none>
In this case, the Pods are running on all the nodes. So, you can send a request to any of the nodes.
Next get the IP address of the node:
If you're using Minikube, you can use the following command:
minikube ip
If you're hosting the cluster locally, you can use the following command:
kubectl get nodes -o wide
If you're using CloudLab, you can visit the node's page and get the IP under Control IP
.
Now, send a request to the Node:
curl -i http://<node-ip>:30001/rest/v1/health/
$ curl -i http://<node-ip>:30001/rest/v1/health/
HTTP/1.1 200 OK
date: Fri, 05 Jul 2024 18:44:34 GMT
server: uvicorn
content-length: 15
content-type: application/json
{"status":"ok"}
Here, we're hitting the node port 30001
. This is the port we've specified in the service.yaml
file. The traffic is routed to the Pods based on the selector.
Understanding the Service manifest
Let's break down the service.yaml
file:
apiVersion: v1
: This tells Kubernetes to use thev1
API version.kind: Service
: This specifies the type of object we're creating, which is a Service.metadata
: This field specifies the additional metadata that should be associated with the Service.name
: This field specifies the name of the Service. In this case, it'sbackend-service
.
spec
: This field specifies the specification of the Service.type
: This field specifies the type of the Service. In this case, it'sNodePort
.selector
: This field specifies the selector that the Service uses to route the traffic to the Pods. In this case, the selector isapp: simple-deployment
.ports
: This field specifies the ports that the Service listens on.protocol
: This field specifies the protocol that the Service listens on. In this case, it'sTCP
.port
: This field specifies the port on which the Service listens. In this case, it's8000
. This port should be used by the pods talk to the service within the cluster.targetPort
: This field specifies the port on the Pods to which the traffic is routed. In this case, it's8000
.nodePort
: This field specifies the port on the Node to which the traffic is routed. In this case, it's30001
.name
: [Optional] This field specifies the name of the port. In this case, it's not specified.
To access a NodePort service from within a cluster, you can use the same method as for a ClusterIP service. You can use the Service name to access the service.
$ kubectl run -i --tty --rm debug --image=alpine -- sh
If you don't see a command prompt, try pressing enter.
/ # apk add curl
fetch https://dl-cdn.alpinelinux.org/alpine/v3.20/main/x86_64/APKINDEX.tar.gz
fetch https://dl-cdn.alpinelinux.org/alpine/v3.20/community/x86_64/APKINDEX.tar.gz
(1/10) Installing ca-certificates (20240226-r0)
(2/10) Installing brotli-libs (1.1.0-r2)
(3/10) Installing c-ares (1.28.1-r0)
(4/10) Installing libunistring (1.2-r0)
(5/10) Installing libidn2 (2.3.7-r0)
(6/10) Installing nghttp2-libs (1.62.1-r0)
(7/10) Installing libpsl (0.21.5-r1)
(8/10) Installing zstd-libs (1.5.6-r0)
(9/10) Installing libcurl (8.8.0-r0)
(10/10) Installing curl (8.8.0-r0)
Executing busybox-1.36.1-r29.trigger
Executing ca-certificates-20240226-r0.trigger
OK: 13 MiB in 24 packages
/ #
/ # curl -i ^C
/ # curl -i http://backend-service:8000/rest/v1/health/
HTTP/1.1 200 OK
date: Fri, 05 Jul 2024 21:12:04 GMT
server: uvicorn
content-length: 15
content-type: application/json
{"status":"ok"}/ #
/ #
Note that here the port is 8000
and not 30001
. This value is defined by the port
field in the service.yaml
file.
Cleaning up
To clean up the resources created in this section, run the following commands:
kubectl delete -f deployment.yaml
kubectl delete -f service.yaml
Summary
In this section, we learned how to create a NodePort Service. We also learned how to access the Service from outside the cluster. We used the nodePort
field to specify the port on the Node to which the traffic is routed. We also learned how to access the Service from within the cluster using the Service name.