Welcome to from-docker-to-kubernetes

Kubernetes Network Policies

Comprehensive guide to implementing, troubleshooting, and managing Kubernetes Network Policies for secure cluster communication

Introduction to Kubernetes Network Policies

Network Policies are essential Kubernetes resources that control the flow of network traffic between pods, providing granular security controls for your containerized applications:

  • Micro-segmentation: Define precise communication boundaries between application components
  • Zero-trust security: Implement least-privilege network access control
  • Regulatory compliance: Meet security requirements for sensitive workloads
  • Threat containment: Limit the blast radius of potential security breaches
  • Multi-tenant isolation: Securely separate workloads in shared clusters

This comprehensive guide explores the architecture, implementation patterns, and best practices for designing, deploying, and troubleshooting Network Policies in Kubernetes environments, helping you build secure, compliant application platforms.

Network Policy Fundamentals

Understanding the Default Network Model

Kubernetes follows an "allow all" default network model without Network Policies:

┌───────────────────────────────────────────────────────────────────┐
│                                                                   │
│                      Kubernetes Cluster                           │
│                                                                   │
│    ┌──────────┐      ┌──────────┐      ┌──────────┐              │
│    │          │      │          │      │          │              │
│    │  Pod A   │◄────►│  Pod B   │◄────►│  Pod C   │              │
│    │          │      │          │      │          │              │
│    └──────────┘      └──────────┘      └──────────┘              │
│                                                                   │
│                   All traffic allowed by default                  │
│                                                                   │
└───────────────────────────────────────────────────────────────────┘

Key characteristics of the default model:

  1. Open communication: Any pod can communicate with any other pod
  2. No segmentation: No built-in network boundaries between namespaces
  3. Unrestricted ingress/egress: Both incoming and outgoing traffic permitted
  4. Flat network: All pods on a single, flat network plane

Network Policy API

Network Policies use a standard Kubernetes API format:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: example-policy
  namespace: default
spec:
  podSelector:
    matchLabels:
      role: db
  policyTypes:
    - Ingress
    - Egress
  ingress:
    - from:
        - podSelector:
            matchLabels:
              role: frontend
      ports:
        - protocol: TCP
          port: 3306
  egress:
    - to:
        - podSelector:
            matchLabels:
              role: monitoring
      ports:
        - protocol: TCP
          port: 9001

Key components of a Network Policy:

  1. podSelector: Defines which pods the policy applies to
  2. policyTypes: Specifies whether the policy applies to ingress, egress, or both
  3. ingress rules: Controls incoming traffic to selected pods
  4. egress rules: Controls outgoing traffic from selected pods
  5. from/to selectors: Specifies source/destination using pod, namespace, or IP-based selectors
  6. ports: Defines the protocol and port numbers allowed

Network Policy Selectors

Pod Selectors

Target specific pods using label selectors:

# Allow traffic to pods with label role=web
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: allow-to-web
spec:
  podSelector:
    matchLabels:
      role: web
  ingress:
    - from: []  # Empty array = allow from anywhere

Pod selectors can use:

  1. matchLabels: Simple equality-based selector
  2. matchExpressions: More complex set-based requirements
  3. Empty selector: Selects all pods in the namespace

Namespace Selectors

Allow traffic based on namespace labels:

# Allow traffic from pods in namespaces with label environment=production
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: allow-from-production
  namespace: backend
spec:
  podSelector: {}  # Select all pods in backend namespace
  ingress:
    - from:
        - namespaceSelector:
            matchLabels:
              environment: production

Namespace selector features:

  1. Cross-namespace control: Allow or deny traffic between namespaces
  2. Environment separation: Isolate development, staging, and production
  3. Team boundaries: Enforce separation between team namespaces
  4. Compliance zones: Create regulatory boundary separation

IP Block Selectors

Control traffic based on IP CIDR ranges:

# Allow specific external IP ranges
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: allow-external-traffic
spec:
  podSelector:
    matchLabels:
      app: web
  ingress:
    - from:
        - ipBlock:
            cidr: 192.168.1.0/24
            except:
              - 192.168.1.13/32

IP block selector capabilities:

  1. External traffic control: Manage traffic from outside the cluster
  2. On-premises integration: Allow specific corporate networks
  3. Cloud service access: Permit traffic to/from specific cloud services
  4. Security zones: Implement network security zones

Combining Selectors

Create sophisticated policies by combining multiple selectors:

# Complex policy combining multiple selectors
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: complex-policy
spec:
  podSelector:
    matchLabels:
      app: api
  ingress:
    - from:
        # AND relationship between elements in an array item
        - podSelector:
            matchLabels:
              role: frontend
          namespaceSelector:
            matchLabels:
              environment: production
        # OR relationship between array items
        - ipBlock:
            cidr: 10.0.0.0/24

Selector combination logic:

  1. AND within array element: Multiple selectors within a single array element (from/to) create an AND condition
  2. OR between array elements: Multiple array elements create an OR condition
  3. Empty array: An empty array means "match nothing"
  4. Missing array: No array specified means "match everything"

Common Network Policy Patterns

Default Deny

Implement a zero-trust approach with default deny policies:

Default deny creates a secure foundation:

  1. Zero-trust base: Start with no allowed traffic
  2. Explicit permissions: Add specific allowances as needed
  3. Complete isolation: Prevent unexpected communication paths
  4. Comprehensive security: Control both incoming and outgoing traffic

Allow Traffic Patterns

Create targeted allowances for necessary communication:

Common allowance patterns include:

  1. Component communication: Allow traffic between application tiers
  2. Service access: Permit access to internal services (e.g., databases, caches)
  3. API gateways: Allow external traffic through designated entry points
  4. Infrastructure services: Enable access to DNS, monitoring, and logging

Namespace Isolation

Implement namespace-level segmentation:

# Namespace isolation policy
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: isolate-namespace
  namespace: team-a
spec:
  podSelector: {}
  policyTypes:
    - Ingress
  ingress:
    - from:
        - podSelector: {}

This policy allows:

  1. Intra-namespace communication: Pods in the same namespace can talk to each other
  2. Namespace boundary: Traffic from other namespaces is blocked
  3. Team isolation: Each team can work independently without interference
  4. Service separation: Services in different namespaces are isolated

Advanced Network Policy Features

Egress Traffic Control

Manage outbound traffic from pods:

# Restrict outbound traffic to specific destinations
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: restrict-egress
  namespace: app
spec:
  podSelector:
    matchLabels:
      app: web
  policyTypes:
    - Egress
  egress:
    # Allow DNS resolution
    - to:
        - namespaceSelector:
            matchLabels:
              kubernetes.io/metadata.name: kube-system
          podSelector:
            matchLabels:
              k8s-app: kube-dns
      ports:
        - protocol: UDP
          port: 53
        - protocol: TCP
          port: 53
    # Allow database access
    - to:
        - podSelector:
            matchLabels:
              app: database
      ports:
        - protocol: TCP
          port: 5432
    # Allow specific external endpoints
    - to:
        - ipBlock:
            cidr: 34.98.0.0/16  # Example external API service
      ports:
        - protocol: TCP
          port: 443

Egress control benefits:

  1. Data exfiltration prevention: Control where data can be sent
  2. Compliance requirements: Meet regulatory needs for data movement
  3. Attack mitigation: Prevent command-and-control communications
  4. Dependency management: Explicit control over external dependencies

Named Port Selection

Reference named ports for more maintainable policies:

# Network policy using named ports
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: allow-web-and-api
  namespace: app
spec:
  podSelector:
    matchLabels:
      app: web
  ingress:
    - ports:
        - protocol: TCP
          port: http  # Named port
        - protocol: TCP
          port: https  # Named port

This works with pods defining named ports:

# Pod with named ports
apiVersion: v1
kind: Pod
metadata:
  name: web-pod
  labels:
    app: web
spec:
  containers:
    - name: web
      image: nginx
      ports:
        - name: http
          containerPort: 80
        - name: https
          containerPort: 443

Named port advantages:

  1. Abstraction: Decouple port numbers from policies
  2. Readability: More descriptive than numeric ports
  3. Maintainability: Change underlying port numbers without updating policies
  4. Consistency: Standardize port names across applications

Implementing Application Layer Policies

Network Policies operate at OSI layers 3 and 4. For application-layer (L7) policies:

# Network Policy allowing traffic to service mesh proxy
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: allow-to-istio-proxy
  namespace: app
spec:
  podSelector:
    matchLabels:
      app: service
  ingress:
    - ports:
        - protocol: TCP
          port: 15001  # Istio proxy ingress port

Combine Network Policies with service mesh solutions like Istio:

# Istio AuthorizationPolicy for L7 filtering
apiVersion: security.istio.io/v1beta1
kind: AuthorizationPolicy
metadata:
  name: http-policy
  namespace: app
spec:
  selector:
    matchLabels:
      app: web
  action: ALLOW
  rules:
    - from:
        - source:
            namespaces: ["frontend"]
      to:
        - operation:
            methods: ["GET"]
            paths: ["/api/products/*"]

Application layer control strategies:

  1. Service mesh integration: Use Istio, Linkerd, or other service meshes
  2. API gateway policies: Implement API-level controls
  3. Ingress controllers: Use advanced ingress controllers with L7 features
  4. WAF integration: Web Application Firewall for HTTP-specific protections

Network Policy Implementation

CNI Plugin Support

Network Policy implementation depends on your Container Network Interface (CNI) plugin:

CNI PluginNetwork Policy SupportFeatures
CalicoFull supportAdvanced network policy, BGP, IPinIP, VXLAN
CiliumFull supporteBPF-based, L7 policy, XDP, encryption
AntreaFull supportOpen vSwitch, Windows support
Weave NetFull supportEncryption, multicast support
FlannelNo support*Simple overlay network
Kube-routerFull supportBGP, IPVS, DSR

*Note: Flannel requires additional components like Calico or Kube-router for Network Policy support.

To check your CNI plugin's Network Policy support:

# Check CNI plugin version and features
kubectl get pods -n kube-system | grep -E 'calico|cilium|antrea|weave|flannel|kube-router'

# View details of the CNI configuration
kubectl get configmap -n kube-system calico-config -o yaml  # Example for Calico

Cluster Setup for Network Policies

Ensure your cluster is correctly configured for Network Policies:

# Create a simple test policy
cat <<EOF | kubectl apply -f -
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: test-policy
  namespace: default
spec:
  podSelector:
    matchLabels:
      app: test
  ingress: []
EOF

# Check if the policy was created
kubectl get networkpolicy test-policy

# Test policy enforcement
kubectl run test-source --image=busybox --rm -it -- wget -q --timeout=5 test-target:80
# Should fail if policies are enforced correctly

Cluster configuration considerations:

  1. CNI installation: Ensure Network Policy capable CNI is installed
  2. Feature gates: Verify NetworkPolicy feature is enabled
  3. Controller configuration: Check network controller is configured for policies
  4. Node configuration: Verify nodes are properly configured for policy enforcement

Network Policy Testing and Validation

Testing Policy Effectiveness

Validate your Network Policies using systematic testing:

# Deploy test pods in different namespaces
kubectl create namespace test-source
kubectl create namespace test-target

# Deploy target pod
kubectl -n test-target run web --image=nginx --labels=app=web --expose --port=80

# Test connectivity before policy
kubectl -n test-source run test --rm -it --image=busybox -- wget -q -O- --timeout=5 web.test-target.svc.cluster.local

# Apply isolation policy
cat <<EOF | kubectl apply -f -
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: web-isolation
  namespace: test-target
spec:
  podSelector:
    matchLabels:
      app: web
  ingress: []
EOF

# Test connectivity after policy (should fail)
kubectl -n test-source run test --rm -it --image=busybox -- wget -q -O- --timeout=5 web.test-target.svc.cluster.local

# Modify policy to allow specific access
cat <<EOF | kubectl apply -f -
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: web-allow-specific
  namespace: test-target
spec:
  podSelector:
    matchLabels:
      app: web
  ingress:
    - from:
        - namespaceSelector:
            matchLabels:
              kubernetes.io/metadata.name: test-source
EOF

# Label the source namespace
kubectl label namespace test-source kubernetes.io/metadata.name=test-source

# Test connectivity again (should succeed)
kubectl -n test-source run test --rm -it --image=busybox -- wget -q -O- --timeout=5 web.test-target.svc.cluster.local

Testing approaches include:

  1. Positive testing: Verify allowed communication paths work
  2. Negative testing: Verify denied communication paths are blocked
  3. Cross-namespace testing: Test policies across namespace boundaries
  4. External connectivity: Test ingress from and egress to external endpoints

Debugging Network Policies

Troubleshoot policy issues with these techniques:

Common policy issues and solutions:

  1. Selector mismatch: Ensure labels match exactly what's in the policy
  2. Missing DNS access: Add explicit policies for DNS resolution
  3. Default deny conflicts: Check for multiple policies affecting the same pods
  4. CNI misconfiguration: Verify CNI plugin is properly installed and configured
  5. Service vs. pod communication: Remember policies work on pod IPs, not service IPs

Network Policy Management at Scale

Policy as Code

Manage Network Policies using GitOps and Infrastructure as Code:

# Kustomize example for network policies
# kustomization.yaml
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
  - base/default-deny.yaml
  - base/allow-dns.yaml
  - base/allow-metrics.yaml
  - namespaces/team-a-policies.yaml
  - namespaces/team-b-policies.yaml

# With Flux GitOps
apiVersion: kustomize.toolkit.fluxcd.io/v1beta2
kind: Kustomization
metadata:
  name: network-policies
  namespace: flux-system
spec:
  interval: 10m
  path: "./policies"
  prune: true
  sourceRef:
    kind: GitRepository
    name: policy-repo

Policy as code benefits:

  1. Version control: Track policy changes over time
  2. Review process: Implement peer review for policy changes
  3. CI/CD integration: Automate policy validation and deployment
  4. Consistent application: Apply policies consistently across clusters
  5. Documentation: Self-documenting policies with inline comments

Policy Templates and Generators

Create reusable policy templates for consistency:

# Helm template for network policy
# templates/default-namespace-isolation.yaml
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: default-isolation
  namespace: {{ .Release.Namespace }}
spec:
  podSelector: {}
  policyTypes:
    - Ingress
    - Egress
  ingress:
    - from:
        - podSelector: {}
  egress:
    - to:
        - namespaceSelector:
            matchLabels:
              kubernetes.io/metadata.name: kube-system
          podSelector:
            matchLabels:
              k8s-app: kube-dns
      ports:
        - protocol: UDP
          port: 53
        - protocol: TCP
          port: 53
    {{- if .Values.allowInternet }}
    - to:
        - ipBlock:
            cidr: 0.0.0.0/0
            except:
              - 10.0.0.0/8
              - 172.16.0.0/12
              - 192.168.0.0/16
      ports:
        - protocol: TCP
          port: 443
    {{- end }}

Policy generation approaches:

  1. Helm charts: Parameterized policy templates
  2. Kustomize generators: Generate policies based on common patterns
  3. Custom operators: Create controllers that generate policies dynamically
  4. Policy libraries: Maintain standard policy building blocks

Multi-Cluster Policy Management

Manage policies across multiple clusters:

# ArgoCD ApplicationSet for multi-cluster policies
apiVersion: argoproj.io/v1alpha1
kind: ApplicationSet
metadata:
  name: network-policies
  namespace: argocd
spec:
  generators:
    - clusters: {}
  template:
    metadata:
      name: '{{name}}-network-policies'
    spec:
      project: default
      source:
        repoURL: https://github.com/org/network-policies.git
        targetRevision: HEAD
        path: policies/{{metadata.labels.environment}}
      destination:
        server: '{{server}}'
        namespace: security

Multi-cluster management strategies:

  1. Cluster segmentation: Different policy sets for different cluster types
  2. Environment progression: Promote policies across dev, staging, production
  3. Centralized governance: Enforce organization-wide security policies
  4. Local customization: Allow cluster-specific policy extensions

Compliance and Security Patterns

PCI DSS Compliance

Implement Payment Card Industry Data Security Standard (PCI DSS) segmentation:

# Network isolation for PCI workloads
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: pci-isolation
  namespace: pci-zone
spec:
  podSelector: {}
  policyTypes:
    - Ingress
    - Egress
  ingress:
    - from:
        - podSelector: {}
        - namespaceSelector:
            matchLabels:
              security-zone: pci-gateway
          podSelector:
            matchLabels:
              app: api-gateway
  egress:
    # Allow DNS
    - to:
        - namespaceSelector:
            matchLabels:
              kubernetes.io/metadata.name: kube-system
          podSelector:
            matchLabels:
              k8s-app: kube-dns
      ports:
        - protocol: UDP
          port: 53
        - protocol: TCP
          port: 53
    # Allow specific internal services
    - to:
        - podSelector: {}
    # Allow logging/monitoring
    - to:
        - namespaceSelector:
            matchLabels:
              security-zone: monitoring

PCI compliance requirements addressed:

  1. Network segmentation: Isolate cardholder data environment
  2. Controlled access: Restrict communication paths to PCI workloads
  3. Traffic monitoring: Enable visibility into all access attempts
  4. Default deny: Implement restrictive communication policies

Zero-Trust Architecture

Implement zero-trust principles with Network Policies:

# Zero-trust foundation policy
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: zero-trust-base
  namespace: app
spec:
  podSelector: {}
  policyTypes:
    - Ingress
    - Egress
  ingress: []  # No ingress allowed by default
  egress: []   # No egress allowed by default

---
# Specific allowances for service
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: auth-service-policy
  namespace: app
spec:
  podSelector:
    matchLabels:
      app: auth-service
  policyTypes:
    - Ingress
    - Egress
  ingress:
    - from:
        - podSelector:
            matchLabels:
              app: api-gateway
      ports:
        - protocol: TCP
          port: 8080
  egress:
    # Allow DNS
    - to:
        - namespaceSelector:
            matchLabels:
              kubernetes.io/metadata.name: kube-system
          podSelector:
            matchLabels:
              k8s-app: kube-dns
      ports:
        - protocol: UDP
          port: 53
    # Allow database access
    - to:
        - podSelector:
            matchLabels:
              app: user-db
      ports:
        - protocol: TCP
          port: 5432

Zero-trust implementation patterns:

  1. Default deny all: Start with no communication allowed
  2. Explicit allowances: Define specific, minimal communication paths
  3. Fine-grained control: Limit communication to specific ports and protocols
  4. Service identities: Base policies on verifiable service identities
  5. Continuous verification: Regularly test and validate policy effectiveness

Security Zone Separation

Create security zones with different trust levels:

# Internet-facing zone
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: dmz-policy
  namespace: dmz
spec:
  podSelector: {}
  policyTypes:
    - Ingress
    - Egress
  ingress:
    - from: []  # Allow all ingress (handled by ingress controllers)
  egress:
    - to:
        - namespaceSelector:
            matchLabels:
              zone: internal
          podSelector:
            matchLabels:
              app: api-gateway

---
# Internal zone
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: internal-policy
  namespace: internal
spec:
  podSelector: {}
  policyTypes:
    - Ingress
  ingress:
    - from:
        - namespaceSelector:
            matchLabels:
              zone: dmz
          podSelector:
            matchLabels:
              app: frontend
    - from:
        - podSelector: {}  # Allow internal traffic

Security zone architecture benefits:

  1. Defense in depth: Multiple layers of network controls
  2. Breach containment: Limit lateral movement within the cluster
  3. Trust boundaries: Clearly defined boundaries between security domains
  4. Data protection: Control data flow between security zones

Future of Kubernetes Network Policies

Enhanced Network Policy Features

The Kubernetes Network Policy API continues to evolve with new features:

  1. EndPort support: Range of ports in a single rule (Kubernetes 1.21+)
  2. FQDN-based policies: Allow/deny traffic based on domain names (via CNI plugins)
  3. Application-layer filtering: L7 filtering support in future API versions
  4. Richer selectors: More powerful label and expression selectors

Keep track of NetworkPolicy API enhancements:

# Check current API version support
kubectl api-resources | grep networkpolicy

# View supported apiVersions for NetworkPolicy
kubectl explain networkpolicy --api-version=networking.k8s.io/v1

CNI-Specific Policy Extensions

Many CNI plugins offer extended policy capabilities beyond the Kubernetes API:

CNI-specific features include:

  1. Application protocol awareness: HTTP, gRPC, Kafka, and other protocol filtering
  2. Advanced rule matching: Regular expressions, header matches, and more
  3. Tiered policies: Policy hierarchy with priority levels
  4. Logging and auditing: Enhanced visibility into policy decisions
  5. Encryption: Transparent encryption of network traffic

Best Practices and Recommendations

Policy Design Guidelines

Follow these guidelines when designing Network Policies:

  1. Start with default deny: Implement default deny policies in all namespaces
  2. Use namespace isolation: Enforce boundaries between different namespaces
  3. Principle of least privilege: Allow only necessary communication paths
  4. Document policies: Maintain clear documentation of policy intent and coverage
  5. Standardize naming: Use consistent naming conventions for policies
  6. Layer policies: Apply multiple policies for different concerns (security, access, etc.)
  7. Consider stateful firewalling: Understand how your CNI handles return traffic

Operational Excellence

Implement these operational best practices:

  1. Policy testing: Regularly test policy effectiveness
  2. Automation: Automate policy deployment and validation
  3. Monitoring: Monitor policy enforcement and violations
  4. Change management: Implement controlled processes for policy changes
  5. Regular reviews: Periodically review and update policies
  6. Emergency procedures: Define processes for temporarily modifying policies in emergencies
  7. Training: Ensure team members understand policy concepts and implementation

Common Pitfalls to Avoid

Beware of these common Network Policy pitfalls:

  1. Overly permissive policies: Allowing more access than necessary
  2. Forgetting DNS access: Not allowing DNS resolution
  3. Incomplete default deny: Missing ingress or egress restrictions
  4. Forgetting the kube-system namespace: Not allowing necessary system access
  5. Label inconsistency: Incorrect or inconsistent pod labeling
  6. Testing in production: Not validating policies before deployment
  7. Ignoring namespaces: Not considering namespace boundaries in policies

Conclusion

Kubernetes Network Policies provide a powerful mechanism for implementing network security within your clusters. By defining precise rules for pod communication, you can enforce the principle of least privilege, meet compliance requirements, and significantly improve your security posture.

As container adoption continues to grow and workloads become more complex, Network Policies become increasingly important as a fundamental security control. The evolving Network Policy API, combined with CNI-specific extensions, offers rich capabilities for implementing sophisticated security architectures that address modern application requirements.

By following the patterns and best practices outlined in this guide, you can create a robust, secure networking environment for your containerized applications while maintaining the flexibility and dynamism that makes Kubernetes so powerful.