Home › CKAD › Topics › Practice tasks › Service Types & Configuration
CKAD · Services & Networking

Expose a Deployment with a NodePort Service

In namespace default, Deployment api-app exists with Pods labeled app=api and container port 9090.

Check live lab access → All CKAD tasks

Live lab access

This task description is public. Live practice requires full access unless this is the selected free weekly task. AI Lab Coach is available in single-task labs, including the free weekly task. See this week's free task.

Create an account to continue →

Read this week's free task →

On a phone? Read the task and create your account here, then sign in on a desktop or laptop for the terminal lab. Nothing starts until you choose Start.

The task

Task

In namespace default, Deployment api-app exists with Pods labeled app=api and container port 9090.

Requirements

Create a Service named api-nodeport that:

Original Prepium guide · Written for Kubernetes v1.35 and checked against the official documentation on 6 October 2026. Use a disposable practice cluster. The tests run from a Pod inside the cluster, so they do not depend on your laptop being able to reach the nodes.

Expose Pods on every node with a NodePort Service, quickly and correctly

A NodePort Service is a normal ClusterIP Service plus one extra port opened on every node. The control plane allocates that node port from a fixed range (30000-32767 by default), and each node forwards traffic on it to the Service's ready endpoints. Getting it right means keeping three numbers straight and making sure the selector really matches your Pods.

outside ──→ any-node-IP:nodePort (e.g. 30042)
inside  ──→ quotes-np:port (7000)
             └──→ Pod:targetPort (80, where httpd listens)

1. Start from a workload whose labels you know

kubectl create namespace prepium-tutorial
kubectl -n prepium-tutorial create deployment quotes --image=httpd:2.4-alpine --replicas=2
kubectl -n prepium-tutorial get pods --show-labels

create deployment labels the Pods app=quotes. Any Service you build must select exactly that.

2. The fast path: expose

kubectl -n prepium-tutorial expose deployment quotes --name=quotes-np \
  --type=NodePort --port=7000 --target-port=80
kubectl -n prepium-tutorial get svc quotes-np
kubectl -n prepium-tutorial get endpointslices -l kubernetes.io/service-name=quotes-np

expose copies the Deployment's selector, so the label match is done for you. The PORT(S) column shows the Service port followed by the node port the control plane picked. The EndpointSlice should list both Pod IPs with port 80. If you left out --target-port, it would default to the Service port, 7000, where nothing is listening.

3. Pinning a specific node port

expose has no dedicated flag for the node port, but kubectl create service nodeport does. It only knows the name and ports you type, so it cannot read your Pods' labels: always inspect the selector it generates before applying.

kubectl -n prepium-tutorial create service nodeport quotes-fixed \
  --tcp=7000:80 --node-port=30042 --dry-run=client -o yaml > quotes-fixed.yaml
grep -A2 selector quotes-fixed.yaml       # change it to app: quotes, then:
kubectl apply -f quotes-fixed.yaml

A requested nodePort must lie inside the configured range and must be free; otherwise the API server rejects the Service. With the default range, ports 30000-30085 form a "static" band that automatic allocation avoids until the rest is used up, so pinned ports there are less likely to collide.

4. Test the way a client would

kubectl -n prepium-tutorial run client --image=busybox:1.36 --restart=Never -- sleep 3600
kubectl -n prepium-tutorial wait --for=condition=Ready pod/client
NODE_IP=$(kubectl get nodes -o jsonpath='{.items[0].status.addresses[?(@.type=="InternalIP")].address}')
kubectl -n prepium-tutorial exec client -- wget -T 3 -qO- "http://$NODE_IP:30042"
kubectl -n prepium-tutorial exec client -- wget -T 3 -qO- http://quotes-fixed:7000

Both should print Apache's default page. The first proves the node port path; the second proves the in-cluster Service port, which a NodePort Service always has as well. The same node port answers on every node, not only on nodes running a quotes Pod.

Common mistakes

Example checkEvidence
Type and portsspec.type is NodePort; port, targetPort and nodePort are the intended numbers
Selector matches PodsEndpointSlice lists the Pod IPs with the target port
Node path worksRequest to a node IP and the node port returns the app
Cluster path worksRequest to the Service name and port returns the app

Cleanup: kubectl delete namespace prepium-tutorial and rm quotes-fixed.yaml. References: Service type NodePort, kubectl expose, kubectl create service nodeport. Next, try Service selector troubleshooting or named ports with NodePort.

Exam
CKAD
Domain
Services & Networking
Grading
Programmatic · partial credit

What this tests

Expose workloads with services and ingress, and restrict traffic with network policies. On the CKAD exam, Services & Networking tasks are graded purely on what you build in the cluster - not multiple choice - so the only way to get faster is to do them on a real cluster against a clock.

Practice it for real

The public description lets you study the task before signing up. Full access includes this live lab; the selected Task of the Week is free with an account. You solve the task in a real terminal, hit validate, and a programmatic checker scores exactly what you got right and wrong (with partial credit). You can open the solution while practising, then retry and use the failed checks to improve your score.

Related CKAD tasks