The Networking Model
Every Pod gets its own IP address. Pods can communicate with each other directly — no NAT needed.
Pod A (10.244.1.5) ←→ Pod B (10.244.2.8)
↕
Service (10.96.0.100)
↕
Ingress (public IP)
Services
Services provide stable endpoints for groups of Pods:
ClusterIP (Internal)
apiVersion: v1
kind: Service
metadata:
name: my-api
spec:
selector:
app: my-api
ports:
- port: 80
targetPort: 3000
type: ClusterIP
Other Pods reach this at my-api.default.svc.cluster.local:80 or just my-api:80.
NodePort (External via Node)
spec:
type: NodePort
ports:
- port: 80
targetPort: 3000
nodePort: 30080
Accessible at <any-node-ip>:30080.
LoadBalancer (Cloud)
spec:
type: LoadBalancer
ports:
- port: 80
targetPort: 3000
Cloud provider creates an external load balancer automatically.
Ingress
Routes external HTTP(S) traffic to services based on hostname or path:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: my-ingress
annotations:
cert-manager.io/cluster-issuer: letsencrypt-prod
spec:
tls:
- hosts: [app.example.com]
secretName: app-tls
rules:
- host: app.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: my-api
port:
number: 80
- path: /admin
pathType: Prefix
backend:
service:
name: admin-panel
port:
number: 80
DNS in Kubernetes
| Query | Resolves To |
|---|---|
my-api |
Service in same namespace |
my-api.production |
Service in production namespace |
my-api.production.svc.cluster.local |
Fully qualified |
Network Policies
Restrict traffic between Pods:
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: api-only-from-web
spec:
podSelector:
matchLabels:
app: api
policyTypes:
- Ingress
ingress:
- from:
- podSelector:
matchLabels:
app: web
ports:
- port: 3000
This only allows traffic to api Pods from web Pods on port 3000.
Tip Start without NetworkPolicies to get things working, then add them to restrict traffic. A deny-all default with explicit allows is the most secure approach.