NetworkPolicy in practice
When you need your own NetworkPolicy
Section titled “When you need your own NetworkPolicy”The four pre-approved rules are all ingress rules: intra-namespace pod traffic, intra-tenant pod traffic, Traefik ingress, and Prometheus scraping. No platform rule touches egress — outbound traffic (including DNS) works out of the box only because egress is unrestricted until a policy with policyTypes: Egress selects the pod. You need a custom NetworkPolicy when:
- A pod must accept traffic from a source outside your tenant (rare — requires an RCS ticket for the cross-tenant side, plus your own allow rule for the destination).
- You want to restrict a pod’s outbound traffic to specific destinations — writing an egress policy is how you lock down the otherwise-unrestricted outbound side.
On the ingress side the floor is default-deny, so every custom ingress rule is additive — it opens a lane without weakening the existing posture. On the egress side the first policy that selects a pod flips the default: outbound traffic is then limited to what your policies allow.
Anatomy of a tenant-scoped rule
Section titled “Anatomy of a tenant-scoped rule”A NetworkPolicy lives in the namespace where the destination pod runs. It selects the destination pod(s) via podSelector and then declares which sources (ingress) or destinations (egress) are allowed.
Key fields:
podSelector— selects which pods in this namespace the rule applies to. An empty selector{}means “all pods in this namespace”.ingress— who can send traffic to the selected pods.egress— where the selected pods can send traffic to.policyTypes— must listIngress,Egress, or both. If you only listIngress, the rule does not affect egress at all (and vice versa).
Example: allow ingress from a specific pod in the same namespace
Section titled “Example: allow ingress from a specific pod in the same namespace”This rule lets pods labelled app: backend receive traffic on port 8080 from pods labelled app: frontend, both in the same namespace.
apiVersion: networking.k8s.io/v1kind: NetworkPolicymetadata: name: allow-frontend-to-backend namespace: <your-tenant>-prodspec: podSelector: matchLabels: app: backend policyTypes: - Ingress ingress: - from: - podSelector: matchLabels: app: frontend ports: - protocol: TCP port: 8080Example: allow egress to an external CIDR
Section titled “Example: allow egress to an external CIDR”This rule lets pods labelled app: data-loader reach an external API at 203.0.113.0/24 on port 443. Egress is unrestricted until a policy with policyTypes: Egress selects a pod — this policy is that first restriction for the pods it selects, so it must also allow DNS explicitly or name resolution breaks.
apiVersion: networking.k8s.io/v1kind: NetworkPolicymetadata: name: allow-egress-external-api namespace: <your-tenant>-prodspec: podSelector: matchLabels: app: data-loader policyTypes: - Egress egress: # Allow DNS (required when specifying explicit egress rules) - to: - namespaceSelector: {} podSelector: matchLabels: k8s-app: kube-dns ports: - protocol: UDP port: 53 - protocol: TCP port: 53 # Allow the external API - to: - ipBlock: cidr: 203.0.113.0/24 ports: - protocol: TCP port: 443Cross-namespace traffic within the same tenant
Section titled “Cross-namespace traffic within the same tenant”The pre-approved intra-tenant rule already permits cross-namespace traffic within your tenant. If you need to restrict it further — for example, allowing only a specific pod in namespace <your-tenant>-staging to reach a pod in <your-tenant>-prod — use namespaceSelector alongside podSelector:
ingress: - from: - namespaceSelector: matchLabels: kubernetes.io/metadata.name: <your-tenant>-staging podSelector: matchLabels: app: deployerNote the indentation: namespaceSelector and podSelector under the same - element means both must match (AND logic). If they are separate - elements, either one matching is enough (OR logic). Getting this wrong is the most common source of overly permissive rules.
Debugging dropped traffic
Section titled “Debugging dropped traffic”When traffic is silently dropped, the problem is almost always a NetworkPolicy that does not match the way you think it does.
Step 1 — Verify the policy exists and selects the right pods:
kubectl get networkpolicy -n <your-tenant>-prodkubectl describe networkpolicy <policy-name> -n <your-tenant>-prodCheck the PodSelector field in the describe output. <none> means an empty podSelector, which selects every pod in the namespace — describe shows the spec, not the match result. To test what a selector actually matches, run kubectl get pods -n <your-tenant>-prod -l <selector>.
Step 2 — Verify pod labels match the selector:
kubectl get pods -n <your-tenant>-prod --show-labelsCompare the labels on the source and destination pods against what the policy expects. Label typos (e.g. app: front-end vs app: frontend) are the single most common cause of “my policy doesn’t work.”
Step 3 — Check that policyTypes includes the direction you care about:
A policy with policyTypes: [Ingress] does not affect egress at all. If traffic is being dropped on the outbound side, you need Egress in policyTypes and an explicit egress allow.
Step 4 — Test connectivity:
kubectl exec -n <your-tenant>-prod <source-pod> -- curl -v --connect-timeout 5 http://<dest-service>:8080/A connection timeout with no response means the packet was dropped by NetworkPolicy. A connection refused means the packet reached the destination but nothing is listening — that is a Service or application issue, not a NetworkPolicy issue.
Common mistakes
Section titled “Common mistakes”| Mistake | Symptom | Fix |
|---|---|---|
| Egress rule without DNS allow | Pods lose all name resolution | Add explicit DNS egress to kube-dns |
| AND vs OR selector indentation | Rule is wider or narrower than intended | Put namespaceSelector and podSelector under the same list element for AND |
| Policy in the wrong namespace | Traffic still blocked | Policy must be in the namespace of the destination pod |
| Label typo in selector | Selector matches zero pods | Compare kubectl get pods --show-labels against the policy |