Skip to content

Lab 04 — Network Policies

In the previous labs, you secured Kubernetes in several layers:

Lab 01
Kubernetes Fundamentals
Understand Resources
Lab 02
Kubernetes RBAC
Control Identity and Permissions
Lab 03
Kyverno
Control Workload Configuration

Now you will secure:

Workload Communication

This lab focuses on Kubernetes NetworkPolicy.

The key question is:

Which workloads
should be allowed
to communicate?

Without proper segmentation, a compromised workload may be able to communicate with systems it never legitimately needed to reach.

Your goal is to move from:

Broad Internal Connectivity

to:

Explicitly Allowed Communication

Difficulty: Intermediate

Estimated Time: 90–120 minutes

Primary Skills:

Kubernetes Networking
NetworkPolicy
Ingress Controls
Egress Controls
Default-Deny
Pod Selectors
Namespace Selectors
Application Segmentation
Connectivity Validation
Network Troubleshooting

Your organization is running a three-tier application in Kubernetes.

The application architecture is:

Frontend
Backend API
Database

The security team has discovered that workloads inside the application namespace can communicate more broadly than required.

Your mission is to enforce the following communication model:

Frontend → Backend
Backend → Database

while preventing unnecessary communication such as:

Frontend → Database
Unknown Pod → Backend
Unknown Pod → Database

You will implement this gradually so that you can observe how each policy changes the network behavior.

By the end of this lab, you should be able to:

  • Explain Kubernetes NetworkPolicy
  • Understand Pod-to-Pod communication
  • Understand ingress and egress
  • Identify required application flows
  • Use Pod labels in network policy
  • Implement default-deny policies
  • Allow specific application traffic
  • Restrict unnecessary lateral movement
  • Understand namespace-based segmentation
  • Validate allowed and denied communication
  • Troubleshoot NetworkPolicy behavior
  • Document network-security findings
  • Apply least-connectivity principles

The objective is similar to least privilege.

For identity:

Minimum Required Permissions

For networking:

Minimum Required Communication

This can be thought of as:

Least Privilege
+
Least Connectivity

You will build:

Kubernetes Cluster
└── ghc-network-lab
├── Frontend
│ ↓
│ frontend-service
├── Backend
│ ↓
│ backend-service
├── Database
│ ↓
│ database-service
└── Test Client

Required flow:

Frontend
Backend
Database

Blocked flow:

Frontend ─X─> Database

and:

Unknown Workload ─X─> Backend

You need:

Authorized Kubernetes Training Cluster
kubectl
Permission to Create:
Namespaces
Deployments
Services
NetworkPolicies

Your Kubernetes networking implementation must support NetworkPolicy.

Not every networking plugin enforces NetworkPolicy in the same way.

NetworkPolicy resources may exist in Kubernetes even if the underlying network implementation does not actually enforce them.

Therefore this lab has two levels of validation:

Policy Object Exists
Network Behavior Changes

You must verify both.

Perform this lab only in:

Your Own Cluster
Training Cluster
Explicitly Authorized Environment

Network policies can break legitimate application traffic.

In production, policy changes should include:

Application Flow Mapping
Testing
Change Approval
Rollback Planning
Monitoring

Part 01 — Understand Kubernetes Networking

Section titled “Part 01 — Understand Kubernetes Networking”

Kubernetes generally gives Pods network connectivity through the cluster networking layer.

Conceptually:

Pod A
Pod B
Pod C

Without additional segmentation, workloads may have broader internal reachability than required.

This creates potential:

Lateral Movement

Suppose:

Internet
Frontend Vulnerability
Frontend Pod Compromised

If the frontend can communicate freely with:

Backend
Database
Monitoring
Other Applications

the attacker’s opportunity increases.

Frontend
Only Backend
Backend
Only Database
Database
Only Required Clients

A NetworkPolicy defines which network connections are permitted for selected Pods.

Conceptually:

Selected Pod
NetworkPolicy
Allowed Sources / Destinations
Allowed Ports

NetworkPolicy can regulate:

Ingress

and:

Egress

Ingress means:

Traffic Coming Into a Pod

Example:

Frontend → Backend

From the backend’s perspective:

Ingress

Egress means:

Traffic Leaving a Pod

Example:

Backend → Database

From the backend’s perspective:

Egress

For every policy ask:

Which Pods Are Selected?
Which Direction?
Who Is Allowed?
Which Port?
Which Protocol?

Think:

podSelector
Selected Workload
policyTypes
Ingress / Egress
ingress / egress
Allowed Flows

Check:

Terminal window
kubectl config current-context

Then:

Terminal window
kubectl cluster-info

Confirm:

Correct Cluster
Correct Context
Training Environment

List the API resource:

Terminal window
kubectl api-resources | grep -i networkpolicy

You should see:

networkpolicies

This confirms the Kubernetes API supports the object.

It does not yet prove the network plugin enforces it.

That will be validated later through connectivity tests.

Create:

Terminal window
kubectl create namespace ghc-network-lab

Set your working namespace:

Terminal window
kubectl config set-context --current --namespace=ghc-network-lab

Verify:

Terminal window
kubectl config view --minify

Create:

frontend.yaml

Add:

apiVersion: apps/v1
kind: Deployment
metadata:
name: frontend
namespace: ghc-network-lab
spec:
replicas: 1
selector:
matchLabels:
app: frontend
template:
metadata:
labels:
app: frontend
tier: frontend
spec:
containers:
- name: frontend
image: nginx
ports:
- containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
name: frontend-service
namespace: ghc-network-lab
spec:
selector:
app: frontend
ports:
- port: 80
targetPort: 80

Apply:

Terminal window
kubectl apply -f frontend.yaml

Create:

backend.yaml

Add:

apiVersion: apps/v1
kind: Deployment
metadata:
name: backend
namespace: ghc-network-lab
spec:
replicas: 1
selector:
matchLabels:
app: backend
template:
metadata:
labels:
app: backend
tier: backend
spec:
containers:
- name: backend
image: nginx
ports:
- containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
name: backend-service
namespace: ghc-network-lab
spec:
selector:
app: backend
ports:
- port: 80
targetPort: 80

Apply:

Terminal window
kubectl apply -f backend.yaml

For this networking lab, you can use another simple HTTP workload to simulate the database network endpoint.

Create:

database.yaml

Add:

apiVersion: apps/v1
kind: Deployment
metadata:
name: database
namespace: ghc-network-lab
spec:
replicas: 1
selector:
matchLabels:
app: database
template:
metadata:
labels:
app: database
tier: database
spec:
containers:
- name: database
image: nginx
ports:
- containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
name: database-service
namespace: ghc-network-lab
spec:
selector:
app: database
ports:
- port: 80
targetPort: 80

Apply:

Terminal window
kubectl apply -f database.yaml

The purpose of this lab is network segmentation rather than database administration.

You need three reachable tiers:

Frontend
Backend
Database

to test network controls safely.

Run:

Terminal window
kubectl get pods

Then:

Terminal window
kubectl get services

Check labels:

Terminal window
kubectl get pods --show-labels

You should see:

app=frontend
app=backend
app=database

NetworkPolicies frequently depend on:

Pod Labels

A wrong label can produce:

Policy Not Applied

or:

Wrong Workload Selected

Create a temporary client workload.

Create:

test-client.yaml

Add:

apiVersion: apps/v1
kind: Deployment
metadata:
name: test-client
namespace: ghc-network-lab
spec:
replicas: 1
selector:
matchLabels:
app: test-client
template:
metadata:
labels:
app: test-client
tier: test
spec:
containers:
- name: client
image: curlimages/curl
command:
- sleep
- "3600"

Apply:

Terminal window
kubectl apply -f test-client.yaml

Verify:

Terminal window
kubectl get pods

Get the test-client Pod name:

Terminal window
kubectl get pods -l app=test-client

Open a shell:

Terminal window
kubectl exec -it <test-client-pod> -- sh

From inside the Pod, test:

Terminal window
curl frontend-service

Then:

Terminal window
curl backend-service

Then:

Terminal window
curl database-service

Before policies are applied, your cluster may allow all three.

Use:

Test Client → Frontend:
Allowed / Denied
Test Client → Backend:
Allowed / Denied
Test Client → Database:
Allowed / Denied

If everything is reachable:

Unknown Application Workload
Can Reach Every Tier

This illustrates broad east-west connectivity.

Get the frontend Pod:

Terminal window
kubectl get pods -l app=frontend

Run:

Terminal window
kubectl exec -it <frontend-pod> -- sh

If the image includes an HTTP client, use it.

If not, perform tests using your dedicated test client with appropriate labels, or use a lab-approved debugging image.

The target connectivity model is:

Frontend → Backend

and not:

Frontend → Database

Part 14 — Map Required Communication Before Blocking

Section titled “Part 14 — Map Required Communication Before Blocking”

Before creating policies, document required flows.

Use:

Source Destination Port Required?
Frontend Backend 80 Yes
Frontend Database 80 No
Backend Database 80 Yes
Test Client Backend 80 No
Test Client Database 80 No

Never start segmentation with:

Block Random Traffic

Start with:

Understand Required Traffic

then implement controls.

Create:

default-deny-ingress.yaml

Add:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: default-deny-ingress
namespace: ghc-network-lab
spec:
podSelector: {}
policyTypes:
- Ingress

Apply:

Terminal window
kubectl apply -f default-deny-ingress.yaml

It selects:

All Pods

in the namespace.

Conceptually:

All Pods Selected
Ingress Isolated
No Ingress Allowed
Unless Another Policy Allows It

From the test client, try:

Terminal window
curl backend-service

and:

Terminal window
curl database-service

They should no longer succeed if NetworkPolicy is being enforced.

If traffic continues to work exactly as before:

NetworkPolicy Object Exists

but:

Policy May Not Be Enforced

Investigate the network implementation in your training cluster.

Run:

Terminal window
kubectl get networkpolicies

Then:

Terminal window
kubectl describe networkpolicy default-deny-ingress

Inspect YAML:

Terminal window
kubectl get networkpolicy default-deny-ingress -o yaml

Create:

allow-frontend-to-backend.yaml

Add:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-frontend-to-backend
namespace: ghc-network-lab
spec:
podSelector:
matchLabels:
app: backend
policyTypes:
- Ingress
ingress:
- from:
- podSelector:
matchLabels:
app: frontend
ports:
- protocol: TCP
port: 80

Apply:

Terminal window
kubectl apply -f allow-frontend-to-backend.yaml

Selected destination:

Backend Pods

Allowed source:

Frontend Pods

Allowed port:

TCP 80
Frontend
│ TCP 80
Backend

but:

Test Client ─X─> Backend

Test the allowed path using an appropriate frontend-labelled client or the actual frontend workload if it contains suitable tools.

Expected:

Frontend → Backend
Allowed

Then test:

Test Client → Backend

Expected:

Denied

You now have:

Identity-Based Traffic Selection

through Pod labels.

Create:

allow-backend-to-database.yaml

Add:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-backend-to-database
namespace: ghc-network-lab
spec:
podSelector:
matchLabels:
app: database
policyTypes:
- Ingress
ingress:
- from:
- podSelector:
matchLabels:
app: backend
ports:
- protocol: TCP
port: 80

Apply:

Terminal window
kubectl apply -f allow-backend-to-database.yaml
Backend → Database
Allowed

while:

Frontend ─X─> Database

and:

Test Client ─X─> Database

Part 21 — Full Allowed Communication Model

Section titled “Part 21 — Full Allowed Communication Model”

Your allowed paths are now:

Frontend
Backend
Database

Unnecessary direct paths should remain unavailable.

Before:

Frontend ──────────────→ Database
├──────────────→ Backend
Test Client ──────→ Everything

After:

Frontend → Backend → Database

Attempt:

Frontend → Database

Expected:

Denied

The database policy allows ingress only from:

app=backend

The frontend has:

app=frontend

Therefore it does not match.

NetworkPolicies are generally additive.

Suppose one policy allows:

Frontend → Backend

and another allows:

Monitoring → Backend

The backend may receive traffic from both permitted sources.

Think:

Allowed by Policy A
+
Allowed by Policy B
Effective Allowed Traffic

This is conceptually similar to cumulative RBAC permissions.

Part 24 — Multiple Policies and Security Review

Section titled “Part 24 — Multiple Policies and Security Review”

Do not inspect only one policy.

Ask:

Which Policies Select This Pod?

Then determine:

What Is the Combined Effective Access?

So far, you have focused mainly on inbound traffic.

Now consider outbound traffic.

A compromised Pod might attempt:

Malicious Download
Command-and-Control
Data Exfiltration

Create:

default-deny-egress.yaml

Add:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: default-deny-egress
namespace: ghc-network-lab
spec:
podSelector: {}
policyTypes:
- Egress

Apply:

Terminal window
kubectl apply -f default-deny-egress.yaml

This will isolate egress for selected Pods.

It may also affect:

DNS

which means service names may stop resolving.

This is an important real-world lesson.

After default-deny egress, attempt:

Terminal window
curl backend-service

You may see a failure related to name resolution.

Why?

Because:

Application
Needs DNS
DNS Traffic Blocked

Policy design must include supporting infrastructure.

Do not think only:

Application Port

Think:

Application Dependencies

Service discovery often depends on cluster DNS.

Conceptually:

Frontend
backend-service
DNS Resolution
Service IP
Backend

If DNS is blocked:

Application Communication Fails

even if the application traffic itself is allowed.

A production-grade DNS policy should be designed for the DNS service and network architecture in your cluster.

For training, first identify the cluster DNS service:

Terminal window
kubectl get services -n kube-system

Look for the DNS service used by your environment.

Then design egress allowing:

UDP 53
TCP 53

toward the appropriate DNS destination.

Do not blindly hardcode DNS IP addresses from another environment.

Discover:

Your Cluster DNS

first.

DNS commonly uses:

UDP 53

but can also use:

TCP 53

Therefore mature policies often consider both.

Part 30 — Allow Frontend Egress to Backend

Section titled “Part 30 — Allow Frontend Egress to Backend”

Create a policy selecting:

app=frontend

and allow outbound traffic toward:

app=backend

on:

TCP 80

Conceptually:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: frontend-egress
namespace: ghc-network-lab
spec:
podSelector:
matchLabels:
app: frontend
policyTypes:
- Egress
egress:
- to:
- podSelector:
matchLabels:
app: backend
ports:
- protocol: TCP
port: 80

You must also account for DNS if service-name resolution is required.

Part 31 — Allow Backend Egress to Database

Section titled “Part 31 — Allow Backend Egress to Database”

Similarly:

Backend
Database

Create a policy selecting:

app=backend

with egress toward:

app=database

on the required port.

For traffic to succeed in a fully isolated design, consider both sides:

Source Egress
+
Destination Ingress

Example:

Frontend

must be allowed to send:

Egress → Backend

and backend must allow:

Ingress ← Frontend

Think:

Frontend Egress
Network
Backend Ingress

Part 33 — Application Communication Matrix

Section titled “Part 33 — Application Communication Matrix”

Create a matrix like:

Source Destination Ingress Required Egress Required Result
Frontend Backend Yes Yes Allow
Frontend Database No No Block
Backend Database Yes Yes Allow
Test Client Backend No No Block
Test Client Database No No Block

This is an excellent enterprise design technique.

NetworkPolicies can also use:

namespaceSelector

This can allow traffic based on namespace labels.

Example architecture:

monitoring Namespace
Application Namespace

The application may need to allow monitoring traffic without identifying every monitoring Pod individually.

Inspect:

Terminal window
kubectl get namespace ghc-network-lab --show-labels

Add a training label if desired:

Terminal window
kubectl label namespace ghc-network-lab environment=training

Verify:

Terminal window
kubectl get namespace ghc-network-lab --show-labels

Part 36 — Namespace-Based Policy Thinking

Section titled “Part 36 — Namespace-Based Policy Thinking”

Suppose:

monitoring Namespace

has:

purpose=monitoring

A policy could conceptually allow traffic from:

namespaceSelector:
purpose=monitoring

Do not use overly broad namespace selectors.

For example:

Any Namespace

may unintentionally reopen the application.

Part 37 — Combine Namespace and Pod Selection

Section titled “Part 37 — Combine Namespace and Pod Selection”

A strong policy can conceptually require:

Namespace = monitoring
AND
Pod = approved-monitor

This is more specific than allowing an entire broad namespace population.

NetworkPolicy can also represent some IP-based network requirements using IP blocks.

Conceptually:

Pod
Allowed External CIDR

This may be useful for controlled egress patterns.

IP-based policy needs careful consideration around:

NAT
Cloud Networking
Service Routing
External Address Changes

Do not assume an IP-based rule always represents application identity.

A common segmentation strategy is:

01 Default Deny
02 Identify Required Flows
03 Add Explicit Allows
04 Validate
05 Monitor

This produces a stronger baseline than:

Allow Everything
Try to Block Bad Traffic Individually

Default-deny is powerful but can break:

DNS
Monitoring
Logging
Service Mesh
Health Checks
External APIs
Package Repositories
Cloud Metadata Access
Management Traffic

Therefore:

Map Dependencies First

If traffic fails unexpectedly, use:

01 Source Pod Healthy?
02 Destination Pod Healthy?
03 Service Correct?
04 DNS Working?
05 NetworkPolicy Selecting Pod?
06 Ingress Allowed?
07 Egress Allowed?
08 Correct Labels?
09 Correct Port?
10 Network Plugin Enforcing Policy?

Run:

Terminal window
kubectl get networkpolicies

Then inspect each:

Terminal window
kubectl describe networkpolicy <policy-name>
Pod Selector
Policy Types
Allowed Sources
Allowed Destinations
Ports

Run:

Terminal window
kubectl get pods --show-labels

Compare labels with:

podSelector

A common issue is:

Policy Expects:
app=backend
Pod Has:
app=backend-api

The policy will not select the intended workload.

If connectivity is failing:

Terminal window
kubectl get endpoints

or:

Terminal window
kubectl get endpointslices

Confirm the Service has healthy backend Pods.

Not every network failure is caused by NetworkPolicy.

You must separate:

Application Problem
Service Problem
DNS Problem
Policy Problem

Part 45 — Controlled Troubleshooting Exercise

Section titled “Part 45 — Controlled Troubleshooting Exercise”

Modify the backend allow policy temporarily so it expects:

app=front-end

instead of:

app=frontend

Test communication.

Expected:

Frontend → Backend
Fails

Check:

Terminal window
kubectl get pods --show-labels

Then:

Terminal window
kubectl describe networkpolicy allow-frontend-to-backend

Compare:

Policy Selector
vs
Actual Labels

Change it back to:

app=frontend

Validate connectivity again.

You followed:

Symptom
Identify Source
Identify Destination
Inspect Labels
Inspect Policy
Find Selector Mismatch
Repair
Validate

Suppose the original application had no NetworkPolicies.

Document:

Finding:
Kubernetes Application Lacks Network Segmentation
Affected Namespace:
ghc-network-lab
Observation:
Application workloads can communicate
with unrelated workloads without explicit
network restrictions.
Threat Scenario:
If an application Pod is compromised,
an attacker may be able to communicate
with additional internal services
and attempt lateral movement.
Business Impact:
Compromise of one workload could increase
risk to other application tiers.
Risk:
High
Recommendation:
Implement default-deny controls
and explicitly allow only required
application communication paths.

Part 47 — Finding: Frontend Can Reach Database

Section titled “Part 47 — Finding: Frontend Can Reach Database”

Another example:

Finding:
Frontend Workload Has Unnecessary
Direct Access to Database Tier
Expected Flow:
Frontend → Backend → Database
Observed Flow:
Frontend → Database
Risk:
High
Threat Scenario:
Compromise of the internet-facing frontend
could provide direct network reachability
to the database tier.
Recommendation:
Restrict database ingress so only
authorized backend workloads can connect.

Part 48 — Network Security Finding Template

Section titled “Part 48 — Network Security Finding Template”

Use:

Finding:
Affected Namespace:
Affected Source:
Affected Destination:
Observed Flow:
Expected Flow:
Port / Protocol:
Evidence:
Threat Scenario:
Business Impact:
Risk:
Recommendation:
Validation:

Capture:

Namespace
Pods and Labels
Services
Baseline Connectivity
NetworkPolicies
Default-Deny Results
Allowed Frontend-to-Backend Test
Blocked Frontend-to-Database Test
Allowed Backend-to-Database Test
Blocked Test-Client Traffic
Troubleshooting Evidence
Final Connectivity Matrix
Lab:
Kubernetes Network Policies
Date:
Cluster:
Namespace:
Baseline Connectivity:
Default-Deny Applied:
Required Flow 01:
Frontend → Backend
Result:
Required Flow 02:
Backend → Database
Result:
Blocked Flow 01:
Frontend → Database
Result:
Blocked Flow 02:
Test Client → Backend
Result:
Finding:
Remediation:
Validation:

Before segmentation:

Internet
Frontend
Backend
Database

But potentially also:

Frontend ─────────→ Database
└──────────────→ Other Workloads

After segmentation:

Internet
Frontend
Backend
Database

with unnecessary paths removed.

You reduced:

Lateral Movement Opportunities

RBAC controls:

API Permissions

NetworkPolicy controls:

Network Communication

A workload could have:

No Kubernetes API Permissions

but still have:

Network Access to Sensitive Services

Therefore both controls matter.

Kyverno can enforce that application teams deploy required network controls.

For example, an organization may require:

Production Namespace
NetworkPolicy Baseline

This combines:

Policy Governance
+
Network Enforcement

Part 53 — NetworkPolicy and Service Accounts

Section titled “Part 53 — NetworkPolicy and Service Accounts”

Kubernetes network policies usually identify network entities primarily through workload and namespace selectors rather than service-account RBAC permissions.

But architecturally you should evaluate both:

Who Is the Workload?

and:

Where Can the Workload Communicate?
Workload
Service Account
API Permission

plus:

Workload
NetworkPolicy
Network Reachability

Suppose a frontend cannot read a database Secret from Kubernetes.

That is good.

But if it can still directly reach the database and somehow obtains valid credentials through another path:

Frontend
Database

network segmentation could have provided another defensive layer.

This is:

Defense in Depth

Part 55 — NetworkPolicy and Runtime Security

Section titled “Part 55 — NetworkPolicy and Runtime Security”

NetworkPolicy attempts to control:

What Network Communication
Should Be Possible

Runtime monitoring helps identify:

What Communication
Actually Occurs

Example:

Unexpected External Connection
Runtime / Network Alert

Together:

Prevent
+
Detect

Suppose a compromised application reads sensitive data.

Without egress restrictions:

Compromised Pod
Internet
Attacker Infrastructure

With carefully designed egress:

Compromised Pod
Only Approved Destinations

This can reduce some exfiltration opportunities.

Part 57 — Egress and Command-and-Control

Section titled “Part 57 — Egress and Command-and-Control”

Malicious software may attempt:

External Connection

to obtain:

Commands
Payloads
Updates

Egress controls can reduce unnecessary external connectivity.

For each workload ask:

Does It Need Internet Access?
Which Domains / Destinations?
Which Ports?
Which Cloud APIs?
Which Internal Services?
Does It Need DNS?

Part 59 — Production Communication Inventory

Section titled “Part 59 — Production Communication Inventory”

A mature organization maintains application flow information.

Example:

Application Source Destination Port Purpose
Storefront Frontend API 443 API requests
Storefront API Database 5432 Data access
Storefront API Payment API 443 Payment processing

This becomes the basis for segmentation.

Apply:

Only Required Sources
Only Required Destinations
Only Required Ports

Avoid:

Any Source
Any Destination
Any Port

unless genuinely required.

Part 61 — Network Security Review Workflow

Section titled “Part 61 — Network Security Review Workflow”

Use:

01 Identify Workloads
02 Map Application Tiers
03 Identify Required Flows
04 Record Ports and Protocols
05 Identify External Dependencies
06 Review Existing Policies
07 Identify Unnecessary Reachability
08 Implement Default-Deny
09 Add Required Allows
10 Validate
11 Monitor

For every NetworkPolicy ask:

Which Pods Does It Select?
Is It Ingress or Egress?
Who Is Allowed?
Which Ports?
Which Namespaces?
Is the Rule Too Broad?
Is There Another Policy Adding Access?

Part 63 — Common Mistake: Wrong podSelector

Section titled “Part 63 — Common Mistake: Wrong podSelector”

Policy:

app=database

Pod:

app=db

Result:

Policy Does Not Select Database

Always validate labels.

Part 64 — Common Mistake: Forgetting DNS

Section titled “Part 64 — Common Mistake: Forgetting DNS”

After default-deny egress:

Service Names Stop Resolving

because DNS was not allowed.

This is one of the most useful lessons from egress-policy testing.

Part 65 — Common Mistake: Assuming Service Controls Traffic

Section titled “Part 65 — Common Mistake: Assuming Service Controls Traffic”

A Kubernetes Service provides routing and discovery.

It is not itself the same as:

Security Segmentation

Use NetworkPolicy for supported workload-level communication controls.

Part 66 — Common Mistake: Only Controlling Ingress

Section titled “Part 66 — Common Mistake: Only Controlling Ingress”

Ingress reduces inbound attack paths.

But egress may still allow:

External Command-and-Control
Data Exfiltration
Unnecessary Internal Access

Assess both directions.

Part 67 — Common Mistake: Overly Broad Namespace Access

Section titled “Part 67 — Common Mistake: Overly Broad Namespace Access”

Allowing:

All Pods From Namespace X

may be broader than necessary.

Consider whether:

Only Specific Pods

actually need access.

A YAML file existing does not prove security.

Always perform:

Allowed Traffic Test
Blocked Traffic Test

For each rule test:

Expected Allowed Flow

and:

Expected Blocked Flow

Example:

Frontend → Backend
Allowed

and:

Frontend → Database
Denied

Organizations can track:

Namespaces With Default-Deny
Workloads Covered by Policies
Unrestricted Egress
Policy Violations
Approved Exceptions

These help measure segmentation maturity.

A control requirement may state:

Production workloads must
be appropriately segmented.

Evidence could include:

NetworkPolicy Configuration
Application Flow Matrix
Connectivity Validation
Change Records

Do not immediately apply aggressive default-deny policies everywhere.

Use:

Map
Observe
Test
Restrict
Validate
Monitor
01 Development
02 Testing
03 Selected Production Workload
04 Wider Production Rollout

Part 73 — NetworkPolicy Troubleshooting Challenge

Section titled “Part 73 — NetworkPolicy Troubleshooting Challenge”

Scenario:

Frontend cannot reach Backend.

Use:

Is Frontend Running?
Can DNS Resolve Backend?
Does Service Have Endpoints?
Does Backend Ingress Allow Frontend?
Does Frontend Egress Allow Backend?
Do Labels Match?
Is Port 80 Allowed?

Scenario:

Test Client can still reach Database
after segmentation.

Investigate:

Which Policies Select Database?
Does Another Policy Allow Test Client?
Is Database Actually Selected?
Are Labels Correct?
Is NetworkPolicy Being Enforced?

Scenario:

curl backend-service
fails after egress isolation.

But using a direct IP behaves differently.

Likely investigation area:

DNS Egress

Your final desired matrix should resemble:

Source Frontend Backend Database
Frontend As Required Allow Deny
Backend Deny/As Required As Required Allow
Database Deny Deny/As Required As Required
Test Client Deny/As Required Deny Deny

Exact requirements vary by application.

The key is:

Explicit Business Requirement

rather than:

Default Broad Reachability

Capture your evidence first.

List policies:

Terminal window
kubectl get networkpolicies

Then delete the training namespace:

Terminal window
kubectl delete namespace ghc-network-lab

Verify:

Terminal window
kubectl get namespace ghc-network-lab

If required:

Terminal window
kubectl config set-context --current --namespace=default

Verify:

Terminal window
kubectl config view --minify
  • Verified Kubernetes context
  • Confirmed NetworkPolicy API
  • Created lab namespace
  • Confirmed network policy enforcement behavior
  • Deployed frontend
  • Deployed backend
  • Deployed database simulation
  • Deployed test client
  • Created Services
  • Tested initial connectivity
  • Recorded application flows
  • Identified unnecessary communication
  • Created default-deny ingress
  • Allowed frontend to backend
  • Allowed backend to database
  • Blocked test client to backend
  • Blocked frontend to database
  • Understood default-deny egress
  • Identified DNS requirement
  • Allowed required application egress
  • Considered external dependencies
  • Understood exfiltration risk
  • Reviewed Pod labels
  • Reviewed NetworkPolicies
  • Checked Services
  • Checked endpoints
  • Investigated selector mismatch
  • Validated corrected traffic
  • Created flow matrix
  • Identified lateral movement risk
  • Documented network-security finding
  • Applied least connectivity
  • Validated remediation

You have now worked with:

Kubernetes Networking
NetworkPolicy
Ingress Controls
Egress Controls
Default-Deny
Pod Selectors
Namespace Selectors
Application Flow Mapping
Network Segmentation
Lateral Movement Reduction
Connectivity Troubleshooting

These skills are highly relevant for:

Kubernetes Security Engineer
Cloud Security Engineer
Platform Security Engineer
DevSecOps Engineer
Cloud Network Security Engineer
Security Architect
Security Consultant

In enterprise Kubernetes, network segmentation becomes particularly important because clusters may host:

Many Applications
Many Teams
Sensitive Workloads
Different Trust Levels
  1. What is a Kubernetes NetworkPolicy?
  2. Why are NetworkPolicies important?
  3. What is ingress?
  4. What is egress?
  5. What does podSelector do?
  6. What does an empty podSelector: {} mean?
  7. What is a default-deny policy?
  8. Why would you implement default-deny ingress?
  9. Why would you implement default-deny egress?
  10. What is lateral movement?
  11. How can NetworkPolicy reduce lateral movement?
  12. How do labels affect NetworkPolicy?
  13. What happens if a policy selector does not match a Pod?
  14. Can multiple NetworkPolicies apply to one Pod?
  15. How do multiple NetworkPolicies affect effective connectivity?
  16. What is a namespaceSelector?
  17. When would you use a namespaceSelector?
  18. Why can overly broad namespace selectors be risky?
  19. What is the purpose of egress filtering?
  20. How can egress controls reduce data-exfiltration risk?
  21. Why can default-deny egress break DNS?
  22. Which ports does DNS commonly use?
  23. Why should DNS be included in network-policy design?
  24. How would you troubleshoot a Service that becomes unreachable after NetworkPolicy changes?
  25. Why should you check Pod labels?
  26. Why should you check Service endpoints?
  27. What is the difference between a Service and a NetworkPolicy?
  28. Why should security teams map required application flows?
  29. What is least connectivity?
  30. Why should frontend workloads not necessarily communicate directly with database workloads?
  31. How would you isolate a database Pod?
  32. How would you allow only backend Pods to reach a database?
  33. How do ingress and egress policies work together?
  34. Why should policy behavior be tested instead of assumed?
  35. What does it mean if a NetworkPolicy exists but traffic is still unrestricted?
  36. How do RBAC and NetworkPolicy complement each other?
  37. How do Kyverno and NetworkPolicy complement each other?
  38. How does runtime monitoring complement NetworkPolicy?
  39. How would you document a Kubernetes network-security finding?
  40. How would you safely introduce network segmentation into production?

You should now be able to receive an architecture:

Frontend
Backend
Database

and derive:

Required Network Flows
Default-Deny
Frontend Allow Rule
Backend Allow Rule
DNS Requirements
Validation

Then prove:

Required Traffic = Allowed
Unnecessary Traffic = Denied

You should also be able to investigate:

Compromised Frontend Pod

and ask:

Can It Reach Backend?
Can It Reach Database?
Can It Reach Other Namespaces?
Can It Reach the Internet?
Can It Reach Internal Services?

This transforms Kubernetes security from:

Is the Pod Secure?

into:

What Can the Pod Reach
If It Is Compromised?

Remember:

APPLICATION ARCHITECTURE
REQUIRED FLOWS
DEFAULT-DENY
EXPLICIT ALLOW
VALIDATE
MONITOR

For every workload:

WHO CAN CONNECT TO IT?

and:

WHERE CAN IT CONNECT?

The security objective is:

Minimum Necessary
Network Reachability

Before this lab:

Your Kubernetes workloads
could communicate based primarily
on the cluster's default networking behavior.

After this lab:

You mapped application flows,
implemented default-deny controls,
allowed required communication,
blocked unnecessary paths,
restricted lateral movement,
investigated DNS dependencies,
troubleshot policy behavior,
and validated network segmentation.

You have moved from:

Kubernetes Connectivity

to:

Kubernetes Network Security.

➡️ Lab 05 — OPA Gatekeeper

In the next lab, you will return to Kubernetes policy enforcement and learn another major policy-as-code approach.

You will work with:

OPA
Gatekeeper
ConstraintTemplates
Constraints
Admission Control
Policy Enforcement
Security Standards
Compliance Validation

The progression becomes:

Lab 01 — Kubernetes Fundamentals
Understand Resources
Lab 02 — Kubernetes RBAC
Control Identity
Lab 03 — Kyverno
Enforce Kubernetes-Native Policy
Lab 04 — Network Policies
Control Communication
Lab 05 — OPA Gatekeeper
Build Advanced Admission Guardrails

You are now combining:

Identity Security
Configuration Security
Network Security
Policy Enforcement

into a layered Kubernetes security model.