Learning about Kubernetes Networking Policies

Overview

  • Set up the testing environment using Minikube
  • Deploy an Nginx container to the defaultnamespace
  • Deploy a container to a new namespace to use as an interactive shell to connect with the Nginx container
  • Dive into use cases and policies to showcase how it works

Tools I’m using for this exercise:

  • Minikube
  • VS Code for editing
  • Windows 10 Pro
  • cmder terminal

Setup

By default, Kubernetes allows all ingress and egress traffic.

  1. Ensure you have the ability to control a test Kubernetes cluster. I use Minikube so here’s my command to start up a cluster with Calico installed. You can use any networking interface that supports Network Policies.
minikube start --network-plugin=cni --cni=calico
kubectl get pods -l k8s-app=calico-node -n kube-system
Proof that I actually run the commands

Deploy an Nginx container

We are going to deploy an Nginx pod to use as the target server for this demo.

apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-for-calico-demo
namespace: default
spec:
selector:
matchLabels:
app: nginx
replicas: 1
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.20.0
ports:
- containerPort: 80
  1. Apply the YAML to your cluster.
kubectl apply -f https://raw.githubusercontent.com/airwavetechio/calico-istio-demo/main/deployments/nginx.yaml
kubectl expose deployment nginx-for-calico-demo

Deploy a container to a new namespace to use as an interactive shell to connect with the Nginx container

Now that we have an accessible web server in the defaultnamespace, let’s create a pod with an interactive shell so we can access it from within the cluster.

  1. Create a new namespace
kubectl create ns airwave-dev
kubectl run -n airwave-dev -it busybox --image=busybox --rm -- shwget --spider http://nginx.default

Dive into use cases and policies to showcase how it works

Official Documentation: https://kubernetes.io/docs/concepts/services-networking/network-policies/

1. The first use case is blocking all ingress traffic for the default namespace.

---
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: default-deny-all
spec:
podSelector: {}
policyTypes:
- Ingress
kubectl apply -f https://raw.githubusercontent.com/airwavetechio/calico-istio-demo/main/policies/deny-default-ingress.yaml
kubectl run -n airwave-dev -it busybox --image=busybox --rm -- shwget --spider http://nginx-for-calico-demo.default
The situation we’re in now.

2. For our 2nd use case, let’s block egress traffic for the namespace airwave-dev.

Notice below in the egress policy namespace is defined. This is because we want to block all egress traffic coming out of the airwave-dev namespace, which would include the busyboxpod.

---
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: deny-all-egress
namespace: airwave-dev
spec:
podSelector: {}
policyTypes:
- Egress
kubectl apply -f https://raw.githubusercontent.com/airwavetechio/calico-istio-demo/main/policies/deny-airwave-dev-egress.yaml
nslookup www.google.com
Our current state

3. Our third example will allow traffic to nginx from our busybox pod in the airwave-dev namespace, but will still block all the other traffic.

This is what the end result will look like
  • Label the namespaces
  • Allow DNS lookups using an egress policy to kube-system namespace
  • An ingress policy allowing nginxto receive traffic from busybox
  • An egress policy allowing busyboxto send traffic to nginx

Label the Namespaces

The reason we need to label the namespaces is that the network policies currently don’t allow targeting namespaces by their name. Since they allow targeting namespaces by labels, let’s create a few.

kubectl label namespace airwave-dev ns=airwave-dev
kubectl label namespace kube-system ns=kube-system
kubectl label namespace default ns=default

Allow DNS using an egress policy

Allowing DNS traffic from the airwave-dev namespace to the kube-system namespace.
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-dns-access
namespace: airwave-dev
spec:
podSelector: {}
policyTypes:
- Egress
egress:
- to:
- namespaceSelector:
matchLabels:
ns: kube-system
ports:
- protocol: UDP
port: 53
kubectl apply -f https://raw.githubusercontent.com/airwavetechio/calico-istio-demo/main/policies/allow-dns.yaml

An ingress policy allowing nginx to receive traffic from busybox

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-ingress-from-busybox
namespace: default
spec:
podSelector:
matchLabels:
app: nginx
policyTypes:
- Ingress
ingress:
- from:
- namespaceSelector:
matchLabels:
ns: airwave-dev
kubectl get deployment -o wide to check my labels.
kubectl apply -f https://raw.githubusercontent.com/airwavetechio/calico-istio-demo/main/policies/allow-ingress-from-busybox.yaml

An egress policy allowing busybox to send traffic to nginx

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-egress-from-busybox
namespace: airwave-dev
spec:
podSelector: {}
policyTypes:
- Egress
egress:
- to:
- namespaceSelector:
matchLabels:
ns: default
podSelector:
matchLabels:
app: nginx
kubectl apply -f https://raw.githubusercontent.com/airwavetechio/calico-istio-demo/main/policies/allow-egress-to-nginx.yaml

Wrapping up

If you’ve made it this far, there’s one more thing to do. Let’s test the network policies.

Our current setup
  • Access the Nginxweb server from the busyboxinstance. According to the diagram above, this should work.
wget http://nginx-for-calico-demo.default --spider
  • Access DNS from your busyboxinstance. According to the diagram above, this should work.
nslookup www.google.com
  • Access an external website from the busyboxinstance. According to the diagram above, this should NOT work.
wget --spider https://www.google.com

UNINSTALLING

If you’d like to roll back any of the changes, use the following:

kubectl delete -f https://raw.githubusercontent.com/airwavetechio/calico-istio-demo/main/policies/allow-dns.yaml
kubectl delete -f https://raw.githubusercontent.com/airwavetechio/calico-istio-demo/main/policies/allow-ingress-from-busybox.yaml
kubectl delete -f https://raw.githubusercontent.com/airwavetechio/calico-istio-demo/main/policies/allow-egress-to-nginx.yaml
kubectl delete -f https://raw.githubusercontent.com/airwavetechio/calico-istio-demo/main/policies/deny-default-ingress.yaml
kubectl delete -f https://raw.githubusercontent.com/airwavetechio/calico-istio-demo/main/policies/deny-airwave-dev-egress.yaml
kubectl delete ns airwave-dev
kubectl delete deployment nginx-for-calico-demo

--

--

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store