At last: Network Policies in AKS with kube-router
Categories:
3 minute read
For ages I’ve been waiting for a way to enforce netwok policies on AKS, so last weekend while I was googling around, I found this hidden gem posted by Marcus Robinson: Enforcing Network Policies using kube-router on AKS and had to test the proposed solution.
Prerequisites:
- Azure Kubernetes Service (AKS) deployed with HTTP application routing enabled.
- kubectl installed
Create a service exposed throuh your AKS DNS Zone
Let’s start by deploying the following service to your Kubernetes cluster, by saving the following content to a file named dni-function.yaml and replacing [YOUR_DNS__ZONE_NAME] with the corresponding value of your service:
apiVersion: apps/v1beta1
kind: Deployment
metadata:
name: dni-function
spec:
replicas: 1
template:
metadata:
labels:
app: dni-function
spec:
containers:
- name: dni-function
image: cmendibl3/dni:1.0.0
ports:
- containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
name: dni-function
spec:
type: ClusterIP
ports:
- name:
port: 80
selector:
app: dni-function
---
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: dni-function
annotations:
kubernetes.io/ingress.class: addon-http-application-routing
spec:
rules:
- host: dni-function.[YOUR_DNS__ZONE_NAME]
http:
paths:
- backend:
serviceName: dni-function
servicePort: 80
path: /
Now deploy it to Kubernetes:
kubectl apply -f ./dni-function.yaml
In a few seconds you’ll have a working Web API (Validates Spanish National Identification Numbers).
Now test the service with the following command:
curl -k http://dni-function.[YOUR_DNS__ZONE_NAME]/api/validate?dni=88410248L
which should return true.
Deploy kube-router
Thanks to Marcus Robinson we can deploy kube-router to AKS:
kubectl apply -f https://raw.githubusercontent.com/marrobi/kube-router/marrobi/aks-yaml/daemonset/kube-router-firewall-daemonset-aks.yaml
Deny all traffic to the service
Now let’s try to deny all the traffic to the service, creating a dni-function-deny-all.yaml file with the following contents:
kind: NetworkPolicy
apiVersion: networking.k8s.io/v1
metadata:
name: dni-function-deny-all
spec:
podSelector:
matchLabels:
app: dni-function
ingress: []
Deploy the policy:
kubectl apply -f ./dni-function-deny-all.yaml
Try calling the service again:
curl -k http://dni-function.[YOUR_DNS__ZONE_NAME]/api/validate?dni=88410248L
This time you should get:
<html>
<head><title>502 Bad Gateway</title></head>
<body bgcolor="white">
<center><h1>502 Bad Gateway</h1></center>
<hr><center>nginx/1.13.12</center>
</body>
</html>
That’s it! Your service is no longer available!!!
Allow only traffic from a specific pod
Create a dni-function-allow-internal.yaml file with the following contents:
kind: NetworkPolicy
apiVersion: networking.k8s.io/v1
metadata:
name: dni-function-allow-internal
spec:
podSelector:
matchLabels:
app: dni-function
ingress:
- from:
- podSelector:
matchLabels:
app: internal
Deploy the policy, which restricts the traffic to pods with the label: app=internal, and check that you still can’t connect:
kubectl apply -f ./dni-function-allow-internal.yaml
curl -k http://dni-function.[YOUR_DNS__ZONE_NAME]/api/validate?dni=88410248L
Now let’s create a pod with the expected label and try calling the dni-function service from it:
kubectl run internal-function-tester --rm -i -t --image=alpine --labels app=internal -- sh
wget -qO- --timeout=2 http://dni-function/api/validate?dni=88410248L
This time you should get true as the result!!!
To learn more about Network Policies check the kubernetes-network-policy-recipes repo and feel free to download the code and files for this post here