A practical test design for Kubernetes egress policy. It covers enforcement support, additive rules, selector logic, DNS paths, plugin-specific FQDN policies, and evidence from allowed and denied connections.
At a glance
Key findings
- A stored NetworkPolicy object does not prove that the network plugin enforces it. Validate support before treating the object as a boundary.
- Allowed traffic is the union of applicable policies for each direction. When both Pods are isolated, source egress and destination ingress must permit the connection.
- A successful name lookup says nothing by itself about the later transport connection or application authorization. Test those stages independently.
Prove enforcement before debugging the allow rule
A successful DNS lookup is an incomplete acceptance test for an egress policy. It can prove that a resolver answered a question while leaving the intended application connection blocked. It can also succeed in a cluster where the policy objects are not enforced at all. Begin by identifying the network implementation, its configuration, and a controlled connection that the intended policy should reject.
Kubernetes requires a networking solution that implements NetworkPolicy; creating an object without suitable enforcement has no effect on traffic. Its documentation also describes policies as additive rather than ordered firewall rules. Review all policies selecting the source or destination, not just the file changed in the current pull request. A separate broad allow can make a narrow new rule irrelevant to the tested connection. [1]
Use a disposable namespace and endpoints you control to establish a simple positive and negative baseline. Keep the source labels, destination labels, port, protocol, and expected result in a short case description. If the denied connection still succeeds, investigate enforcement and matching first. Do not add increasingly complicated DNS exceptions to compensate for a policy engine that has not demonstrated the basic boundary.
Evaluate source and destination as separate decisions
For Pod-to-Pod traffic, a source egress restriction and a destination ingress restriction can both apply. Kubernetes requires both relevant directions to allow the connection. If either side is not isolated in that direction, its behavior differs from a selected deny-by-default case. Describe the source and destination state explicitly instead of reporting that the namespace is isolated without naming the direction. [1]
For each test, list the policies selecting the source for egress and the destination for ingress. Derive the allowed destinations or sources from their combined rules. This is a reasoning aid, not a replacement for a connection test. It gives a reviewer a concrete explanation for an observed result and helps reveal when a policy outside the changed file supplies the permission.
Keep transport success distinct from the application response. A connection can reach a service that then rejects a credential, or a network test can fail before any application identity is evaluated. Record which stage failed using a test client with understandable error output. A single label such as access denied obscures the difference between a functioning network restriction and a functioning application permission check.
Separate name resolution from the destination connection
Review DNS from the same network namespace and resolver configuration used by the application. Kubernetes DNS behavior includes namespace search paths; ordinary Services and headless Services can return different kinds of addresses. A short service name queried from another namespace can therefore produce a different result from the application's query. Record the name and answer actually used rather than a convenient lookup from an administrator's laptop. [3]
Treat DNS as a separate dependency with its own destination and protocol requirements. After resolution, the application still needs permission to connect to the returned address and service port. The diagram separates those checks deliberately. It is not a packet trace and does not imply that every network plugin evaluates rules at identical points in the packet-processing path.
A useful fixture contains an allowed resolver, an allowed service, and an otherwise reachable service that should be denied. Test the application's ordinary lookup and connection sequence, then test the disallowed destination with a fresh connection. Keep expected DNS success and expected application failure in the same case where appropriate. This demonstrates why name resolution alone cannot establish that the network policy is correct.
A name lookup is only one leg of the connection
Resolver access, connection policy, and application authorization need separate acceptance cases.

Source. Kubernetes NetworkPolicy, DNS, and API documentation [1][3][5].
Method. Original logical review diagram based on documented behavior. It separates questions rather than depicting measured packet timing or identical internals across network plugins.
Accessible table and figure data
| Review point | Question | Evidence to retain |
|---|---|---|
| DNS path | Can the application use its intended resolver? | Queried name and returned address |
| Source egress | Does the policy union allow this destination and port? | Source labels and selecting policies |
| Destination ingress | Does the policy union allow this source and port? | Destination labels and selecting policies |
| Application access | May this caller perform the requested operation? | Sanitized identity and response |
| Review point | Question | Evidence to retain |
|---|---|---|
| DNS path | Can the application use its intended resolver? | Queried name and returned address |
| Source egress | Does the policy union allow this destination and port? | Source labels and selecting policies |
| Destination ingress | Does the policy union allow this source and port? | Destination labels and selecting policies |
| Application access | May this caller perform the requested operation? | Sanitized identity and response |
Read peer selectors as logic, not indentation
A NetworkPolicy peer containing both namespaceSelector and podSelector selects Pods satisfying both conditions. Separate peers instead represent alternatives. That distinction can turn a rule intended for a particular application in one namespace into a much wider allow. The API reference defines these fields; compare the resulting selection with the labels in the test fixture before approving the change. [5]
Core Kubernetes NetworkPolicy should not be confused with a plugin's additional policy language. Cilium documents toFQDNs controls and DNS-related rules that can support name-based egress decisions. Those fields and their processing are Cilium-specific. A portable NetworkPolicy object does not acquire equivalent hostname filtering simply because a comment names a domain. Check the implementation and version used by the cluster. [4]
Make selector intent reviewable with a few named examples. Include one permitted source, a similarly labeled source in the wrong namespace, and a source missing one required label. State whether each should match before running the test. This catches misunderstandings that a large manifest review can miss, especially when teams reuse common labels such as app or environment for unrelated services.
Test fresh connections and realistic resolver paths
Kubernetes' network policy walkthrough demonstrates checking connectivity before and after introducing a policy and an intended exception. Use that pattern with your own application topology, but do not treat the walkthrough's addresses, image choices, or commands as a production deployment recipe. The fixture's value comes from clearly different allowed and denied cases, not from reproducing a screenshot. [2]
For each case, create a fresh connection after the policy reaches the expected state. Include the protocol and port the application actually uses, not only an HTTP request chosen for convenience. Existing connections, host-network workloads, address translation, and node-local DNS can need implementation-specific interpretation. Keep those cases visible as separate limitations rather than assuming a simple Pod-to-Pod result covers them all.
Run at least the intended allowed request, the intended denied destination, the wrong source labels, and the wrong namespace. Test the DNS path separately and include a failure case that isolates the destination's application authorization. Record timeout versus refusal versus an application response where your tools can distinguish them. Those observations help the owner decide which configuration to inspect next without exposing production secrets.
Retain the labels and topology with the result
A policy test without the matching labels is difficult to reproduce. Save the relevant policy revision, source and destination labels, namespace labels, network implementation version, resolver path, and connection tuple. Add the expected and observed outcome for each case. A result from yesterday may no longer describe today's selection if a deployment or namespace label changed independently.
Assign ownership for those label changes alongside ownership for the policy files. During review, ask whether a team can place an unrelated workload into a permitted group simply by choosing a label. Where the trust boundary depends on that selection, the ability to change the selecting information needs its own control. This is an authorization design question that packet filtering alone cannot settle.
Repeat the fixture when changing the network plugin, DNS architecture, relevant labels, or the application's connection behavior. Preserve the narrow cases that previously caught a mistake instead of expanding every test into a full cluster exercise. The resulting evidence should explain both why the required request works and why a plausible unwanted request does not. Neither a green DNS lookup nor an accepted YAML object provides that explanation.
Method and provenance
Primary documentation reviewed on August 28, 2026. The article combines the cited platform behavior with an original review procedure and visual explanation. Suggested acceptance cases are not reported experiments.
No cluster or network plugin was tested. The review distinguishes core NetworkPolicy from Cilium extensions. Host networking, NAT, node-local DNS, and existing connections need implementation-specific verification.
AI assistance. AI assistance was used for source research, drafting, editorial checks, and figure preparation. No human technical review or production experiment is claimed.
Published under the Cloud Security Desk organizational byline. Read the series policy.
References
- Kubernetes Network Policies Kubernetes. Accessed .
- Kubernetes network policy test walkthrough Kubernetes. Accessed .
- Kubernetes DNS for Services and Pods Kubernetes. Accessed .
- Cilium DNS policy documentation Cilium. Accessed .
- Kubernetes NetworkPolicy v1 API reference Kubernetes. Accessed .