Introduction
In our previous article on Kubernetes networking, we explored how pods communicate across a cluster using a flat network model. While this model enables seamless communication, it raises an important question: How do we control and secure this communication?
By default, Kubernetes allows unrestricted communication between all pods in a cluster. Looking at our diagram below, you can see a frontend pod and a backend pod that can freely communicate with each other and receive external traffic. While this default behavior simplifies initial setup, it may not meet your security requirements.
Network Policies address this challenge by allowing you to define rules that control pod communication. Think of them as firewall rules specifically designed for Kubernetes - they let you specify which pods can communicate with each other and with external endpoints.
In this article, you’ll learn:
- How Network Policies control pod communication
- The basic components of a Network Policy
- How to create and test your first policy
- Practical implementation using Kind
Let’s start by understanding how Network Policies fit into the Kubernetes networking model and what they can help you achieve.
Network Policy Fundamentals: How Kubernetes Controls Pod Traffic
In a Kubernetes cluster, pods start with complete freedom to communicate. Our diagram below illustrates this default state - the frontend pod receives external traffic and communicates with the backend pod without restrictions. This allow-all approach simplifies development and testing but often falls short for production environments.
Production deployments typically need finer control over network traffic. You might need to:
- Restrict external access to only specific pods
- Control which pods can communicate with each other
- Isolate certain workloads for security or compliance reasons
Network Policies provide this control through rules that filter pod traffic. Our diagram shows a network policy layer (represented by the red rectangle) that intercepts and controls communication between pods and external sources.
How Kubernetes Identifies Pods
Controlling pod communication starts with understanding how Kubernetes identifies pods. Every pod in Kubernetes can have labels - simple key-value pairs that identify pods. For example:
|
|
These labels help you organize and select pods. Think of labels like name tags that help identify which pods are which.
Applying Network Policies
Network Policies use these labels to determine which pods they affect. When creating a policy, you specify which pods it applies to using label selectors. For example, you might want your policy to affect all pods with the label app: frontend
.
Let’s use a simple example: imagine you have:
- Frontend pods labeled
app: frontend
- Backend pods labeled
app: backend
- Database pods labeled
app: database
You could create a policy that applies to frontend pods, controlling exactly how they communicate with backend and database pods.
The Implicit Deny Rule
When you apply a Network Policy to a pod, something important happens: that pod’s networking behavior changes fundamentally. It switches from allowing all traffic to denying all traffic except what you explicitly permit.
For example, if you create a policy for your frontend pods that only allows communication with backend pods on port 8080, two things happen:
- Frontend pods can communicate with backend pods on port 8080
- All other communication to and from frontend pods is automatically blocked
This “implicit deny” behavior is a crucial security feature - it ensures pods only communicate in ways you specifically authorize.
Note: Network Policies are defined in Kubernetes but enforced by your Container Network Interface (CNI) plugin. You’ll need a CNI plugin like Calico, Flannel with Calico, or Cilium to implement these rules.
Now that we understand these fundamentals, let’s examine how to create Network Policies using these concepts…
Key Components of a Kubernetes Network Policy
Now that we understand how pods are identified and selected, let’s examine how to build a Network Policy. A policy consists of three main parts that work together to control pod communication:
Pod Selectors
The first thing a Network Policy needs to specify is which pods it affects. We do this using pod selectors that match pod labels. For example:
|
|
Let’s break this down:
kind: NetworkPolicy
tells Kubernetes we’re creating a Network Policymetadata.name
gives our policy a unique identifierspec.podSelector
defines which pods this policy affectsmatchLabels: app: frontend
means this policy applies to all pods with labelapp: frontend
Any pods without the specified label continue with unrestricted communication.
Traffic Direction
Network Policies can control two types of traffic:
- Ingress: incoming traffic to the selected pods
- Egress: outgoing traffic from the selected pods
You can configure either or both directions in a single policy. For example:
|
|
This configuration:
- Applies to pods labeled
app: frontend
- Controls incoming (ingress) traffic
- Allows traffic only from pods labeled
app: backend
- Since egress isn’t specified, all outgoing traffic is blocked (remember the implicit deny rule)
Traffic Rules
Within each direction (ingress or egress), you specify rules about:
- Which pods can communicate (using pod selectors)
- Which ports are allowed
- Which protocols can be used
Here’s an example combining all these elements:
|
|
Breaking this down:
- The
from
section specifies the source (pods labeledapp: backend
) - The
ports
section allows only TCP traffic on port 80 - Any other ports or protocols are blocked
- Traffic from pods not labeled
app: backend
is denied
These components combine to create precise rules about pod communication. In the next section, we’ll create a complete Network Policy that puts all these pieces together in a practical example.
Walkthrough: Creating Your First Kubernetes Network Policy
Let’s put these components together to create a complete Network Policy. We’ll use a common scenario: allowing frontend pods to receive traffic only from specific backend pods.
Here’s the complete policy:
|
|
Let’s walk through what this policy does:
-
Policy Target:
- Applies to all pods labeled
app: frontend
- Any other pods remain unaffected
- Applies to all pods labeled
-
Ingress Rules:
- Allows incoming connections only from pods labeled
app: backend
- Permits only TCP traffic on port 80
- All other incoming traffic is blocked
- Allows incoming connections only from pods labeled
-
Egress Behavior:
- Since we haven’t specified any egress rules
- All outgoing traffic from frontend pods is blocked (implicit deny)
This policy effectively creates a one-way communication channel where backend pods can send requests to frontend pods on port 80, while blocking all other traffic.
In the next section, we’ll set up a test environment using Kind and see this policy in action.
Implementing and Testing Network Policies with Kind (Kubernetes in Docker)
Let’s see our Network Policy in action using Kubernetes in Docker (Kind). We’ll create a simple test environment with frontend and backend services, then apply and verify our policy.
Prerequisites
Ensure these tools are installed on your local machine:
- Docker: Install Docker
- Kind: Install Kind
- kubectl: Install kubectl
Setting Up the Environment
First, let’s create a Kind cluster with Calico, a CNI plugin that supports Network Policies. Create a file named kind-config.yaml
:
|
|
Create the cluster and install Calico:
|
|
Deploying Sample Applications
Create a file named sample-app.yaml
:
|
|
Deploy the applications:
|
|
Applying the Network Policy
Create our policy in frontend-policy.yaml
:
|
|
Apply the policy:
|
|
Verifying the Policy
Let’s test our policy by attempting connections to the frontend service:
|
|
The first command should succeed because our policy allows traffic from pods labeled app: backend
, while the second should fail because the client-pod isn’t allowed to communicate with frontend pods.
To verify the pods are running and services are properly configured:
|
|
If you need to troubleshoot, you can check the policy details:
|
|
In the next section, we’ll look at best practices and common challenges when working with Network Policies.
Best Practices and Common Challenges with Kubernetes Network Policies
When implementing Network Policies in Kubernetes, following certain practices can help you maintain secure and manageable network rules.
Start with Default Deny
One of the most important security practices is to start with a default deny policy. Create this policy early in your cluster setup:
|
|
This policy blocks all traffic to and from every pod in the namespace. You can then add specific policies to allow required communication, following the principle of least privilege.
Policy Organization
Keep your Network Policies:
- Focused on specific applications or components
- Well-documented with clear comments
- Named consistently and descriptively
- Organized by namespace
For example, prefix policies with their application name:
|
|
Common Challenges
- CNI Plugin Compatibility
- Always verify your CNI plugin supports Network Policies
- Some features might work differently across CNI plugins
- Document which CNI plugin your policies are tested with
- Troubleshooting Access Issues
- Network Policy problems often manifest as connection timeouts
- Use these commands for troubleshooting:
1 2 3 4 5 6 7 8
# Check if policies exist kubectl get networkpolicies -A # View policy details kubectl describe networkpolicy <policy-name> # Check pod labels kubectl get pods --show-labels
- Policy Conflicts
- Multiple policies affecting the same pod combine additively
- If any policy allows traffic, it’s allowed
- Keep policies simple to avoid unexpected interactions
Performance Considerations
When designing Network Policies:
- Avoid creating too many individual policies
- Use label selectors efficiently
- Consider the impact on large-scale deployments
- Monitor network performance after applying policies
In our next article, we’ll explore advanced networking capabilities with Cilium, including enhanced Network Policy features and improved observability.
Conclusion
Throughout this article, we’ve explored how Network Policies help secure communication in Kubernetes clusters. Starting from the default allow-all state, we’ve seen how to implement precise controls over pod-to-pod communication using labels, selectors, and traffic rules.
Key takeaways:
- Network Policies control pod communication using pod labels and selectors
- Once a policy is applied to a pod, it denies all traffic except what’s explicitly allowed
- Policies require a compatible CNI plugin like Calico for enforcement
- Using Services with Network Policies provides stable, reliable communication
We’ve also implemented a practical example using Kind, demonstrating how to:
- Set up a test environment
- Create and apply Network Policies
- Verify policy behavior
- Troubleshoot common issues
While Network Policies provide essential security controls, they’re just the beginning of Kubernetes networking security. In our next article, we’ll explore Cilium, a powerful CNI plugin that extends these capabilities with enhanced security features, better performance, and improved observability.