K8s Network Policies
In this blog post, let’s try understanding “K8s Network Policy”. We will be following the structure as below.
- Some network communication fundamentals- What is a NetworkPolicy- What are NetworkPolicy agents- Concluding thoughts
To start with, let’s lay out some fundamentals for K8s Networking for Pods for a given cluster by default.
- Each Pod gets its own unique IP address.
- All Pods can talk with any other Pod within the cluster(there is no NAT business, i.e., Network address translation)
Extending the idea above, a Pod in namespaceA can also talk with a Pod in namespaceB, so the communication between Pods is namespace independent too.
Let’s try to see this with an example. Let’s say we have three namespaces
MyK8sInstance> kubectl get ns | grep ns
ns-1 Active 43s
ns-2 Active 41s
ns-3 Active 40s
Let’s create a pod in each namespace
kubectl -n ns-1 run pod1 --image=nginx
kubectl -n ns-2 run pod2 --image=nginx
kubectl -n ns-3 run pod3 --image=nginxMyK8sInstance> kubectl get po -A -o wide | grep -i nsns-1 pod1-68d8cf5958-64wxf 1/1 Running 0 6m25s 172.17.0.2 minikube <none> <none>
ns-2 pod2-656d7df678-pn58q 1/1 Running 0 6m19s 172.17.0.3 minikube <none> <none>
ns-3 pod3-544fd994c4-xfqwx 1/1 Running 0 6m12s 172.17.0.4 minikube <none> <none>
Let’s now try to reach pod2 from pod1 (in different namespaces); we see the connectivity works. Here
MyK8sInstance> kubectl -n ns-1 exec pod1-68d8cf5958-64wxf -- curl 172.17.0.3 | grep Welcome
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 612 100 612 0 0 68000 0 --:--:-- --:--:-- --:--:-- 68000
<title>Welcome to nginx!</title>
<h1>Welcome to nginx!</h1>pod1-68d8cf5958-64wxf => pod1 which belongs to ns-1
172.17.0.3 => pod2 which belong to ns-2
Similarly, the pod in ns-2 can talk with the pod in ns-3
MyK8sInstance> kubectl -n ns-2 exec pod2-656d7df678-pn58q -- curl 172.17.0.4 | grep Welcome
<title>Welcome to nginx!</title>
<h1>Welcome to nginx!</h1>
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 612 100 612 0 0 298k 0 --:--:-- --:--:-- --:--:-- 597k
Any pod can talk with any other pod in a cluster by default. Something like below.
What if we would like something like below, where in pod in “ns-2” should able to talk with only pod in “ns-3” for incoming connections and nothing else
This is where network policies help. Let’s understand how. But before that is there a use-case or requirement for this?
There surely might be a use-case for this; let’s understand with an example.
Let’s say we have a set of pods hosting an application in prod and another set of pods hosting an application in dev. What if we would like the pods in dev not to talk with pods in prod. This is one use-case where Network Policies help.
First, let’s label each namespace and each pod. Check here for more details on K8s labels. This will help us decide which NetworkPolicy to apply to which set of K8s objects(pods, namespaces, etc.)
MyK8sInstance> k get ns --all-namespaces --show-labels | grep ns
ns-1 Active 77m ns-name=ns1
ns-2 Active 77m ns-name=ns2
ns-3 Active 77m ns-name=ns3MyK8sInstance> k get po --all-namespaces --show-labels | grep pod
ns-1 pod1-68d8cf5958-64wxf 1/1 Running 0 72m pod-name=pod1,pod-template-hash=68d8cf5958,run=pod1
ns-2 pod2-656d7df678-pn58q 1/1 Running 0 72m pod-name=pod2,pod-template-hash=656d7df678,run=pod2
ns-3 pod3-544fd994c4-xfqwx 1/1 Running 0 72m pod-name=pod3,pod-template-hash=544fd994c4,run=pod3
Let use this example from K8s documentation and apply it for our use-case, i.e., the pods in ns-2 should not be allowed to talk to pods in ns-3, specifically for outgoing requests.
So what we would like is
- An ingress request from ns-3 pod3 should be allowed to ns-2 pod
- An ingress request from ns-1 pod1 should not be allowed to ns-2 pod
Let’s create a NetworkPolicy object; pay close attention to the podSelector; it helps select pods to apply the ingress policy to. Here it selects pod2 and allows ingress only from pod3.
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: test-network-policy
namespace: ns-2
spec:
podSelector:
matchLabels:
pod-name: pod2
policyTypes:
- Ingress
ingress:
- from:
- podSelector:
matchLabels:
pod-name: pod3
Let’s see what happens after applying this policy
MyK8sInstance> k apply -f np.yaml
networkpolicy.networking.k8s.io/test-network-policy createdMyK8sInstance> k get po --all-namespaces -o wide | grep -i pod
ns-1 pod1-68d8cf5958-64wxf 1/1 Running 0 83m 172.17.0.2 minikube <none> <none>
ns-2 pod2-656d7df678-pn58q 1/1 Running 0 83m 172.17.0.3 minikube <none> <none>
ns-3 pod3-544fd994c4-xfqwx 1/1 Running 0 83m 172.17.0.4 minikube <none> <none>
We can see pod2 allows ingress from pod3 and also pod1, what????????
This clearly isn’t working right? So NetworkPolicy doesnot work?
Well not really let’s see whats happening
MyK8sInstance> kubectl -n ns-3 exec pod3-544fd994c4-xfqwx -- curl 172.17.0.3 | grep Welcome
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 612 100 612 0 0 68000 0 --:--:-- --:--:-- --:--:-- 68000
<title>Welcome to nginx!</title>
<h1>Welcome to nginx!</h1>MyK8sInstance> kubectl -n ns-1 exec pod1-68d8cf5958-64wxf -- curl 172.17.0.3 | grep Welcome
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 612 100 612 0 0 597k 0 --:--:-- --:--:-- --:--:-- 597k
<title>Welcome to nginx!</title>
<h1>Welcome to nginx!</h1>
This is not working because Network Policy requires networkpolicy agents to be installed.
These are not installed by default on K8s clusters. There are many agents(like calico, weave-net, antrea etc.) , here let’s take a look at a calico agent.
One can install calico from here. After successful installation, we see the below
MyK8sInstance> kubectl get daemonset calico-node --namespace calico-system
NAME DESIRED CURRENT READY UP-TO-DATE AVAILABLE NODE SELECTOR AGE
calico-node 1 1 0 1 0 kubernetes.io/os=linux 1s
Now, if we validate, we can see that the ingress policy is applied correctly 🎉. In this example, we saw how to apply the NetworkPolicy K8s object using podselector
. One can also use namespace-selector or ipaddress
to apply Ingress and Egress policies. One can also use a combination of these methods together.
💡Something else to note is, the Network policy can be applied to a specific port, i.e., the Ingress policy from only port 8080 is allowed on namespace1.
What might be the difference between K8s Network Policy and K8s ServiceMesh? As both seem to control traffic within a K8s cluster
NetworkPolicy works at OSI-Layer3 and OSI-Layer4. It controls traffic using ipaddress, ports or namespace related to the pods.
ServiceMesh works at OSI-Layer7, it uses application properties like header, path etc. to control traffic.
To conclude, NetworkPolicy is an essential K8s object in the modern world where controlling traffic flow and applying better controls is extremely important.
That's it for now related to NeworkPolicy in K8s; if you have any questions/comments/feedback, feel free to add. Until next time ciao!