Cyber Intelligence
Network Security · Network isolation

L11. Network Policies: Ingress, Egress and Default Deny

Video generating

Check back soon for the video lesson on Network Policies: Ingress, Egress and Default Deny

By default, every pod can talk to every other pod. Network Policies let you enforce microsegmentation at the namespace and pod level. Learn how to implement default-deny and whitelist-only rules.

The Default: No Isolation

In a default Kubernetes cluster, any pod can communicate with any other pod across all namespaces. There is no firewall, no segmentation, no access control on the network layer.

This means a compromised pod in a development namespace can reach databases in production, scan for other services, and attempt lateral movement.

How Network Policies Work

Network Policies are namespace-scoped resources that select pods using labels and define allowed ingress (incoming) and egress (outgoing) traffic. They are enforced by the CNI plugin (Calico, Cilium, Antrea) and not by Kubernetes itself. Critical requirement: Your CNI must support Network Policies. Some CNIs (like Flannel) do not enforce them. Use Calico, Cilium, or Antrea for production clusters.

Default Deny All

The first Network Policy in every namespace should be a default deny:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: default-deny-all
  namespace: production
spec:
  podSelector: {}
  policyTypes:
<ul class="list-disc pl-6 mb-4 space-y-2">
<li class="text-slate-300">Ingress</li>
<li class="text-slate-300">Egress</li>
</ul>

An empty podSelector selects all pods. With no ingress or egress rules defined, all traffic is blocked. You then whitelist specific flows.

Allowing Specific Traffic

After default deny, add policies for legitimate traffic:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: allow-web-to-api
  namespace: production
spec:
  podSelector:
    matchLabels:
      app: api
  policyTypes:
<ul class="list-disc pl-6 mb-4 space-y-2">
<li class="text-slate-300">Ingress</li>
</ul>
  ingress:
<ul class="list-disc pl-6 mb-4 space-y-2">
<li class="text-slate-300">from:</li>
<li class="text-slate-300">podSelector:</li>
</ul>
            matchLabels:
              app: web
      ports:
<ul class="list-disc pl-6 mb-4 space-y-2">
<li class="text-slate-300">protocol: TCP</li>
</ul>
          port: 8080

This allows pods labeled app: web to reach pods labeled app: api on port 8080. All other ingress to the API pods is blocked.

Cross-Namespace Rules

To allow traffic from another namespace, use namespaceSelector:

ingress:
<ul class="list-disc pl-6 mb-4 space-y-2">
<li class="text-slate-300">from:</li>
<li class="text-slate-300">namespaceSelector:</li>
</ul>
          matchLabels:
            environment: monitoring
        podSelector:
          matchLabels:
            app: prometheus

This allows Prometheus pods in namespaces labeled environment: monitoring to scrape metrics.

DNS Egress

Default deny blocks DNS too. Always allow egress to the cluster DNS service:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: allow-dns
  namespace: production
spec:
  podSelector: {}
  policyTypes:
<ul class="list-disc pl-6 mb-4 space-y-2">
<li class="text-slate-300">Egress</li>
</ul>
  egress:
<ul class="list-disc pl-6 mb-4 space-y-2">
<li class="text-slate-300">to:</li>
<li class="text-slate-300">namespaceSelector: {}</li>
</ul>
          podSelector:
            matchLabels:
              k8s-app: kube-dns
      ports:
<ul class="list-disc pl-6 mb-4 space-y-2">
<li class="text-slate-300">protocol: UDP</li>
</ul>
          port: 53
<ul class="list-disc pl-6 mb-4 space-y-2">
<li class="text-slate-300">protocol: TCP</li>
</ul>
          port: 53

Limitations

Network Policies have limitations:

  • They operate at L3/L4 (IP and port). For L7 policies (HTTP path, headers), use a service mesh
  • They do not apply to host-network pods
  • They cannot restrict traffic to external IPs by DNS name (only CIDR blocks)
  • Policy ordering is not guaranteed: all matching policies are merged
Exam Focus Points
  • By default, every pod can communicate with every other pod across all namespaces with no isolation
  • Network Policies are enforced by the CNI plugin (Calico, Cilium, Antrea), not by Kubernetes core: verify your CNI supports them
  • Always start with a default-deny-all policy (empty podSelector, no rules) then whitelist specific flows
  • Default deny blocks DNS too: always include an egress rule allowing UDP/TCP port 53 to kube-dns
  • Network Policies operate at L3/L4 only: for L7 policies (HTTP path, headers) use a service mesh
Knowledge Check

1. What is the default network behavior in Kubernetes when no Network Policies exist?

2. What must you remember to allow when implementing a default-deny egress policy?

3. Which CNI plugins support Kubernetes Network Policy enforcement?