CKA — NetworkPolicies
CKA Exam Domain
Services & Networking — 20%
NetworkPolicies are a high-frequency CKA exam topic. You’ll almost certainly get at least one question asking you to create a policy that allows or denies specific traffic. Practice writing these from scratch — the YAML structure is tricky to memorize.
What Are NetworkPolicies?
A NetworkPolicy is a Kubernetes resource that controls network traffic to and from Pods. Think of it as a firewall for your Pods.
By default, Kubernetes allows all traffic between all Pods in the cluster — any Pod can talk to any other Pod, in any namespace. NetworkPolicies let you restrict this.
Key concepts:
- Ingress rules control incoming traffic to selected Pods
- Egress rules control outgoing traffic from selected Pods
- Policies are namespace-scoped — they apply to Pods in the same namespace
- Policies are additive — if multiple policies select the same Pod, the union of all rules applies
- Once a Pod is selected by any NetworkPolicy, all traffic not explicitly allowed is denied
CNI Requirement
Important: NetworkPolicies only work if your cluster’s CNI (Container Network Interface) plugin supports them.
| CNI Plugin | NetworkPolicy Support |
|---|---|
| Calico | Yes |
| Cilium | Yes |
| Weave Net | Yes |
| Flannel | No |
| Canal (Flannel + Calico) | Yes |
If your cluster uses Flannel, NetworkPolicy resources will be created but won’t be enforced. The CKA exam environments typically use a CNI that supports NetworkPolicies.
Ingress Rules
Ingress rules control incoming traffic to the selected Pods. Here’s a complete example:
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-api-to-web
namespace: default
spec:
podSelector:
matchLabels:
app: web # This policy applies to Pods with app=web
policyTypes:
- Ingress
ingress:
- from:
- podSelector:
matchLabels:
app: api # Allow traffic FROM Pods with app=api
ports:
- protocol: TCP
port: 80 # Only on port 80
This policy says: Pods labeled app: web can receive TCP traffic on port 80 only from Pods labeled app: api.
All other incoming traffic to app: web Pods is denied.
Breaking Down the Spec
| Field | Purpose |
|---|---|
spec.podSelector |
Which Pods this policy applies to (the “target”) |
spec.policyTypes |
Which direction(s) the policy controls: Ingress, Egress, or both |
spec.ingress[].from |
List of allowed sources |
spec.ingress[].ports |
List of allowed ports |
Egress Rules
Egress rules control outgoing traffic from the selected Pods:
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: api-egress
namespace: default
spec:
podSelector:
matchLabels:
app: api
policyTypes:
- Egress
egress:
- to:
- podSelector:
matchLabels:
app: database
ports:
- protocol: TCP
port: 5432
- to: # Second egress rule: allow DNS
ports:
- protocol: UDP
port: 53
- protocol: TCP
port: 53
This policy says: Pods labeled app: api can send traffic to app: database Pods on port 5432, and to any destination on port 53 (DNS).
Critical: Always allow DNS (port 53) in egress policies, or your Pods won’t be able to resolve Service names.
Selectors
NetworkPolicies use three types of selectors to specify traffic sources and destinations:
podSelector
Select Pods by labels within the same namespace:
from:
- podSelector:
matchLabels:
app: frontend
namespaceSelector
Select all Pods in namespaces matching the label:
from:
- namespaceSelector:
matchLabels:
env: production
This allows traffic from all Pods in namespaces labeled env: production.
ipBlock
Select traffic by IP CIDR range:
from:
- ipBlock:
cidr: 172.17.0.0/16
except:
- 172.17.1.0/24 # Exclude this subnet
Combining Selectors
Watch out — the YAML structure matters:
# AND logic — Pod must match BOTH selectors
from:
- podSelector:
matchLabels:
app: api
namespaceSelector:
matchLabels:
env: prod
# OR logic — Pod can match EITHER selector
from:
- podSelector:
matchLabels:
app: api
- namespaceSelector:
matchLabels:
env: prod
The difference is subtle but critical:
| Structure | Logic | Meaning |
|---|---|---|
| Single list item with both selectors | AND | Pods labeled app: api AND in namespace labeled env: prod |
| Two separate list items | OR | Pods labeled app: api OR any Pod in namespace labeled env: prod |
Default Deny All
The most common exam pattern. Create a policy that blocks all traffic and then selectively allow what you need.
Default Deny All Ingress
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: default-deny-ingress
namespace: default
spec:
podSelector: {} # Selects ALL Pods in the namespace
policyTypes:
- Ingress
# No ingress rules = deny all incoming
Default Deny All Egress
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: default-deny-egress
namespace: default
spec:
podSelector: {}
policyTypes:
- Egress
# No egress rules = deny all outgoing
Default Deny All (Both Directions)
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: default-deny-all
namespace: default
spec:
podSelector: {}
policyTypes:
- Ingress
- Egress
Exam tip: Start with a default deny policy, then create additional policies to whitelist specific traffic. This is the standard security pattern.
Allow Specific Traffic
After setting up default deny, create targeted policies to allow only what’s needed:
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: web-policy
namespace: default
spec:
podSelector:
matchLabels:
app: web
policyTypes:
- Ingress
- Egress
ingress:
- from:
- podSelector:
matchLabels:
app: frontend
ports:
- protocol: TCP
port: 80
- from:
- namespaceSelector:
matchLabels:
name: monitoring
ports:
- protocol: TCP
port: 9090
egress:
- to:
- podSelector:
matchLabels:
app: database
ports:
- protocol: TCP
port: 5432
- to: # Allow DNS resolution
ports:
- protocol: UDP
port: 53
- protocol: TCP
port: 53
This policy:
- Allows
app: frontendPods to accessapp: webon port 80 - Allows monitoring namespace Pods to access
app: webon port 9090 - Allows
app: webto connect toapp: databaseon port 5432 - Allows
app: webto make DNS queries
NetworkPolicy Gotchas
These are the mistakes that cost you points on the exam:
1. Policies Are Namespace-Scoped
A NetworkPolicy in namespace default only affects Pods in default. To protect Pods in production, create a separate policy there.
2. Policies Are Additive
If two policies select the same Pod, the allowed traffic is the union of both policies. There’s no way for one policy to override or negate another.
3. Empty podSelector Means All Pods
spec:
podSelector: {} # Matches ALL Pods in the namespace
4. DNS Must Be Explicitly Allowed
When you create an egress policy, DNS traffic is also blocked. If your Pods need to resolve Service names, you must allow port 53:
egress:
- to:
ports:
- protocol: UDP
port: 53
- protocol: TCP
port: 53
5. No from/to = Allow All
An ingress rule with no from field allows traffic from everywhere:
ingress:
- ports:
- protocol: TCP
port: 80
# No "from" = allow from ANY source on port 80
6. policyTypes Matters
If you specify policyTypes: [Ingress] but don’t include any ingress rules, all ingress is denied. The same applies for Egress. If you omit policyTypes, it’s inferred:
- If
ingressrules are present → Ingress type is implied - If
egressrules are present → Egress type is implied
Best practice: Always explicitly set policyTypes to avoid ambiguity.
kubectl Commands
# List all NetworkPolicies in the current namespace
kubectl get networkpolicies
# List NetworkPolicies across all namespaces
kubectl get networkpolicies -A
# Describe a specific policy
kubectl describe networkpolicy deny-all
# Create from YAML
kubectl apply -f network-policy.yaml
# Delete a policy
kubectl delete networkpolicy deny-all
Practice Questions
Q1. Create a default deny all ingress NetworkPolicy for the production namespace.
Show Answer
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: default-deny-ingress
namespace: production
spec:
podSelector: {}
policyTypes:
- Ingress
This selects all Pods in the production namespace and blocks all incoming traffic (no ingress rules defined).
Q2. Create a NetworkPolicy that allows Pods labeled role: api to receive traffic from Pods labeled role: frontend on port 8080.
Show Answer
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-frontend-to-api
namespace: default
spec:
podSelector:
matchLabels:
role: api
policyTypes:
- Ingress
ingress:
- from:
- podSelector:
matchLabels:
role: frontend
ports:
- protocol: TCP
port: 8080
Q3. What is the difference between AND and OR logic in NetworkPolicy selectors?
Show Answer
AND logic — both selectors in a single from/to entry:
from:
- podSelector:
matchLabels:
app: api
namespaceSelector:
matchLabels:
env: prod
Means: Pods that are labeled app: api AND are in a namespace labeled env: prod.
OR logic — separate entries in the from/to list:
from:
- podSelector:
matchLabels:
app: api
- namespaceSelector:
matchLabels:
env: prod
Means: Pods labeled app: api OR any Pod in a namespace labeled env: prod.
Q4. Why must you allow DNS (port 53) in egress NetworkPolicies?
Show Answer
When you create an egress NetworkPolicy, all outgoing traffic not explicitly allowed is denied — including DNS queries. Pods need DNS to resolve Service names to ClusterIPs. Without allowing port 53 (both UDP and TCP), Pods won’t be able to reach Services by name even if the actual service port is allowed.
egress:
- to:
ports:
- protocol: UDP
port: 53
- protocol: TCP
port: 53
Q5. Which CNI plugins support NetworkPolicies? Which one does NOT?
Show Answer
Support NetworkPolicies: Calico, Cilium, Weave Net, Canal (Flannel + Calico)
Does NOT support NetworkPolicies: Flannel
With Flannel, you can create NetworkPolicy resources, but they won’t be enforced — all traffic will still flow freely.