Services and Ingress
What You Will Learn
- How traffic flows from users to Pods
- What Services and Ingress do
- The three-step chain: Pod, Service, Ingress
The Problem
Pods get random IP addresses. When a Pod restarts, it gets a new IP. If you have 3 copies of a Pod, you have 3 different IPs. You cannot give your users a random, changing IP address.
You need two things:
- A stable internal address that finds the right Pods (this is a Service)
- A public domain name that routes internet traffic in (this is an Ingress)
The Traffic Flow
Here is how a user's request reaches your app:
User's browser
↓
https://app.my-client.junovy.com
↓
┌─────────────────┐
│ Ingress │ Routes the domain to a Service
└────────┬────────┘
↓
┌─────────────────┐
│ Service │ Finds healthy Pods and load-balances
└────────┬────────┘
↓
┌────┐ ┌────┐ ┌────┐
│Pod1│ │Pod2│ │Pod3│ The actual containers running your app
└────┘ └────┘ └────┘
Services
A Service gives your Pods a stable address inside the cluster. It uses labels to find which Pods to route to.
apiVersion: v1
kind: Service
metadata:
name: my-app # the stable name other things use to find this
namespace: hst-my-client
spec:
type: ClusterIP # only accessible inside the cluster
selector:
app: my-app # finds Pods with this label (matches the Deployment)
ports:
- port: 80 # the port the Service listens on
targetPort: 8080 # the port the Pod listens on (containerPort from Deployment)
The key line is selector: app: my-app. This tells the Service: "send traffic to any Pod that has the label app: my-app." That label matches the one in the Deployment template.
Ingress
An Ingress exposes a Service to the internet with a domain name and TLS (HTTPS). At Junovy, we use Traefik as the ingress controller. Traefik has a built-in ACME resolver that automatically gets TLS certificates from Let's Encrypt. We also use external-dns to automatically create DNS records.
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: my-app
namespace: hst-my-client
annotations:
# Use Traefik's built-in ACME resolver for automatic TLS certificates
traefik.ingress.kubernetes.io/router.tls.certresolver: letsencrypt
traefik.ingress.kubernetes.io/router.entrypoints: websecure
# Automatically create a DNS record for this domain
external-dns.alpha.kubernetes.io/hostname: app.my-client.junovy.com
spec:
ingressClassName: traefik-external
tls:
- hosts:
- app.my-client.junovy.com # the domain
secretName: my-app-tls # Traefik manages certificates internally via ACME
rules:
- host: app.my-client.junovy.com # match this domain
http:
paths:
- path: / # match all paths
pathType: Prefix
backend:
service:
name: my-app # route to this Service
port:
number: 80 # on this port
How They Connect
| Object | Points To | Connected By |
|---|---|---|
| Ingress | Service | backend.service.name matches Service metadata.name |
| Service | Pods | selector matches Pod labels |
| Deployment | Creates Pods | template defines the Pod blueprint |
This chain is the same for every application at Junovy. Once you learn it, you will see the same pattern everywhere.
Key Takeaways
- A Service provides a stable internal address that finds Pods by label
- An Ingress exposes a Service to the internet with a domain name and TLS
- The chain is always: Ingress -> Service -> Pods
What Is Next
Next up: Namespaces where you will learn how Junovy isolates each client's environment.