# Using a NodePort in a Kubernetes Cluster on top of VirtualBox

> Kubernetes tutorial explaining how to use a NodePort to publish applications in a Kubernetes cluster running in VirtualBox with Vagrant and Ansible

- Source: https://www.itwonderlab.com/nodeport-kubernetes-cluster/
- Published: 2020-06-15
- Updated: 2026-10-05
- Author: Javier Ruiz Jiménez (https://www.javierruizjimenez.com/)
- Site: IT Wonder Lab (https://www.itwonderlab.com/)

---

Accessing applications deployed in a Kubernetes Cluster using VirtualBox requires a [NodePort](https://kubernetes.io/docs/concepts/services-networking/service/#nodeport). In a cloud provider, a load balancer will be used (see [AWS Load Balancers](https://www.itwonderlab.com/aws-elastic-load-balancing/)).

Deploying a Kubernetes Cluster on top of VirtualBox requires a specific network configuration as seen in the [Kubernetes Cluster using Vagrant and Ansible](https://www.itwonderlab.com/ansible-kubernetes-vagrant-tutorial/) and [First Steps After Kubernetes Installation](https://www.itwonderlab.com/installating-kubernetes-dashboard/) tutorials.

![LAN, NAT, HOST Only and Tunnel Kubernetes networks](https://www.itwonderlab.com/media/Kubernetes/Istio/ansible-kubernetes-vagrant-tutorial-Overview.png "Networking in a Kubernetes Cluster using VirtualBox")

The tutorial shows how to deploy an application and a NodePort to publish the application outside the Kubernetes Cluster.

Prerequisites:

-   [Kubernetes Cluster using Vagrant and Ansible](https://www.itwonderlab.com/ansible-kubernetes-vagrant-tutorial/)
-   [First Steps After Kubernetes Installation](https://www.itwonderlab.com/installating-kubernetes-dashboard/)

## Deploying Applications in Kubernetes

Create an Application configuration file that defines the name of the application, labels, number of replicas, and the docker images that are needed. Save the file as nginx.yaml.

```yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
spec:
  selector:
    matchLabels:
      app: nginx
  replicas: 3
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
        - name: my-echo
          image: gcr.io/google_containers/echoserver:1.8
```

Apply the configuration to the Kubernetes Cluster

```shell
$ kubectl apply -f nginx.yaml 
deployment.apps/nginx-deployment created
```

The Docker image, in this example nginx, has to be available in the official public Docker Registry (if using a local Docker image, it first needs to be uploaded to the public registry or a private registry, see [Pull an Image from a Private Registry](https://kubernetes.io/docs/tasks/configure-pod-container/pull-image-private-registry/) or the section [Building the Color Application](https://www.itwonderlab.com/istio-patterns-traffic-splitting-in-kubernetes/#building-the-color-application) in the [Istio Patterns: Traffic Splitting in Kubernetes (Canary Release)](https://www.itwonderlab.com/istio-patterns-traffic-splitting-in-kubernetes/) tutorial).

## Publish an Application Outside Kubernetes Cluster

To access the echo server that we just deployed from outside the cluster, a NodePort needs to be created. The NodePort allows us to access each of the Nginx echo servers (in round-robin) from outside the cluster.

In a Kubernetes cluster hosted in a cloud provider like Azure, Google or AWS a cloud-native Load Balancer will be used instead of the NodePort.

Add the following definition to nginx.yaml (the file created before)

```yaml
---
apiVersion: v1
kind: Service
metadata:
  name: nginx-service-np
  labels:
    name: nginx-service-np
spec:
  type: NodePort
  ports:
    - port: 8082        # Cluster IP, i.e. http://10.103.75.9:8082
      targetPort: 8080  # Application port
      nodePort: 30000   # (EXTERNAL-IP VirtualBox IPs) i.e. http://192.168.50.11:30000/ http://192.168.50.12:30000/ http://192.168.50.13:30000/
      protocol: TCP
      name: http
  selector:
    app: nginx
```

Apply the configuration to the Kubernetes Cluster

```shell
$ kubectl apply -f nginx.yaml 
deployment.apps/nginx-deployment unchanged
service/nginx-service-np created
```

Check that the NodePort has been created

```shell
$ kubectl get services
NAME               TYPE           CLUSTER-IP     EXTERNAL-IP   PORT(S)          AGE
kubernetes         ClusterIP      10.96.0.1      <none>        443/TCP          7h55m
nginx-service-np   NodePort       10.103.75.9    <none>        8082:30000/TCP   5h43m
```

Access the application with curl (or with a web browser) from the development environment using one of the public Kubernetes Cluster IPs (192.168.50.11, 192.168.50.12, 192.168.50.13) and the NodePort (30000):

```shell
$ curl http://192.168.50.11:30000/
Hostname: nginx-deployment-d7b95894f-2hpjk
Pod Information:
	-no pod information available-
Server values:
	server_version=nginx: 1.13.3 - lua: 10008
Request Information:
	client_address=192.168.116.0
	method=GET
	real path=/
	query=
	request_version=1.1
	request_uri=http://192.168.50.11:8080/
Request Headers:
	accept=*/*
	host=192.168.50.11:30000
	user-agent=curl/7.61.0
Request Body:
	-no body in request-
```

Repeat the request and see that the value of hostname changes as Kubernetes is accessing the different instances of the application among the available PODS. The hostname corresponds to the NAME of the different PODS for the Nginx deployment:

```shell
$ kubectl get pods
NAME                               READY   STATUS    RESTARTS   AGE
nginx-deployment-d7b95894f-2hpjk   1/1     Running   1          5h44m
nginx-deployment-d7b95894f-49lrh   1/1     Running   1          5h44m
nginx-deployment-d7b95894f-wl497   1/1     Running   1          5h44m
```

### Kubernetes NodePort Diagram

The diagram shows the different elements that are involved in publishing an application outside the Kubernetes cluster using a NodePort. The Kubernetes master, not shown, executes a proxy as well.

![NodePort traffic in Kubernetes Cluster](https://www.itwonderlab.com/media/2019/04/ansible-kubernetes-vagrant-tutorial-NodePort-1.png)

Network traffic when doing *curl [http://192.168.50.12:30000/](http://192.168.50.12:30000/)*

1.  A request to access 192.168.50.12:30000 (Node 1 Port NodePort) is received by the vboxnet router.
2.  It is routed to the external IP of the Kubernetes node 1, port 30000
3.  The request is sent to the Kubernetes Proxy
4.  The Kubernetes Proxy sends the request to the Cluster IP 10.103.75.9 and port 8082 that has been assigned to the nginx-services-np (Nginx service NodePort).
5.  The Nginx service NodePort sends the request to one of the available pods for the application Nginx, it can be any of the pods located at the same Kubernetes node or in a different node (like K8S-N-2)
