Kubernetes network policy best practices
Tags: cloudnativesecurity, devsecops, ecosystems
Published: 2023-01-09 10:08:26

---
title: Kubernetes network policy best practices
published: true
date: 2022-12-21 14:22:31 UTC
tags: CloudNativeSecurity,DevSecOps,Ecosystems
canonical_url: https://snyk.io/blog/kubernetes-network-policy-best-practices/
---

Controlling and filtering traffic when containerizing a workload within Kubernetes Pods is just as crucial as a firewall in a more traditional network setup. The difference is that, in this scenario, those capabilities are provided by the Kubernetes NetworkPolicy API.

This article will explore Kubernetes NetworkPolicy by creating an example network policy and examining its core parameters. Then, we’ll look at some common NetworkPolicy use cases and learn how to monitor them using kubectl. Finally, we’ll discover how to implement Container Network Interface (CNI) using third-party Kubernetes extensions.

## Why you shouldn’t shy away from Kubernetes network policies

Implementing network policies is critical to operating a Kubernetes environment. Without a configured network policy, all Pods within a cluster can communicate with each other by default. So, when our Pod contains sensitive data, such as a backend database holding confidential information, we must ensure that only certain frontend Pods can connect to it. 

Alternatively, we can isolate network traffic across Pods in a development environment from those running in a production environment. Without network policies, all traffic moves freely to and from all points in the network. 

Fortunately, configuring Kubernetes NetworkPolicy is a simple, effective, and holistic means for ensuring our network traffic flows only as intended.

## Defining Kubernetes network policies

Let’s take a look at a sample [NetworkPolicy](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.25/#networkpolicy-v1-networking-k8s-io). Consider a [sample workload](https://kubernetes.io/docs/tutorials/stateful-application/mysql-wordpress-persistent-volume/) with a WordPress front end and MySQL database back end, running a collection of Pods containing both web and database services, all deployed within the Kubernetes `default` namespace. The company’s security protocols mandate that we isolate network traffic for specific workloads and allow the minimum necessary incoming and outgoing traffic to use these workloads. 

This strategy involves the following conditions:

- Blocking the default Kubernetes behavior that allows all traffic.
- Ensuring that only Pods labeled `wordpress` in the `default` namespace can communicate with one another.
- Allowing incoming (`ingress`) connectivity from public internet on ports `80`/`443` and the `172.16.0.0` IP range.
- Only allowing the Pods labeled `wordpress` to connect to the MySQL database Pods on port `3306`.
- Always allowing connectivity to the Kubernetes DNS service (port `53`).
- Blocking all outgoing connectivity outside of the cluster.

The network diagram below illustrates how these rules might look.

![](https://snyk.io/wp-content/uploads/blog-k8s-networkpolicy-chart.png)

For this example, we can either distribute the network policies across the policy definition files or combine all policies into a single YAML manifest file. Since our example uses one workload (`webapp`), using one rulebase definition file makes sense. However, since this example holds several ingress and egress connections, we could alternatively create individual configuration files for each connection within the cluster.

Let’s walk through several of the parameters used above to understand how they relate to the configuration and affect network traffic behavior.

### API and metadata

In the first line of the YAML file below, we specify the networking API (`networking.k8s.io`) and its version (`v1`). We also define the kind of YAML file as `NetworkPolicy`, informing the Kubernetes API controller that we’re configuring network policies. The `name` and `namespace` items in the `metadata` section contain the name we give this ruleset and the namespace to which it’s linked. 

```
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: sample-network-policy
  namespace: default
```

The next portion of the YAML file contains the specifications (`specs`) section, where we can stipulate filters to which the network policy will apply.

The below segment features several vital parameters:

- `podSelector` — Specifies which Pods are subject to the prescribed traffic policies. Our example uses the matchLabels parameter to ensure that the network policy applies to all Pods labeled app: `wordpress`. As a secondary result, the parameter excludes all other Pods from this network policy.
- `policyTypes` — Contains two categories: `Ingress` and `Egress`
- `Ingress` — Defines all incoming Pod/namespace/Pod collection traffic
- `Egress` — Defines all outgoing Pod/namespace/Pod collection traffic

```
spec:
  podSelector:
    matchLabels:
      app: wordpress
  policyTypes:
    - Egress
    - Ingress
```

Next, the `ingress` section of the network policy defines the types of permitted incoming traffic. The below section allows ingress on ports `443` and `80` from:

- All Pods labeled `wordpress`
- All public internet traffic (`cidr: 0.0.0.0/0`)
- All IP addresses within the range `172.16.0.0/16`, which might represent a corporate IP range (a VPN, VLAN, or subnet).

The YAML snippet that enables the above traffic would look like this:

```
  ingress:
    - from:
      - podSelector:
          matchLabels:
            app: wordpress
      ports:
        - port: 443
        - port: 80  
    - from:
      - ipBlock:
          cidr: 172.16.0.0/16
      ports:
        - port: 443
        - port: 80
    - from:
      - ipBlock:
          cidr: 0.0.0.0/0
      ports:
        - port: 443
        - port: 80
```

Finally, we detail the `egress` section with the outgoing traffic rules. We allow all outgoing traffic communication from Pods labeled webapp on ports `1433` (SQL) and `53` (DNS). 

Specifying the webapp label ensures no other Pod can communicate with the SQL Server instances, eliminating all associated security risks. Similarly, the configuration allows port `53` to connect to all Pods in the cluster. 

There is one more critical takeaway from this policy definition. Once we integrate network policy to control Pod connectivity, we need to configure the allow/deny settings in both directions. Allowing egress traffic from the front end without allowing ingress traffic to the back end will prevent communication. 

The YAML snippet for this part of the traffic looks like the below example:

```
  egress: 
    - to:
        - namespaceSelector: {}
          podSelector:
            matchLabels:
              k8s-app: kube-dns
      ports:
        - port: 53
          protocol: UDP

    - to:
        - podSelector:
            matchLabels:
              app: wordpress
      ports:
        - port: 3306
```

## Applying Kubernetes network policies

We’ve now finished our sample YAML Network Policy manifest, which looks like this:

```
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: sample-network-policy
  namespace: default
spec:
  podSelector:
    matchLabels:
      app: webapp
  policyTypes:
    - Egress
    - Ingress
  ingress:
    - from:
        - podSelector:
            matchLabels:
              app: webapp
      ports:
        - port: 443
        - port: 80
    - from:
        - podSelector: {}
    - from:
        - ipBlock:
            cidr: 172.16.0.0/16
      ports:
        - port: 443
        - port: 80
    - from:
        - ipBlock:
            cidr: 0.0.0.0/0
      ports:
        - port: 443
        - port: 80
  egress:
    - to:
        - namespaceSelector: {}
          podSelector:
            matchLabels:
              k8s-app: kube-dns
      ports:
        - port: 53
          protocol: UDP
    - to:
        - podSelector: {}
    - to:
        - podSelector:
            matchLabels:
              app: webapp
      ports:
        - port: 443
        - port: 80
```

Now, we have to inject our file into the Kubernetes cluster. To do so, first, save this file as `sample-network-policy.yaml`.

Now, we apply the definition file similarly to most other Kubernetes configurations: using the kubectl command line interface (CLI). 

Run the following command: 

```
kubectl apply -f sample-network-policy.yaml
```

![](https://snyk.io/wp-content/uploads/blog-k8s-networkpolicy-apply.png)

## Validating and monitoring Kubernetes network policies

Similar to traditional firewall management, validating and monitoring Kubernetes network policies requires operational oversight. Occasionally, we must reevaluate existing network rules to decide whether they still apply to the associated workload. 

We may also need to validate the rulebase to troubleshoot traffic issues or investigate conflicts across different network policies. Fortunately, we can validate Network Policies using the kubectl CLI. Running the following command analyzes and monitors your current network policies:

```
kubectl describe networkpolicy <networkpolicy name as listed in the YAML manifest>
```

Below is a sample output for the `ingress` policy type.

![](https://snyk.io/wp-content/uploads/blog-k8s-networkpolicy-ingress.png)

Additionally, this image shows a sample output for the `egress` policy type:

![](https://snyk.io/wp-content/uploads/blog-k8s-networkpolicy-egress.png)

## Best practices for applying Kubernetes network policies

As with any network security configuration, we should employ several best practices for our Kubernetes network policy:

- Use the default `deny-all` network policy to ensure that only explicitly permitted communication occurs.
- Group Pods that must communicate with one another using the `PodSelector` parameter.
- Only allow inter-namespace communication when necessary.
- Don’t allow unnecessary network communication — even within the Kubernetes cluster.
- Use caution when allowing Pods within the cluster to receive non-cluster network traffic.
- Denying outgoing public internet traffic might interfere with specific application updates or validation processes.

## Kubernetes CNI plugins optimize network policy management

One of the benefits of CNI plugins is that they abstract away the implementation details of Network Policy, ensuring cluster administrators can choose the best solution for their needs without exposing the complexity of the underlying technologies. 

However, default installations of Kubernetes do not have a preinstalled CNI plugin unless your distribution or provider has added one. This means that you’ll need to choose and install the plugin that best suits your needs. Additionally, even if your distribution has a default plugin, you may find that more aptly accommodates your requirements.

There is a [multitude of CNI providers](https://kubernetes.io/docs/concepts/cluster-administration/addons/#networking-and-network-policy), and some of the most popular include:

- [Cilium](https://github.com/cilium/cilium)
- [Calico](https://github.com/projectcalico/calico)
- [Antrea](https://github.com/antrea-io/antrea) 

Each plugin has certain unique capabilities, meaning that you might need to try out a few to decide which option best meets your network and network security requirements.

## Conclusion

Configuring enterprise network topology with complex routing, traffic rules, and security integrations can be tedious. Fortunately, network policies can achieve in a Kubernetes environment what firewalls did best within a traditional infrastructure. 

Of course, configuring network policies is only the first step in a process that requires occasional reassessment and maintenance. While the built-in kubenet plugin provides certain network capabilities for your policy management, other CNI plugins offer more advanced capabilities. Fortunately, the right policy and management combination ensures that your network traffic remains secure and efficient.

### Additional Kubernetes security resources

- [Kubernetes security: Common issues and best practices](https://snyk.io/learn/kubernetes-security/)
- [Building Docker images in Kubernetes](https://snyk.io/blog/building-docker-images-kubernetes/)
- [Kubernetes Monitoring 2022 guide](https://snyk.io/learn/kubernetes-security/kubernetes-monitoring/)
- [10 Kubernetes Security Context settings you should understand](https://snyk.io/blog/10-kubernetes-security-context-settings-you-should-understand/)
- [Security implications of Kubernetes operators](https://snyk.io/blog/security-implications-of-kubernetes-operators/)