NetworkPolicies: Controlling Pod Traffic
NetworkPolicies define which traffic is allowed between Pods and Namespaces when supported by the cluster networking layer.
What this lesson covers
By default, many Kubernetes clusters allow broad Pod-to-Pod communication. NetworkPolicies let you define which traffic should be allowed between Pods and Namespaces, when supported by the cluster networking plugin.
- What NetworkPolicies do
- Why default allow is risky
- How labels select Pods
- How ingress and egress rules work
- How to deny traffic by default
- How to allow only specific traffic
The short version
NetworkPolicy: Selects Pods Defines allowed ingress and/or egress traffic Denies traffic that is not explicitly allowed for selected Pods
Important local lab note
A basic kind cluster may not enforce NetworkPolicies depending on the networking implementation. This lesson teaches the manifests and troubleshooting model. In a future security lab, you can use a policy-capable CNI such as Calico or Cilium to enforce and test behavior end to end.
Before you start
kubectl config current-context kubectl get nodes kubectl create namespace network-lab
Step 1: Create a web Deployment and Service
kubectl create deployment web --image=nginx:latest -n network-lab kubectl expose deployment web --port=80 --target-port=80 --type=ClusterIP -n network-lab kubectl get pods --show-labels -n network-lab kubectl get service web -n network-lab
Step 2: Create a client Pod
kubectl run client --image=busybox:latest -n network-lab --restart=Never --command -- sleep 3600 kubectl get pods -n network-lab
Step 3: Test access from client to web
kubectl exec -it client -n network-lab -- wget -qO- http://web
Without enforced NetworkPolicy restrictions, this should usually work.
Step 4: Create a default-deny ingress policy
Create a file named:
default-deny-ingress.yaml
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: default-deny-ingress
namespace: network-lab
spec:
podSelector: {}
policyTypes:
- Ingress
kubectl apply -f default-deny-ingress.yaml kubectl get networkpolicies -n network-lab
This selects all Pods in the Namespace and denies ingress unless another policy allows it.
Step 5: Allow client traffic to web
Label the client Pod:
kubectl label pod client role=client -n network-lab
Create a file named:
allow-client-to-web.yaml
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-client-to-web
namespace: network-lab
spec:
podSelector:
matchLabels:
app: web
policyTypes:
- Ingress
ingress:
- from:
- podSelector:
matchLabels:
role: client
ports:
- protocol: TCP
port: 80
kubectl apply -f allow-client-to-web.yaml kubectl describe networkpolicy allow-client-to-web -n network-lab
Step 6: Add a second Pod that should not be allowed
kubectl run random-client --image=busybox:latest -n network-lab --restart=Never --command -- sleep 3600 kubectl get pods --show-labels -n network-lab
The random-client Pod lacks the role=client label, so the policy does not allow it.
Step 7: Understand egress policies
Ingress controls traffic coming into selected Pods. Egress controls traffic leaving selected Pods.
Create a file named:
default-deny-egress.yaml
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: default-deny-egress
namespace: network-lab
spec:
podSelector: {}
policyTypes:
- Egress
kubectl apply -f default-deny-egress.yaml
In a policy-enforcing cluster, this denies outbound traffic unless explicit egress policies allow it.
Step 8: Allow DNS egress conceptually
Egress policies can easily break DNS if you deny everything. In real clusters, allow DNS to the cluster DNS service when workloads need service discovery.
DNS policy details vary by cluster, Namespace, labels, and DNS service implementation, so this training path saves a full enforced DNS lab for a later security module.
Common NetworkPolicy commands
kubectl get networkpolicies -n <namespace> kubectl describe networkpolicy <policy-name> -n <namespace> kubectl get pods --show-labels -n <namespace> kubectl get namespaces --show-labels kubectl exec -it <pod-name> -n <namespace> -- wget -qO- http://<service-name> kubectl get events -n <namespace> --sort-by=.metadata.creationTimestamp
Common mistakes
- Assuming policies are enforced without confirming CNI support.
- Using selectors that do not match the intended Pods.
- Denying egress and accidentally breaking DNS.
- Forgetting that policies are additive; allowed traffic can come from multiple policies.
- Not labeling Namespaces and Pods intentionally.
Step 9: Clean up
kubectl delete namespace network-lab
Check your understanding
- What does a NetworkPolicy select?
- What is ingress traffic?
- What is egress traffic?
- Why can a default-deny policy be useful?
- Why can default-deny egress break applications?
- What must the CNI support for NetworkPolicies to work?
- What command shows Pod labels?
- Are NetworkPolicies additive?
- What are three common NetworkPolicy troubleshooting commands?
- Why are labels important for network security?
Answer key
- Pods.
- Traffic coming into selected Pods.
- Traffic leaving selected Pods.
- It blocks traffic unless explicitly allowed.
- Pods may need DNS and external services.
- NetworkPolicy enforcement.
- kubectl get pods --show-labels.
- Yes.
- Examples: get networkpolicies, describe networkpolicy, get pods --show-labels, exec connectivity test.
- Policies use labels and selectors to decide which Pods rules apply to.