Services & Connectivity
The front-end Deployment in namespace prepium has an nginx container with no port specification. Task 1: Set your current namespace context to prepium.
Live lab access
This task description is public. Its live lab requires full access; six other CKA labs are available in Free Practice with AI Lab Coach.
Create an account to continue →
Explore the six free labs with AI Lab Coach →
Read the brief on any device. Use a desktop or laptop for the terminal lab. Nothing starts until you choose Start.
The task
The front-end Deployment in namespace prepium has an nginx container with no port specification.
Task 1: Set your current namespace context to prepium.
Task 2: Update the Deployment to add a container port named http (port 80/TCP).
Task 3: Create a Service named front-end-svc that:
- Selects pods with
app: front-end - Exposes port
80 - Uses
targetPort: httpto reference the named pod port - Type: NodePort
Original Prepium workshop · Tested on Kubernetes v1.35.0 on 1 October 2026 in a three-node kind cluster. Run this independent example in a disposable cluster. All traffic tests run from a Pod inside the cluster, so they work the same whether or not your nodes are reachable from your laptop.
Named container ports and a NodePort Service, end to end
A Service has up to three port numbers, and mixing them up is the most common Service mistake:
client ──→ nodeIP:nodePort (30000-32767, every node)
──→ serviceIP:port (8080, inside the cluster)
──→ Pod:targetPort ("web" → containerPort 80)
targetPort can be a number or the name of a container port. A name lets each Pod say which of its ports it means, so the Service keeps working if the container port number later changes.
1. Deploy a workload with a named port and expose it
Save this as nodeport-named.yaml:
apiVersion: apps/v1
kind: Deployment
metadata:
name: greeter
namespace: prepium-tutorial
spec:
replicas: 2
selector:
matchLabels:
app: greeter
template:
metadata:
labels:
app: greeter
spec:
containers:
- name: web
image: nginx:1.27-alpine
ports:
- name: web
containerPort: 80
protocol: TCP
---
apiVersion: v1
kind: Service
metadata:
name: greeter
namespace: prepium-tutorial
spec:
type: NodePort
selector:
app: greeter
ports:
- name: http
port: 8080
targetPort: web
protocol: TCP
kubectl create namespace prepium-tutorial
kubectl config set-context --current --namespace=prepium-tutorial
kubectl apply -f nodeport-named.yaml
kubectl rollout status deployment/greeter
kubectl get svc greeter
kubectl get endpointslices -l kubernetes.io/service-name=greeter
The second command makes prepium-tutorial the default namespace for your current context, so later commands can drop -n. Check it with kubectl config view --minify | grep namespace, and remember to set it back afterwards. The Service shows 8080:3xxxx/TCP: the cluster port, then the node port Kubernetes picked from the 30000-32767 range. The EndpointSlice lists both Pod IPs with port 80, which proves the name web was resolved to the container port.
2. Test both ways in
kubectl run probe --image=busybox:1.36 --restart=Never --command -- sleep 3600
kubectl wait --for=condition=Ready pod/probe
NODE_PORT=$(kubectl get svc greeter -o jsonpath='{.spec.ports[0].nodePort}')
NODE_IP=$(kubectl get nodes -o jsonpath='{.items[0].status.addresses[?(@.type=="InternalIP")].address}')
kubectl exec probe -- wget -T 3 -qO- http://greeter:8080 | head -4
kubectl exec probe -- wget -T 3 -qO- "http://$NODE_IP:$NODE_PORT" | head -4
Both return the nginx welcome page. The first goes through the Service name and cluster port; the second goes through a node's IP and the node port, which is the path an external client would take. A NodePort Service is also a ClusterIP Service, so both always work together.
3. Break the name and read the symptom
kubectl patch svc greeter --type=json -p '[{"op":"replace","path":"/spec/ports/0/targetPort","value":"wbe"}]'
kubectl get endpointslices -l kubernetes.io/service-name=greeter
kubectl exec probe -- wget -T 3 -qO- http://greeter:8080
The patch is accepted: the API server does not check that a named port exists in any Pod. The EndpointSlice still lists both Pod addresses, but its PORTS column is now <unset>, because no container port is called wbe. The request fails. When a Service has Pods but traffic does not arrive, look at the slice's ports, not only its addresses. Put web back and the request succeeds again within a few seconds.
The same check catches the other variant of this mistake: a Pod template with no ports section at all. Named targets need the name declared on the container; numeric targets do not, because containerPort is informational for numeric routing.
| Example check | Evidence |
|---|---|
| Container declares the named port | ports[].name and containerPort in the Pod template |
| Service selects the Pods and targets the name | EndpointSlice has addresses and a resolved port |
| Correct Service type | TYPE NodePort with an allocated node port |
| Traffic flows | Request through the Service returns the app |
Cleanup: kubectl config set-context --current --namespace=default, then kubectl delete namespace prepium-tutorial. Reference: Service. Next, try Service selector troubleshooting or Ingress path routing.
What this tests
Expose workloads with services and ingress, and restrict traffic with network policies. On the CKA 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 every live lab. Six selected CKA scenarios are included in Free Practice, with five shared sessions each week. 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.