Network Policy in Kubernetes

By default, pods accept traffic from any source. A network policy helps to specify how a group of pods can communicate with each other and other network endpoints. NetworkPolicy uses labels to select pods and define rules to specify what traffic is allowed to the selected pods Once there is a NetworkPolicy applied on a particular pod, that pod will reject connections that are not allowed the NetworkPolicy. The pods that are not selected by any NetworkPolicy will continue to accept all traffic.

To know more about NetworkPolicy in detail, visit the official page of Kubernetes here.

In this article, we will see the usage of Ingress and Egress NetworkPolicy where ingress is incoming traffic to the pod, and egress is outgoing traffic from the pod.

Pre-requisites

  1. Kubernetes Cluster with at least 1 worker node.
    If you want to learn to create a Kubernetes Cluster, click here. This guide will help you create a Kubernetes cluster with 1 Master and 2 Nodes on AWS Ubuntu 18.04 EC2 Instances. 

What will we do?

  1. Create Network Policies

Create Network Policies

Ingress Network Policy

Create a hello-web pod with a label "app-destination-pod" and service on which we will allow incoming traffic on port 8080.

kubectl run hello-web --labels app=destination-pod --image=gcr.io/google-samples/hello-app:1.0 --port 8080 --
kubectl get pod | grep hello-web

kubectl get service | grep hello-web

creat-a-pod-and-a-service

Create an ingress definition file using the following content which allows traffic on the "hello-web" pod with label "app=destination-pod" on port 8080 from the pod matching the label "app=source-pod".

vim ingress.yml
kind: NetworkPolicy
apiVersion: networking.k8s.io/v1
metadata:
  name: destination-pod-allow-from-source-pod
spec:
  policyTypes:
  - Ingress
  podSelector:
    matchLabels:
      app: destination-pod
  ingress:
  - from:
    - podSelector:
        matchLabels:
          app: source-pod

ingress-network-policy-defination

Before we create an ingress policy create a pod with label "app=unknown" not matching the rule of the policy.

kubectl run -l app=unknown --image=alpine --restart=Never --rm -i -t test-1

Now when we try to access our "hello-web" pod on port 8080 from this pod, the pod will be accessible.

wget -qO- --timeout=2 http://hello-web:8080

create-an-unknown-pod

Now create a policy that allows connection on the pod with label "app=destination-pod" from the pod with label "app=source-pod" and get details of it.

kubectl apply -f ingress.yml
kubectl get networkpolicy destination-pod-allow-from-source-pod

create-ingress-network-policy

Now, again create a pod with a label not matching the rule defined in the policy.

kubectl run -l app=unknown --image=alpine --restart=Never --rm -i -t test-1

If we again try to access the "hello-web" pod from this pod, the "hello-web" pod will not be reachable.

wget -qO- --timeout=2 http://hello-web:8080

try-to-access-from-unknown-pod

This time, let's create a pod matching the network policy rule i.e. pod with label "app=source-app" 

kubectl run -l app=source-pod --image=alpine --restart=Never --rm -i -t test-1

Now, if we try to access the "hello-web" pod  from the pod with label "app=source-pod", the "hello-web" can be accessed.

wget -qO- --timeout=2 http://hello-web:8080

try-to-access-from-known-pod

In the above screenshot, you can see that the "hello-web" pod was accessible from the pod with label "app=source-pod". This means that we restricted connections on our "hello-web" and only pods with label "app=source-pod"  can connect to it.

Egress Network Policy

Create a new file for Egress Network Policy with the following content.

vim egress.yml
kind: NetworkPolicy
apiVersion: networking.k8s.io/v1
metadata:
  name: source-pod-allow-to-destination-pod
spec:
  policyTypes:
  - Egress
  podSelector:
    matchLabels:
      app: source-pod
  egress:
  - to:
    - podSelector:
        matchLabels:
          app: destination-pod
  - ports:
    - port: 53
      protocol: TCP
    - port: 53
      protocol: UDP

egress-network-policy-defination

The above policy will allow outgoing connections from the pod with label "app=source-pod" to the pod with label "app=destination-pod" and also on port 53 for DNS resolution.

Before we apply Egress Policy in the cluster, create a pod "hello-web-2" and service which does not match our policy.

kubectl run hello-web-2 --labels app=hello-2 --image=gcr.io/google-samples/hello-app:1.0 --port 8080 --expose
kubectl get pod | grep hello-web-2
kubectl get service | grep hello-web-2

create-unknown-application

Now create a pod with label "app=source-pod".

kubectl run -l app=source-pod --image=alpine --restart=Never --rm -i -t test-2

Before we apply the Egress policy, both the apps "hello-web" and "hello-web-2" can be accessed from the pod with label "app=source-pod"

wget -qO- --timeout=2 http://hello-web:8080
wget -qO- --timeout=2 http://hello-web-2:8080

access-to-unknow-application-available

Now, create a Network policy with egress rule.

kubectl create -f egress.yml
kubectl get networkpolicy | grep source-pod-allow-to-destination-pod

create-egress-network-policy

Let's create a pod with label "app=source-pod" and try to access both the pod "app=source-pod"

kubectl run -l app=source-pod --image=alpine --restart=Never --rm -i -t test-3

wget -qO- --timeout=2 http://hello-web:8080

wget -qO- --timeout=2 http://hello-web-2:8080

access-to-unknown-application-not-available

In the above screenshot, you can observe that this time the pod "hello-web-2" was not reachable as it does not match the egress policy which allows connection from a pod with label "app=source-pod" to the pod with label "app=destination-pod".

Conclusion

In this article, we saw the steps to create an ingress and egress network policy. We also saw how the incoming and outgoing connection can be restricted using ingress and egress respectively and to understand this better we saw its implementation using a simple web-app.

Share this page:

0 Comment(s)