iwantcoding.com
🔥 Daily 👥 Rooms 🏆 Top Log in Sign up

Network Policies

By default every pod in a Kubernetes namespace can reach every other pod. NetworkPolicy is the firewall that fixes that, expressed as Kubernetes objects so the rules ship with the workload. They are CNI-implemented (Calico, Cilium, etc.) — confirm your cluster has one installed, otherwise the policies are silently ignored.

Default-deny, then explicitly allow what is needed

EXAMPLE
# 1) Default-deny ALL ingress in this namespace.
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata: { name: default-deny-ingress, namespace: shop }
spec:
  podSelector: {}             # selects every pod in the namespace
  policyTypes: [Ingress]

---
# 2) Allow the API pods to be reached only from the web pods, on port 8080.
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata: { name: api-from-web, namespace: shop }
spec:
  podSelector:
    matchLabels: { app: api }
  policyTypes: [Ingress]
  ingress:
    - from:
        - podSelector:
            matchLabels: { app: web }
      ports:
        - protocol: TCP
          port: 8080

---
# 3) Allow the DB pods to be reached only from API, AND only from this namespace.
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata: { name: db-from-api, namespace: shop }
spec:
  podSelector:
    matchLabels: { app: postgres }
  policyTypes: [Ingress, Egress]
  ingress:
    - from:
        - namespaceSelector:
            matchLabels: { kubernetes.io/metadata.name: shop }
          podSelector:
            matchLabels: { app: api }
      ports: [{ protocol: TCP, port: 5432 }]
  egress:
    - to: []                  # nothing — DB pods make no outbound calls
      ports: []

---
# 4) Egress allow-list for the API: only DNS, the DB, and our payment gateway.
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata: { name: api-egress, namespace: shop }
spec:
  podSelector:
    matchLabels: { app: api }
  policyTypes: [Egress]
  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 }]
    - to:
        - podSelector: { matchLabels: { app: postgres } }
      ports: [{ protocol: TCP, port: 5432 }]
    - 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 }]

# Verify a rule actually denies what you think it does:
kubectl run probe --rm -it --image=alpine -n shop -- sh -c 'apk add curl; curl http://api:8080'

Why it matters

Always start with a default-deny policy, then layer narrow allows on top. The opposite order — adding deny rules to plug holes — leaves the holes open between deploys, and forgotten allow-all rules tend to outlive the team member who wrote them.

Tip: Tweak the snippet with Try it Yourself », then sit the quiz at the bottom of the page.

Example

Example
# Default-deny + allow what's needed. Like security groups but for pods.
Try it Yourself »

Discussion

Loading…