Kubernetes NetworkPolicy

NetworkPolicy is Kubernetes’ built-in L3/L4 policy API. It describes which Pods may talk to which peers on which ports. The API is portable, but enforcement is not automatic; the CNI plugin must implement it.

Command Examples

kubectl get networkpolicy -A
kubectl describe networkpolicy <policy>
kubectl get pods --show-labels
kubectl get namespace --show-labels
kubectl exec -it <pod> -- nc -vz <service> <port>
kubectl exec -it <pod> -- nslookup kubernetes.default.svc.cluster.local

Example output and meaning:

Command Example output What it does
kubectl get networkpolicy -A default-deny, allow-dns, and app-specific policies by namespace. Shows whether policy isolation exists at all and where it is scoped.
kubectl get pods --show-labels app=frontend,tier=web labels on source and destination Pods. Confirms whether selectors match the workloads you think they match.
kubectl exec -it <pod> -- nc -vz <service> <port> succeeded or timed out. Tests the allowed traffic path from the source Pod, not from your workstation.

Isolation Model

Pods are non-isolated by default. A Pod becomes isolated for ingress when at least one NetworkPolicy selects it for ingress. It becomes isolated for egress when at least one NetworkPolicy selects it for egress. Once isolated, only traffic allowed by applicable policies is permitted.

Policies are additive. There is no explicit deny rule in the standard NetworkPolicy API. If any policy allows a flow, that flow is allowed.

Additive allow truth table:

Selected By Ingress Policy? Any Ingress Rule Allows Source/Port? Result
No Not needed Allowed by default for ingress.
Yes No Denied for ingress.
Yes Yes Allowed for that matching flow.

For egress, the same isolation rule applies independently:

Selected By Egress Policy? Any Egress Rule Allows Destination/Port? Result
No Not needed Allowed by default for egress.
Yes No Denied for egress.
Yes Yes Allowed for that matching flow.

Selectors

NetworkPolicy rules combine:

  • podSelector for Pods in the policy namespace,
  • namespaceSelector for namespaces,
  • ipBlock for CIDR ranges outside normal Pod selector logic,
  • ports and protocols.

A small YAML indentation error can change meaning. namespaceSelector and podSelector in the same list item mean both must match. Separate list items mean either may match.

DNS and Egress

Default-deny egress often breaks DNS first. Applications then fail with confusing name resolution errors even though Service objects are healthy. If egress is isolated, allow DNS to the cluster DNS Service on UDP and TCP 53, or to the intended DNS endpoints.

Lab Scenarios

Use a disposable namespace for these patterns. The point is to see how selectors and directions combine before relying on policy during an incident.

Default-deny all ingress and egress:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: default-deny
spec:
  podSelector: {}
  policyTypes: ["Ingress", "Egress"]

Allow DNS egress to CoreDNS:

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

Allow frontend Pods in namespaces labeled team=web to call API Pods on port 8080:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: api-from-web
spec:
  podSelector:
    matchLabels:
      app: api
  policyTypes: ["Ingress"]
  ingress:
    - from:
        - namespaceSelector:
            matchLabels:
              team: web
          podSelector:
            matchLabels:
              role: frontend
      ports:
        - protocol: TCP
          port: 8080

Ingress plus egress isolation test:

kubectl run np-client --image=busybox:1.36 -it --rm --restart=Never --labels role=frontend -- sh
nslookup kubernetes.default.svc.cluster.local
nc -vz api.default.svc.cluster.local 8080
nc -vz api.default.svc.cluster.local 5432

If the policy should allow traffic but packets still fail, check CNI enforcement, namespace labels, Pod labels, generated endpoint identities, and whether traffic is hostNetwork or node-local. CNI-specific policy extensions may add explicit deny, L7 rules, or FQDN rules, but standard NetworkPolicy does not.

Limitations

Standard NetworkPolicy is not a full firewall language:

  • it is namespace-scoped,
  • it targets Pods, not arbitrary nodes,
  • it is L3/L4, not HTTP-aware,
  • it does not define explicit deny precedence,
  • behavior can vary where CNIs add extensions,
  • some traffic involving hostNetwork or node-local paths may not behave like normal Pod traffic.

It also does not define FQDN policy. A standard rule cannot say “allow egress to api.example.com” because policy matching happens on Pod selectors, namespace selectors, IP blocks, and ports. Some CNIs add FQDN-aware policy as an extension, but the behavior then depends on DNS cache timing, TTLs, wildcard rules, and the CNI’s DNS interception model.

If you need FQDN egress, document whether the CNI resolves names centrally, observes DNS answers from Pods, pins IPs until TTL expiry, handles CNAMEs, and fails open or closed when DNS is unavailable.

Debugging Flow

  1. Confirm the CNI enforces NetworkPolicy.
  2. List policies in the source and destination namespaces.
  3. Check whether policies select the affected Pods.
  4. Check labels on Pods and namespaces.
  5. Test DNS separately from application traffic.
  6. Test ingress and egress directions separately.
  7. Check CNI policy logs or flow observability if available.
  8. Use a temporary debug Pod with matching labels to reproduce intentionally.

Study Cards

Question

When is a Pod isolated for ingress?

Answer

When at least one ingress NetworkPolicy selects that Pod; then only allowed ingress traffic is permitted.

Question

Why do default-deny egress policies often break DNS?

Answer

DNS to cluster DNS on UDP and TCP 53 must be allowed explicitly when egress is isolated.

Question

Does Kubernetes enforce NetworkPolicy by itself?

Answer

No. The CNI plugin must implement NetworkPolicy enforcement.

Question

What does namespaceSelector plus podSelector in one from item mean?

Answer

Both selectors must match: the source Pod must match the Pod selector inside a namespace matching the namespace selector.

References