Skip to main content
πŸŽ“ Claude Code Masterclass Learn AI-assisted development on Udemy β€” plus the companion book on Leanpub & Amazon. Start Learning
Kubernetes Network Policies: Zero Trust Microsegmentation Guide
Platform Engineering

Kubernetes Network Policies: Zero Trust Guide

Implement zero-trust networking in Kubernetes β€” default-deny policies, namespace isolation, egress control, and DNS-based rules.

LB
Luca Berton
Β· 1 min read

Default: Everything Talks to Everything

By default, every pod in Kubernetes can reach every other pod across all namespaces. That’s terrifying in production.

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚  Default Kubernetes Networking               β”‚
β”‚                                              β”‚
β”‚  frontend ←→ backend ←→ database ←→ redis  β”‚
β”‚      ↕           ↕          ↕         ↕     β”‚
β”‚  monitoring ←→ logging ←→ anything ←→ !!!  β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Step 1: Default Deny All

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: default-deny-all
  namespace: production
spec:
  podSelector: {}  # Applies to ALL pods in namespace
  policyTypes:
    - Ingress
    - Egress

Now nothing can talk to anything in this namespace. Start opening only what’s needed.

Step 2: Allow Specific Traffic

# Allow frontend β†’ backend on port 8080
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: backend-allow-frontend
  namespace: production
spec:
  podSelector:
    matchLabels:
      app: backend
  policyTypes:
    - Ingress
  ingress:
    - from:
        - podSelector:
            matchLabels:
              app: frontend
      ports:
        - port: 8080
          protocol: TCP
---
# Allow backend β†’ database on port 5432
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: database-allow-backend
  namespace: production
spec:
  podSelector:
    matchLabels:
      app: database
  policyTypes:
    - Ingress
  ingress:
    - from:
        - podSelector:
            matchLabels:
              app: backend
      ports:
        - port: 5432

Step 3: Egress Control

# Allow DNS (required for service discovery)
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: allow-dns
  namespace: production
spec:
  podSelector: {}
  policyTypes:
    - Egress
  egress:
    - to:
        - namespaceSelector:
            matchLabels:
              kubernetes.io/metadata.name: kube-system
          podSelector:
            matchLabels:
              k8s-app: kube-dns
      ports:
        - port: 53
          protocol: UDP
        - port: 53
          protocol: TCP
---
# Allow egress to external APIs (specific CIDRs)
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: allow-external-apis
spec:
  podSelector:
    matchLabels:
      app: backend
  policyTypes:
    - Egress
  egress:
    - to:
        - ipBlock:
            cidr: 0.0.0.0/0
            except:
              - 10.0.0.0/8      # Block internal
              - 172.16.0.0/12   # Block internal
              - 192.168.0.0/16  # Block internal
      ports:
        - port: 443

Cross-Namespace Policies

# Allow monitoring namespace to scrape all pods
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: allow-prometheus
  namespace: production
spec:
  podSelector: {}
  ingress:
    - from:
        - namespaceSelector:
            matchLabels:
              kubernetes.io/metadata.name: monitoring
          podSelector:
            matchLabels:
              app: prometheus
      ports:
        - port: 9090
        - port: 8080

CNI Requirements

Not all CNIs enforce NetworkPolicies:

CNINetworkPolicyEgressFQDN-based
Ciliumβœ…βœ…βœ… (L7)
Calicoβœ…βœ…βœ…
Flannel❌❌❌
AWS VPC CNI⚠️ (requires Calico addon)⚠️❌
Azure CNIβœ…βœ…βŒ

Verification

# Test connectivity
kubectl exec -n production frontend-pod -- curl -s --max-time 3 http://backend:8080/health
# Should succeed

kubectl exec -n production frontend-pod -- curl -s --max-time 3 http://database:5432
# Should timeout (blocked)

Common Patterns

PatternUse Case
Default deny + explicit allowProduction namespaces
Allow same namespaceDevelopment/staging
Allow ingress controller onlyPublic-facing services
Block metadata APIPrevent SSRF (169.254.169.254)
Allow monitoringCross-namespace Prometheus

Free 30-min AI & Cloud consultation

Book Now