Lesson 12 NetworkPolicies
Theme:
Lesson 12 · Slide 1

NetworkPolicies

Firewalling at the pod level: controlling traffic flow in Kubernetes.

Lesson 12 · Slide 2

Default Behavior & Default-Deny

Without any NetworkPolicy, all pods can talk to all pods across every namespace. A default-deny policy flips this to zero-trust.

Deny All Ingress

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: default-deny-ingress
spec:
  podSelector: {}
  policyTypes:
    - Ingress

Deny All Egress

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: default-deny-egress
spec:
  podSelector: {}
  policyTypes:
    - Egress
Notes: An empty podSelector: {} matches every pod in the namespace. An empty ingress: [] or egress: [] field (or omission) means no traffic is allowed for that direction.
Lesson 12 · Slide 3

Ingress Rules

Each ingress rule specifies from sources and optional ports.

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: allow-frontend
spec:
  podSelector:
    matchLabels:
      app: api
  policyTypes:
    - Ingress
  ingress:
    - from:
        - podSelector:
            matchLabels:
              app: frontend
        - namespaceSelector:
            matchLabels:
              env: production
        - ipBlock:
            cidr: 10.0.0.0/8
            except:
              - 10.0.1.0/24
      ports:
        - protocol: TCP
          port: 8080
Notes: OR logic: Each item in the from array is OR'd together. Traffic matching any of the three selectors above is allowed on port 8080.
Lesson 12 · Slide 4

AND vs OR Logic

The distinction between AND and OR is one of the trickiest parts of NetworkPolicy.

OR (separate list items)

ingress:
  - from:
      - podSelector:
          matchLabels:
            app: frontend
      - namespaceSelector:
          matchLabels:
            env: staging

Allows pods labeled app: frontend in any namespace OR any pod in namespaces labeled env: staging.

AND (single list item)

ingress:
  - from:
      - podSelector:
          matchLabels:
            app: frontend
        namespaceSelector:
          matchLabels:
            env: staging

Allows only pods labeled app: frontend that are also in namespaces labeled env: staging.

Notes: The YAML dash (-) makes all the difference. Two dashes = two separate items (OR). One dash with both selectors = single item (AND).
Lesson 12 · Slide 5

Egress Rules & DNS Pattern

Egress rules control outbound traffic. A common requirement: allow DNS resolution (port 53) even when egress is otherwise denied.

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: restricted-egress
spec:
  podSelector:
    matchLabels:
      app: api
  policyTypes:
    - Egress
  egress:
    # Allow DNS
    - to: []
      ports:
        - protocol: UDP
          port: 53
        - protocol: TCP
          port: 53
    # Allow traffic to the database
    - to:
        - podSelector:
            matchLabels:
              app: postgres
      ports:
        - protocol: TCP
          port: 5432
Notes: Always include a DNS egress rule when using default-deny egress. Without it, pods cannot resolve any service names and will appear completely broken.
Lesson 12 · Slide 6

Templating NetworkPolicies in Helm

{{- if .Values.networkPolicy.enabled }}
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: {{ include "mychart.fullname" . }}
  labels:
    {{- include "mychart.labels" . | nindent 4 }}
spec:
  podSelector:
    matchLabels:
      {{- include "mychart.selectorLabels" . | nindent 6 }}
  policyTypes:
    {{- if .Values.networkPolicy.ingress }}
    - Ingress
    {{- end }}
    {{- if .Values.networkPolicy.egress }}
    - Egress
    {{- end }}
  {{- if .Values.networkPolicy.ingress }}
  ingress:
    {{- toYaml .Values.networkPolicy.ingress | nindent 4 }}
  {{- end }}
  {{- if .Values.networkPolicy.egress }}
  egress:
    {{- toYaml .Values.networkPolicy.egress | nindent 4 }}
  {{- end }}
{{- end }}

Corresponding values.yaml:

networkPolicy:
  enabled: false
  ingress:
    - from:
        - podSelector:
            matchLabels:
              app: frontend
      ports:
        - protocol: TCP
          port: 8080
  egress:
    - to: []
      ports:
        - protocol: UDP
          port: 53
Lesson 12 · Slide 7

CNI Requirements & Testing

CNI Support

  • Calico — full support, most popular
  • Cilium — full support + L7 policies
  • Weave Net — full support
  • Flannel — no support (policies are silently ignored)
  • AWS VPC CNI — needs Calico addon
Notes: NetworkPolicy objects are always accepted by the API server. A missing CNI means they simply do nothing.

Testing Policies

# Exec into a pod and curl
kubectl exec -it deploy/frontend \
  -- curl -s --max-time 3 \
  http://api:8080/health

# Check applied policies
kubectl get netpol -n myns
kubectl describe netpol \
  allow-frontend -n myns

# Quick test pod
kubectl run test --rm -it \
  --image=busybox:1.36 \
  --restart=Never -- \
  wget -qO- --timeout=3 \
  http://api.myns:8080/health
Lesson 12 · Slide 8

Summary

Next: Lesson 13

1 / ?