Master Kubernetes NetworkPolicy: Secure Pod Communication with Real‑World Examples
This article explains Kubernetes NetworkPolicy, covering its purpose, how pod and namespace selectors work, required fields, policy types, and detailed YAML examples, followed by practical scenarios and step‑by‑step commands for deploying and testing network policies in a cluster.
Network Policy Overview
With the rise of micro‑service architectures and serverless frameworks, the demand for inter‑module network calls has grown dramatically. Kubernetes introduced NetworkPolicy in version 1.3 to provide application‑centric, policy‑based network control that isolates workloads and reduces the attack surface.
Pod communication can be verified through three combinations: allowed Pods, allowed namespaces, and IP CIDR blocks.
Version Changes
Brief Introduction
Related Explanation
By default, Pods are non‑isolated and accept any traffic.
When a Pod is selected by a NetworkPolicy, it becomes isolated. Any Pod in the same namespace that is not selected continues to accept all traffic.
Network policies do not conflict; a Pod selected by multiple policies is subject to the union of all inbound (Ingress) and outbound (Egress) rules.
When using NetworkPolicy, the network plugin must support it, such as Calico, Romana, Weave Net, or Trireme. "Egress" refers to outbound traffic, "Ingress" to inbound traffic.
Struct Definition
staging/src/k8s.io/api/networking/v1/types.goBelow is a sample NetworkPolicy; see the official struct documentation for full details.
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: network-policy-sample
namespace: default
spec:
podSelector:
matchLabels:
role: db
policyTypes:
- Ingress
- Egress
ingress:
- from:
- ipBlock:
cidr: 172.17.0.0/16
except:
- 172.17.1.0/24
- namespaceSelector:
matchLabels:
project: myproject
- podSelector:
matchLabels:
role: frontend
ports:
- protocol: TCP
port: 6379
egress:
- to:
- ipBlock:
cidr: 10.0.0.0/24
ports:
- protocol: TCP
port: 5978Required fields: apiVersion, kind, and metadata (name, namespace).
spec contains all information needed to define a policy within a namespace.
podSelector selects the Pods the policy applies to; an empty selector matches all Pods in the namespace.
policyTypes lists Ingress, Egress, or both. If omitted, Ingress is assumed; Egress is added when egress rules are present.
ingress defines a whitelist of allowed inbound traffic, matching both "from" and "ports".
egress defines a whitelist of allowed outbound traffic, matching "to" and "ports".
Isolate Pods with label role=db in the default namespace.
Egress restriction: allow Pods with label role=frontend in default, Pods in namespaces labeled project=myproject, and IP ranges 172.17.0.0/16 except 172.17.1.0/24 to reach port 6379/TCP on the selected Pods.
Ingress restriction: allow any Pod in namespaces with label role=db to reach port 5978/TCP on CIDR 10.0.0.0/24.
Simple Example (Calico)
1) Configure kubelet to use the CNI network plugin (usually pre‑configured).
kubelet --network-plugin=cni --cni-conf-dir=/etc/cni/net.d --cni-bin-dir=/opt/cni/bin ...2) Install the Calico network plugin.
# Note: adjust CIDR to match the cluster's pod‑network‑cidr (default 192.168.0.0/16)
# Installation for clusters with fewer than 50 nodes
kubectl apply -f https://docs.projectcalico.org/manifests/calico.yaml3) Deploy an application (nginx).
$ kubectl create deployment nginx --image=nginx
deployment "nginx" created
$ kubectl expose deployment nginx --port=80
service "nginx" exposedTest the network:
$ kubectl get svc,pod
... (output omitted for brevity)
$ kubectl run busybox --rm -ti --image=busybox /bin/sh
/ # wget --spider --timeout=1 nginx
Connecting to nginx (10.233.27.142:80)
remote file exists
/ #Application Scenarios
General Scenarios
a) Deny access to a specific service.
$ kubectl run web --image=nginx --labels app=web --expose --port 80
# Without a policy, the service is reachable
$ kubectl run busybox --rm -ti --image=busybox /bin/sh
/ # wget -qO- http://web
<!DOCTYPE html>
<html>...</html>Create a deny‑all policy:
# cat web-deny-all.yaml
kind: NetworkPolicy
apiVersion: networking.k8s.io/v1
metadata:
name: web-deny-all
spec:
podSelector:
matchLabels:
app: web
ingress: []
$ kubectl apply -f web-deny-all.yaml
networkpolicy "web-deny-all" createdTest that the service is now blocked:
$ kubectl run busybox --rm -ti --image=busybox /bin/sh
/ # wget -qO- --timeout=2 http://web
wget: download timed outNamespace Restrictions
a) Block non‑whitelisted traffic in a namespace.
# cat default-deny-all.yaml
kind: NetworkPolicy
apiVersion: networking.k8s.io/v1
metadata:
name: default-deny-all
namespace: default
spec:
podSelector: {}
ingress: []
$ kubectl apply -f default-deny-all.yaml
networkpolicy "default-deny-all" createdb) Block traffic from other namespaces.
$ kubectl create namespace secondary
$ kubectl run web --namespace secondary --image=nginx --labels=app=web --expose --port 80 # cat web-deny-other-namespaces.yaml
kind: NetworkPolicy
apiVersion: networking.k8s.io/v1
metadata:
namespace: secondary
name: web-deny-other-namespaces
spec:
podSelector:
matchLabels:
ingress:
- from:
- podSelector: {}
$ kubectl apply -f web-deny-other-namespaces.yamlTesting shows that pods in the default namespace cannot reach the service, while pods in secondary can.
Allow All Namespaces
# cat web-allow-all-namespaces.yaml
kind: NetworkPolicy
apiVersion: networking.k8s.io/v1
metadata:
namespace: default
name: web-allow-all-namespaces
spec:
podSelector:
matchLabels:
app: web
ingress:
- from:
- namespaceSelector: {}
$ kubectl apply -f web-allow-all-namespaces.yamlThis policy permits traffic from any namespace to Pods labeled app=web.
Restrict Access to Specific Namespaces
# cat web-allow-prod.yaml
kind: NetworkPolicy
apiVersion: networking.k8s.io/v1
metadata:
name: web-allow-prod
spec:
podSelector:
matchLabels:
app: web
ingress:
- from:
- namespaceSelector:
matchLabels:
purpose: production
$ kubectl apply -f web-allow-prod.yamlOnly namespaces labeled purpose=production can access the web service.
Allow Specific Pods Across Namespaces
# cat web-allow-all-ns-monitoring.yaml
kind: NetworkPolicy
apiVersion: networking.k8s.io/v1
metadata:
name: web-allow-all-ns-monitoring
namespace: default
spec:
podSelector:
matchLabels:
app: web
ingress:
- from:
- namespaceSelector:
matchLabels:
team: operations
podSelector:
matchLabels:
type: monitoring
$ kubectl apply -f web-allow-all-ns-monitoring.yamlPods with label type=monitoring in namespaces labeled team=operations are allowed to reach the web service.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
Efficient Ops
This public account is maintained by Xiaotianguo and friends, regularly publishing widely-read original technical articles. We focus on operations transformation and accompany you throughout your operations career, growing together happily.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
