Networking
Think of a Network Policy as a Firewall for Pods. By default, Kubernetes has a "Flat Network" philosophy: every pod can talk to every other pod. A Network Policy is how you break that philosophy to keep your data safe.
1. Why do we need them? (The "Blast Radius")¶
In a cluster without policies:
-
If a hacker compromises your Frontend Nginx pod, they can immediately "reach out" and talk to your Database pod.
-
They can scan your whole network, find your internal APIs, and steal data.
With Network Policies, you create Islands. Even if someone breaks into the Frontend, they can only go where you explicitly allowed them to go (e.g., only to the Backend API on port 8080).
2. The 3 Golden Rules of NetPol¶
Before looking at YAML, you have to understand these three behaviors:
-
Additive Only: There is no such thing as a "Deny" rule. You only write "Allow" rules.
-
The "Isolation" Trigger: As soon as a pod is selected by a Network Policy, it becomes Isolated. It stops talking to everyone except what is in your "Allow" list.
-
No Policy = Open Bar: If no policy selects a pod, it's wide open.
3. Real-World Examples¶
Example A: The "Default Deny" (The Deadbolt)¶
This is the first thing you should apply to a production namespace. It locks everything down so nothing can talk to anything. You start from zero and "allow" only what's necessary.
YAML
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: default-deny-all
spec:
podSelector: {} # {} means "Select ALL pods in this namespace"
policyTypes:
- Ingress
- Egress
# Since there are no 'ingress' or 'egress' rules defined below,
# everything is blocked by default.
Example B: The "Database Shield"¶
Imagine a database that should only be touched by the "Backend" app.
YAML
spec:
podSelector:
matchLabels:
app: mongodb # The pod we are protecting
ingress:
- from:
- podSelector:
matchLabels:
app: backend # The only pod allowed in
ports:
- protocol: TCP
port: 27017 # Only on this specific port
Example C: Cross-Namespace Access¶
Sometimes your "Monitoring" tool is in a different namespace. You have to use a namespaceSelector.
YAML
ingress:
- from:
- namespaceSelector:
matchLabels:
kubernetes.io/metadata.name: monitoring # Allow from the monitoring namespace
4. How to read the YAML (The "Dash" Secret)¶
This is where everyone trips up. Look at these two snippets:
Snippet 1 (AND logic):
YAML
from:
- podSelector: { matchLabels: { role: client } }
namespaceSelector: { matchLabels: { user: admin } }
Because there is only one dash, this means: "Allow if the pod has label role: client AND it is in a namespace labeled user: admin."
Snippet 2 (OR logic):
YAML
from:
- podSelector: { matchLabels: { role: client } }
- namespaceSelector: { matchLabels: { user: admin } }
Because there are two dashes, this means: "Allow if the pod has label role: client OR if the traffic comes from any pod in the user: admin namespace."
5. Summary Cheat Sheet¶
| Situation | podSelector |
namespaceSelector |
|---|---|---|
| Same Namespace | Use podSelector |
Leave out |
| Different Namespace | Use podSelector |
Use namespaceSelector |
| The whole internet | Leave out | Use ipBlock |
| All pods in namespace | {} |
Leave out |
Export to Sheets
One final warning: Remember that Network Policies are enforced by the CNI (the network plugin). If you are using a basic setup like Flannel, these YAMLs will successfully "Apply" but they will do absolutely nothing. You need something like Calico, Cilium, or Azure/AWS CNI to actually block the traffic.
Does the "AND vs OR" logic make the exercise you just passed feel a bit more "wrong" now?