Summary

  • Kubernetes describes a NetworkPolicy as desired behavior for selected Pods. Its ingress and egress rules are additive, and a Pod-to-Pod connection requires the relevant source egress and destination ingress allowance.
  • The same documentation limits the inference: a policy without an implementing network controller has no effect; handling is eventual, the API does not show exactly when it occurred, and changes to existing connections are implementation-defined.
  • A defensible statement about one flow needs distinct records for the policy revision, selector and endpoint state, network implementation, time-bounded connection observation, and any separate identity or application decision.

The words “default deny” can make a YAML object sound like a completed security result. They should not. Kubernetes NetworkPolicy is valuable precisely because it gives an operator a declarative control surface: selected Pods can become isolated for ingress, egress, or both, while policy rules describe the connections that remain allowed. That is a governance decision about the desired network boundary. It is not evidence that a named connection was actually denied, that an allowed connection was actually established, or that a workload was secure.

Kubernetes makes the first boundary in the resource model. NetworkPolicySpec represents desired behavior. A policy selects Pods, describes Ingress and Egress isolation, and supplies rules. The effects are additive rather than ordered overrides. Once a Pod is isolated for a direction, the permitted connections in that direction are the union of what all applicable policies allow. For a connection from one Pod to another, the source egress side and the destination ingress side must both allow it. That is an important rule for interpreting a policy set. It is not a record of the source address, destination address, port, protocol, time, process, packet path, or outcome of a connection.

Selector state is part of the boundary. A podSelector, namespaceSelector, or ipBlock is not a permanent list of concrete endpoints. Labels can change; Pods can be replaced; endpoint and Service machinery can change the path; and the documents caution that ingress and egress mechanisms may rewrite addresses. Where that happens, Kubernetes says it is not defined whether rewriting occurs before or after NetworkPolicy processing, and behavior can differ by network plugin, cloud provider, Service implementation, or their combination. A manifest can therefore explain a proposed scope without settling how a particular observed packet was represented at the enforcement point.

The implementation layer is separate again. Kubernetes says NetworkPolicy is implemented by the network plugin. It is explicit that creating the API object without a controller that implements NetworkPolicy has no effect. The API can still be present. This is not an accusation against an implementation or an administrator; it is a design fact that makes the evidence smaller. A cluster object establishes that an object was accepted by the API server. It does not establish which data-plane component was capable, configured, healthy, or active for that policy.

Timing matters even where the implementation is conformant. Kubernetes documents that a newly created NetworkPolicy will eventually be handled, but that the API offers no way to identify exactly when. It also describes a window in which distributed handling can leave Pods with slightly inconsistent views while Pods or policies change. The effect of a changed policy on an existing connection is implementation-defined. These are not loopholes. They are reasons to avoid asking a configuration snapshot to answer a runtime question it was not designed to preserve.

Protocol scope sets another limit. NetworkPolicy is defined for layer-4 TCP, UDP, and optionally SCTP connections. Kubernetes says behavior for other protocols may vary across network plugins. A policy that appears to draw a general network boundary must therefore not be reworded as a universal assertion about every packet type, every transport, every host-network path, every service mesh, or every identity check. Encryption, workload identity, authentication, DNS resolution, application authorization, and delivery remain different control surfaces unless separately evidenced.

Daniel Kade recommends a five-part flow receipt when the claim matters. First, preserve a policy revision: namespace, policy identifier, generation or immutable capture, selector expression, direction, rules, and observation time. Second, preserve the selector and endpoint state: the relevant Pod and Namespace labels, IP or endpoint mapping, and the exact time those states were read. Third, identify the network implementation and its declared NetworkPolicy capability, version, relevant configuration, and health evidence.

Fourth, record a time-bounded connection observation with its source and destination as observed, protocol, port, direction, result, collector, and known visibility limits. Fifth, retain a separate record for any workload identity, authorization, TLS, DNS, application response, or deployment claim. Sensitive details can remain protected; joining identities is not the same thing as publishing them.

This method protects ordinary outcomes from false narratives. A carefully written policy can be correct and an unrelated data-plane fault can still prevent a connection. A connection can be permitted by both NetworkPolicy directions and then fail DNS, TLS, authentication, application authorization, or a remote service. A policy change can be accepted by the API before a specific plugin has made it effective. A successful request can occur through a path that a reader has not reconstructed. None of these states proves a defect or an incident. They show why one configuration record should not be forced to carry the history of a network flow.

Sources

  1. Kubernetes — Network Policies
  2. Kubernetes — Services, Load Balancing, and Networking
  3. Kubernetes API reference — NetworkPolicy v1