Kubernetes is a container management system designed to automate containerized applications' deployment, scaling, and management. It was created by Google based on its 15 years of experience in running industrialized workloads in different companies and can be considered the standard for container orchestration.
In Kubernetes, there is such a thing as a pod. It is the smallest unit of deployment that combines one or more containers and their associated resources. They play an important role in enforcing network policies, namely acting as the source and destination of traffic to which access and security rules apply. Each pod has its own IP address within the cluster, allowing you to manage network traffic at the pod level.
Network policies in Kubernetes are a relatively new functionality that consists of a set of rules that define which pods or groups of pods can communicate with each other over network connections within the cluster. Network policies help users control traffic and customize security by restricting access to certain services or pods.
In this article, we will look at network policies in Kubernetes and examples of how to apply them.
In this section, we will cover the main benefits of using network policies in Kubernetes:
Application security
Network policies allow users to define strict rules for accessing network traffic between pods, thus preventing unauthorized access attempts and minimizing the attack surface.
Isolation and multitenancy
Network policies are used when creating isolated network zones within a cluster. The user can define different access rules for different namespaces, suppressing the possibility of network traffic crossing between applications from different groups. This is especially useful in multitenant environments, where multiple clients or teams may utilize a single Kubernetes cluster.
Simplified management
Network policies also simplify the process of managing network connections in the cluster. Users can configure both general rules and individual rules for specific components.
Increased fault tolerance
Self-exclusion or self-healing rules increase application resiliency. For example, if one pod fails, all traffic will be automatically redirected to the running instances, thus ensuring business continuity.
NetworkPolicy
in Kubernetes is a mechanism designed to define access rules for network traffic between pods in a cluster. With NetworkPolicy
, users can restrict inbound and outbound network traffic based on various attributes: IP addresses, ports, and labels.
To implement network policies, you will need a network plugin that supports NetworkPolicy
.
Below are the main fields in the NetworkPolicy
:
apiVersion
is responsible for the API version used to define NetworkPolicy
. For example, for Kubernetes version 1.22, the value of this field could be networking.k8s.io/v1
.
kind
indicates the type of the NetworkPolicy
object. Regarding network policies, the value of kind
would be NetworkPolicy
.
metadata
contains the NetworkPolicy
object metadata (name, namespace, annotations, and labels).
spec
defines the basic parameters and rules of the network policy. It may have the following subfields:
podSelector
specifies the pods to which the network policy applies.
policyTypes
specifies the types of policies to be applied to the selected pods. There are two types of policies for pods: ingress
and egress
. The user can specify either or both types.
ingress
contains a list of access rules for incoming network traffic.
egress
contains a list of access rules for outgoing network traffic.
status
contains information about the state of the network policy. It can include conditions that reflect the current state of the policy.
Here is a simple example of a network policy that contains all of the above fields:
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: example-network-policy
namespace: example-namespace
labels:
app: example-app
spec:
podSelector:
matchLabels:
app: example-app
policyTypes:
- Ingress
- Egress
ingress:
- from:
- podSelector:
matchLabels:
app: allowed-app
ports:
- protocol: TCP
port: 80
egress:
- to:
- podSelector:
matchLabels:
app: allowed-app
ports:
- protocol: TCP
port: 443
status:
conditions:
- type: NetworkPolicyReady
status: "True"
lastTransitionTime: "2023-06-27T12:00:00Z"
Here, we create a network policy named example-network-policy
in the example-namespace
. The policy applies to pods labeled app: example-app
and contains both types of policies. The ingress
rule allows incoming TCP traffic on port 80 from pods labeled app: allowed-app
. The egress
rule allows outbound TCP traffic on port 443 to pods labeled app: allowed-app
. The status
field indicates that the policy is ready for use.
In this chapter, we will provide some common network policies. You can explore other examples in the GitHub repository.
This policy involves blocking all traffic to application pods, which can be useful in the following cases:
Blocking all traffic before creating a whitelist with allowed resources;
Prohibiting interaction of other pods with the specified one;
Temporary isolating the service from other pods.
First of all, you need to run an nginx pod with special labels, also specifying the port:
kubectl run web --image=nginx --labels app=web,env=prod --expose --port 80
Now enable a temporary pod and send a request to the service:
kubectl run --rm -i -t --image=alpine test-$RANDOM -- sh
/ # wget -qO- http://web
After successfully running and sending the request, compile the NetworkPolicy
and save it to the banning-all-traffic.yaml
file:
kind: NetworkPolicy
apiVersion: networking.k8s.io/v1
metadata:
name: banning-all-traffic
spec:
podSelector:
matchLabels:
app: web
ingress: []
Apply it to the cluster:
kubectl apply -f banning-all-traffic.yaml
Now, run the pod and send the request again:
kubectl run --rm -i -t --image=alpine test-$RANDOM -- sh
/ # wget -qO- --timeout=2 http://web
If you receive a message that the download time has expired, then everything is successful!
You can restrict traffic for an application by allowing it from certain pods and denying it from others. This policy can be useful in the following cases:
Allowing traffic to those applications that need it.
Allowing traffic to the database for the required applications.
Suppose the application is a REST API server labeled as app=example2
and role=api
:
kubectl run apiserver --image=nginx --labels="app=example2,role=api" --expose --port=80
Then, the network policy for restricting traffic will look like this:
kind: NetworkPolicy
apiVersion: networking.k8s.io/v1
metadata:
name: traffic-restriction
spec:
podSelector:
matchLabels:
app: example2
role: api
ingress:
- from:
- podSelector:
matchLabels:
app: example2
Save it to the traffic-restriction.yaml
file and apply it to the cluster:
kubectl apply -f traffic-restriction.yaml
Let's run the pod with and without the app=example2
label to verify that the network policy works.
The pod with the label:
kubectl run test-$RANDOM --rm -i -t --image=alpine --labels="app=example2,role=frontend" -- sh
/ # wget -qO- --timeout=2 http://apiserver
Without the label:
kubectl run test-$RANDOM --rm -i -t --image=alpine -- sh
/ # wget -qO- --timeout=2 http://apiserver
In the first case, traffic should be allowed, and in the second case, restricted.
Allowing all traffic for applications may be required after applying a "deny all traffic" policy to allow access to the application from all pods in the specified namespace.
Let's start a web application:
kubectl run web --image=nginx --labels="app=web" --expose --port=80
Write the network policy:
kind: NetworkPolicy
apiVersion: networking.k8s.io/v1
metadata:
name: resolution-all-traffic
namespace: default
spec:
podSelector:
matchLabels:
app: web
ingress:
- {}
Here, we use the empty entry rule, {}
. It allows incoming traffic both in the current namespace and any other namespace. The empty entry rule is equivalent to the following fragment:
- from:
- podSelector: {}
namespaceSelector: {}
Save the policy in the allow-all-traffic.yaml
file and apply it to the cluster:
kubectl apply -f allow-all-traffic.yaml
You can also apply a traffic denial policy to check that applying allow-all-traffic.yaml
will invalidate it.
Finally, let's verify that our policy works:
kubectl run test-$RANDOM --rm -i -t --image=alpine -- sh
/ # wget -qO- --timeout=2 http://web
As a result, you should see that the traffic is allowed.
In this article, we studied Kubernetes cluster network policies, analyzed their syntax, and provided examples for a more detailed understanding of their work. Network policies allow us to configure access rules flexibly and control network traffic within a cluster. Their use provides security, isolation, and simplified management in your Kubernetes cluster.
This article provides general information about network policies. For a more detailed understanding, refer to the official documentation and do additional research considering the specifics of your cluster and the requirements of your application.