Skip to content

Kubernetes NetworkPolicy

Default deny patterns

Default deny all ingress and egress

Blocks all traffic in and out of all pods in a namespace.

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

Default deny ingress only

Blocks all incoming traffic; egress remains unchanged.

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

Default deny egress only

Blocks all outgoing traffic; ingress remains unchanged.

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

Explicit allow patterns

Allow all egress

Overrides egress isolation and allows all outbound traffic.

yaml
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: allow-all-egress
spec:
  podSelector: {}
  policyTypes:
  - Egress
  egress:
  - {}

Allow all ingress

Overrides ingress isolation and allows all inbound traffic.

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

Selectors

podSelector

Selects pods within the same namespace.

yaml
podSelector:
  matchLabels:
    role: frontend

namespaceSelector

Selects entire namespaces.

yaml
namespaceSelector:
  matchLabels:
    project: myproject

Combined namespaceSelector + podSelector (AND logic)

Selects pods matching both conditions.

yaml
from:
- namespaceSelector:
    matchLabels:
      user: alice
  podSelector:
    matchLabels:
      role: client

ipBlock

Used for external CIDR ranges (not Pod IPs).

yaml
ipBlock:
  cidr: 172.17.0.0/16
  except:
  - 172.17.1.0/24

matchLabels vs matchExpressions

matchLabels (simple equality, implicit AND)

yaml
matchLabels:
  app: web
  tier: frontend

matchExpressions (advanced logic)

yaml
matchExpressions:
- key: env
  operator: In
  values: ["prod", "staging"]
- key: version
  operator: NotIn
  values: ["v1"]

Supported operators:

  • In
  • NotIn
  • Exists
  • DoesNotExist

AND vs OR behavior (critical)

AND behavior

  • Within a single rule:

    • from AND ports
    • namespaceSelector AND podSelector
    • All conditions must match

OR behavior

  • Multiple entries in arrays are OR’ed

OR in from

yaml
from:
- podSelector:
    matchLabels:
      role: frontend
- namespaceSelector:
    matchLabels:
      project: myproject

OR across rules

yaml
ingress:
- from:
  - podSelector:
      matchLabels:
        role: frontend
- from:
  - ipBlock:
      cidr: 10.0.0.0/24

Meaning of {}

LocationMeaning
podSelector: {}Select all pods
ingress: - {}Allow all ingress
egress: - {}Allow all egress
empty ingress listAllow nothing
empty egress listAllow nothing

Evaluation rules

  • Policies are additive
  • Traffic is allowed if any policy allows it
  • If at least one policy selects a pod, default becomes deny
  • No policies → allow all traffic

Mandatory note

NetworkPolicy has no effect unless the CNI plugin supports it (e.g., Calico, Cilium).


Additional examples (practical and expressive)

Example 1 — Allow frontend → backend on HTTP and HTTPS only

yaml
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: backend-ingress-web
  namespace: backend
spec:
  podSelector: {}
  policyTypes: [Ingress]
  ingress:
  - from:
    - namespaceSelector:
        matchLabels:
          kubernetes.io/metadata.name: frontend
    ports:
    - protocol: TCP
      port: 80
    - protocol: TCP
      port: 443

Example 2 — Allow egress only to database Service by label

yaml
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: app-egress-db
  namespace: app
spec:
  podSelector:
    matchLabels:
      app: api
  policyTypes: [Egress]
  egress:
  - to:
    - podSelector:
        matchLabels:
          role: db
    ports:
    - protocol: TCP
      port: 5432

Example 3 — Allow DNS egress only (UDP/TCP 53)

yaml
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: dns-only-egress
  namespace: workload
spec:
  podSelector: {}
  policyTypes: [Egress]
  egress:
  - to:
    - namespaceSelector:
        matchLabels:
          kubernetes.io/metadata.name: kube-system
    ports:
    - protocol: UDP
      port: 53
    - protocol: TCP
      port: 53

Example 4 — Allow ingress from specific CIDR to NodePort-facing pods

yaml
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: allow-office-cidr
  namespace: edge
spec:
  podSelector:
    matchLabels:
      expose: nodeport
  policyTypes: [Ingress]
  ingress:
  - from:
    - ipBlock:
        cidr: 203.0.113.0/24
    ports:
    - protocol: TCP
      port: 30080

Example 5 — Use matchExpressions to select multiple app versions

yaml
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: canary-ingress
  namespace: api
spec:
  podSelector:
    matchExpressions:
    - key: version
      operator: In
      values: ["v2", "v3"]
  policyTypes: [Ingress]
  ingress:
  - from:
    - namespaceSelector:
        matchLabels:
          team: platform
    ports:
    - protocol: TCP
      port: 8080

Example 6 — Strict isolation with explicit allow list (classic zero-trust)

yaml
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: zero-trust
  namespace: payments
spec:
  podSelector: {}
  policyTypes: [Ingress, Egress]

  ingress:
  - from:
    - podSelector:
        matchLabels:
          role: gateway
    ports:
    - protocol: TCP
      port: 8443

  egress:
  - to:
    - ipBlock:
        cidr: 10.20.0.0/16
    ports:
    - protocol: TCP
      port: 443

Released under the MIT License.