Network Policies are an application-centric construct that allows you to specify how a pod is allowed to communicate with various network “entities”
Prerequisite
This tutorial is a continuation of my previous articles:
These articles aimed to help you use Ansible¹ to create a Kubernetes Cluster in Google Cloud Platform (GCP)² and deploy a Nginx³ pod. Therefore, if you didn’t do it already, review the mentioned articles before proceeding.
The code used to create this tutorial is available in this repository.
From this point on, I assume you already have an up and running GKE cluster and an Nginx pod.
Kubernetes Network Policies
By default, Pods are non-isolated; they accept traffic from any source. However, this is a feature that does not work for all scenarios. As we can see in the diagram above, we don’t want that our Nginx Pod receive only traffic from the busybox Pod in the same namespace.
To fulfill this requirement, configure a NetworkPolicy in our Kubernetes cluster. With that configuration in place, we say that the Pod is now isolated.
This article will provide a basic example of how to configure, use, and test a NetworkPolicy.
Enabling NetworkPolicy in GKE
Depending on your GKE cluster configuration, the option to use NetworkPolicy is not enabled. Please refer to Google GKE documentation⁵ to see how to enable it.
If you’re using the GKE cluster created from the Prerequisites section, this option is already enabled.
Ansible Directory Layout
Refer to this GitHub repository section to see the details of the Ansible structure.
Ansible Roles
Create a new Ansible role on ansible/roles/k8s-policies with the following main.yml file under tasks. This role will be responsible for creating the namespace=external, deploy one busybox Pod in the nginx namespace and one in the external namespace, and the NetworkPolicy.
---
- name: Create busybox pod on Nginx namespace
kubernetes.core.k8s:
state: present
definition:
apiVersion: v1
kind: Pod
metadata:
name: busybox
namespace: "{{ namespace }}"
labels:
app: busybox
spec:
containers:
- name: busybox
image: busybox
imagePullPolicy: Always
command:
- sleep
- "3600"
- name: Create external namespace
kubernetes.core.k8s:
state: present
definition:
apiVersion: v1
kind: Namespace
metadata:
name: external
- name: Create busybox pod on External namespace
kubernetes.core.k8s:
state: present
definition:
apiVersion: v1
kind: Pod
metadata:
name: busybox
namespace: external
labels:
app: busybox
spec:
containers:
- name: busybox
image: busybox
imagePullPolicy: Always
command:
- sleep
- "3600"
- name: Create network policy to deny ingress
kubernetes.core.k8s:
state: present
definition:
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-traffic-nginx
namespace: "{{ namespace }}"
spec:
podSelector: {}
policyTypes:
- Ingress
ingress:
- from:
- namespaceSelector:
matchLabels:
app: "{{ namespace }}"
Also, a label was added to the nginx namespace configuration role on ansible/roles/k8s-deployments.
...
metadata:
name: "{{ app }}"
namespace: "{{ namespace }}"
labels:
app: "{{ app }}"
Ansible Playbook
The last step is to create an Ansible playbook to execute the k8s-policies role. In the ansible folder, I created a file called secure-app-k8s.yml:
---
- name: deploy application
hosts: localhost
gather_facts: false
environment:
GOOGLE_CREDENTIALS: "{{ credentials_file }}"
roles:
- k8s-policies
Deploying a NetworkPolicy
Retrieve the ip address of the nginx pod:
kubectl get pods --namespace nginx -l "app=nginx" -o jsonpath="{.items[0].status.podIP}"
10.40.1.10
Testing communication from a Pod in the Nginx namespace
Use the busybox container to connect to the nginx pod:
kubectl -n nginx exec busybox -- wget --spider 10.40.1.10
Output:
Connecting to 10.40.1.10 (10.40.1.10:80)
remote file exists
Testing communication from a pod in the External namespace
kubectl -n external exec busybox -- wget --spider 10.40.1.13
Output:
Connecting to 10.40.1.13 (10.40.1.13:80)
wget: can't connect to remote host (10.40.1.13): Connection timed out
command terminated with exit code 1
This is the expected behaviour because our goal is to only allow access from Pods in the nginx namespace.
Cleaning up
Execute the following playbook to remove the NetworkPolicy and re-run the wget command from the external namespace and see what happens!
ansible-playbook ansible/unsecure-app-k8s.yml -i ansible/inventory/<your-inventory-filename>
Conclusion
This article has shown how to configure and test Kubernetes NetworkPolicy and how they can be efective in controlling who can access your Pods. NetworkPolicy is a powerful resource to start securing your Kubernetes Cluster.
Please refer to the Kubernetes NetworkPolicies⁴ documentation for more details for this resource.
Comments