Secure your Kubernetes Application with Network Policies
This guide walks you through the basic Kubernetes network policy operations. First you are introduced to the Kubernetes network policies and network plugins. Then you apply these concepts to a multi-tier WordPress installation in kubeadm by completing the following steps:
- Install a Network plugin.
- Deploy a Wordpress Helm chart.
- Apply two network policies for securing the WordPress deployment.
At the end of this guide, you should be able to install a Kubernetes network plugin and apply network policies in your cluster. The examples described in this guide were tested in kubeadm, but they can be applied to any Kubernetes cluster.
By default, all pods in a Kubernetes cluster can communicate freely with each other without any issues. In many environments, you can isolate the services running in pods from each other by applying network restrictions. For example, the following can improve your cluster’s security:
- Only allow traffic between pods that form part of the same application. For example, in a frontend-backend application, only allow communication to the backend from frontend pods.
- Isolate pod traffic in namespaces. That is, a pod can only communicate with pods that belong to the same namespace.
This guide shows you how you can use the Kubernetes network policies to apply these kinds of restrictions. These restrictions can be combined with pod security policies which are explained in this guide.
Prerequisites and assumptions
This guide makes the following assumptions:
- You have kubeadm installed.
- You have a Kubernetes cluster running.
- You have the kubectl command line (kubectl CLI) installed.
- You have Helm and Tiller installed.
- You have an advanced level of understanding of how Kubernetes works, and its core resources and operations. You are expected to be familiar with concepts like:
Network policies in Kubernetes
A network policy is a set of network traffic rules applied to a given group of pods in a Kubernetes cluster. Just like every element in Kubernetes, it is modeled using an API Resource: NetworkPolicy. The following describes the broad structure of a network policy:
- The metadata section of the policy specifies its name.
The spec section of the policy outlines the key criteria a pod must fulfil in order to be allowed to run.
Here is a brief description of the main options available (you can find more details in the official Kubernetes API Reference):
podSelector: if the conditions defined in the next element apply, the podSelector establishes which pods the network can accept traffic from (destination pods from now on). Pods can be specified using the following criteria:
- namespaceSelector: a pod belongs to a given namespace.
- labelSelector: a pod contains a given label.
Network Policy Ingress Rules (ingress): establishes a set of allowed traffic rules. You can specify:
- from (origin pods): specifies which pods are allowed to access the previously specified destination pods. Just like with destination pods, these origin pods can be specified using NamespaceSelectors and LabelSelectors.
- ports (allowed ports): specifies which destination pod’s ports can be accessed by the origin pods.
You can find an example of what this looks like in the Kubernetes official documentation.
Kubernetes network plugins
In order to implement network policies in your cluster, you must use a compatible container network plugin.
In a usable Kubernetes cluster, pods must be able to communicate between themselves, with services and outside the cluster. Kubernetes is flexible enough (thanks to the use of the Container Networking Interface), or CNI) to allow the administrator to choose between numerous container network technologies (known as CNI plugins). Each one has its own properties and advantages (it is out of the scope of this guide to go through all of them), but not all of them are compatible with the Kubernetes network policies. The following are examples of compatible technologies:
You can find more information on Kubernetes networking in Kubernetes official documentation.
Installing a network plugin in kubeadm
To use the network policies, you must install a network plugin in kubeadm . You can choose among any of the ones detailed in the previous section. For this guide, we will use the Calico plugin.
Install the Calico CNI plugin.
$ kubectl apply -f https://docs.projectcalico.org/v2.4/getting-started/kubernetes/installation/hosted/kubeadm/1.6/calico.yaml
Use case: WordPress installation
In this example, you will add the following network policies:
- Restrict all traffic between pods.
- Allow only traffic from Wordpress to MariaDB through port 3306 in a WordPress+MariaDB installation.Crea
Step 1: Deploy a WordPress+MariaDB installation using Helm
If you do not have helm installed, install it using the following guide.
Deploy a Wordpress Helm chart. We will use the name np-test so we know that the WordPress pod will have the app: np-test-wordpress label and the MariaDB pod will have the app: np-test-mariadb label.
$ helm install stable/wordpress --name np-test
Step 2: Restrict traffic between pods
Create a policy-deny-all.yaml using the content below. In this yaml file you are creating a network rule with an empty PodSelector, which is equal to a wildcard. As there is no ingress section, no traffic is allowed. This means that, unless there are other network rules applied, no pod can communicate with any other pod.
apiVersion: networking.k8s.io/v1 kind: NetworkPolicy metadata: name: default-deny spec: podSelector:
Create the network policy using the kubectl create command:
$ kubectl create -f policy-deny-all.yaml
After some time, check that the WordPress pod crashes because it cannot connect to the MariaDB pod. This is expected as we restricted traffic between all pods.
Step 3: Allow traffic only from the WordPress pod to the MariaDB pod
Now that we have restricted all network traffic between pods, we create an additional policy that allows WordPress to connect to the MariaDB service. We can create additional network rules such as this to ensure that we only allow traffic where needed.
Create a policy-wordpress-mariadb.yaml with the content below. In this yaml file you are creating a network rule with the MariaDB pods (i.e. all pods with label app: np-test-mariadb) as destination pods. In the network policy ingress rules, you set the WordPress pods (that is, all pods with label app: np-test-wordpress) as the origin pods, and 3306 as the allowed port.
apiVersion: networking.k8s.io/v1 kind: NetworkPolicy metadata: name: db-frontend-allow spec: podSelector: matchLabels: app: np-test-mariadb ingress: - from: - podSelector: matchLabels: app: np-test-wordpress ports: - protocol: TCP port: 3306
Create the network policy using the kubectl create command:
$ kubectl create -f policy-wordpress-mariadb.yaml
Check that the WordPress pod now works without issues.
$ kubectl get pods NAME READY STATUS RESTARTS AGE np-test-mariadb-2450482308-4sw28 1/1 Running 0 2d np-test-wordpress-2742268951-kg4km 1/1 Running 7 2d
Now you are able to perform basic network policy operationIn this guide we walked you through the concept of network policies and network plugins. Thanks to that, you were able to secure a multi-tier application (Wordpress+MariaDB Helm chart) by isolating them from the rest of the cluster pods. This is a first step in the numerous applications where network policies and network plugins offer to your cluster. For more information, see the following links:
- Official Kubernetes documentation for network policies
- Official Kubernetes example with an NGINX container
- Configure RBAC in your Kubernetes Cluster
- Secure a Kubernetes Cluster with Pod Security Policies
- Sealed Secrets: Protecting Your Passwords Before They Reach Kubernetes
- Kubeadm Setup Tool