Network Policy :-
A Network Policy in
Kubernetes is a specification that defines how groups of pods are allowed to
communicate with each other and other network endpoints. It acts as a firewall
for your Kubernetes cluster, controlling traffic at the IP address or port
level (OSI layer 3 or 4). Network Policies require a compatible CNI
(Container Network Interface) plugin that supports the Network Policy
API such as Calico, Cilium, or Weave Net.
Flannel does not support network policy.
Ingress: incoming
Egress: outgoing
features of Network Policies:
- They are namespace-scoped.
- They use labels to select pods and define
rules for ingress (incoming) and egress (outgoing) traffic.
- If no Network Policy is applied to a pod, it allows all traffic by default.(depending on the network plugin configuration).
1. podSelector (Target Pods)
- Defines which Pods the policy
applies to.
- Uses labels to select Pods.
Example: Apply
policy to all Pods with app: backend
podSelector:
matchLabels:
app: backend
If empty ({}), it applies to all Pods in
the namespace.
2. policyTypes
(Traffic Direction)
- Defines whether the policy controls
Ingress (incoming) or Egress (outgoing) traffic.
- Can have:
- Ingress → Controls incoming traffic.
- Egress → Controls outgoing traffic.
- Both.
Example: Apply
only to incoming traffic
policyTypes:
- Ingress
3. ingress
(Allowed Incoming Traffic)
- Defines which sources can send
traffic to the selected Pods.
- Uses from field with:
- podSelector (Allow specific Pods)
- namespaceSelector (Allow Pods from
specific namespaces)
- ipBlock (Allow specific IP ranges)
Example: Allow
traffic only from Pods with app: frontend
ingress:
- from:
- podSelector:
matchLabels:
app: frontend
4. egress
(Allowed Outgoing Traffic)
- Defines which destinations the
selected Pods can talk to.
- Uses to field with:
- podSelector (Allow traffic to specific
Pods)
- namespaceSelector (Allow traffic to
specific namespaces)
- ipBlock (Allow traffic to specific IPs)
Example: Allow
outgoing traffic only to app: database Pods
egress:
- to:
- podSelector:
matchLabels:
app: database
5. ports
(Restrict by Port & Protocol)
- Defines specific ports that are
allowed.
- Supports:
- protocol: TCP/UDP
- port: <port_number>
Example: Allow
only HTTP (port 80) traffic
ingress:
- from:
- podSelector:
matchLabels:
app: frontend
ports:
- protocol: TCP
port: 80
6. namespaceSelector (Restrict by Namespace)
- Allows traffic only from specific namespaces.
Example: Allow
traffic from trusted namespace
ingress:
- from:
- namespaceSelector:
matchLabels:
security: trusted
7. ipBlock (Restrict by IP Range)
- Allows or denies traffic based on CIDR
IP ranges.
- Does not work with Pod IPs
(only external networks).
Example: Allow
only 192.168.1.0/24
ingress:
- from:
- ipBlock:
cidr: 192.168.1.0/24
Parameter |
Purpose |
Example |
podSelector |
Select
which Pods the policy applies to |
matchLabels: {app: backend} |
policyTypes |
Control Ingress
and/or Egress |
policyTypes: [Ingress,
Egress] |
Ingress |
Define
allowed incoming traffic at pods, namespace, IPBlock. |
from: {podSelector: {app:
frontend}} |
Egress |
Define
allowed outgoing traffic at pods, namespace, IPBlock. |
to: {podSelector: {app:
database}} |
Ports |
Restrict
by port & protocol |
port: 80, protocol: TCP |
namespaceSelector |
Allow
traffic only from specific namespaces |
namespaceSelector:
{security: trusted} |
ipBlock |
Restrict
by IP range (CIDR) |
cidr: 192.168.1.0/24 |
Scenarios for
Network Policy in Kubernetes.
Here are some common scenarios where Network Policies are used:
Isolate Pods in a Namespace:
o Only frontend
pods can
communicate with backend
pods.
o All other traffic to backend
pods is blocked.
o Allow Traffic Based on Pod Labels. Example: Allow only pods with the label role: frontend to communicate with pods labeled role: backend.
i)Deploy the
Applications
Create two deployments: frontend and backend.
# vim backend-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: backend
namespace: isolate-ns
labels:
app: backend
spec:
replicas: 1
selector:
matchLabels:
app: backend
template:
metadata:
labels:
app: backend
spec:
containers:
- name: nginx
image: nginx
ports:
- containerPort: 80
# vim frontend-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: frontend
namespace:
isolate-ns
labels:
app: frontend
spec:
replicas: 1
selector:
matchLabels:
app: frontend
template:
metadata:
labels:
app: frontend
spec:
containers:
- name: busybox
image: nginx
command: ["sleep", "3600"]
# kubectl apply -f
backend-deployment.yaml
# kubectl apply -f
frontend-deployment.yaml
Verify Pod
Communication
# kubectl get pods -n isolate-ns
# cat service.yaml
apiVersion: v1
kind: Service
metadata:
name: backend-service
namespace: isolate-ns
spec:
selector:
app: backend
ports:
- protocol: TCP
port: 80 # Service Port
targetPort: 80 # Container Port
type: ClusterIP # Change to
NodePort or LoadBalancer if needed
# kubectl get svc -n isolate-ns
# vim
backend-policy.yaml
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: backend-policy
namespace: isolate-ns
spec:
podSelector:
matchLabels:
app: backend
policyTypes:
- Ingress
ingress:
- from:
- podSelector:
matchLabels:
app: frontend
ports:
- protocol: TCP
port: 80
# kubectl apply -f backend-policy.yaml
# kubectl get networkpolicies -n
isolate-ns
# kubectl describe networkpolicies -n
isolate-ns
Verify connectivity
:-
# kubectl get all -n isolate-ns
Nginx not connect
from test-pod.
# kubectl get svc -n isolate-ns
# kubectl run test-pod --image=nginx
--restart=Never -- sleep 3600
# kubectl exec -it test-pod -- /bin/bash
The frontend pod
will only connect to the Nginx backend pod.
# kubectl exec -it
--namespace=isolate-ns frontend-7766f6c5f8-k8m2l -- curl 10.99.1.82:80
# kubectl exec -it
--namespace=isolate-ns frontend-9585465bd-rz4q5 -- curl backend-service:80
Allow Traffic from Specific Namespaces:
o Permit traffic from pods in one namespace to
pods in another namespace.
o Example: Allow monitoring tools in the monitoring namespace
to scrape metrics from pods in the app namespace.
# kubectl create namespace frontend-ns
# kubectl create namespace backend-ns
# kubectl get ns backend-ns
frontend-ns
Deploy
Applications
# cat
backend-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: backend
namespace:
backend-ns
labels:
app: backend
spec:
replicas: 2
selector:
matchLabels:
app: backend
template:
metadata:
labels:
app: backend
spec:
containers:
- name: nginx
image: nginx
ports:
- containerPort: 80
# kubectl apply -f
backend-deployment.yaml
# kubectl get pods -n backend-ns
Deploy Service.
# vim backend-service.yaml
apiVersion: v1
kind: Service
metadata:
name: backend-service
namespace: backend-ns
spec:
selector:
app: backend
ports:
- protocol: TCP
port: 80
targetPort: 80
# kubectl apply -f
backend-service.yaml
# kubectl get svc -n backend-ns
# cat
frontend-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: frontend
namespace: frontend-ns
labels:
app: frontend
spec:
replicas: 1
selector:
matchLabels:
app: frontend
template:
metadata:
labels:
app: frontend
spec:
containers:
- name: busybox
image: nginx
command: ["sleep", "3600"]
# backend-policy.yaml
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: backend-policy
namespace: backend
spec:
podSelector:
matchLabels:
app: backend
policyTypes:
- Ingress
ingress:
- from:
- namespaceSelector:
matchLabels:
kubernetes.io/metadata.name: frontend-ns
ports:
- protocol: TCP
port: 80
# kubectl apply -f backend-policy.yaml
# kubectl describe networkpolicies -n
backend-ns
5. Test the Network Policy
Allowed Traffic:
- Exec into the frontend pod and
test connectivity to the backend pod:
# kubectl exec -it -n frontend-ns
frontend-9585465bd-qp4d4 -- curl 10.109.247.255:80
Blocked Traffic:
- Create a new pod in a different namespace
(e.g., dev) and try to access the backend pod:
# kubectl run test-pod -n dev
--image=nginx --restart=Never -- sleep 3600
# kubectl exec -it test-pod -n dev --
/bin/bash
3.Disable
internet access for Kubernetes pods.
Network Policies to block all
egress traffic to external IPs. This ensures that pods can only communicate
within the cluster or with explicitly allowed external endpoints.
# busybox-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: busybox
spec:
replicas: 1
selector:
matchLabels:
app: busybox
template:
metadata:
labels:
app: busybox
spec:
containers:
- name: busybox
image: busybox
command: ["sleep", "3600"]
# kubectl get pods
Without network policy,
# kubectl exec -it
busybox-6fc6c44c5b-k2qxp -- ping google.com
Create a
Network Policy to Disable Internet Access
# cat disable-internet-policy.yaml
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: disable-internet
spec:
podSelector: {} #
Applies to all pods in the namespace
policyTypes:
- Egress
egress:
- to:
- ipBlock:
cidr: 0.0.0.0/0
except:
- 10.0.0.0/8 # Allow internal
cluster traffic (replace with your cluster's CIDR)
- 172.16.0.0/12
- 192.168.0.0/16
# kubectl get netpol
# kubectl describe netpol
disable-internet
# kubectl exec -it
busybox-6fc6c44c5b-k2qxp -- ping google.com
Note :- Only the default namespace will not
run on the internet and other namespaces will run on the internet.