Expose an Application Externally with an Ingress
The application must be reachable externally using the URL http://external.prepium.local/. Any request whose path starts with / must be routed to the Service web-app.
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 →
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
Context
An existing web application must be exposed externally.
The Deployment web-app and its Service web-app (port 80) already exist in namespace prepium.
Task
The application must be reachable externally using the URL http://external.prepium.local/. Any request whose path starts with / must be routed to the Service web-app.
Create an Ingress named web-app-ingress in namespace prepium that:
- Routes host
external.prepium.local - Path
/withpathType: Prefix - Backend Service
web-appon port80 - Uses API version
networking.k8s.io/v1
Original Prepium guide · Written for Kubernetes v1.35 and checked against the official documentation on 6 October 2026. Use a disposable practice cluster. An Ingress object does nothing on its own: the cluster needs a running Ingress controller.
Route HTTP by host and path with an Ingress, then prove it with curl
An Ingress is a set of HTTP routing rules. Each rule may name a host, and each path in it points at a Service name and port. A controller (the proxy that actually receives traffic) watches Ingress objects of its class and turns them into proxy configuration. On the exam you will usually write the object quickly, so the real skill is knowing which fields decide matching and how to test the result honestly.
client ──Host: orders.example.test──→ Ingress controller ──→ Service orders:80 ──→ Pods
client ──Host: menu.example.test────→ Ingress controller ──→ Service menu:80 ──→ Pods
client ──any other host─────────────→ Ingress controller ──→ defaultBackend (menu)
1. Find the controller and its class
kubectl get ingressclass
kubectl get pods -A | grep -i ingress
ingressClassName must name one of the listed IngressClasses, otherwise no controller claims the Ingress. If the field is omitted, the class marked with the annotation ingressclass.kubernetes.io/is-default-class: "true" is filled in for you; when no class is marked default, it is safer to set the field explicitly.
2. Create two backends
kubectl create namespace prepium-tutorial
kubectl -n prepium-tutorial create deployment menu --image=nginx:1.27-alpine
kubectl -n prepium-tutorial create deployment orders --image=httpd:2.4-alpine
kubectl -n prepium-tutorial expose deployment menu --port=80
kubectl -n prepium-tutorial expose deployment orders --port=80
The two images return different default pages, which makes routing visible in a single curl.
3. Write the rules
Save this as ckad-ingress-hosts.yaml, replace the class name, and apply it.
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: food-court
namespace: prepium-tutorial
spec:
ingressClassName: CHANGE-ME # a NAME from: kubectl get ingressclass
defaultBackend:
service:
name: menu
port:
number: 80
rules:
- host: menu.example.test
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: menu
port:
number: 80
- host: orders.example.test
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: orders
port:
number: 80
kubectl apply -f ckad-ingress-hosts.yaml
kubectl -n prepium-tutorial describe ingress food-court
Both the host and the path have to match before a rule applies. pathType is mandatory and changes meaning: Prefix matches whole path elements, so /shop covers /shop/cart but not /shopping; Exact matches one literal, case-sensitive path; ImplementationSpecific leaves it to the controller. When several paths match, the longest wins. The defaultBackend catches requests that match no rule. describe lists each host, path and backend, and shows a Service's endpoints when it has ready Pods.
For speed, kubectl create ingress NAME --class=... --rule="host/path*=service:port" builds the same structure; a trailing * on the path means Prefix, and --default-backend=service:port sets the catch-all.
4. Test through the controller, choosing the Host header
Find an address that reaches the controller: the ADDRESS column of kubectl get ingress if your environment fills it, or a node IP plus the NodePort of the controller's Service in most practice clusters. Then send requests with explicit Host headers so you do not need DNS:
CTRL=203.0.113.10:30080 # your controller address
curl -s -H "Host: menu.example.test" "http://$CTRL/" | head -n 4
curl -s -H "Host: orders.example.test" "http://$CTRL/"
curl -s -H "Host: nothing.example.test" "http://$CTRL/" | head -n 4
Expect the nginx welcome page, then Apache's short default page, then nginx again from the default backend. Curl sends your -H value instead of its own Host header, which is exactly what the controller matches rules against.
Common mistakes
- Testing the Service ClusterIP instead of the controller. That bypasses the Ingress entirely and proves nothing about the rules.
- A class name that no controller owns: the API server accepts the object, but nothing acts on it, so requests never follow your rules.
- Pointing the backend at the container port instead of the Service port. The Ingress talks to the Service, so
port.numberis the Service'sport. - Expecting
Prefix/shopto match/shopping. Matching is per path element, not per character.
| Example check | Evidence |
|---|---|
| Claimed by a controller | spec.ingressClassName matches an existing IngressClass |
| Rule shape | Host, path, pathType and backend.service.name/port in describe |
| Backend is live | describe shows Pod endpoints next to each backend |
| Routing works | curl with each Host header returns the expected page |
Cleanup: kubectl delete namespace prepium-tutorial. References: Ingress, Ingress Controllers, kubectl create ingress. Next, try Ingress troubleshooting or the Gateway API.
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.