Network policy in Kubernetes using Calico Networking.
Introduction
Calico is open-source networking and network security solution for containers, virtual machines, and native host-based workloads. In this tutorial, we are going to create a network policy in Kubernetes using calico CNI. So that only selected namespaces will be able to communicate with each other.
Prerequisite
- Your Kubernetes cluster is up and running.
- Calico is installed. If not installed, you can follow this link to find out the installation steps
- Application services are deployed in different namespaces. (For this task we have created an application in default, frontend and backend namespaces.)
For this tutorial, we created a manifest for the calico network policy which will create a rule in our Kubernetes cluster, that only frontend and backend namespaces will be able to communicate with each other.
Network Policy Manifest
In this tutorial, we have allowed communication between the kube-system, calico-system, backend and frontend namespaces.
The below given manifest will create a Network Policy that will only allow traffic between the namespaces mentioned in the manifest file under the namespaceSelector section. You can change this manifest according to your need by adding or removing different namespaces of your choice.
You can read more about GlobalNetworkPolicy and its parameter in detail here.
apiVersion: crd.projectcalico.org/v1
kind: GlobalNetworkPolicy
metadata:
name: default-deny
spec:
namespaceSelector: has(kubernetes.io/metadata.name) && kubernetes.io/metadata.name not in {"kube-system", "calico-system", "backend", "frontend"}
types:
- Ingress
- Egress
egress:
- action: Allow
protocol: UDP
destination:
selector: 'k8s-app == "kube-dns"'
ports:
- 53
Testing Connectivity
For testing, you can deploy your application or use the below-mentioned manifest and deploy it in different namespaces.
---
apiVersion: v1
kind: Service
metadata:
name: demo
spec:
type: ClusterIP
ports:
- targetPort: 80
port: 80
selector:
app: test-one
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: test-one
spec:
replicas: 1
selector:
matchLabels:
app: test-one
template:
metadata:
labels:
app: test-one
spec:
containers:
- name: test-one
image: sagar27/testing:latest
ports:
- containerPort: 80
We have used 3 namespaces to deploy our application: -
- frontend
- backend
- default
Testing from the frontend namespace.
When we did SSH into the pod which is running in the frontend namespace and tried to curl the applications running in the backend and default namespace. We get the following results
As you can see in the above-attached screenshot the curl request is giving the HTTP response “ 200 ok ” when we try to access the application running in the frontend and backend namespaces and we are getting a Request Timeout Error when we tried to access the application running in the default namespace.
Testing from the backend namespace.
Now we did SSH into the pod running in the backend namespace and tried to access applications running in the frontend and the backend namespace. As shown in the below screenshot: -
The result was the same as the previous test, we were able to make a curl request to the service running in the backend namespace but got a timeout error when we tried to access the backend service.