Stage 5 · Platform
Networking, Storage & Service Mesh
Services & Ingress
ClusterIP, NodePort, LoadBalancer, ExternalName, and Ingress controllers.
Service Types
Services provide stable networking for pods. Pods are ephemeral — they get IPs that change on restart. Services give a fixed DNS name and IP that load-balances traffic to healthy pods. There are four service types, each for a different access pattern.
| Type | Scope | Use Case |
|---|---|---|
| ClusterIP | Cluster-internal | Default — internal microservices |
| NodePort | Node IP + port | Direct node access, dev/testing |
| LoadBalancer | Cloud LB + external IP | Production external access |
| ExternalName | DNS CNAME | External service alias |
ClusterIP
ClusterIP is the default service type. It creates a virtual IP (VIP) inside the cluster that load-balances to pods matching the selector. The VIP is managed by kube-proxy (iptables/IPVS) and is reachable only from within the cluster.
apiVersion: v1
kind: Service
metadata:
name: api-service
namespace: production
spec:
type: ClusterIP
selector:
app: api
version: v2
ports:
- name: http
port: 80
targetPort: 8080
protocol: TCP
- name: grpc
port: 9090
targetPort: 9090
protocol: TCPOther pods reach this service at api-service.production.svc.cluster.local:80. The selector routes to pods with labels app=api and version=v2. Multiple ports are supported — name them for clarity.
NodePort
NodePort exposes the service on a static port (30000-32767) on every node. Traffic to any node IP on that port is forwarded to the service. This is useful for development, testing, or when you need direct node access.
apiVersion: v1
kind: Service
metadata:
name: dashboard
spec:
type: NodePort
selector:
app: dashboard
ports:
- port: 80
targetPort: 9090
nodePort: 30080 # Optional — auto-assigned if omitted
protocol: TCPAccess via any node IP: http://node-ip:30080. NodePort is not recommended for production because it exposes all nodes directly. Use LoadBalancer or Ingress instead.
NodePort opens a port on every node, including control plane nodes. This bypasses any ingress firewall rules. In production, use LoadBalancer with a WAF or an Ingress controller instead.
LoadBalancer
LoadBalancer provisions an external load balancer (cloud provider specific) and assigns an external IP. Traffic to the external IP is forwarded to the service. On bare-metal, MetalLB or similar controllers provide this functionality.
apiVersion: v1
kind: Service
metadata:
name: api-external
annotations:
# Azure-specific annotations
service.beta.kubernetes.io/azure-load-balancer-resource-group: my-rg
service.beta.kubernetes.io/azure-load-balancer-internal: "false"
# AWS-specific annotations
# service.beta.kubernetes.io/aws-load-balancer-type: nlb
# service.beta.kubernetes.io/aws-load-balancer-scheme: internet-facing
spec:
type: LoadBalancer
selector:
app: api
ports:
- port: 443
targetPort: 8443
protocol: TCP
externalTrafficPolicy: Local # Preserve client IPexternalTrafficPolicy: Local preserves the client source IP but may cause uneven load distribution. externalTrafficPolicy: Cluster (default) masks the client IP but distributes more evenly.
Ingress Controllers
Ingress provides HTTP/HTTPS routing based on hostnames and paths. An Ingress controller (NGINX, Traefik, Envoy) watches Ingress resources and configures routing rules. Ingress is the standard way to expose HTTP services externally.
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: api-ingress
annotations:
nginx.ingress.kubernetes.io/ssl-redirect: "true"
nginx.ingress.kubernetes.io/proxy-body-size: "10m"
nginx.ingress.kubernetes.io/rate-limit: "100"
spec:
ingressClassName: nginx
tls:
- hosts:
- api.example.com
secretName: api-tls-cert
rules:
- host: api.example.com
http:
paths:
- path: /v1
pathType: Prefix
backend:
service:
name: api-v1
port:
number: 80
- path: /v2
pathType: Prefix
backend:
service:
name: api-v2
port:
number: 80The TLS section references a Secret containing the TLS certificate. The rules section routes /v1 to api-v1 and /v2 to api-v2. ingressClassName selects which controller handles this Ingress.
Session Affinity
Session affinity ensures requests from the same client go to the same pod. This is useful for applications that maintain session state. Kubernetes supports ClientIP affinity (based on source IP) and None (no affinity, default round-robin).
apiVersion: v1
kind: Service
metadata:
name: session-app
spec:
type: ClusterIP
sessionAffinity: ClientIP
sessionAffinityConfig:
clientIP:
timeoutSeconds: 10800 # 3 hours
selector:
app: session-app
ports:
- port: 80
targetPort: 8080ClientIP affinity uses the source IP to determine which pod receives the request. timeoutSeconds controls how long affinity is maintained. Note: this is IP-based, not cookie-based — multiple clients behind a NAT share one IP.
Services are discoverable via DNS: service-name.namespace.svc.cluster.local. Pods use this DNS automatically. You can also use headless services (clusterIP: None) to get individual pod IPs instead of a VIP.
Mark this lesson complete to store local progress and unlock a cleaner resume path the next time you visit.