NodePort
kind
Kubernetes
networking
tutorial

How to use NodePort with kind?

System Design practice on Codemia

Work through 120+ system design problems with detailed solutions, from rate limiters to multi-region storage.

Practice system design

Introduction

Kind (Kubernetes IN Docker) runs a full Kubernetes cluster inside Docker containers on your local machine. Because the cluster nodes are themselves containers rather than real hosts, exposing a Kubernetes NodePort service to your laptop requires an extra configuration step: you must tell kind to map container ports to host ports at cluster creation time.

This article walks through the complete workflow -- creating a kind cluster with port mappings, deploying a sample application, exposing it via a NodePort service, and verifying access from your host machine.

Prerequisites

Before you begin, make sure you have the following installed:

  • Docker (version 20.10 or later)
  • kubectl (matching your target Kubernetes version)
  • kind (version 0.11 or later). Install instructions are at https://kind.sigs.k8s.io

Step 1 -- Create a Kind Cluster with extraPortMappings

By default, kind does not expose any container ports to the host. You must provide a cluster configuration file that maps a host port to the container port you plan to use for your NodePort service.

Create a file called kind-config.yaml:

yaml
1kind: Cluster
2apiVersion: kind.x-k8s.io/v1alpha4
3nodes:
4  - role: control-plane
5    extraPortMappings:
6      - containerPort: 30007
7        hostPort: 30007
8        protocol: TCP

The containerPort value must match the nodePort you will assign to your Kubernetes Service (in the valid range of 30000-32767). The hostPort is the port that becomes accessible on localhost.

Now create the cluster:

bash
kind create cluster --name my-cluster --config kind-config.yaml

Verify the cluster is running:

bash
kubectl cluster-info --context kind-my-cluster

Step 2 -- Deploy a Sample Application

Create a file called deployment.yaml with a simple Nginx deployment:

yaml
1apiVersion: apps/v1
2kind: Deployment
3metadata:
4  name: nginx-deployment
5  labels:
6    app: nginx
7spec:
8  replicas: 2
9  selector:
10    matchLabels:
11      app: nginx
12  template:
13    metadata:
14      labels:
15        app: nginx
16    spec:
17      containers:
18        - name: nginx
19          image: nginx:1.25
20          ports:
21            - containerPort: 80

Apply it:

bash
kubectl apply -f deployment.yaml

Wait for the pods to become ready:

bash
kubectl get pods -l app=nginx --watch

Step 3 -- Expose the Deployment with a NodePort Service

Create a file called service.yaml:

yaml
1apiVersion: v1
2kind: Service
3metadata:
4  name: nginx-service
5spec:
6  type: NodePort
7  selector:
8    app: nginx
9  ports:
10    - port: 80
11      targetPort: 80
12      nodePort: 30007

The nodePort: 30007 must match the containerPort in your kind configuration from Step 1. Apply the service:

bash
kubectl apply -f service.yaml

Check that the service is running and the NodePort is assigned:

bash
kubectl get svc nginx-service

You should see output similar to:

 
NAME            TYPE       CLUSTER-IP     EXTERNAL-IP   PORT(S)        AGE
nginx-service   NodePort   10.96.45.123   <none>        80:30007/TCP   5s

Step 4 -- Access the Service from Your Host

Because the kind configuration mapped hostPort: 30007 to containerPort: 30007, you can now reach the Nginx server from your laptop:

bash
curl http://localhost:30007

You should see the default Nginx welcome page HTML.

How the Networking Works

The chain of connections looks like this:

  1. Your browser or curl sends a request to localhost:30007.
  2. Docker forwards it from host port 30007 to the kind container's port 30007.
  3. Inside the container, the Kubernetes kube-proxy matches port 30007 to the NodePort service.
  4. The service routes the request to one of the Nginx pods on container port 80.

Without the extraPortMappings entry, step 2 would fail because Docker would have no port-forwarding rule.

Cleanup

When you are finished experimenting, delete the cluster:

bash
kind delete cluster --name my-cluster

Common Pitfalls

  • Forgetting extraPortMappings at cluster creation. Port mappings can only be set when the cluster is created. You cannot add them to a running cluster; you must delete and recreate it.
  • Mismatched port numbers. The containerPort in kind-config.yaml must exactly match the nodePort in your Kubernetes Service manifest. A mismatch means traffic never reaches the service.
  • Port already in use on the host. If another process (or another kind cluster) is already listening on the host port, cluster creation will fail. Check with lsof -i :30007 before creating the cluster.
  • Using NodePort outside the valid range. Kubernetes only allows NodePort values between 30000 and 32767 by default. Specifying a port outside this range causes the service creation to fail.
  • Not waiting for pods to be ready. Applying the service before the deployment pods are running results in connection refused errors. Always verify pod readiness with kubectl get pods --watch before testing.

Summary

  • Kind requires extraPortMappings in its cluster configuration to forward host ports into the Docker container that acts as a Kubernetes node.
  • The containerPort in the kind config must match the nodePort in your Kubernetes Service manifest.
  • After applying the deployment and NodePort service, access your application at localhost:\<hostPort\>.
  • Port mappings cannot be added after cluster creation; plan them before running kind create cluster.
  • Use kubectl get svc and curl to verify end-to-end connectivity from your host to the pods.

Related reading
Course
Beginner
27 lessons
10 hours
System Design Fundamentals

Build a strong foundation in designing scalable, reliable distributed systems.

View the course
Track what you have practised

A free account saves your progress, solutions and study plan across every problem on Codemia.

System Design practice on Codemia

Work through 120+ system design problems with detailed solutions, from rate limiters to multi-region storage.

Practice system design

All Rights Reserved.