Control traffic flow to and from Kubernetes pods with Network Policies

Rafael Natali
FAUN — Developer Community 🐾
4 min readMay 24, 2021

--

Network Policies are an application-centric construct that allows you to specify how a pod is allowed to communicate with various network “entities”

Kubernetes Network Policies implementation diagram.
Kubernetes Network Policies implementation diagram.

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.

Manage NetworkPolicies with Ansible

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

Testing communication between the pods

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

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

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.

Execute the following playbook to remove the Network Policy 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.

References

  1. https://ansible.com
  2. https://cloud.google.com/kubernetes-engine
  3. https://www.nginx.com
  4. https://kubernetes.io/docs/concepts/services-networking/network-policies/
  5. https://cloud.google.com/kubernetes-engine/docs/how-to/network-policy
  6. https://faun.pub/automation-deploying-an-app-in-gke-using-ansible-4b6687967ac3
  7. https://faun.pub/how-to-automate-the-setup-of-a-kubernetes-cluster-on-gcp-e97918bf41de

Join FAUN: Website 💻|Podcast 🎙️|Twitter 🐦|Facebook 👥|Instagram 📷|Facebook Group 🗣️|Linkedin Group 💬| Slack 📱|Cloud Native News 📰|More.

If this post was helpful, please click the clap 👏 button below a few times to show your support for the author 👇

--

--