CKA — NetworkPolicies

7 minute read

CKA Exam Domain

Services & Networking — 20%

NetworkPolicies are a high-frequency CKA exam topic. You’ll almost certainly get at least one question asking you to create a policy that allows or denies specific traffic. Practice writing these from scratch — the YAML structure is tricky to memorize.

What Are NetworkPolicies?

A NetworkPolicy is a Kubernetes resource that controls network traffic to and from Pods. Think of it as a firewall for your Pods.

By default, Kubernetes allows all traffic between all Pods in the cluster — any Pod can talk to any other Pod, in any namespace. NetworkPolicies let you restrict this.

Key concepts:

  • Ingress rules control incoming traffic to selected Pods
  • Egress rules control outgoing traffic from selected Pods
  • Policies are namespace-scoped — they apply to Pods in the same namespace
  • Policies are additive — if multiple policies select the same Pod, the union of all rules applies
  • Once a Pod is selected by any NetworkPolicy, all traffic not explicitly allowed is denied

CNI Requirement

Important: NetworkPolicies only work if your cluster’s CNI (Container Network Interface) plugin supports them.

CNI Plugin NetworkPolicy Support
Calico Yes
Cilium Yes
Weave Net Yes
Flannel No
Canal (Flannel + Calico) Yes

If your cluster uses Flannel, NetworkPolicy resources will be created but won’t be enforced. The CKA exam environments typically use a CNI that supports NetworkPolicies.

Ingress Rules

Ingress rules control incoming traffic to the selected Pods. Here’s a complete example:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: allow-api-to-web
  namespace: default
spec:
  podSelector:
    matchLabels:
      app: web                     # This policy applies to Pods with app=web
  policyTypes:
  - Ingress
  ingress:
  - from:
    - podSelector:
        matchLabels:
          app: api                 # Allow traffic FROM Pods with app=api
    ports:
    - protocol: TCP
      port: 80                    # Only on port 80

This policy says: Pods labeled app: web can receive TCP traffic on port 80 only from Pods labeled app: api.

All other incoming traffic to app: web Pods is denied.

Breaking Down the Spec

Field Purpose
spec.podSelector Which Pods this policy applies to (the “target”)
spec.policyTypes Which direction(s) the policy controls: Ingress, Egress, or both
spec.ingress[].from List of allowed sources
spec.ingress[].ports List of allowed ports

Egress Rules

Egress rules control outgoing traffic from the selected Pods:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: api-egress
  namespace: default
spec:
  podSelector:
    matchLabels:
      app: api
  policyTypes:
  - Egress
  egress:
  - to:
    - podSelector:
        matchLabels:
          app: database
    ports:
    - protocol: TCP
      port: 5432
  - to:                            # Second egress rule: allow DNS
    ports:
    - protocol: UDP
      port: 53
    - protocol: TCP
      port: 53

This policy says: Pods labeled app: api can send traffic to app: database Pods on port 5432, and to any destination on port 53 (DNS).

Critical: Always allow DNS (port 53) in egress policies, or your Pods won’t be able to resolve Service names.

Selectors

NetworkPolicies use three types of selectors to specify traffic sources and destinations:

podSelector

Select Pods by labels within the same namespace:

from:
- podSelector:
    matchLabels:
      app: frontend

namespaceSelector

Select all Pods in namespaces matching the label:

from:
- namespaceSelector:
    matchLabels:
      env: production

This allows traffic from all Pods in namespaces labeled env: production.

ipBlock

Select traffic by IP CIDR range:

from:
- ipBlock:
    cidr: 172.17.0.0/16
    except:
    - 172.17.1.0/24              # Exclude this subnet

Combining Selectors

Watch out — the YAML structure matters:

# AND logic — Pod must match BOTH selectors
from:
- podSelector:
    matchLabels:
      app: api
  namespaceSelector:
    matchLabels:
      env: prod

# OR logic — Pod can match EITHER selector
from:
- podSelector:
    matchLabels:
      app: api
- namespaceSelector:
    matchLabels:
      env: prod

The difference is subtle but critical:

Structure Logic Meaning
Single list item with both selectors AND Pods labeled app: api AND in namespace labeled env: prod
Two separate list items OR Pods labeled app: api OR any Pod in namespace labeled env: prod

Default Deny All

The most common exam pattern. Create a policy that blocks all traffic and then selectively allow what you need.

Default Deny All Ingress

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: default-deny-ingress
  namespace: default
spec:
  podSelector: {}                  # Selects ALL Pods in the namespace
  policyTypes:
  - Ingress
  # No ingress rules = deny all incoming

Default Deny All Egress

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: default-deny-egress
  namespace: default
spec:
  podSelector: {}
  policyTypes:
  - Egress
  # No egress rules = deny all outgoing

Default Deny All (Both Directions)

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: default-deny-all
  namespace: default
spec:
  podSelector: {}
  policyTypes:
  - Ingress
  - Egress

Exam tip: Start with a default deny policy, then create additional policies to whitelist specific traffic. This is the standard security pattern.

Allow Specific Traffic

After setting up default deny, create targeted policies to allow only what’s needed:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: web-policy
  namespace: default
spec:
  podSelector:
    matchLabels:
      app: web
  policyTypes:
  - Ingress
  - Egress
  ingress:
  - from:
    - podSelector:
        matchLabels:
          app: frontend
    ports:
    - protocol: TCP
      port: 80
  - from:
    - namespaceSelector:
        matchLabels:
          name: monitoring
    ports:
    - protocol: TCP
      port: 9090
  egress:
  - to:
    - podSelector:
        matchLabels:
          app: database
    ports:
    - protocol: TCP
      port: 5432
  - to:                            # Allow DNS resolution
    ports:
    - protocol: UDP
      port: 53
    - protocol: TCP
      port: 53

This policy:

  • Allows app: frontend Pods to access app: web on port 80
  • Allows monitoring namespace Pods to access app: web on port 9090
  • Allows app: web to connect to app: database on port 5432
  • Allows app: web to make DNS queries

NetworkPolicy Gotchas

These are the mistakes that cost you points on the exam:

1. Policies Are Namespace-Scoped

A NetworkPolicy in namespace default only affects Pods in default. To protect Pods in production, create a separate policy there.

2. Policies Are Additive

If two policies select the same Pod, the allowed traffic is the union of both policies. There’s no way for one policy to override or negate another.

3. Empty podSelector Means All Pods

spec:
  podSelector: {}    # Matches ALL Pods in the namespace

4. DNS Must Be Explicitly Allowed

When you create an egress policy, DNS traffic is also blocked. If your Pods need to resolve Service names, you must allow port 53:

egress:
- to:
  ports:
  - protocol: UDP
    port: 53
  - protocol: TCP
    port: 53

5. No from/to = Allow All

An ingress rule with no from field allows traffic from everywhere:

ingress:
- ports:
  - protocol: TCP
    port: 80
# No "from" = allow from ANY source on port 80

6. policyTypes Matters

If you specify policyTypes: [Ingress] but don’t include any ingress rules, all ingress is denied. The same applies for Egress. If you omit policyTypes, it’s inferred:

  • If ingress rules are present → Ingress type is implied
  • If egress rules are present → Egress type is implied

Best practice: Always explicitly set policyTypes to avoid ambiguity.

kubectl Commands

# List all NetworkPolicies in the current namespace
kubectl get networkpolicies

# List NetworkPolicies across all namespaces
kubectl get networkpolicies -A

# Describe a specific policy
kubectl describe networkpolicy deny-all

# Create from YAML
kubectl apply -f network-policy.yaml

# Delete a policy
kubectl delete networkpolicy deny-all

Practice Questions

Q1. Create a default deny all ingress NetworkPolicy for the production namespace.

Show Answer
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: default-deny-ingress
  namespace: production
spec:
  podSelector: {}
  policyTypes:
  - Ingress

This selects all Pods in the production namespace and blocks all incoming traffic (no ingress rules defined).

Q2. Create a NetworkPolicy that allows Pods labeled role: api to receive traffic from Pods labeled role: frontend on port 8080.

Show Answer
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: allow-frontend-to-api
  namespace: default
spec:
  podSelector:
    matchLabels:
      role: api
  policyTypes:
  - Ingress
  ingress:
  - from:
    - podSelector:
        matchLabels:
          role: frontend
    ports:
    - protocol: TCP
      port: 8080

Q3. What is the difference between AND and OR logic in NetworkPolicy selectors?

Show Answer

AND logic — both selectors in a single from/to entry:

from:
- podSelector:
    matchLabels:
      app: api
  namespaceSelector:
    matchLabels:
      env: prod

Means: Pods that are labeled app: api AND are in a namespace labeled env: prod.

OR logic — separate entries in the from/to list:

from:
- podSelector:
    matchLabels:
      app: api
- namespaceSelector:
    matchLabels:
      env: prod

Means: Pods labeled app: api OR any Pod in a namespace labeled env: prod.

Q4. Why must you allow DNS (port 53) in egress NetworkPolicies?

Show Answer

When you create an egress NetworkPolicy, all outgoing traffic not explicitly allowed is denied — including DNS queries. Pods need DNS to resolve Service names to ClusterIPs. Without allowing port 53 (both UDP and TCP), Pods won’t be able to reach Services by name even if the actual service port is allowed.

egress:
- to:
  ports:
  - protocol: UDP
    port: 53
  - protocol: TCP
    port: 53

Q5. Which CNI plugins support NetworkPolicies? Which one does NOT?

Show Answer

Support NetworkPolicies: Calico, Cilium, Weave Net, Canal (Flannel + Calico)

Does NOT support NetworkPolicies: Flannel

With Flannel, you can create NetworkPolicy resources, but they won’t be enforced — all traffic will still flow freely.

Updated: