Understanding Policy Rules

We've seen the building blocks: podSelector to target Pods, policyTypes to specify direction (ingress/egress), and from/to/ports to define allowed peers and protocols/ports. Now, let's clarify how these pieces work together, especially when multiple rules or policies apply to the same Pod.

1. Network Policies are Allowlist (Whitelist) Based

This is the most fundamental concept. Network Policies only define what traffic is allowed. They do not explicitly define "deny" rules. The denial happens implicitly:

  • If a Pod is not selected by any NetworkPolicy, all traffic is allowed (the default Kubernetes behavior).

  • If a Pod is selected by at least one NetworkPolicy for a specific direction (Ingress or Egress), then all traffic in that direction is denied by default, unless it is explicitly allowed by at least one of the rules in any of the policies selecting that Pod.

2. Multiple Policies Selecting the Same Pod: Union of Allows

What happens if multiple NetworkPolicies select the same Pod? For example, one policy allows ingress from frontend Pods, and another policy allows ingress from monitoring Pods to the same backend Pod.

The rules are additive. The Pod will allow traffic that matches the rules of any policy that selects it. In the example above, the backend Pod would accept ingress traffic from both frontend Pods and monitoring Pods (assuming port rules match). Think of it as a logical OR between different policies selecting the same pod.

3. from/to and ports within a Single Rule: AND Logic

Within a single ingress or egress rule block (e.g., one entry in the ingress: list), the from (or to) section and the ports section work together with logical AND.

  • Ingress Example: For an ingress rule like the one below:

    ingress:
    - from:
      - podSelector: {app: frontend}
      ports:
      - protocol: TCP
        port: 8080

    Traffic is allowed only if it comes from a Pod matching app=frontend AND it is destined for TCP port 8080 on the target Pod. Traffic from app=frontend to a different port would be denied (by this rule). Traffic from a different source to port 8080 would also be denied (by this rule).

4. Multiple Rules within ingress or egress: OR Logic

If you define multiple rule blocks within the ingress: or egress: list of a single policy, they act as a logical OR. Traffic is allowed if it matches any of these individual rule blocks.

  • Ingress Example:

    ingress:
    - from: # Rule 1
      - podSelector: {app: frontend}
      ports:
      - protocol: TCP
        port: 8080
    - from: # Rule 2
      - podSelector: {role: monitoring}
      ports:
      - protocol: TCP
        port: 9100

    This policy allows ingress traffic if:

    • (It comes from app=frontend AND targets port 8080) OR

    • (It comes from role=monitoring AND targets port 9100).

5. Multiple Peers within from or to: OR Logic

Within a single rule block, if you list multiple peers in the from or to section, these also act as a logical OR. The source (for ingress) or destination (for egress) only needs to match one of the specified peers.

  • Ingress Example:

    ingress:
    - from: # Allow from EITHER of these...
      - podSelector: {app: api-gateway}
      - ipBlock: {cidr: 192.168.1.0/24}
      ports: # ...to this port
      - protocol: TCP
        port: 5000

    This allows ingress to TCP port 5000 if the traffic comes from EITHER a Pod matching app=api-gateway OR from any IP within the 192.168.1.0/24 range.

Summary of Logic:

  • Between Policies selecting the same Pod: OR (Union of allows)

  • Between Rules within ingress/egress list: OR

  • Between Peers within a from/to list: OR

  • Between Peers (from/to) and ports within the same Rule: AND

Revisiting the Default Deny:

It's worth restating: if spec.policyTypes includes Ingress, and you define an ingress: section (even if it's empty like ingress: []), all ingress traffic to the selected Pods is denied unless specifically allowed by a rule. The same applies to Egress. This is how you establish a "default deny" posture – create a policy selecting Pods, include Ingress and/or Egress in policyTypes, but leave the corresponding ingress: or egress: sections empty or omit them entirely.

# Example: Default Deny Ingress for all pods in the namespace
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: default-deny-ingress
  namespace: my-secure-ns
spec:
  podSelector: {} # Selects all pods in the namespace
  policyTypes:
  - Ingress      # Apply to ingress direction
  # NO ingress: rules defined, so all ingress is denied by default

Last updated

Was this helpful?