Kubernetes Security

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
Field note: NetworkPolicies are only enforced when the cluster network plugin supports them. In production, confirm your CNI behavior before assuming policy is active.

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
Bottom line: NetworkPolicies define allowed network paths for selected Pods. They are powerful, but only when enforced by the cluster networking layer and backed by clean labeling.

Check your understanding

  1. What does a NetworkPolicy select?
  2. What is ingress traffic?
  3. What is egress traffic?
  4. Why can a default-deny policy be useful?
  5. Why can default-deny egress break applications?
  6. What must the CNI support for NetworkPolicies to work?
  7. What command shows Pod labels?
  8. Are NetworkPolicies additive?
  9. What are three common NetworkPolicy troubleshooting commands?
  10. Why are labels important for network security?
Answer key
  1. Pods.
  2. Traffic coming into selected Pods.
  3. Traffic leaving selected Pods.
  4. It blocks traffic unless explicitly allowed.
  5. Pods may need DNS and external services.
  6. NetworkPolicy enforcement.
  7. kubectl get pods --show-labels.
  8. Yes.
  9. Examples: get networkpolicies, describe networkpolicy, get pods --show-labels, exec connectivity test.
  10. Policies use labels and selectors to decide which Pods rules apply to.
← Previous: ServiceAccounts and RBAC Series index Next: Helm Basics →