top of page
Writer's pictureRafael Natali

Securing Kubernetes Workloads: Implementing Effective Network Policies

Updated: Jan 22

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.

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.


References




4 views0 comments

Recent Posts

See All

Comments


bottom of page