Lesson: Services & Ingress
What you'll learn
- Why Pod IPs are not enough, and how labels/selectors connect things.
- The Service types: ClusterIP, NodePort, and LoadBalancer.
- What an Ingress does and how it routes by hostname/path.
- How the lab exposes apps through its Kong gateway.
Skill gained: you can give your app a stable address inside the cluster and expose it to the outside.
The lesson
Your Deployment creates Pods, and each Pod gets an IP. But Pod IPs are useless to rely on: Pods die and get replaced with new IPs all the time. You need a stable address that always points at the current, healthy Pods. That is a Service. And to let traffic in from outside the cluster on a real hostname, you use an Ingress.
1. Labels and selectors — the glue
Kubernetes connects objects using labels (key/value tags on objects) and selectors (a filter that matches those labels). A Service does not list Pod IPs; it says "send traffic to any Pod with label app: web," and the set updates automatically as Pods come and go.
Service (selector app=web)
|
| matches by label, not by IP
v
Pod(app=web) Pod(app=web) Pod(app=web)
So your Pods carry labels: { app: web }, and your Service carries selector: { app: web }. Get those two to match and traffic flows.
2. ClusterIP — the default, internal address
A ClusterIP Service gives your app a single virtual IP and DNS name reachable only inside the cluster. This is how one app calls another (frontend -> backend).
apiVersion: v1
kind: Service
metadata:
name: web
spec:
type: ClusterIP # the default; you can omit it
selector:
app: web
ports:
- port: 80 # the Service's port
targetPort: 80 # the container's port
Now any Pod in the cluster can reach it at http://web (same namespace) or http://web.<namespace>.svc.cluster.local. Kubernetes runs an internal DNS that turns the Service name into its ClusterIP. This is the type you will use most.
kubectl apply -f web-svc.yaml
kubectl get svc web # see its CLUSTER-IP
kubectl get endpoints web # the actual Pod IPs it currently targets
3. NodePort and LoadBalancer — reaching from outside
ClusterIP is internal only. Two types open the app up:
-
NodePort opens the same high port (30000–32767) on every node. Traffic to
nodeIP:nodePortreaches the Service. So you could hit10.100.100.8:31000. Simple, but ugly ports and you must know node IPs. -
LoadBalancer asks the infrastructure for an external load balancer with its own IP. On cloud providers this is automatic; in a bare lab there may be nothing to provide one, so it can stay
<pending>.
apiVersion: v1
kind: Service
metadata:
name: web
spec:
type: NodePort
selector:
app: web
ports:
- port: 80
targetPort: 80
nodePort: 31000 # optional; otherwise auto-assigned
ClusterIP NodePort LoadBalancer
reach from inside only inside + nodeIP:port external IP
typical use app-to-app quick external test cloud public service
NodePort is fine for a quick test, but for real exposure you do not want callers juggling node IPs and odd ports. That is what Ingress is for.
4. Ingress — HTTP routing by hostname and path
An Ingress is a set of HTTP routing rules: "requests for app.example.com go to Service web; requests for api.example.com go to Service api." It lets many apps share one entry point and one external address, routed by hostname or URL path.
An Ingress object is just rules — it does nothing without an ingress controller, the actual proxy that reads those rules and routes traffic. In the lab, that controller is the Kong gateway, whose proxy listens at 10.100.100.100. So you write Ingress rules and Kong does the routing.
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: web
spec:
ingressClassName: kong # tell the lab's Kong to handle this
rules:
- host: web.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: web
port:
number: 80
Internet / lab network
|
v
Kong gateway (10.100.100.100) <- reads Ingress rules
| web.example.com -> Service web
| api.example.com -> Service api
v
ClusterIP Services -> Pods
kubectl apply -f web-ingress.yaml
kubectl get ingress
kubectl describe ingress web # check the rules and that Kong picked it up
In this lab, TLS (HTTPS) is terminated upstream at the edge, so your Ingress and Services serve plain HTTP — you do not configure certificates on the Service or Ingress here.
5. Putting it together
The normal exposure chain for a web app in the lab is:
Deployment (Pods, labels app=web)
^ selector app=web
Service (ClusterIP web) <- stable internal address
^ backend
Ingress (host web.example.com) <- HTTP routing rules
^ handled by
Kong gateway 10.100.100.100 <- the actual proxy / entry point
You will build exactly this in Assignment 1.
6. Quick debugging
kubectl get svc,endpoints # does the Service have endpoints? empty = selector mismatch
kubectl run tmp --image=busybox:1.36 -it --rm -- sh # a throwaway Pod to test from inside
# inside it: wget -qO- http://web (hits your ClusterIP by DNS name)
kubectl describe ingress web # are the rules right and the class set to kong?
The most common mistake is a label/selector mismatch: the Service's selector does not match the Pods' labels, so kubectl get endpoints shows none and nothing connects. Always check endpoints first.
Dig deeper
Search terms
kubernetes clusterip nodeport loadbalancer differencekubernetes service selector labelskubernetes ingress explained for beginnerskubernetes service no endpoints debugkong ingress controller kubernetes
Check yourself
- Why can't you just hardcode a Pod's IP in another app?
- What connects a Service to the right set of Pods?
- Which Service type is internal-only, and what is it used for?
- What does an Ingress do that a Service does not, and what actually performs the routing in this lab?
- If
kubectl get endpointsshows none for your Service, what is the likely cause?
No comments to display
No comments to display