Kubernetes NetworkPolicy: isolation, additive rules and selector logic
Understand Kubernetes NetworkPolicy ingress and egress isolation, additive permissions and combined selectors. Review a database access policy and a practical allow/deny test matrix.
TL;DR: NetworkPolicy selects Pods and permits connections by direction, peer and port. Policies combine additively. A connection between two isolated Pods needs permission from the source's egress rules and the destination's ingress rules.
A policy object needs an enforcing network implementation
Kubernetes accepts NetworkPolicy resources through its API, but enforcement requires a network plugin that supports them. A successfully applied YAML file is not proof that packets are filtered. Verify the cluster's implementation and exercise both allowed and denied connections.
Ingress and egress isolation are independent. With no selecting policy for a direction, a Pod is generally non-isolated in that direction. Once selected, its allowed traffic is the union of applicable rules. There is no ordinary first-match ordering in which a later NetworkPolicy cancels an earlier allow. The Kubernetes NetworkPolicy reference describes these semantics and implementation boundaries.
Passing policy checks still does not prove the application listens, routing works or credentials are valid. Separate the network permission question from DNS resolution, service endpoint selection and application authorization.
Read the indentation as logic
This illustrative policy selects database Pods in the payments namespace and permits TCP 5432 from API Pods in that same named namespace. The namespace and Pod selectors appear inside one peer entry, so both conditions must match.
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: database-from-api
namespace: payments
spec:
podSelector:
matchLabels:
app: database
policyTypes: [Ingress]
ingress:
- from:
- namespaceSelector:
matchLabels:
kubernetes.io/metadata.name: payments
podSelector:
matchLabels:
app: api
ports:
- protocol: TCP
port: 5432
Turning podSelector into a second item under from changes the expression. The policy would then allow matching namespace peers or matching Pod peers, potentially admitting far more traffic. Review the parsed structure, not just the presence of familiar labels.
This policy isolates selected databases for ingress. It does not isolate their egress or constrain unrelated Pods. Another policy that permits all ingress to the same databases would add that permission back. Inventory every selecting policy before interpreting one file in isolation.
Test identities and ports separately
Create disposable test clients with known labels and namespaces in an authorized test cluster. Confirm the application listener independently. Then exercise a small matrix and record source identity, destination, protocol and result.
| Source and destination | Expected under this policy alone | Why |
|---|---|---|
| payments API to database TCP 5432 | Allowed | Both peer selectors and port match |
| payments worker to database TCP 5432 | Denied | Pod label does not match |
| another namespace's API to database TCP 5432 | Denied | Namespace does not match |
| payments API to database TCP 8080 | Denied | Port does not match |
These expectations assume an enforcing plugin, no additional allowing policy, and no source-egress restriction blocking the test. Include those assumptions with any reported result. A local YAML parser can catch structure mistakes but cannot prove dataplane enforcement.
Egress lockdown changes dependencies
When adding egress isolation, account for the actual resolver path and its UDP/TCP DNS requirements. Clusters may use node-local DNS or other routing arrangements. Copying one namespace selector for CoreDNS without checking the environment can break service discovery before the application reaches its destination.
IP-based rules also interact with address translation. Kubernetes documents that the ordering of NAT and policy processing can vary with network and Service implementation. Validate the observed address at the enforcement point when using ipBlock; a diagram based only on the original destination hostname is insufficient.
NetworkPolicy normally addresses network-layer peers and ports. It does not implement arbitrary HTTP path authorization or verify a user's token. Use the application or an appropriate proxy control for those requirements, while keeping the network policy as another distinct boundary.
Self-check: a restrictive database policy is correct, but a namespace-wide allow-all ingress policy also selects the database. Why can an unauthorized test Pod connect? Permissions are additive. Remove or narrow the conflicting allow policy through the approved change process and rerun both positive and negative tests. Reordering YAML files cannot create a deny precedence that the API does not provide.
Service mesh identity and traffic policy adds workload authentication and HTTP-aware enforcement, with different responsibilities for Istio sidecars, ztunnel and waypoints.