πŸ“šBook Signing at KubeCon EU 2026Meet us at Booking.com HQ (Mon 18:30-21:00) & vCluster booth #521 (Tue 24 Mar, 12:30-1:30pm) β€” free book giveaway!RSVP Booking.com Event
Networking intermediate ⏱ 12 minutes K8s 1.28+

Kubernetes Egress Network Policies

Control outbound traffic from pods with egress NetworkPolicies. Allow DNS, block internet access, and restrict pod-to-pod communication by namespace.

By Luca Berton β€’ β€’ πŸ“– 5 min read

πŸ’‘ Quick Answer: Egress NetworkPolicies restrict outbound traffic from pods. Always allow DNS (port 53 to kube-dns) in egress rules, then whitelist specific destinations by CIDR, namespace, or pod labels.

The Problem

By default, pods can reach any IP β€” the internet, other namespaces, metadata services (169.254.169.254). In a zero-trust model, you need to explicitly allow only required outbound connections.

The Solution

Default Deny All Egress

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: default-deny-egress
  namespace: production
spec:
  podSelector: {}
  policyTypes:
    - Egress

Allow DNS + Specific Services

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: app-egress
  namespace: production
spec:
  podSelector:
    matchLabels:
      app: web-api
  policyTypes:
    - Egress
  egress:
    # Allow DNS
    - to:
        - namespaceSelector: {}
          podSelector:
            matchLabels:
              k8s-app: kube-dns
      ports:
        - protocol: UDP
          port: 53
        - protocol: TCP
          port: 53
    # Allow database in same namespace
    - to:
        - podSelector:
            matchLabels:
              app: postgres
      ports:
        - protocol: TCP
          port: 5432
    # Allow external API
    - to:
        - ipBlock:
            cidr: 203.0.113.0/24
      ports:
        - protocol: TCP
          port: 443

Block Cloud Metadata Service

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: block-metadata
  namespace: production
spec:
  podSelector: {}
  policyTypes:
    - Egress
  egress:
    - to:
        - ipBlock:
            cidr: 0.0.0.0/0
            except:
              - 169.254.169.254/32

Allow Traffic to Another Namespace

egress:
  - to:
      - namespaceSelector:
          matchLabels:
            name: monitoring
        podSelector:
          matchLabels:
            app: prometheus
    ports:
      - protocol: TCP
        port: 9090
graph LR
    P[Pod: web-api] -->|Port 53| DNS[kube-dns βœ“]
    P -->|Port 5432| DB[postgres βœ“]
    P -->|Port 443| API[External API βœ“]
    P -.->|Port 80| Internet[Internet βœ—]
    P -.->|Port 169.254| Meta[Metadata βœ—]

Common Issues

All DNS breaks after applying egress deny Always include DNS allow rule:

- to:
    - namespaceSelector: {}
      podSelector:
        matchLabels:
          k8s-app: kube-dns
  ports:
    - protocol: UDP
      port: 53

Policy not enforced NetworkPolicies require a CNI that supports them (Calico, Cilium, Weave). Flannel does NOT enforce policies:

kubectl get pods -n kube-system | grep -E "calico|cilium"

Egress to headless service fails Use pod/namespace selectors instead of ipBlock for in-cluster services β€” pod IPs change.

Best Practices

  • Always start with default-deny-egress per namespace
  • Allow DNS first in every egress policy
  • Use namespace selectors for in-cluster communication
  • Use CIDR blocks for external services with stable IPs
  • Block metadata endpoint (169.254.169.254) in multi-tenant clusters
  • Test policies with kubectl exec + curl/nc before enforcing
  • Use Cilium’s CiliumNetworkPolicy for L7 (HTTP path/method) egress rules

Key Takeaways

  • Egress policies control outbound traffic from selected pods
  • An empty egress: [] in policyTypes blocks all outbound traffic
  • DNS (UDP/TCP 53) must be explicitly allowed when egress is restricted
  • ipBlock works for external IPs; pod/namespace selectors for in-cluster
  • Multiple egress rules are ORed β€” matching any rule allows the traffic
  • CNI must support NetworkPolicy (Calico, Cilium) β€” Flannel doesn’t enforce
#network-policy #egress #security #zero-trust
Luca Berton
Written by Luca Berton

Principal Solutions Architect specializing in Kubernetes, AI/GPU infrastructure, and cloud-native platforms. Author of Kubernetes Recipes and creator of CopyPasteLearn courses.

Kubernetes Recipes book cover

Want More Kubernetes Recipes?

This recipe is from Kubernetes Recipes, our 750-page practical guide with hundreds of production-ready patterns.

Luca Berton Ansible Pilot Ansible by Example Open Empower K8s Recipes Terraform Pilot CopyPasteLearn ProteinLens