Pods come and go. Their IP addresses change every time a Pod is recreated. If Service A needed to track the current IP of every Service B Pod, the system would be fragile. Kubernetes solves this with Services — a stable abstraction on top of a dynamic set of Pods.
The Kubernetes Network Model
Kubernetes enforces a flat network model:
- Every Pod gets a unique cluster-wide IP address
- Pods can communicate with any other Pod directly (no NAT)
- Pods can reach Services by DNS name
This flat model is implemented by a CNI plugin (Calico, Flannel, Cilium, AWS VPC CNI, etc.).
Services
A Service is a stable endpoint (virtual IP + DNS name) that load-balances traffic to a set of Pods matching a label selector.
apiVersion: v1
kind: Service
metadata:
name: my-app
spec:
selector:
app: my-app # targets Pods with this label
ports:
- port: 80 # Service port
targetPort: 3000 # Pod's container port
type: ClusterIP
Service Types
| Type | Accessibility | Use Case |
|---|---|---|
| ClusterIP | Internal only | Default; service-to-service communication |
| NodePort | Exposes on every node at a static port (30000–32767) | Development; direct node access |
| LoadBalancer | Provisions a cloud load balancer | Production internet-facing services on managed K8s |
| ExternalName | CNAME alias to external DNS | Pointing to external services |
DNS-Based Service Discovery
CoreDNS (running in kube-system) resolves Service names to their ClusterIP:
- Within the same namespace:
http://my-apporhttp://my-app:80 - Across namespaces:
http://my-app.production.svc.cluster.local
This means application code never hard-codes IP addresses — it uses DNS names.
Ingress
A LoadBalancer Service per application is expensive (each gets its own cloud LB). Ingress provides a single entry point that routes HTTP/HTTPS traffic to multiple Services based on hostname and URL path rules.
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: my-ingress
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /
spec:
rules:
- host: app.example.com
http:
paths:
- path: /api
pathType: Prefix
backend:
service:
name: api-service
port:
number: 80
- path: /
pathType: Prefix
backend:
service:
name: frontend-service
port:
number: 80
tls:
- hosts:
- app.example.com
secretName: tls-secret
Ingress requires an Ingress Controller to be installed (e.g., NGINX Ingress Controller, AWS Load Balancer Controller, Traefik). The controller watches Ingress objects and configures the actual load balancer.
Network Policies
By default, all Pods can communicate with all other Pods. NetworkPolicy objects restrict traffic — defining which Pods can connect to which:
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-frontend-to-api
spec:
podSelector:
matchLabels:
app: api
ingress:
- from:
- podSelector:
matchLabels:
app: frontend
ports:
- port: 3000
NetworkPolicies require a CNI plugin that supports them (Calico, Cilium, Weave — not Flannel).
Next: storage in Kubernetes — Volumes, PersistentVolumes, and how stateful applications manage their data.